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
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
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 /* Is the first argument an instance of the class?
51 bool isl_class::first_arg_matches_class(FunctionDecl
*method
) const
56 if (method
->getNumParams() < 1)
59 param
= method
->getParamDecl(0);
60 type
= param
->getOriginalType();
61 if (!generator::is_isl_type(type
))
63 return generator::extract_type(type
) == name
;
66 /* Should "method" be considered to be a static method?
67 * That is, is the first argument something other than
68 * an instance of the class?
70 * If this method was copied from a superclass, then check
71 * whether the method is static with respect to this superclass.
73 bool isl_class::is_static(FunctionDecl
*method
) const
75 if (copied_from
.count(method
) != 0)
76 return copied_from
.at(method
).is_static(method
);
77 return !first_arg_matches_class(method
);
80 /* Should "method" be considered to be a static method?
81 * That is, is the first argument something other than
82 * an instance of the class?
84 bool generator::is_static(const isl_class
&clazz
, FunctionDecl
*method
)
86 return clazz
.is_static(method
);
89 /* Does "fd" modify an object of "clazz"?
90 * That is, is it an object method that takes the object and
91 * returns (gives) an object of the same type?
93 bool generator::is_mutator(const isl_class
&clazz
, FunctionDecl
*fd
)
96 QualType type
, return_type
;
98 if (fd
->getNumParams() < 1)
100 if (is_static(clazz
, fd
))
105 param
= fd
->getParamDecl(0);
108 type
= param
->getOriginalType();
109 return_type
= fd
->getReturnType();
110 return return_type
== type
;
113 /* Find the FunctionDecl with name "name",
114 * returning NULL if there is no such FunctionDecl.
115 * If "required" is set, then error out if no FunctionDecl can be found.
117 FunctionDecl
*generator::find_by_name(const string
&name
, bool required
)
119 map
<string
, FunctionDecl
*>::iterator i
;
121 i
= functions_by_name
.find(name
);
122 if (i
!= functions_by_name
.end())
125 die("No " + name
+ " function found");
129 /* List of conversion functions that are used to automatically convert
130 * the second argument of the conversion function to its function result.
132 const std::set
<std::string
> generator::automatic_conversion_functions
= {
133 "isl_id_read_from_str",
134 "isl_val_int_from_si",
137 /* Extract information about the automatic conversion function "fd",
138 * storing the results in this->conversions.
140 * A function used for automatic conversion has exactly two arguments,
141 * an isl_ctx and a non-isl object, and it returns an isl object.
142 * Store a mapping from the isl object return type
143 * to the non-isl object source type.
145 void generator::extract_automatic_conversion(FunctionDecl
*fd
)
147 QualType return_type
= fd
->getReturnType();
148 const Type
*type
= return_type
.getTypePtr();
150 if (fd
->getNumParams() != 2)
151 die("Expecting two arguments");
152 if (!is_isl_ctx(fd
->getParamDecl(0)->getOriginalType()))
153 die("Expecting isl_ctx first argument");
154 if (!is_isl_type(return_type
))
155 die("Expecting isl object return type");
156 conversions
[type
] = fd
->getParamDecl(1);
159 /* Extract information about all automatic conversion functions
160 * for the given class, storing the results in this->conversions.
162 * In particular, look through all exported constructors for the class and
163 * check if any of them is explicitly marked as a conversion function.
165 void generator::extract_class_automatic_conversions(const isl_class
&clazz
)
167 const function_set
&constructors
= clazz
.constructors
;
168 function_set::iterator fi
;
170 for (fi
= constructors
.begin(); fi
!= constructors
.end(); ++fi
) {
171 FunctionDecl
*fd
= *fi
;
172 string name
= fd
->getName().str();
173 if (automatic_conversion_functions
.count(name
) != 0)
174 extract_automatic_conversion(fd
);
178 /* Extract information about all automatic conversion functions,
179 * storing the results in this->conversions.
181 void generator::extract_automatic_conversions()
183 map
<string
, isl_class
>::iterator ci
;
185 for (ci
= classes
.begin(); ci
!= classes
.end(); ++ci
)
186 extract_class_automatic_conversions(ci
->second
);
189 /* Add a subclass derived from "decl" called "sub_name" to the set of classes,
190 * keeping track of the _to_str, _copy and _free functions, if any, separately.
191 * "sub_name" is either the name of the class itself or
192 * the name of a type based subclass.
193 * If the class is a proper subclass, then "super_name" is the name
194 * of its immediate superclass.
196 void generator::add_subclass(RecordDecl
*decl
, const string
&super_name
,
197 const string
&sub_name
)
199 string name
= decl
->getName().str();
201 classes
[sub_name
].name
= name
;
202 classes
[sub_name
].superclass_name
= super_name
;
203 classes
[sub_name
].subclass_name
= sub_name
;
204 classes
[sub_name
].type
= decl
;
205 classes
[sub_name
].fn_to_str
= find_by_name(name
+ "_to_str", false);
206 classes
[sub_name
].fn_copy
= find_by_name(name
+ "_copy", true);
207 classes
[sub_name
].fn_free
= find_by_name(name
+ "_free", true);
210 /* Add a class derived from "decl" to the set of classes,
211 * keeping track of the _to_str, _copy and _free functions, if any, separately.
213 void generator::add_class(RecordDecl
*decl
)
215 return add_subclass(decl
, "", decl
->getName().str());
218 /* Given a function "fn_type" that returns the subclass type
219 * of a C object, create subclasses for each of the (non-negative)
222 * The function "fn_type" is also stored in the superclass,
223 * along with all pairs of type values and subclass names.
225 void generator::add_type_subclasses(FunctionDecl
*fn_type
)
227 QualType return_type
= fn_type
->getReturnType();
228 const EnumType
*enum_type
= return_type
->getAs
<EnumType
>();
229 EnumDecl
*decl
= enum_type
->getDecl();
230 isl_class
*c
= method2class(fn_type
);
231 DeclContext::decl_iterator i
;
233 c
->fn_type
= fn_type
;
234 for (i
= decl
->decls_begin(); i
!= decl
->decls_end(); ++i
) {
235 EnumConstantDecl
*ecd
= dyn_cast
<EnumConstantDecl
>(*i
);
236 int val
= (int) ecd
->getInitVal().getSExtValue();
237 string name
= ecd
->getNameAsString();
241 c
->type_subclasses
[val
] = name
;
242 add_subclass(c
->type
, c
->subclass_name
, name
);
246 /* Add information about the enum values in "decl", set by "fd",
247 * to c->set_enums. "prefix" is the prefix of the generated method names.
248 * In particular, it has the name of the enum type removed.
250 * In particular, for each non-negative enum value, keep track of
251 * the value, the name and the corresponding method name.
253 static void add_set_enum(isl_class
*c
, const string
&prefix
, EnumDecl
*decl
,
256 DeclContext::decl_iterator i
;
258 for (i
= decl
->decls_begin(); i
!= decl
->decls_end(); ++i
) {
259 EnumConstantDecl
*ecd
= dyn_cast
<EnumConstantDecl
>(*i
);
260 int val
= (int) ecd
->getInitVal().getSExtValue();
261 string name
= ecd
->getNameAsString();
266 method_name
= prefix
+ name
.substr(4);
267 c
->set_enums
[fd
].push_back(set_enum(val
, name
, method_name
));
271 /* Check if "fd" sets an enum value and, if so, add information
272 * about the enum values to c->set_enums.
274 * A function is considered to set an enum value if:
275 * - the function returns an object of the same type
276 * - the last argument is of type enum
277 * - the name of the function ends with the name of the enum
279 static bool handled_sets_enum(isl_class
*c
, FunctionDecl
*fd
)
283 const EnumType
*enum_type
;
290 if (!generator::is_mutator(*c
, fd
))
292 n
= fd
->getNumParams();
295 param
= fd
->getParamDecl(n
- 1);
296 enum_type
= param
->getType()->getAs
<EnumType
>();
299 decl
= enum_type
->getDecl();
300 enum_name
= decl
->getName().str();
301 enum_name
= enum_name
.substr(4);
302 fd_name
= c
->method_name(fd
);
303 pos
= fd_name
.find(enum_name
);
304 if (pos
== std::string::npos
)
306 prefix
= fd_name
.substr(0, pos
);
308 add_set_enum(c
, prefix
, decl
, fd
);
313 /* Return the callback argument of a function setting
314 * a persistent callback.
315 * This callback is in the second argument (position 1).
317 ParmVarDecl
*generator::persistent_callback_arg(FunctionDecl
*fd
)
319 return fd
->getParamDecl(1);
322 /* Does the given function set a persistent callback?
323 * The following heuristics are used to determine this property:
324 * - the function returns an object of the same type
325 * - its name starts with "set_"
326 * - it has exactly three arguments
327 * - the second (position 1) of which is a callback
329 static bool sets_persistent_callback(isl_class
*c
, FunctionDecl
*fd
)
333 if (!generator::is_mutator(*c
, fd
))
335 if (fd
->getNumParams() != 3)
337 param
= generator::persistent_callback_arg(fd
);
338 if (!generator::is_callback(param
->getType()))
340 return prefixcmp(c
->method_name(fd
).c_str(),
341 c
->set_callback_prefix
) == 0;
344 /* Does this function take any enum arguments?
346 static bool takes_enums(FunctionDecl
*fd
)
350 n
= fd
->getNumParams();
351 for (unsigned i
= 0; i
< n
; ++i
) {
352 ParmVarDecl
*param
= fd
->getParamDecl(i
);
353 if (param
->getType()->getAs
<EnumType
>())
359 /* Sorting function that places declaration of functions
360 * with a shorter name first.
362 static bool less_name(const FunctionDecl
*a
, const FunctionDecl
*b
)
364 return a
->getName().size() < b
->getName().size();
367 /* Collect all functions that belong to a certain type, separating
368 * constructors from methods that set an enum value,
369 * methods that set a persistent callback and
370 * from regular methods, while keeping track of the _to_str,
371 * _copy and _free functions, if any, separately.
372 * Methods that accept any enum arguments that are not specifically handled
374 * If there are any overloaded
375 * functions, then they are grouped based on their name after removing the
376 * argument type suffix.
377 * Check for functions that describe subclasses before considering
378 * any other functions in order to be able to detect those other
379 * functions as belonging to the subclasses.
380 * Sort the names of the functions based on their lengths
381 * to ensure that nested subclasses are handled later.
383 * Also extract information about automatic conversion functions.
385 generator::generator(SourceManager
&SM
, set
<RecordDecl
*> &exported_types
,
386 set
<FunctionDecl
*> exported_functions
, set
<FunctionDecl
*> functions
) :
389 set
<FunctionDecl
*>::iterator in
;
390 set
<RecordDecl
*>::iterator it
;
391 vector
<FunctionDecl
*> type_subclasses
;
392 vector
<FunctionDecl
*>::iterator iv
;
394 for (in
= functions
.begin(); in
!= functions
.end(); ++in
) {
395 FunctionDecl
*decl
= *in
;
396 functions_by_name
[decl
->getName().str()] = decl
;
399 for (it
= exported_types
.begin(); it
!= exported_types
.end(); ++it
)
402 for (in
= exported_functions
.begin(); in
!= exported_functions
.end();
404 if (is_subclass(*in
))
405 type_subclasses
.push_back(*in
);
407 std::sort(type_subclasses
.begin(), type_subclasses
.end(), &less_name
);
408 for (iv
= type_subclasses
.begin(); iv
!= type_subclasses
.end(); ++iv
) {
409 add_type_subclasses(*iv
);
412 for (in
= exported_functions
.begin(); in
!= exported_functions
.end();
414 FunctionDecl
*method
= *in
;
417 if (is_subclass(method
))
420 c
= method2class(method
);
423 if (is_constructor(method
)) {
424 c
->constructors
.insert(method
);
425 } else if (handled_sets_enum(c
, method
)) {
426 } else if (sets_persistent_callback(c
, method
)) {
427 c
->persistent_callbacks
.insert(method
);
428 } else if (takes_enums(method
)) {
429 std::string name
= method
->getName().str();
430 die(name
+ " has unhandled enum argument");
432 string name
= c
->method_name(method
);
433 c
->methods
[name
].insert(method
);
437 extract_automatic_conversions();
440 /* Print error message "msg" and abort.
442 void generator::die(const char *msg
)
444 fprintf(stderr
, "%s\n", msg
);
448 /* Print error message "msg" and abort.
450 void generator::die(string msg
)
455 /* Return a sequence of the types of which the given type declaration is
456 * marked as being a subtype.
457 * The order of the types is the opposite of the order in which they
458 * appear in the source. In particular, the first annotation
459 * is the one that is closest to the annotated type and the corresponding
460 * type is then also the first that will appear in the sequence of types.
461 * This is also the order in which the annotations appear
462 * in the AttrVec returned by Decl::getAttrs() in older versions of clang.
463 * In newer versions of clang, the order is that in which
464 * the attribute appears in the source.
465 * Use the position of the "isl_export" attribute to determine
466 * whether this is an old (with reversed order) or a new version.
467 * The "isl_export" attribute is automatically added
468 * after each "isl_subclass" attribute. If it appears in the list before
469 * any "isl_subclass" is encountered, then this must be a reversed list.
471 std::vector
<string
> generator::find_superclasses(Decl
*decl
)
473 vector
<string
> super
;
474 bool reversed
= false;
476 if (!decl
->hasAttrs())
479 string sub
= "isl_subclass";
480 size_t len
= sub
.length();
481 AttrVec attrs
= decl
->getAttrs();
482 for (AttrVec::const_iterator i
= attrs
.begin(); i
!= attrs
.end(); ++i
) {
483 const AnnotateAttr
*ann
= dyn_cast
<AnnotateAttr
>(*i
);
486 string s
= ann
->getAnnotation().str();
487 if (s
== "isl_export" && super
.size() == 0)
489 if (s
.substr(0, len
) == sub
) {
490 s
= s
.substr(len
+ 1, s
.length() - len
- 2);
494 super
.insert(super
.begin(), s
);
501 /* Is "decl" marked as describing subclasses?
503 bool generator::is_subclass(FunctionDecl
*decl
)
505 return find_superclasses(decl
).size() > 0;
508 /* Is decl marked as being part of an overloaded method?
510 bool generator::is_overload(Decl
*decl
)
512 return has_annotation(decl
, "isl_overload");
515 /* Is decl marked as a constructor?
517 bool generator::is_constructor(Decl
*decl
)
519 return has_annotation(decl
, "isl_constructor");
522 /* Is decl marked as consuming a reference?
524 bool generator::takes(Decl
*decl
)
526 return has_annotation(decl
, "isl_take");
529 /* Is decl marked as preserving a reference?
531 bool generator::keeps(Decl
*decl
)
533 return has_annotation(decl
, "isl_keep");
536 /* Is decl marked as returning a reference that is required to be freed.
538 bool generator::gives(Decl
*decl
)
540 return has_annotation(decl
, "isl_give");
543 /* Return the class that has a name that best matches the initial part
544 * of the name of function "fd" or NULL if no such class could be found.
546 isl_class
*generator::method2class(FunctionDecl
*fd
)
549 map
<string
, isl_class
>::iterator ci
;
550 string name
= fd
->getNameAsString();
552 for (ci
= classes
.begin(); ci
!= classes
.end(); ++ci
) {
553 size_t len
= ci
->first
.length();
554 if (len
> best
.length() && name
.substr(0, len
) == ci
->first
&&
559 if (classes
.find(best
) == classes
.end()) {
560 cerr
<< "Unable to find class of " << name
<< endl
;
564 return &classes
[best
];
567 /* Is "type" the type "isl_ctx *"?
569 bool generator::is_isl_ctx(QualType type
)
571 if (!type
->isPointerType())
573 type
= type
->getPointeeType();
574 if (type
.getAsString() != "isl_ctx")
580 /* Is the first argument of "fd" of type "isl_ctx *"?
582 bool generator::first_arg_is_isl_ctx(FunctionDecl
*fd
)
586 if (fd
->getNumParams() < 1)
589 param
= fd
->getParamDecl(0);
590 return is_isl_ctx(param
->getOriginalType());
596 /* Return the first location in the range returned by
597 * clang::SourceManager::getImmediateExpansionRange.
598 * Older versions of clang return a pair of SourceLocation objects.
599 * More recent versions return a CharSourceRange.
601 static SourceLocation
range_begin(
602 const std::pair
<SourceLocation
,SourceLocation
> &p
) {
605 static SourceLocation
range_begin(const CharSourceRange
&range
) {
606 return range
.getBegin();
612 /* Does the callback argument "param" take its argument at position "pos"?
614 * The memory management annotations of arguments to function pointers
615 * are not recorded by clang, so the information cannot be extracted
616 * from the type of "param".
617 * Instead, go to the location in the source where the callback argument
618 * is declared, look for the right argument of the callback itself and
619 * then check if it has an "__isl_take" memory management annotation.
621 * If the return value of the function has a memory management annotation,
622 * then the spelling of "param" will point to the spelling
623 * of this memory management annotation. Since the macro is defined
624 * on the command line (in main), this location does not have a file entry.
625 * In this case, move up one level in the macro expansion to the location
626 * where the memory management annotation is used.
628 bool generator::callback_takes_argument(ParmVarDecl
*param
,
632 const char *s
, *end
, *next
;
635 loc
= param
->getSourceRange().getBegin();
636 if (!SM
.getFileEntryForID(SM
.getFileID(SM
.getSpellingLoc(loc
))))
637 loc
= ClangAPI::range_begin(SM
.getImmediateExpansionRange(loc
));
638 s
= SM
.getCharacterData(loc
);
640 die("No character data");
643 die("Cannot find function pointer");
644 s
= strchr(s
+ 1, '(');
646 die("Cannot find function pointer arguments");
647 end
= strchr(s
+ 1, ')');
649 die("Cannot find end of function pointer arguments");
651 s
= strchr(s
+ 1, ',');
653 die("Cannot find function pointer argument");
655 next
= strchr(s
+ 1, ',');
656 if (next
&& next
< end
)
658 s
= strchr(s
+ 1, '_');
660 die("Cannot find function pointer argument annotation");
661 takes
= prefixcmp(s
, "__isl_take") == 0;
662 keeps
= prefixcmp(s
, "__isl_keep") == 0;
663 if (!takes
&& !keeps
)
664 die("Cannot find function pointer argument annotation");
669 /* Is "type" that of a pointer to an isl_* structure?
671 bool generator::is_isl_type(QualType type
)
673 if (type
->isPointerType()) {
676 type
= type
->getPointeeType();
677 if (type
->isFunctionType())
679 s
= type
.getAsString();
680 return s
.substr(0, 4) == "isl_";
686 /* Is "type" one of the integral types with a negative value
687 * indicating an error condition?
689 bool generator::is_isl_neg_error(QualType type
)
691 return is_isl_bool(type
) || is_isl_stat(type
) || is_isl_size(type
);
694 /* Is "type" the primitive type with the given name?
696 static bool is_isl_primitive(QualType type
, const char *name
)
700 if (type
->isPointerType())
703 s
= type
.getAsString();
707 /* Is "type" the type isl_bool?
709 bool generator::is_isl_bool(QualType type
)
711 return is_isl_primitive(type
, "isl_bool");
714 /* Is "type" the type isl_stat?
716 bool generator::is_isl_stat(QualType type
)
718 return is_isl_primitive(type
, "isl_stat");
721 /* Is "type" the type isl_size?
723 bool generator::is_isl_size(QualType type
)
725 return is_isl_primitive(type
, "isl_size");
728 /* Is "type" that of a pointer to a function?
730 bool generator::is_callback(QualType type
)
732 if (!type
->isPointerType())
734 type
= type
->getPointeeType();
735 return type
->isFunctionType();
738 /* Is the parameter at position "i" of "fd" a pointer to a function?
740 bool generator::is_callback_arg(FunctionDecl
*fd
, int i
)
742 ParmVarDecl
*param
= fd
->getParamDecl(i
);
743 QualType type
= param
->getOriginalType();
745 return is_callback(type
);
748 /* Is "type" that of "char *" of "const char *"?
750 bool generator::is_string(QualType type
)
752 if (type
->isPointerType()) {
753 string s
= type
->getPointeeType().getAsString();
754 return s
== "const char" || s
== "char";
760 /* Is "type" that of "long"?
762 bool generator::is_long(QualType type
)
764 const BuiltinType
*builtin
= type
->getAs
<BuiltinType
>();
765 return builtin
&& builtin
->getKind() == BuiltinType::Long
;
768 /* Is "type" that of "unsigned int"?
770 static bool is_unsigned_int(QualType type
)
772 const BuiltinType
*builtin
= type
->getAs
<BuiltinType
>();
773 return builtin
&& builtin
->getKind() == BuiltinType::UInt
;
776 /* Return the name of the type that "type" points to.
777 * The input "type" is assumed to be a pointer type.
779 string
generator::extract_type(QualType type
)
781 if (type
->isPointerType())
782 return type
->getPointeeType().getAsString();
783 die("Cannot extract type from non-pointer type");
786 /* Given the type of a function pointer, return the corresponding
787 * function prototype.
789 const FunctionProtoType
*generator::extract_prototype(QualType type
)
791 return type
->getPointeeType()->getAs
<FunctionProtoType
>();
794 /* Given the type of a function pointer, return the number of arguments
795 * of the corresponding function prototype.
797 int generator::prototype_n_args(QualType type
)
799 return extract_prototype(type
)->getNumArgs();
802 /* Return the function name suffix for the type of "param".
804 * If the type of "param" is an isl object type,
805 * then the suffix is the name of the type with the "isl" prefix removed,
806 * but keeping the "_".
807 * If the type is an unsigned integer, then the type suffix is "_ui".
809 static std::string
type_suffix(ParmVarDecl
*param
)
813 type
= param
->getOriginalType();
814 if (generator::is_isl_type(type
))
815 return generator::extract_type(type
).substr(3);
816 else if (is_unsigned_int(type
))
818 generator::die("Unsupported type suffix");
821 /* If "suffix" is a suffix of "s", then return "s" with the suffix removed.
822 * Otherwise, simply return "s".
824 std::string
generator::drop_suffix(const std::string
&s
,
825 const std::string
&suffix
)
827 size_t len
, suffix_len
;
830 suffix_len
= suffix
.length();
832 if (len
>= suffix_len
&& s
.substr(len
- suffix_len
) == suffix
)
833 return s
.substr(0, len
- suffix_len
);
838 /* If "method" is overloaded, then return its name with the suffixes
839 * corresponding to the types of the final arguments removed.
840 * Otherwise, simply return the name of the function.
841 * Start from the final argument and keep removing suffixes
842 * matching arguments, independently of whether previously considered
845 string
isl_class::name_without_type_suffixes(FunctionDecl
*method
)
850 name
= method
->getName().str();
851 if (!generator::is_overload(method
))
854 num_params
= method
->getNumParams();
855 for (int i
= num_params
- 1; i
>= 0; --i
) {
859 param
= method
->getParamDecl(i
);
860 type
= type_suffix(param
);
862 name
= generator::drop_suffix(name
, type
);
868 /* Is function "fd" with the given name a "get" method?
870 * A "get" method is an instance method
871 * with a name that starts with the get method prefix.
873 bool isl_class::is_get_method_name(FunctionDecl
*fd
, const string
&name
) const
875 return !is_static(fd
) && prefixcmp(name
.c_str(), get_prefix
) == 0;
878 /* Extract the method name corresponding to "fd".
880 * If "fd" is a "get" method, then drop the "get" method prefix.
882 string
isl_class::method_name(FunctionDecl
*fd
) const
884 string base
= base_method_name(fd
);
886 if (is_get_method_name(fd
, base
))
887 return base
.substr(strlen(get_prefix
));