diff options
Diffstat (limited to 'AspectC++/ClangTransformInfo.h')
-rw-r--r-- | AspectC++/ClangTransformInfo.h | 470 |
1 files changed, 311 insertions, 159 deletions
diff --git a/AspectC++/ClangTransformInfo.h b/AspectC++/ClangTransformInfo.h index 0c91fbf..d53e511 100644 --- a/AspectC++/ClangTransformInfo.h +++ b/AspectC++/ClangTransformInfo.h @@ -19,6 +19,15 @@ #ifndef __ClangTransformInfo_h__ #define __ClangTransformInfo_h__ +// TODO: This should be in a helper file. Also see TODOs for +// isTemplateInstantiation and inside_template_instance +enum TriStateEnableFeature { + TSEF_ENABLE = true, + TSEF_DISABLE = false, + TSEF_DONOTCHANGE = 2, +}; + +#include "version.h" #include "ACModel/Elements.h" #include "ACToken.h" #include "ACFileID.h" @@ -27,9 +36,11 @@ #include "SyntacticContext.h" #include "CFlow.h" #include "WeaverBase.h" +#if CLANG_VERSION_NUMBER < VERSION_NUMBER_9_0_0 #include "ClangAdjustedTypePrinter.h" -#include "version.h" - +#else +#include "clang/AST/QualTypeNames.h" +#endif #include "clang/Basic/Version.h" #include "clang/Basic/SourceLocation.h" #include "clang/AST/Decl.h" @@ -38,9 +49,6 @@ #include "clang/AST/ExprCXX.h" #include "llvm/Support/raw_ostream.h" #include "clang/AST/CXXInheritance.h" -#if 0 && CLANG_VERSION_NUMBER >= VERSION_NUMBER_6_0_0 -#include "clang/AST/QualTypeNames.h" -#endif class TI_CodeAdvice : public ModelTransformInfo { // Condition is located here instead of in the AdviceInfo object because @@ -178,14 +186,17 @@ public: } private: - // Returns a printing policy setup according to given flags for adjusted type printing - static inline clang::PrintingPolicy get_preset_printing_policy(const clang::ASTContext* ctx, - bool unnamed, - TriStateEnableFeature absolute_qualified) { + // Returns a printing policy setup according to given flags for (adjusted) type printing + static inline clang::PrintingPolicy + get_preset_printing_policy(const clang::ASTContext *ctx, + TriStateEnableFeature absolute_qualified, + bool keep_typedef, + TriStateEnableFeature elaborated_type_spec, + bool unnamed, bool remove_attributes) { // TODO: always create, setup and use own printing policy? - clang::PrintingPolicy policy = ctx - ? ctx->getPrintingPolicy() - : clang::PrintingPolicy(clang::LangOptions()); + clang::PrintingPolicy policy = + ctx ? ctx->getPrintingPolicy() + : clang::PrintingPolicy(clang::LangOptions()); // Ensure some policy properties: policy.SuppressSpecifiers = false; @@ -198,6 +209,37 @@ private: // <unnamed> later policy.SuppressUnwrittenScope = !unnamed; policy.AnonymousTagLocations = unnamed; + +#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0 + // Since the adjusted typeprinter is not used anymore, enforce desired + // scope printing behavior through the printing policy (and + // TypeName::getFullyQualifiedType below) + if (absolute_qualified == TSEF_DISABLE) { + policy.SuppressScope = true; + } else if (absolute_qualified == TSEF_ENABLE) { + policy.SuppressScope = false; + // The following only works for decls and does not add the global + // namespace specifier. Thus, it has currently no effect. This is still + // here as a reminder for future Clang versions. + policy.FullyQualifiedName = true; + } + + // Adding elaborated type specifiers is not supported natively. + assert(elaborated_type_spec != TSEF_ENABLE && "Adding of elaborated type specifier is not supported with Clang >= 9.0.0."); + // ... but suppression is supported. Suppress them if requested and do not + // change them otherwise (which usually results in the default + // SuppressTagKeyword = true): + if(elaborated_type_spec == TSEF_DISABLE) { + policy.SuppressTagKeyword = true; + } + + // Removal of typedefs is supported natively: + policy.PrintCanonicalTypes = !keep_typedef; + + // Do not print attributes in declarations (for types, outer attributes are + // removed in get_type_text below): + policy.PolishForDeclaration = remove_attributes; +#endif return policy; } @@ -235,16 +277,69 @@ private: } public: + // Retrieves the ast context of the given QualType object. This would return 0 + // if the type could not be retrieved from the type object. + static const clang::ASTContext *get_ast_context(clang::QualType type) { + using namespace clang; + + // Try to get the AST context from the given QualType. + const ASTContext *ctx = nullptr; + QualType contextType = type; + while (true) { + if (const TagDecl *tagDecl = contextType->getAsTagDecl()) { + ctx = &tagDecl->getASTContext(); + } else if (const TemplateTypeParmType *ttpType = + dyn_cast<TemplateTypeParmType>(contextType)) { + ctx = &ttpType->getDecl()->getASTContext(); + } else if (const TypedefType *tdType = + dyn_cast<TypedefType>(contextType)) { + ctx = &tdType->getDecl()->getASTContext(); + } else if (const TemplateSpecializationType *tsType = + dyn_cast<TemplateSpecializationType>(contextType)) { + if (tsType->getNumArgs() > 0) { + if (tsType->getArg(0).getKind() == TemplateArgument::Declaration) { + ctx = &tsType->getArg(0).getAsDecl()->getASTContext(); + } else if (tsType->getArg(0).getKind() == TemplateArgument::Type) { + contextType = tsType->getArg(0).getAsType(); + continue; + } else if (tsType->getArg(0).getKind() == + TemplateArgument::Expression) { + contextType = tsType->getArg(0).getAsExpr()->getType(); + continue; + } else { +// cout << tsType->getArg(0).getKind() << endl; + } + } + } else if (const DependentTemplateSpecializationType *tsType = + dyn_cast<DependentTemplateSpecializationType>(contextType)) { + if (tsType->getNumArgs() > 0) { + if (tsType->getArg(0).getKind() == TemplateArgument::Declaration) { + ctx = &tsType->getArg(0).getAsDecl()->getASTContext(); + } else if (tsType->getArg(0).getKind() == TemplateArgument::Type) { + contextType = tsType->getArg(0).getAsType(); + continue; + } else if (tsType->getArg(0).getKind() == + TemplateArgument::Expression) { + contextType = tsType->getArg(0).getAsExpr()->getType(); + continue; + } else { +// cout << tsType->getArg(0).getKind() << endl; + } + } + } + break; + } + return ctx; + } /** Returns the textual representation of a declaration name. * \param decl The declaration - * \param ctx The ASTContext * \param absolute_qualified Add all nested name specifiers as well as the * root qualifier (ENABLE), do not change nested name specifiers (DONOTCHANGE) * or remove all nested name specifiers (DISABLE). * \param keep_typedef If the type is typedef'd, keep the typedef and return * the typedef'd type (and not the underlying type) - * \param elaborated_type_spec Add elaborated type specifier before + * \param elaborated_type_spec Add/remove elaborated type specifier before * class, union, and enumeration types. * \param unnamed Do not suppress printing of unwritten scope and convert printed * namespaces to '<unnamed>' @@ -252,23 +347,68 @@ public: * */ static string get_decl_name_text(const clang::NamedDecl* decl, TriStateEnableFeature absolute_qualified = TSEF_DONOTCHANGE, - bool keep_typedef = true, // TODO: Currently ignored if Clang >= 5.0.0 + bool keep_typedef = true, TriStateEnableFeature elaborated_type_spec = TSEF_DONOTCHANGE, bool unnamed = false, bool remove_attributes = false ) { - clang::PrintingPolicy policy = get_preset_printing_policy(&decl->getASTContext(), unnamed, absolute_qualified); + using namespace clang; + + const ASTContext& ctx = decl->getASTContext(); + PrintingPolicy policy = get_preset_printing_policy(&ctx, absolute_qualified, keep_typedef, elaborated_type_spec, unnamed, remove_attributes); + string decl_string = ""; +#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0 + // If the decl declares a type, print the type instead of the decl: + if(const TypeDecl *type_decl = dyn_cast<TypeDecl>(decl)) { + decl_string = get_type_text(ctx.getTypeDeclType(type_decl), &ctx, 0, absolute_qualified, keep_typedef, elaborated_type_spec, unnamed, remove_attributes); + } + else { + // If this is a variable, function or enum constant declared in a class, + // print the class's type and append the variable/function/enumconstant + // name. + if(const ValueDecl *val_decl = dyn_cast<ValueDecl>(decl)) { + if (const DeclContext *decl_ctx = val_decl->getDeclContext()) { + if (decl_ctx->isRecord()) { + // Print qualifiers: + if (absolute_qualified != TSEF_DISABLE) { + decl_string = + get_decl_name_text(cast<RecordDecl>(decl_ctx), + absolute_qualified, keep_typedef, + elaborated_type_spec, unnamed, + remove_attributes) + + "::"; + } + // Print name: + decl_string += decl->getName().str(); + } + } + } + // Fallback by using clang default implementation: + if(decl_string.empty()){ + llvm::raw_string_ostream stream(decl_string); + if (absolute_qualified == TSEF_DISABLE) { + decl->printName(stream); + } + else { + decl->printQualifiedName(stream, policy); + } + // Flush stream data to decl_string: + stream.str(); + } + } +#else string string_buffer; llvm::raw_string_ostream stream(string_buffer); AdjustedTypePrinter(policy, absolute_qualified, keep_typedef, elaborated_type_spec, remove_attributes, false, 0) .adjusted_NamedDecl_printQualifiedName(decl, stream); - - return get_with_unified_types(stream.str(), unnamed); + decl_string = stream.str(); +#endif + return get_with_unified_types(decl_string, unnamed); } - /** Returns the textual representation of a list of template arguments. + /** Returns a textual C++ representation of the given list of template arguments. * \param template_args The list of template arguments * \param ctx The ASTContext * \param absolute_qualified Add all nested name specifiers as well as the @@ -276,7 +416,7 @@ public: * or remove all nested name specifiers (DISABLE). * \param keep_typedef If the type is typedef'd, keep the typedef and return * the typedef'd type (and not the underlying type) - * \param elaborated_type_spec Add elaborated type specifier before + * \param elaborated_type_spec Add/remove elaborated type specifier before * class, union, and enumeration types. * \param unnamed Do not suppress printing of unwritten scope and convert printed * namespaces to '<unnamed>' @@ -290,34 +430,62 @@ public: bool unnamed = false, bool remove_attributes = false ) { - clang::PrintingPolicy policy = get_preset_printing_policy(ctx, unnamed, absolute_qualified); - string string_buffer; - llvm::raw_string_ostream stream(string_buffer); - + using namespace clang; + + PrintingPolicy policy = get_preset_printing_policy(ctx, absolute_qualified, keep_typedef, elaborated_type_spec, unnamed, remove_attributes); + string ta_list_string_buffer; + llvm::raw_string_ostream ta_list_stream(ta_list_string_buffer); +#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0 + ta_list_stream << '<'; + bool first = true; + bool needs_space = false; + for (TemplateArgument templ_arg : template_args.asArray()) { + string templ_arg_string = get_templ_arg_text(templ_arg, ctx, absolute_qualified, keep_typedef, elaborated_type_spec, unnamed, remove_attributes); + if (first) { + if (!templ_arg_string.empty() && templ_arg_string[0] == ':') { + // "If this is the first argument and its string representation + // begins with the global scope specifier ('::foo'), add a space + // to avoid printing the diagraph '<:'." (Clang source) + ta_list_stream << ' '; + } + first = false; + } + else { + ta_list_stream << ','; + } + ta_list_stream << templ_arg_string; + // Avoid printing ">>": + needs_space = !templ_arg_string.empty() && templ_arg_string[templ_arg_string.length() - 1] == '>'; + } + if(needs_space) { + ta_list_stream << ' '; + } + ta_list_stream << '>'; +#else AdjustedTypePrinter(policy, absolute_qualified, keep_typedef, elaborated_type_spec, remove_attributes, false, ctx) - .adjusted_PrintTemplateArgumentList(stream, + .adjusted_PrintTemplateArgumentList(ta_list_stream, template_args.data(), template_args.size()); - - return get_with_unified_types(stream.str(), unnamed); +#endif + return get_with_unified_types(ta_list_stream.str(), unnamed); } - /** Returns the textual representation of template argument. - * \param temp_arg The template argument + /** Returns a textual C++ representation of the given template argument. + * \param templ_arg The template argument * \param ctx The ASTContext * \param absolute_qualified Add all nested name specifiers as well as the * root qualifier (ENABLE), do not change nested name specifiers (DONOTCHANGE) * or remove all nested name specifiers (DISABLE). * \param keep_typedef If the type is typedef'd, keep the typedef and return * the typedef'd type (and not the underlying type) - * \param elaborated_type_spec Add elaborated type specifier before + * \param elaborated_type_spec Add/remove elaborated type specifier before * class, union, and enumeration types. * \param unnamed Do not suppress printing of unwritten scope and convert printed * namespaces to '<unnamed>' * \param remove_attributes Remove occurrences of attributes * */ - static string get_templ_arg_text(const clang::TemplateArgument& temp_arg, + static string get_templ_arg_text(const clang::TemplateArgument& templ_arg, const clang::ASTContext* ctx, TriStateEnableFeature absolute_qualified = TSEF_ENABLE, bool keep_typedef = true, @@ -325,19 +493,49 @@ public: bool unnamed = false, bool remove_attributes = false ) { - clang::PrintingPolicy policy = get_preset_printing_policy(ctx, unnamed, absolute_qualified); - - string temp_arg_string_buffer; - llvm::raw_string_ostream temp_arg_stream(temp_arg_string_buffer); - + using namespace clang; + + PrintingPolicy policy = get_preset_printing_policy(ctx, absolute_qualified, keep_typedef, elaborated_type_spec, unnamed, remove_attributes); + string templ_arg_string_buffer; + llvm::raw_string_ostream templ_arg_stream(templ_arg_string_buffer); +#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0 + if (absolute_qualified == TSEF_ENABLE) { + // The following is a workaround since getFullyQualifiedTemplateArgument + // in QualTypeNames.cpp is not exposed. We use the fact that if a + // TemplateSpecializationType is passed to getFullyQualifiedType, it will + // call getFullyQualifiedTemplateArgument on each of the + // TemplateSpecializationType's template arguments. + + // Copy the template argument before fully-qualifying, i.e., modifying, + // and printing it: + TemplateArgument temporary_templ_arg(templ_arg); + // Create a fake TemplateSpecializationType around the template argument + // that needs to be fully qualified: + QualType fake_templ_spec_type = ctx->getTemplateSpecializationType(TemplateName(), + llvm::ArrayRef<TemplateArgument>(temporary_templ_arg), ctx->IntTy); + // Indirectly call getFullyQualifiedTemplateArgument to fully qualify the + // template argument: + fake_templ_spec_type = TypeName::getFullyQualifiedType(fake_templ_spec_type, *ctx, /*WithGlobalNsPrefix=*/true); + // Extract the fully qualified template argument from the + // TemplateSpecializationType: + temporary_templ_arg = cast<TemplateSpecializationType>(fake_templ_spec_type)->getArg(0); + // Use the native printing function and the preset policy to print the + // fully qualified template argument: + temporary_templ_arg.print(policy, templ_arg_stream); + } + else { + // Just print the template argument using the policy: + templ_arg.print(policy, templ_arg_stream); + } +#else AdjustedTypePrinter(policy, absolute_qualified, keep_typedef, elaborated_type_spec, remove_attributes, false, ctx) - .adjusted_TemplateArgument_print(temp_arg, temp_arg_stream); - - return get_with_unified_types(temp_arg_stream.str(), unnamed); + .adjusted_TemplateArgument_print(templ_arg, templ_arg_stream); +#endif + return get_with_unified_types(templ_arg_stream.str(), unnamed); } - /** Returns the textual representation of a type for the use in woven code. + /** Returns the textual C++ representation for the use in woven code of the given type * \param type The type * \param ctx The ASTContext * \param var_name If this is unequal zero, the type is returned @@ -359,7 +557,7 @@ public: false); // Do not make signature parameter type adjustments (because the result is not used for signatures) } - /** Returns the textual representation of a type for the use in AspectC++ signatures. + /** Returns the textual C++ representation for the use in AspectC++ signatures of the given type * \param type The type * \param ctx The ASTContext * \param var_name If this is unequal zero, the type is returned @@ -386,10 +584,7 @@ public: as_parameter_signature_type); } - - - - /** Returns the textual representation of a type. + /** Returns the textual C++ representation of the given type * \param type The type * \param ctx The ASTContext * \param var_name If this is unequal zero, the type is returned @@ -397,11 +592,11 @@ public: * (e.g. void(*)(int) is returned as void(*example)(int) if "example" is * provided as variable name.) * \param absolute_qualified Add all nested name specifiers as well as the - * root qualifier (ENABLE), do not change nested name specifiers (DONOTCHANGE) + * global namespace qualifier (ENABLE), do not change nested name specifiers (DONOTCHANGE) * or remove all nested name specifiers (DISABLE). * \param keep_typedef If the type is typedef'd, keep the typedef and return - * the typedef'd type (and not the underlying type) - * \param elaborated_type_spec Add elaborated type specifier before + * the typedef'd type (and not the underlying type). Otherwise, try to eliminate all typedefs. + * \param elaborated_type_spec Add or remove elaborated type specifier before * class, union, and enumeration types. * \param unnamed Do not suppress printing of unwritten scope and convert printed * namespaces to '<unnamed>' @@ -419,112 +614,69 @@ public: bool remove_attributes = false, bool as_parameter_signature_type = false ) { + using namespace clang; // Check invalid combinations: assert(!(keep_typedef && elaborated_type_spec == TSEF_ENABLE) && "A typedef type can not be " "printed together with an elaborated type specifier."); - assert(!(as_parameter_signature_type && !ctx) && "as_parameter_signature_type flag needs an ASTContext"); // TODO: more!? - clang::PrintingPolicy policy = get_preset_printing_policy(ctx, unnamed, absolute_qualified); - + PrintingPolicy policy = get_preset_printing_policy(ctx, absolute_qualified, keep_typedef, elaborated_type_spec, unnamed, remove_attributes); - // Start printing: + // Construct the string around which the type will be printed: string resulting_type_text = var_name ? var_name : ""; string type_string_buffer; llvm::raw_string_ostream type_stream(type_string_buffer); -// TODO: This does not always work yet! -// Idea: Use QualTypeNames's getFullyQualifiedType(...) to avoid using adjusted type printer -#if 0 && CLANG_VERSION_NUMBER >= VERSION_NUMBER_6_0_0 +#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0 // Make sure there is an ASTContext because it is mandatory for getFullyQualifiedType - if(!ctx) { - // TODO: Move this to TI_Type!? - // TODO: Maybe it is easier to make sure that all calls to get_type_text provide an ASTContext instead of retrieving it from the type? - - // If no ASTContext was provided, try to get it from the QualType: - clang::QualType contextType = type; - while(true) { - if (clang::TagDecl *tagDecl = contextType->getAsTagDecl()) { - ctx = &(tagDecl->getASTContext()); - } else if (const clang::TemplateTypeParmType *ttpType = clang::dyn_cast<clang::TemplateTypeParmType>(contextType)) { - ctx = &(ttpType->getDecl()->getASTContext()); - } else if (const clang::TypedefType *tdType = clang::dyn_cast<clang::TypedefType>(contextType)) { - ctx = &(tdType->getDecl()->getASTContext()); - } else if (const clang::TemplateSpecializationType *tsType = clang::dyn_cast<clang::TemplateSpecializationType>(contextType)) { - if (tsType->getNumArgs() > 0) { - if (tsType->getArg(0).getKind() == clang::TemplateArgument::Declaration) { - ctx = &(tsType->getArg(0).getAsDecl()->getASTContext()); - } - else if (tsType->getArg(0).getKind() == clang::TemplateArgument::Type) { - contextType = tsType->getArg(0).getAsType(); - continue; - } - else if (tsType->getArg(0).getKind() == clang::TemplateArgument::Expression) { - contextType = tsType->getArg(0).getAsExpr()->getType(); - continue; - } - else { - cout << tsType->getArg(0).getKind() << endl; - } - } - } else if (const clang::DependentTemplateSpecializationType *tsType = clang::dyn_cast<clang::DependentTemplateSpecializationType>( - contextType)) { - if (tsType->getNumArgs() > 0) { - if (tsType->getArg(0).getKind() == clang::TemplateArgument::Declaration) { - ctx = &(tsType->getArg(0).getAsDecl()->getASTContext()); - } - else if (tsType->getArg(0).getKind() == clang::TemplateArgument::Type) { - contextType = tsType->getArg(0).getAsType(); - continue; - } - else if (tsType->getArg(0).getKind() == clang::TemplateArgument::Expression) { - contextType = tsType->getArg(0).getAsExpr()->getType(); - continue; - } - else { - cout << tsType->getArg(0).getKind() << endl; - } - } - } - break; + // and getSignatureParameterType. + // TODO: Maybe it is easier to ensure that all calls to get_type_text provide an ASTContext instead of + // retrieving it from the type? + if(!ctx && (as_parameter_signature_type || absolute_qualified == TSEF_ENABLE)) { + ctx = get_ast_context(type); + if(!ctx) { + // We need the context but we do not have it. + // TODO: Better handling! + throw std::runtime_error("AST context not available for type " + type.getAsString()); } } - if(keep_typedef == false) { - // while(clang::isa<clang::TypedefType>(type)) { - // type = clang::dyn_cast<clang::TypedefType>(type)->desugar(); - // } - // Doing type = type.desugar() in a loop until we do not have a TypedefType anymore does not - // work always. Counterexample: array type with typedef'd element type. - - type = type.getCanonicalType(); + if(remove_attributes) { + if(const AttributedType *attributed_type = dyn_cast<AttributedType>(type)) + // Take the type that the attributes modify. This corresponds to + // syntactically removing the attributes. (To retrieve the type that is + // semantically formed by the written type and its attributes, + // use getEquivalentType().) + // TODO: This does not remove attributes from nested types! + type = attributed_type->getModifiedType(); } + if(as_parameter_signature_type) { type = ctx->getSignatureParameterType(type); } + // Suppressing all scopes is enforces through the printing policy. Adding + // all scopes including global namespace specifier is done via + // getFullyQualifiedType. + // TODO: getFullyQualifiedType is not perfect yet. + // - E.g. see https://bugs.llvm.org/show_bug.cgi?id=41210. + // - For TemplateSpecializationTypes with a function pointer template + // type, getFullyQualifiedType *removes* the qualifiers of the function + // type's argument and return types if(absolute_qualified == TSEF_ENABLE) { - if(ctx) { - // Add all scopes to the type: - type = clang::TypeName::getFullyQualifiedType(type, *ctx, true); - } - else { - cout << "no context: " << type->getTypeClassName() << ":" << type.getAsString() << endl; - //throw "no context"; - //return string("<no context>"); - } + type = TypeName::getFullyQualifiedType(type, *ctx, + /*WithGlobalNsPrefix=*/true); } - // Actually print the type using the non adjusted type printer + // Actually print the type using the native type printer type.print(type_stream, policy, resulting_type_text); #else AdjustedTypePrinter(policy, absolute_qualified, keep_typedef, elaborated_type_spec, remove_attributes, as_parameter_signature_type, ctx) .print(type, type_stream, resulting_type_text); #endif - resulting_type_text = type_stream.str(); return get_with_unified_types(resulting_type_text, unnamed); } @@ -665,11 +817,11 @@ public: clang::SourceLocation min_loc; for (clang::DeclContext::decl_iterator i = _decl->decls_begin (); i != _decl->decls_end (); ++i) { - clang::SourceLocation cur_loc = (*i)->getLocStart(); + clang::SourceLocation cur_loc = CLANG_GET_LOC_START(*i); if ((*i)->isImplicit () || !cur_loc.isValid ()) continue; if (!min_loc.isValid () || (cur_loc < min_loc)) - min_loc = (*i)->getLocStart(); + min_loc = CLANG_GET_LOC_START(*i); } if (min_loc.isValid ()) return wb.weave_pos(min_loc, WeavePos::WP_BEFORE); @@ -691,13 +843,13 @@ public: // return the position of the first token of the class definition const WeavePos &objdecl_start_pos (WeaverBase &wb) const { - return wb.weave_pos (_decl->getLocStart(), WeavePos::WP_BEFORE); + return wb.weave_pos (CLANG_GET_LOC_START(_decl), WeavePos::WP_BEFORE); } // return the position after the ";" of the class definition const WeavePos &objdecl_end_pos (WeaverBase &wb) const { // FIXME: This relies on the lack of spaces between the closing '}' and ';'. - return wb.weave_pos (_decl->getLocEnd().getLocWithOffset(1), WeavePos::WP_AFTER); + return wb.weave_pos (CLANG_GET_LOC_END(_decl).getLocWithOffset(1), WeavePos::WP_AFTER); } // check whether this is a class and not a struct @@ -1069,7 +1221,7 @@ public: return false; // in case of calls to const member functions Clang adds an implicit cast that turn the object // into a const object even if it was non-const. So we have to ignore implicit casts here. - clang::Expr *real_target = _target_expr->IgnoreImpCasts (); + clang::Expr *real_target = _target_expr->IgnoreImplicit(); // now check whether the object type was const before any implicit casts clang::QualType t = real_target->getType(); // if the target is a pointer we need check the object's const-ness and ignore the pointer. @@ -1088,7 +1240,7 @@ public: virtual clang::Expr *find_target_expr() const { // analog to clang::CXXMemberCallExpr::getImplicitObjectArgument() if( const clang::MemberExpr *member = llvm::dyn_cast<clang::MemberExpr>( _ref_node ) ) - return member->getBase()->IgnoreImpCasts(); + return member->getBase()->IgnoreImplicit(); else if( const clang::BinaryOperator *op = llvm::dyn_cast<clang::BinaryOperator>( _ref_node ) ) if( op->getOpcode() == clang::BO_PtrMemD || op->getOpcode() == clang::BO_PtrMemI ) return op->getLHS(); @@ -1165,25 +1317,25 @@ public: virtual const WeavePos &before_pos (WeaverBase &wb) { // jump into parenthesis and ignore exprs that don't change anything // cant do this early (or _node in general as ImplicitCast can be skipped here but not for type compuatations) - return wb.weave_pos( skipTransparent( _node )->getLocStart(), WeavePos::WP_BEFORE ); + return wb.weave_pos( CLANG_GET_LOC_START(skipTransparent( _node )), WeavePos::WP_BEFORE ); } virtual const WeavePos &after_pos (WeaverBase &wb) { // jump into parenthesis and ignore exprs that don't change anything // cant do this early (or _node in general as ImplicitCast can be skipped here but not for type compuatations) - return get_pos_after_token( skipTransparent( _node )->getLocEnd(), wb ); + return get_pos_after_token( CLANG_GET_LOC_END(skipTransparent( _node )), wb ); } const WeavePos &entity_before_pos( WeaverBase &wb ) { - return wb.weave_pos( ref_node()->getLocStart(), WeavePos::WP_BEFORE ); + return wb.weave_pos( CLANG_GET_LOC_START(ref_node()), WeavePos::WP_BEFORE ); } const WeavePos &entity_after_pos( WeaverBase &wb ) { - return get_pos_after_token( ref_node()->getLocEnd(), wb, WeavePos::WP_AFTER ); + return get_pos_after_token( CLANG_GET_LOC_END(ref_node()), wb, WeavePos::WP_AFTER ); } const WeavePos &entity_op_before_pos( WeaverBase &wb ) { assert( clang::isa<clang::MemberExpr>( ref_node() ) ); clang::MemberExpr *me = clang::dyn_cast<clang::MemberExpr>( ref_node() ); // clang3.4 seems to miss getOperatorLoc() //return wb.weave_pos( me->getOperatorLoc(), WeavePos::WP_BEFORE ); - return get_pos_after_token( me->getBase()->getLocEnd(), wb, WeavePos::WP_BEFORE ); + return get_pos_after_token( CLANG_GET_LOC_END(me->getBase()), wb, WeavePos::WP_BEFORE ); } const WeavePos &entity_op_after_pos( WeaverBase &wb ) { assert( clang::isa<clang::MemberExpr>( ref_node() ) ); @@ -1303,41 +1455,41 @@ public: // returns the position directly in front of the opening bracket [ virtual const WeavePos &index_open_before_pos (WeaverBase &wb) { assert (is_index_expr ()); - return get_pos_after_token(arg(0)->getLocEnd(), wb, WeavePos::WP_BEFORE); + return get_pos_after_token(CLANG_GET_LOC_END(arg(0)), wb, WeavePos::WP_BEFORE); } // returns the position directly behind the opening bracket [ virtual const WeavePos &index_open_after_pos (WeaverBase &wb) { assert (is_index_expr ()); - return wb.weave_pos(arg(1)->getLocStart (), WeavePos::WP_AFTER); + return wb.weave_pos(CLANG_GET_LOC_START(arg(1)), WeavePos::WP_AFTER); } // returns the position directly in front of the closing bracket ] virtual const WeavePos &index_close_before_pos (WeaverBase &wb) { assert (is_index_expr ()); - return get_pos_after_token(arg(1)->getLocEnd (), wb, WeavePos::WP_BEFORE); + return get_pos_after_token(CLANG_GET_LOC_END(arg(1)), wb, WeavePos::WP_BEFORE); } // returns the position directly behind the closing bracket ] virtual const WeavePos &index_close_after_pos (WeaverBase &wb) { assert (is_index_expr ()); - return get_pos_after_token(TI_Access::tree_node()->getLocEnd (), wb, WeavePos::WP_AFTER); + return get_pos_after_token(CLANG_GET_LOC_END(TI_Access::tree_node()), wb, WeavePos::WP_AFTER); } // The following member-functions return the corresponding weave-positions of ternary operators // (first delimiter = "?", second delimiter = ":") virtual const WeavePos& ternary_op_first_delim_before_pos(WeaverBase &wb) { assert (is_ternary_expr()); - return get_pos_after_token(arg(0)->getLocEnd(), wb, WeavePos::WP_BEFORE); + return get_pos_after_token(CLANG_GET_LOC_END(arg(0)), wb, WeavePos::WP_BEFORE); } virtual const WeavePos& ternary_op_first_delim_after_pos(WeaverBase &wb) { assert (is_ternary_expr()); - return wb.weave_pos(arg(1)->getLocStart(), WeavePos::WP_AFTER); + return wb.weave_pos(CLANG_GET_LOC_START(arg(1)), WeavePos::WP_AFTER); } virtual const WeavePos& ternary_op_second_delim_before_pos(WeaverBase &wb) { assert (is_ternary_expr()); - return get_pos_after_token(arg(1)->getLocEnd(), wb, WeavePos::WP_BEFORE); + return get_pos_after_token(CLANG_GET_LOC_END(arg(1)), wb, WeavePos::WP_BEFORE); } virtual const WeavePos& ternary_op_second_delim_after_pos(WeaverBase &wb) { assert (is_ternary_expr()); - return wb.weave_pos(arg(2)->getLocStart(), WeavePos::WP_AFTER); + return wb.weave_pos(CLANG_GET_LOC_START(arg(2)), WeavePos::WP_AFTER); } }; @@ -1468,7 +1620,7 @@ public: if (!mce) return false; // TODO: is there a better way to distinguish 'c' from 'c.operator int*()'? - return (mce->getCallee ()->getLocEnd () == TI_Access::tree_node()->getLocEnd ()); + return (CLANG_GET_LOC_END(mce->getCallee ()) == CLANG_GET_LOC_END(TI_Access::tree_node())); } virtual bool is_implicit_dereference() const { @@ -1490,29 +1642,29 @@ public: return ce->getOperatorLoc (); assert( false && "This is no operator." ); - return TI_Access::tree_node()->getLocStart(); // dummy + return CLANG_GET_LOC_START(TI_Access::tree_node()); // dummy } const WeavePos &args_open_before_pos (WeaverBase &wb) { if (is_call_op ()) - return wb.weave_pos (tree_node()->getCallee ()->getLocStart (), WeavePos::WP_BEFORE); + return wb.weave_pos (CLANG_GET_LOC_START(tree_node()->getCallee ()), WeavePos::WP_BEFORE); else - return get_pos_after_token(tree_node()->getCallee ()->getLocEnd (), wb, WeavePos::WP_BEFORE); + return get_pos_after_token(CLANG_GET_LOC_END(tree_node()->getCallee ()), wb, WeavePos::WP_BEFORE); } const WeavePos &args_open_after_pos (WeaverBase &wb) { if (call_args () > 0) - return wb.weave_pos (arg (0)->getLocStart (), WeavePos::WP_AFTER); + return wb.weave_pos (CLANG_GET_LOC_START(arg (0)), WeavePos::WP_AFTER); else - return wb.weave_pos (TI_Access::tree_node()->getLocEnd (), WeavePos::WP_AFTER); + return wb.weave_pos (CLANG_GET_LOC_END(TI_Access::tree_node()), WeavePos::WP_AFTER); } const WeavePos &args_close_before_pos (WeaverBase &wb) { - return wb.weave_pos(TI_Access::tree_node()->getLocEnd (), WeavePos::WP_BEFORE); + return wb.weave_pos(CLANG_GET_LOC_END(TI_Access::tree_node()), WeavePos::WP_BEFORE); } const WeavePos &args_close_after_pos (WeaverBase &wb) { - return get_pos_after_token(TI_Access::tree_node()->getLocEnd (), wb, WeavePos::WP_AFTER); + return get_pos_after_token(CLANG_GET_LOC_END(TI_Access::tree_node()), wb, WeavePos::WP_AFTER); } const WeavePos &callee_before_pos (WeaverBase &wb) { @@ -1524,24 +1676,24 @@ public: callee = clang::dyn_cast<clang::ParenExpr> (callee)->getSubExpr (); const clang::MemberExpr *me = clang::dyn_cast<clang::MemberExpr> (callee); assert (me); - return get_pos_after_token(me->getBase ()->getLocEnd (), wb, WeavePos::WP_BEFORE); + return get_pos_after_token(CLANG_GET_LOC_END(me->getBase ()), wb, WeavePos::WP_BEFORE); } else { if (is_call_op ()) - return wb.weave_pos (TI_Access::tree_node()->getLocStart (), WeavePos::WP_BEFORE); + return wb.weave_pos (CLANG_GET_LOC_START(TI_Access::tree_node()), WeavePos::WP_BEFORE); else - return wb.weave_pos (tree_node()->getCallee ()->getLocStart (), WeavePos::WP_BEFORE); + return wb.weave_pos (CLANG_GET_LOC_START(tree_node()->getCallee ()), WeavePos::WP_BEFORE); } } const WeavePos &callee_after_pos (WeaverBase &wb) { if (is_call_op ()) - return wb.weave_pos (tree_node()->getCallee ()->getLocStart (), WeavePos::WP_AFTER); + return wb.weave_pos (CLANG_GET_LOC_START(tree_node()->getCallee ()), WeavePos::WP_AFTER); else { const clang::Expr *callee = tree_node()->getCallee (); while (clang::dyn_cast<clang::ParenExpr> (callee)) callee = clang::dyn_cast<clang::ParenExpr> (callee)->getSubExpr (); - return get_pos_after_token(callee->getLocEnd (), wb, WeavePos::WP_AFTER); + return get_pos_after_token(CLANG_GET_LOC_END(callee), wb, WeavePos::WP_AFTER); } } @@ -1685,14 +1837,14 @@ public: virtual const WeavePos &after_pos (WeaverBase &wb) { if( TI_Builtin::is_implicit_dereference() ) { - return get_pos_after_token( skipTransparent( arg(0) )->getLocEnd(), wb ); + return get_pos_after_token( CLANG_GET_LOC_END(skipTransparent( arg(0) )), wb ); } return TI_CommonCall::after_pos(wb); } virtual const WeavePos &before_pos (WeaverBase &wb) { if( TI_Builtin::is_implicit_dereference() ) { - return wb.weave_pos( skipTransparent( arg(0) )->getLocStart(), WeavePos::WP_BEFORE ); + return wb.weave_pos( CLANG_GET_LOC_START(skipTransparent( arg(0) )), WeavePos::WP_BEFORE ); } return TI_CommonCall::before_pos(wb); } @@ -1926,7 +2078,7 @@ public: } assert( false && "The expr does not have THE ONE operator-location." ); - return node->getLocStart(); // dummy + return CLANG_GET_LOC_START(node); // dummy } // returns whether the current operator returns something |