summaryrefslogtreecommitdiff
path: root/AspectC++/ClangTransformInfo.h
diff options
context:
space:
mode:
Diffstat (limited to 'AspectC++/ClangTransformInfo.h')
-rw-r--r--AspectC++/ClangTransformInfo.h470
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