cpp_generator::class_printer::print_method_variants: pass in method name
[isl.git] / interface / generator.cc
blobf92a7113a38948fa527c82e28fb3602185f6c52c
1 /*
2 * Copyright 2011,2015 Sven Verdoolaege. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY SVEN VERDOOLAEGE ''AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * The views and conclusions contained in the software and documentation
29 * are those of the authors and should not be interpreted as
30 * representing official policies, either expressed or implied, of
31 * Sven Verdoolaege.
34 #include <stdio.h>
35 #include <string.h>
36 #include <algorithm>
37 #include <iostream>
39 #include <clang/AST/Attr.h>
40 #include <clang/Basic/SourceManager.h>
42 #include "isl_config.h"
43 #include "extract_interface.h"
44 #include "generator.h"
46 const char *isl_class::get_prefix = "get_";
47 const char *isl_class::set_callback_prefix = "set_";
49 /* Should "method" be considered to be a static method?
50 * That is, is the first argument something other than
51 * an instance of the class?
53 bool isl_class::is_static(FunctionDecl *method) const
55 ParmVarDecl *param;
56 QualType type;
58 if (method->getNumParams() < 1)
59 return true;
61 param = method->getParamDecl(0);
62 type = param->getOriginalType();
63 if (!generator::is_isl_type(type))
64 return true;
65 return generator::extract_type(type) != name;
68 /* Should "method" be considered to be a static method?
69 * That is, is the first argument something other than
70 * an instance of the class?
72 bool generator::is_static(const isl_class &clazz, FunctionDecl *method)
74 return clazz.is_static(method);
77 /* Does "fd" modify an object of "clazz"?
78 * That is, is it an object method that takes the object and
79 * returns (gives) an object of the same type?
81 bool generator::is_mutator(const isl_class &clazz, FunctionDecl *fd)
83 ParmVarDecl *param;
84 QualType type, return_type;
86 if (fd->getNumParams() < 1)
87 return false;
88 if (is_static(clazz, fd))
89 return false;
91 if (!gives(fd))
92 return false;
93 param = fd->getParamDecl(0);
94 if (!takes(param))
95 return false;
96 type = param->getOriginalType();
97 return_type = fd->getReturnType();
98 return return_type == type;
101 /* Find the FunctionDecl with name "name",
102 * returning NULL if there is no such FunctionDecl.
103 * If "required" is set, then error out if no FunctionDecl can be found.
105 FunctionDecl *generator::find_by_name(const string &name, bool required)
107 map<string, FunctionDecl *>::iterator i;
109 i = functions_by_name.find(name);
110 if (i != functions_by_name.end())
111 return i->second;
112 if (required)
113 die("No " + name + " function found");
114 return NULL;
117 /* List of conversion functions that are used to automatically convert
118 * the second argument of the conversion function to its function result.
120 const std::set<std::string> generator::automatic_conversion_functions = {
121 "isl_id_read_from_str",
122 "isl_val_int_from_si",
125 /* Extract information about the automatic conversion function "fd",
126 * storing the results in this->conversions.
128 * A function used for automatic conversion has exactly two arguments,
129 * an isl_ctx and a non-isl object, and it returns an isl object.
130 * Store a mapping from the isl object return type
131 * to the non-isl object source type.
133 void generator::extract_automatic_conversion(FunctionDecl *fd)
135 QualType return_type = fd->getReturnType();
136 const Type *type = return_type.getTypePtr();
138 if (fd->getNumParams() != 2)
139 die("Expecting two arguments");
140 if (!is_isl_ctx(fd->getParamDecl(0)->getOriginalType()))
141 die("Expecting isl_ctx first argument");
142 if (!is_isl_type(return_type))
143 die("Expecting isl object return type");
144 conversions[type] = fd->getParamDecl(1);
147 /* Extract information about all automatic conversion functions
148 * for the given class, storing the results in this->conversions.
150 * In particular, look through all exported constructors for the class and
151 * check if any of them is explicitly marked as a conversion function.
153 void generator::extract_class_automatic_conversions(const isl_class &clazz)
155 const function_set &constructors = clazz.constructors;
156 function_set::iterator fi;
158 for (fi = constructors.begin(); fi != constructors.end(); ++fi) {
159 FunctionDecl *fd = *fi;
160 string name = fd->getName().str();
161 if (automatic_conversion_functions.count(name) != 0)
162 extract_automatic_conversion(fd);
166 /* Extract information about all automatic conversion functions,
167 * storing the results in this->conversions.
169 void generator::extract_automatic_conversions()
171 map<string, isl_class>::iterator ci;
173 for (ci = classes.begin(); ci != classes.end(); ++ci)
174 extract_class_automatic_conversions(ci->second);
177 /* Add a subclass derived from "decl" called "sub_name" to the set of classes,
178 * keeping track of the _to_str, _copy and _free functions, if any, separately.
179 * "sub_name" is either the name of the class itself or
180 * the name of a type based subclass.
181 * If the class is a proper subclass, then "super_name" is the name
182 * of its immediate superclass.
184 void generator::add_subclass(RecordDecl *decl, const string &super_name,
185 const string &sub_name)
187 string name = decl->getName().str();
189 classes[sub_name].name = name;
190 classes[sub_name].superclass_name = super_name;
191 classes[sub_name].subclass_name = sub_name;
192 classes[sub_name].type = decl;
193 classes[sub_name].fn_to_str = find_by_name(name + "_to_str", false);
194 classes[sub_name].fn_copy = find_by_name(name + "_copy", true);
195 classes[sub_name].fn_free = find_by_name(name + "_free", true);
198 /* Add a class derived from "decl" to the set of classes,
199 * keeping track of the _to_str, _copy and _free functions, if any, separately.
201 void generator::add_class(RecordDecl *decl)
203 return add_subclass(decl, "", decl->getName().str());
206 /* Given a function "fn_type" that returns the subclass type
207 * of a C object, create subclasses for each of the (non-negative)
208 * return values.
210 * The function "fn_type" is also stored in the superclass,
211 * along with all pairs of type values and subclass names.
213 void generator::add_type_subclasses(FunctionDecl *fn_type)
215 QualType return_type = fn_type->getReturnType();
216 const EnumType *enum_type = return_type->getAs<EnumType>();
217 EnumDecl *decl = enum_type->getDecl();
218 isl_class *c = method2class(fn_type);
219 DeclContext::decl_iterator i;
221 c->fn_type = fn_type;
222 for (i = decl->decls_begin(); i != decl->decls_end(); ++i) {
223 EnumConstantDecl *ecd = dyn_cast<EnumConstantDecl>(*i);
224 int val = (int) ecd->getInitVal().getSExtValue();
225 string name = ecd->getNameAsString();
227 if (val < 0)
228 continue;
229 c->type_subclasses[val] = name;
230 add_subclass(c->type, c->subclass_name, name);
234 /* Add information about the enum values in "decl", set by "fd",
235 * to c->set_enums. "prefix" is the prefix of the generated method names.
236 * In particular, it has the name of the enum type removed.
238 * In particular, for each non-negative enum value, keep track of
239 * the value, the name and the corresponding method name.
241 static void add_set_enum(isl_class *c, const string &prefix, EnumDecl *decl,
242 FunctionDecl *fd)
244 DeclContext::decl_iterator i;
246 for (i = decl->decls_begin(); i != decl->decls_end(); ++i) {
247 EnumConstantDecl *ecd = dyn_cast<EnumConstantDecl>(*i);
248 int val = (int) ecd->getInitVal().getSExtValue();
249 string name = ecd->getNameAsString();
250 string method_name;
252 if (val < 0)
253 continue;
254 method_name = prefix + name.substr(4);
255 c->set_enums[fd].push_back(set_enum(val, name, method_name));
259 /* Check if "fd" sets an enum value and, if so, add information
260 * about the enum values to c->set_enums.
262 * A function is considered to set an enum value if:
263 * - the function returns an object of the same type
264 * - the last argument is of type enum
265 * - the name of the function ends with the name of the enum
267 static bool handled_sets_enum(isl_class *c, FunctionDecl *fd)
269 unsigned n;
270 ParmVarDecl *param;
271 const EnumType *enum_type;
272 EnumDecl *decl;
273 string enum_name;
274 string fd_name;
275 string prefix;
276 size_t pos;
278 if (!generator::is_mutator(*c, fd))
279 return false;
280 n = fd->getNumParams();
281 if (n < 2)
282 return false;
283 param = fd->getParamDecl(n - 1);
284 enum_type = param->getType()->getAs<EnumType>();
285 if (!enum_type)
286 return false;
287 decl = enum_type->getDecl();
288 enum_name = decl->getName().str();
289 enum_name = enum_name.substr(4);
290 fd_name = c->method_name(fd);
291 pos = fd_name.find(enum_name);
292 if (pos == std::string::npos)
293 return false;
294 prefix = fd_name.substr(0, pos);
296 add_set_enum(c, prefix, decl, fd);
298 return true;
301 /* Return the callback argument of a function setting
302 * a persistent callback.
303 * This callback is in the second argument (position 1).
305 ParmVarDecl *generator::persistent_callback_arg(FunctionDecl *fd)
307 return fd->getParamDecl(1);
310 /* Does the given function set a persistent callback?
311 * The following heuristics are used to determine this property:
312 * - the function returns an object of the same type
313 * - its name starts with "set_"
314 * - it has exactly three arguments
315 * - the second (position 1) of which is a callback
317 static bool sets_persistent_callback(isl_class *c, FunctionDecl *fd)
319 ParmVarDecl *param;
321 if (!generator::is_mutator(*c, fd))
322 return false;
323 if (fd->getNumParams() != 3)
324 return false;
325 param = generator::persistent_callback_arg(fd);
326 if (!generator::is_callback(param->getType()))
327 return false;
328 return prefixcmp(c->method_name(fd).c_str(),
329 c->set_callback_prefix) == 0;
332 /* Does this function take any enum arguments?
334 static bool takes_enums(FunctionDecl *fd)
336 unsigned n;
338 n = fd->getNumParams();
339 for (unsigned i = 0; i < n; ++i) {
340 ParmVarDecl *param = fd->getParamDecl(i);
341 if (param->getType()->getAs<EnumType>())
342 return true;
344 return false;
347 /* Sorting function that places declaration of functions
348 * with a shorter name first.
350 static bool less_name(const FunctionDecl *a, const FunctionDecl *b)
352 return a->getName().size() < b->getName().size();
355 /* Collect all functions that belong to a certain type, separating
356 * constructors from methods that set an enum value,
357 * methods that set a persistent callback and
358 * from regular methods, while keeping track of the _to_str,
359 * _copy and _free functions, if any, separately.
360 * Methods that accept any enum arguments that are not specifically handled
361 * are not supported.
362 * If there are any overloaded
363 * functions, then they are grouped based on their name after removing the
364 * argument type suffix.
365 * Check for functions that describe subclasses before considering
366 * any other functions in order to be able to detect those other
367 * functions as belonging to the subclasses.
368 * Sort the names of the functions based on their lengths
369 * to ensure that nested subclasses are handled later.
371 * Also extract information about automatic conversion functions.
373 generator::generator(SourceManager &SM, set<RecordDecl *> &exported_types,
374 set<FunctionDecl *> exported_functions, set<FunctionDecl *> functions) :
375 SM(SM)
377 set<FunctionDecl *>::iterator in;
378 set<RecordDecl *>::iterator it;
379 vector<FunctionDecl *> type_subclasses;
380 vector<FunctionDecl *>::iterator iv;
382 for (in = functions.begin(); in != functions.end(); ++in) {
383 FunctionDecl *decl = *in;
384 functions_by_name[decl->getName().str()] = decl;
387 for (it = exported_types.begin(); it != exported_types.end(); ++it)
388 add_class(*it);
390 for (in = exported_functions.begin(); in != exported_functions.end();
391 ++in) {
392 if (is_subclass(*in))
393 type_subclasses.push_back(*in);
395 std::sort(type_subclasses.begin(), type_subclasses.end(), &less_name);
396 for (iv = type_subclasses.begin(); iv != type_subclasses.end(); ++iv) {
397 add_type_subclasses(*iv);
400 for (in = exported_functions.begin(); in != exported_functions.end();
401 ++in) {
402 FunctionDecl *method = *in;
403 isl_class *c;
405 if (is_subclass(method))
406 continue;
408 c = method2class(method);
409 if (!c)
410 continue;
411 if (is_constructor(method)) {
412 c->constructors.insert(method);
413 } else if (handled_sets_enum(c, method)) {
414 } else if (sets_persistent_callback(c, method)) {
415 c->persistent_callbacks.insert(method);
416 } else if (takes_enums(method)) {
417 std::string name = method->getName().str();
418 die(name + " has unhandled enum argument");
419 } else {
420 string name = c->method_name(method);
421 c->methods[name].insert(method);
425 extract_automatic_conversions();
428 /* Print error message "msg" and abort.
430 void generator::die(const char *msg)
432 fprintf(stderr, "%s\n", msg);
433 abort();
436 /* Print error message "msg" and abort.
438 void generator::die(string msg)
440 die(msg.c_str());
443 /* Return a sequence of the types of which the given type declaration is
444 * marked as being a subtype.
445 * The order of the types is the opposite of the order in which they
446 * appear in the source. In particular, the first annotation
447 * is the one that is closest to the annotated type and the corresponding
448 * type is then also the first that will appear in the sequence of types.
449 * This is also the order in which the annotations appear
450 * in the AttrVec returned by Decl::getAttrs() in older versions of clang.
451 * In newer versions of clang, the order is that in which
452 * the attribute appears in the source.
453 * Use the position of the "isl_export" attribute to determine
454 * whether this is an old (with reversed order) or a new version.
455 * The "isl_export" attribute is automatically added
456 * after each "isl_subclass" attribute. If it appears in the list before
457 * any "isl_subclass" is encountered, then this must be a reversed list.
459 std::vector<string> generator::find_superclasses(Decl *decl)
461 vector<string> super;
462 bool reversed = false;
464 if (!decl->hasAttrs())
465 return super;
467 string sub = "isl_subclass";
468 size_t len = sub.length();
469 AttrVec attrs = decl->getAttrs();
470 for (AttrVec::const_iterator i = attrs.begin(); i != attrs.end(); ++i) {
471 const AnnotateAttr *ann = dyn_cast<AnnotateAttr>(*i);
472 if (!ann)
473 continue;
474 string s = ann->getAnnotation().str();
475 if (s == "isl_export" && super.size() == 0)
476 reversed = true;
477 if (s.substr(0, len) == sub) {
478 s = s.substr(len + 1, s.length() - len - 2);
479 if (reversed)
480 super.push_back(s);
481 else
482 super.insert(super.begin(), s);
486 return super;
489 /* Is "decl" marked as describing subclasses?
491 bool generator::is_subclass(FunctionDecl *decl)
493 return find_superclasses(decl).size() > 0;
496 /* Is decl marked as being part of an overloaded method?
498 bool generator::is_overload(Decl *decl)
500 return has_annotation(decl, "isl_overload");
503 /* Is decl marked as a constructor?
505 bool generator::is_constructor(Decl *decl)
507 return has_annotation(decl, "isl_constructor");
510 /* Is decl marked as consuming a reference?
512 bool generator::takes(Decl *decl)
514 return has_annotation(decl, "isl_take");
517 /* Is decl marked as preserving a reference?
519 bool generator::keeps(Decl *decl)
521 return has_annotation(decl, "isl_keep");
524 /* Is decl marked as returning a reference that is required to be freed.
526 bool generator::gives(Decl *decl)
528 return has_annotation(decl, "isl_give");
531 /* Return the class that has a name that best matches the initial part
532 * of the name of function "fd" or NULL if no such class could be found.
534 isl_class *generator::method2class(FunctionDecl *fd)
536 string best;
537 map<string, isl_class>::iterator ci;
538 string name = fd->getNameAsString();
540 for (ci = classes.begin(); ci != classes.end(); ++ci) {
541 size_t len = ci->first.length();
542 if (len > best.length() && name.substr(0, len) == ci->first &&
543 name[len] == '_')
544 best = ci->first;
547 if (classes.find(best) == classes.end()) {
548 cerr << "Unable to find class of " << name << endl;
549 return NULL;
552 return &classes[best];
555 /* Is "type" the type "isl_ctx *"?
557 bool generator::is_isl_ctx(QualType type)
559 if (!type->isPointerType())
560 return false;
561 type = type->getPointeeType();
562 if (type.getAsString() != "isl_ctx")
563 return false;
565 return true;
568 /* Is the first argument of "fd" of type "isl_ctx *"?
570 bool generator::first_arg_is_isl_ctx(FunctionDecl *fd)
572 ParmVarDecl *param;
574 if (fd->getNumParams() < 1)
575 return false;
577 param = fd->getParamDecl(0);
578 return is_isl_ctx(param->getOriginalType());
581 namespace {
583 struct ClangAPI {
584 /* Return the first location in the range returned by
585 * clang::SourceManager::getImmediateExpansionRange.
586 * Older versions of clang return a pair of SourceLocation objects.
587 * More recent versions return a CharSourceRange.
589 static SourceLocation range_begin(
590 const std::pair<SourceLocation,SourceLocation> &p) {
591 return p.first;
593 static SourceLocation range_begin(const CharSourceRange &range) {
594 return range.getBegin();
600 /* Does the callback argument "param" take its argument at position "pos"?
602 * The memory management annotations of arguments to function pointers
603 * are not recorded by clang, so the information cannot be extracted
604 * from the type of "param".
605 * Instead, go to the location in the source where the callback argument
606 * is declared, look for the right argument of the callback itself and
607 * then check if it has an "__isl_take" memory management annotation.
609 * If the return value of the function has a memory management annotation,
610 * then the spelling of "param" will point to the spelling
611 * of this memory management annotation. Since the macro is defined
612 * on the command line (in main), this location does not have a file entry.
613 * In this case, move up one level in the macro expansion to the location
614 * where the memory management annotation is used.
616 bool generator::callback_takes_argument(ParmVarDecl *param,
617 int pos)
619 SourceLocation loc;
620 const char *s, *end, *next;
621 bool takes, keeps;
623 loc = param->getSourceRange().getBegin();
624 if (!SM.getFileEntryForID(SM.getFileID(SM.getSpellingLoc(loc))))
625 loc = ClangAPI::range_begin(SM.getImmediateExpansionRange(loc));
626 s = SM.getCharacterData(loc);
627 if (!s)
628 die("No character data");
629 s = strchr(s, '(');
630 if (!s)
631 die("Cannot find function pointer");
632 s = strchr(s + 1, '(');
633 if (!s)
634 die("Cannot find function pointer arguments");
635 end = strchr(s + 1, ')');
636 if (!end)
637 die("Cannot find end of function pointer arguments");
638 while (pos-- > 0) {
639 s = strchr(s + 1, ',');
640 if (!s || s > end)
641 die("Cannot find function pointer argument");
643 next = strchr(s + 1, ',');
644 if (next && next < end)
645 end = next;
646 s = strchr(s + 1, '_');
647 if (!s || s > end)
648 die("Cannot find function pointer argument annotation");
649 takes = prefixcmp(s, "__isl_take") == 0;
650 keeps = prefixcmp(s, "__isl_keep") == 0;
651 if (!takes && !keeps)
652 die("Cannot find function pointer argument annotation");
654 return takes;
657 /* Is "type" that of a pointer to an isl_* structure?
659 bool generator::is_isl_type(QualType type)
661 if (type->isPointerType()) {
662 string s;
664 type = type->getPointeeType();
665 if (type->isFunctionType())
666 return false;
667 s = type.getAsString();
668 return s.substr(0, 4) == "isl_";
671 return false;
674 /* Is "type" one of the integral types with a negative value
675 * indicating an error condition?
677 bool generator::is_isl_neg_error(QualType type)
679 return is_isl_bool(type) || is_isl_stat(type) || is_isl_size(type);
682 /* Is "type" the primitive type with the given name?
684 static bool is_isl_primitive(QualType type, const char *name)
686 string s;
688 if (type->isPointerType())
689 return false;
691 s = type.getAsString();
692 return s == name;
695 /* Is "type" the type isl_bool?
697 bool generator::is_isl_bool(QualType type)
699 return is_isl_primitive(type, "isl_bool");
702 /* Is "type" the type isl_stat?
704 bool generator::is_isl_stat(QualType type)
706 return is_isl_primitive(type, "isl_stat");
709 /* Is "type" the type isl_size?
711 bool generator::is_isl_size(QualType type)
713 return is_isl_primitive(type, "isl_size");
716 /* Is "type" that of a pointer to a function?
718 bool generator::is_callback(QualType type)
720 if (!type->isPointerType())
721 return false;
722 type = type->getPointeeType();
723 return type->isFunctionType();
726 /* Is "type" that of "char *" of "const char *"?
728 bool generator::is_string(QualType type)
730 if (type->isPointerType()) {
731 string s = type->getPointeeType().getAsString();
732 return s == "const char" || s == "char";
735 return false;
738 /* Is "type" that of "long"?
740 bool generator::is_long(QualType type)
742 const BuiltinType *builtin = type->getAs<BuiltinType>();
743 return builtin && builtin->getKind() == BuiltinType::Long;
746 /* Is "type" that of "unsigned int"?
748 static bool is_unsigned_int(QualType type)
750 const BuiltinType *builtin = type->getAs<BuiltinType>();
751 return builtin && builtin->getKind() == BuiltinType::UInt;
754 /* Return the name of the type that "type" points to.
755 * The input "type" is assumed to be a pointer type.
757 string generator::extract_type(QualType type)
759 if (type->isPointerType())
760 return type->getPointeeType().getAsString();
761 die("Cannot extract type from non-pointer type");
764 /* Given the type of a function pointer, return the corresponding
765 * function prototype.
767 const FunctionProtoType *generator::extract_prototype(QualType type)
769 return type->getPointeeType()->getAs<FunctionProtoType>();
772 /* Return the function name suffix for the type of "param".
774 * If the type of "param" is an isl object type,
775 * then the suffix is the name of the type with the "isl" prefix removed,
776 * but keeping the "_".
777 * If the type is an unsigned integer, then the type suffix is "_ui".
779 static std::string type_suffix(ParmVarDecl *param)
781 QualType type;
783 type = param->getOriginalType();
784 if (generator::is_isl_type(type))
785 return generator::extract_type(type).substr(3);
786 else if (is_unsigned_int(type))
787 return "_ui";
788 generator::die("Unsupported type suffix");
791 /* If "suffix" is a suffix of "s", then return "s" with the suffix removed.
792 * Otherwise, simply return "s".
794 static std::string drop_suffix(const std::string &s, const std::string &suffix)
796 size_t len, suffix_len;
798 len = s.length();
799 suffix_len = suffix.length();
801 if (len >= suffix_len && s.substr(len - suffix_len) == suffix)
802 return s.substr(0, len - suffix_len);
803 else
804 return s;
807 /* If "method" is overloaded, then return its name with the suffixes
808 * corresponding to the types of the final arguments removed.
809 * Otherwise, simply return the name of the function.
810 * Start from the final argument and keep removing suffixes
811 * matching arguments, independently of whether previously considered
812 * arguments matched.
814 string isl_class::name_without_type_suffixes(FunctionDecl *method)
816 int num_params;
817 string name;
819 name = method->getName().str();
820 if (!generator::is_overload(method))
821 return name;
823 num_params = method->getNumParams();
824 for (int i = num_params - 1; i >= 0; --i) {
825 ParmVarDecl *param;
826 string type;
828 param = method->getParamDecl(i);
829 type = type_suffix(param);
831 name = drop_suffix(name, type);
834 return name;
837 /* Is function "fd" with the given name a "get" method?
839 * A "get" method is an instance method
840 * with a name that starts with the get method prefix.
842 bool isl_class::is_get_method_name(FunctionDecl *fd, const string &name) const
844 return !is_static(fd) && prefixcmp(name.c_str(), get_prefix) == 0;
847 /* Extract the method name corresponding to "fd".
849 * If "fd" is a "get" method, then drop the "get" method prefix.
851 string isl_class::method_name(FunctionDecl *fd) const
853 string base = base_method_name(fd);
855 if (is_get_method_name(fd, base))
856 return base.substr(strlen(get_prefix));
857 return base;