summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinhard Tartler <siretart@tauware.de>2020-02-29 18:15:17 -0500
committerReinhard Tartler <siretart@tauware.de>2020-02-29 18:15:17 -0500
commita4ac05fb82711919d01f98cc350ee817ebf5cfc7 (patch)
tree4d6abcd6d70502f5f610d32cd7d44c2864c4ece8
parent03f550f8322a113f6b430cabfd83125edafcf4c6 (diff)
parent0a56b56f511f94b12d1ecbf73568332cda107816 (diff)
Update upstream source from tag 'upstream/2.2+git20200229'
Update to upstream version '2.2+git20200229' with Debian dir 23d9509c563bc846d67afae0ea41b55655e96a6f
-rw-r--r--.gitignore2
-rw-r--r--Ag++/AGxxConfig.cc19
-rw-r--r--Ag++/AGxxConfig.h2
-rw-r--r--AspectC++/.cproject42
-rw-r--r--AspectC++/.project4
-rw-r--r--AspectC++/ACProject.cc4
-rw-r--r--AspectC++/ClangASTConsumer.cc3
-rw-r--r--AspectC++/ClangAdjustedTypePrinter.cc179
-rw-r--r--AspectC++/ClangAdjustedTypePrinter.h47
-rw-r--r--AspectC++/ClangBinding.cc38
-rw-r--r--AspectC++/ClangBinding.h27
-rw-r--r--AspectC++/ClangFlowAnalysis.cc24
-rw-r--r--AspectC++/ClangInclusionRewriter.cc19
-rw-r--r--AspectC++/ClangIntroParser.cc19
-rw-r--r--AspectC++/ClangIntroSema.cc93
-rw-r--r--AspectC++/ClangIntroSema.h30
-rw-r--r--AspectC++/ClangIntroducer.cc30
-rw-r--r--AspectC++/ClangModelBuilder.cc8
-rw-r--r--AspectC++/ClangSyntacticContext.h14
-rw-r--r--AspectC++/ClangTransformInfo.h470
-rw-r--r--AspectC++/ClangWeaverBase.cc34
-rw-r--r--AspectC++/CodeWeaver.cc14
-rw-r--r--AspectC++/Makefile4
-rw-r--r--AspectC++/ThisJoinPoint.cc22
-rw-r--r--AspectC++/Transformer.cc18
-rw-r--r--AspectC++/config/clang-3.5.2.mk1
-rw-r--r--AspectC++/config/clang-5.0.2.mk1
-rw-r--r--AspectC++/config/clang-9.0.0.mk1
-rw-r--r--AspectC++/config/clang.mk6
-rw-r--r--AspectC++/tests/EntityInfo/JPTL.h893
-rw-r--r--AspectC++/tests/EntityInfo/Makefile2
-rw-r--r--AspectC++/tests/EntityInfo/feature.ref17
-rw-r--r--AspectC++/tests/EntityInfo/main.cc122
-rw-r--r--AspectC++/tests/Makefile3
-rw-r--r--AspectC++/tests/TypePrinting_FunctionPointers/Makefile2
-rw-r--r--AspectC++/tests/TypePrinting_FunctionPointers/feature.ref0
-rw-r--r--AspectC++/tests/TypePrinting_FunctionPointers/main.cc56
-rwxr-xr-xAspectC++/tests/make_testall_multiple_clang_versions.sh125
-rw-r--r--AspectC++/version.h14
-rw-r--r--Puma/src/common/Config.cc2
-rw-r--r--Puma/src/compile.mk2
41 files changed, 2139 insertions, 274 deletions
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 39200f4..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-.pc
-Puma/lib
diff --git a/Ag++/AGxxConfig.cc b/Ag++/AGxxConfig.cc
index d5e1f28..0a400cf 100644
--- a/Ag++/AGxxConfig.cc
+++ b/Ag++/AGxxConfig.cc
@@ -42,7 +42,8 @@ string AGxxConfig::_gcc_option_arg[] = { "-aux-info", "-print-prog-name=",
"-print-file-name=", "-idirafter", "-imacros", "-iprefix", "-iwithprefix",
"-iwithprefixbefore", "-isystem", "--gen_size_type", "-B", "-l", "-I", "-L",
"-specs=", "-MF", "-MT", "-MQ", "-x", "--param=", "--param", "-Xlinker",
- "-u", "-V", "-b", "-G", };
+ "-u", "-V", "-b", "-G", "-isysroot",
+ "-F", "-arch", }; // macOS
string AGxxConfig::_gcc_option_info[] = { "-print","-dump", };
@@ -128,6 +129,10 @@ static OptsParser::Option options[] = {
"\t" "Override the compiler's target triple", OptsParser::AT_MANDATORY},
{ AGxxConfig::ACOPT_PRE_INCLUDE, "I", NULL,
"\t\t" "Add new include path", OptsParser::AT_MANDATORY},
+ { AGxxConfig::ACOPT_PRE_ISYSROOT, "isysroot", NULL,
+ "\t\t" "Specify isysroot path", OptsParser::AT_MANDATORY},
+ { AGxxConfig::ACOPT_PRE_FRAMEWORK, "F", NULL,
+ "\t\t" "Add new framework include path", OptsParser::AT_MANDATORY}, // macOS
{ AGxxConfig::ACOPT_PRE_DEFINE, "D", NULL,
"\t\t" "Define a preprocessor macro", OptsParser::AT_MANDATORY},
{ AGxxConfig::ACOPT_PRE_UNDEFINE, "U", NULL,
@@ -357,6 +362,18 @@ AGxxConfig::parseOptions()
(OptionItem::OPT_ACC | OptionItem::OPT_GCC));
continue;
+ case ACOPT_PRE_ISYSROOT:
+ _optvec.pushback("--isysroot", " \"" + op.getArgument() + "\" ",
+ (OptionItem::OPT_ACC));
+ _optvec.pushback("-isysroot", " \"" + op.getArgument() + "\" ",
+ (OptionItem::OPT_GCC));
+ continue;
+
+ case ACOPT_PRE_FRAMEWORK:
+ _optvec.pushback("-F", " \"" + op.getArgument() + "\" ",
+ (OptionItem::OPT_ACC | OptionItem::OPT_GCC));
+ continue;
+
case ACOPT_SYS_INCLUDE:
_optvec.pushback("--isystem", " \"" + op.getArgument() + "\" ",
(OptionItem::OPT_ACC ));
diff --git a/Ag++/AGxxConfig.h b/Ag++/AGxxConfig.h
index c090cb8..8885573 100644
--- a/Ag++/AGxxConfig.h
+++ b/Ag++/AGxxConfig.h
@@ -186,6 +186,8 @@ public:
ACOPT_PRE_INCLUDE,
ACOPT_PRE_DEFINE,
ACOPT_PRE_UNDEFINE,
+ ACOPT_PRE_ISYSROOT,
+ ACOPT_PRE_FRAMEWORK, // macOS
ACOPT_ALWAYS_INCLUDE,
ACOPT_SYS_INCLUDE
};
diff --git a/AspectC++/.cproject b/AspectC++/.cproject
index ead2249..f7dd999 100644
--- a/AspectC++/.cproject
+++ b/AspectC++/.cproject
@@ -7,18 +7,6 @@
<extensions/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
- <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
- <buildTargets>
- <target name="test" path="" targetID="org.eclipse.cdt.make.MakeTargetBuilder">
- <buildCommand>make</buildCommand>
- <buildArguments>SHARED=1 -j4</buildArguments>
- <buildTarget>testclean test</buildTarget>
- <stopOnError>false</stopOnError>
- <useDefaultCommand>true</useDefaultCommand>
- <runAllBuilders>true</runAllBuilders>
- </target>
- </buildTargets>
- </storageModule>
</cconfiguration>
</storageModule>
<storageModule moduleId="scannerConfiguration">
@@ -112,12 +100,26 @@
<content-type-mapping configuration="" content-type="org.eclipse.cdt.core.cxxSource" language="org.eclipse.cdt.core.g++"/>
</project-mappings>
</storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.language.mapping">
+ <project-mappings>
+ <content-type-mapping configuration="" content-type="org.eclipse.cdt.core.cxxHeader" language="org.eclipse.cdt.core.g++"/>
+ <content-type-mapping configuration="" content-type="org.eclipse.cdt.core.cxxSource" language="org.eclipse.cdt.core.g++"/>
+ </project-mappings>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
+ <buildTargets>
+ <target name="test" path="" targetID="org.eclipse.cdt.make.MakeTargetBuilder">
+ <buildCommand>make</buildCommand>
+ <buildArguments>SHARED=1 -j4</buildArguments>
+ <buildTarget>testclean test</buildTarget>
+ <stopOnError>false</stopOnError>
+ <useDefaultCommand>true</useDefaultCommand>
+ <runAllBuilders>true</runAllBuilders>
+ </target>
+ </buildTargets>
+ </storageModule>
<storageModule moduleId="org.eclipse.cdt.core.pathentry">
- <pathentry base-path="Puma" include="include" kind="inc" path="" system="true"/>
- <pathentry include="../llvm-3.6.2/tools/clang/include" kind="inc" path="" system="true"/>
- <pathentry include="../llvm-3.6.2/include" kind="inc" path="" system="true"/>
<pathentry include="/usr/include/libxml2" kind="inc" path="" system="true"/>
- <pathentry include="/home/olaf/clang+llvm-3.8.0-x86_64-opensuse13.2/include" kind="inc" path="" system="true"/>
<pathentry base-ref="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO" include="/usr/include/c++/4.8" kind="inc" path="" system="true"/>
<pathentry base-ref="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO" include="/usr/include/c++/4.8/x86_64-suse-linux" kind="inc" path="" system="true"/>
<pathentry base-ref="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO" include="/usr/include/c++/4.8/backward" kind="inc" path="" system="true"/>
@@ -126,14 +128,10 @@
<pathentry base-ref="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO" include="/usr/lib64/gcc/x86_64-suse-linux/4.8/include-fixed" kind="inc" path="" system="true"/>
<pathentry base-ref="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO" include="/usr/x86_64-suse-linux/include" kind="inc" path="" system="true"/>
<pathentry base-ref="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO" include="/usr/include" kind="inc" path="" system="true"/>
+ <pathentry include="/store/olaf/clang+llvm-3.8.1-x86_64-opensuse13.2/include" kind="inc" path="" system="true"/>
+ <pathentry include="/store/olaf/workspace-acxx/Puma/include" kind="inc" path="" system="true"/>
<pathentry kind="mac" name="FRONTEND_CLANG" path="" value="38"/>
<pathentry kind="src" path=""/>
<pathentry kind="out" path=""/>
</storageModule>
- <storageModule moduleId="org.eclipse.cdt.core.language.mapping">
- <project-mappings>
- <content-type-mapping configuration="" content-type="org.eclipse.cdt.core.cxxHeader" language="org.eclipse.cdt.core.g++"/>
- <content-type-mapping configuration="" content-type="org.eclipse.cdt.core.cxxSource" language="org.eclipse.cdt.core.g++"/>
- </project-mappings>
- </storageModule>
</cproject>
diff --git a/AspectC++/.project b/AspectC++/.project
index 431b3c3..3fce615 100644
--- a/AspectC++/.project
+++ b/AspectC++/.project
@@ -23,7 +23,7 @@
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.build.arguments</key>
- <value>make SHARED=1 FRONTEND=Clang -j6</value>
+ <value>make SHARED=1 -j6</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.build.command</key>
@@ -83,7 +83,7 @@
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.environment</key>
- <value></value>
+ <value>LLVMCONF=/store/olaf/clang+llvm-3.8.1-x86_64-opensuse13.2/bin/llvm-config|</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
diff --git a/AspectC++/ACProject.cc b/AspectC++/ACProject.cc
index ded7fb9..2ae9b6f 100644
--- a/AspectC++/ACProject.cc
+++ b/AspectC++/ACProject.cc
@@ -300,9 +300,9 @@ void ACProject::create_compiler_instance (ACConfig &conf) {
Args.push_back("-fheinous-gnu-extensions"); // see bug 766 (ignore strange casts of LValues)
}
- // Pass macro definitions and include paths to clang. Everything else is
+ // Pass macro definitions, include paths, and framework paths to clang. Everything else is
// Puma-specific and dropped.
- if ((strncmp(Name, "-I", 2) && strncmp(Name, "-i", 2)))
+ if (strncmp(Name, "-I", 2) && strncmp(Name, "-i", 2) && strncmp(Name, "-F", 2))
continue;
Args.push_back(Name);
diff --git a/AspectC++/ClangASTConsumer.cc b/AspectC++/ClangASTConsumer.cc
index 7287150..4de277d 100644
--- a/AspectC++/ClangASTConsumer.cc
+++ b/AspectC++/ClangASTConsumer.cc
@@ -187,6 +187,9 @@ bool ClangASTConsumer::VisitVarDecl( VarDecl *VD ) {
if( ! isInProject( VD ) )
return true;
+ // cout << "DUMP" << endl;
+ // VD->dump();
+
if( VD->getType()->isReferenceType() && ! VD->isFileVarDecl() )
return true; // skip references for now, but only if they are not on the top level as we need these as context for joinpoints
diff --git a/AspectC++/ClangAdjustedTypePrinter.cc b/AspectC++/ClangAdjustedTypePrinter.cc
index c6a4601..e69bec5 100644
--- a/AspectC++/ClangAdjustedTypePrinter.cc
+++ b/AspectC++/ClangAdjustedTypePrinter.cc
@@ -60,16 +60,22 @@
// 14.03.2017: - Made AdjustedTypePrinter compatible with Clang 4.0.0
// 17.09.2017: - Made AdjustedTypePrinter compatible with Clang 5.0.0
// 18.03.2018: - Made AdjustedTypePrinter compatible with Clang 6.0.0
+// 19.02.2019: - Made AdjustedTypePrinter compatible with Clang 7.0.1
//AC++: beginning of TypePrinter.cpp is located in ClangAdjustedTypePrinter.h
//AC++: includes added:
+#include "version.h"
+
+//AC++: added if:
+#if CLANG_VERSION_NUMBER < VERSION_NUMBER_9_0_0
+
+//AC++: includes added:
#include "ClangTransformInfo.h"
#include "ClangAdjustedTypePrinter.h"
#include "clang/AST/TemplateBase.h"
-#include "version.h"
-//#if CLANG_VERSION_NUMBER < VERSION_NUMBER_6_0_0
+
using namespace clang;
//AC++: Changed name of parameter from "C99" to "HasRestrictKeyword"
@@ -212,6 +218,10 @@ bool AdjustedTypePrinter::canPrefixQualifiers(const Type *T,
#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_6_0_0
case Type::DependentAddressSpace:
#endif
+//AC++: added #if for backward compatibility
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_7_0_0
+ case Type::DependentVector:
+#endif
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
@@ -355,14 +365,23 @@ void AdjustedTypePrinter::printBlockPointerAfter(const BlockPointerType *T,
printAfter(T->getPointeeType(), OS);
}
+// When printing a reference, the referenced type might also be a reference.
+// If so, we want to skip that before printing the inner type.
+static QualType skipTopLevelReferences(QualType T) {
+ if (auto *Ref = T->getAs<ReferenceType>())
+ return skipTopLevelReferences(Ref->getPointeeTypeAsWritten());
+ return T;
+}
+
void AdjustedTypePrinter::printLValueReferenceBefore(const LValueReferenceType *T,
raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
- printBefore(T->getPointeeTypeAsWritten(), OS);
+ QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
+ printBefore(Inner, OS);
// Handle things like 'int (&A)[4];' correctly.
// FIXME: this should include vectors, but vectors use attributes I guess.
- if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+ if (isa<ArrayType>(Inner))
OS << '(';
OS << '&';
}
@@ -370,21 +389,23 @@ void AdjustedTypePrinter::printLValueReferenceAfter(const LValueReferenceType *T
raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
+ QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
// Handle things like 'int (&A)[4];' correctly.
// FIXME: this should include vectors, but vectors use attributes I guess.
- if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+ if (isa<ArrayType>(Inner))
OS << ')';
- printAfter(T->getPointeeTypeAsWritten(), OS);
+ printAfter(Inner, OS);
}
void AdjustedTypePrinter::printRValueReferenceBefore(const RValueReferenceType *T,
raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
- printBefore(T->getPointeeTypeAsWritten(), OS);
+ QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
+ printBefore(Inner, OS);
// Handle things like 'int (&&A)[4];' correctly.
// FIXME: this should include vectors, but vectors use attributes I guess.
- if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+ if (isa<ArrayType>(Inner))
OS << '(';
OS << "&&";
}
@@ -392,11 +413,12 @@ void AdjustedTypePrinter::printRValueReferenceAfter(const RValueReferenceType *T
raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
+ QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
// Handle things like 'int (&&A)[4];' correctly.
// FIXME: this should include vectors, but vectors use attributes I guess.
- if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+ if (isa<ArrayType>(Inner))
OS << ')';
- printAfter(T->getPointeeTypeAsWritten(), OS);
+ printAfter(Inner, OS);
}
void AdjustedTypePrinter::printMemberPointerBefore(const MemberPointerType *T,
@@ -612,7 +634,58 @@ void AdjustedTypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS
}
void AdjustedTypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) {
printAfter(T->getElementType(), OS);
-}
+}
+
+//AC++: added #if for backward compatibility
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_7_0_0
+void AdjustedTypePrinter::printDependentVectorBefore(
+ const DependentVectorType *T, raw_ostream &OS) {
+ switch (T->getVectorKind()) {
+ case VectorType::AltiVecPixel:
+ OS << "__vector __pixel ";
+ break;
+ case VectorType::AltiVecBool:
+ OS << "__vector __bool ";
+ printBefore(T->getElementType(), OS);
+ break;
+ case VectorType::AltiVecVector:
+ OS << "__vector ";
+ printBefore(T->getElementType(), OS);
+ break;
+ case VectorType::NeonVector:
+ OS << "__attribute__((neon_vector_type(";
+ if (T->getSizeExpr())
+ T->getSizeExpr()->printPretty(OS, nullptr, Policy);
+ OS << "))) ";
+ printBefore(T->getElementType(), OS);
+ break;
+ case VectorType::NeonPolyVector:
+ OS << "__attribute__((neon_polyvector_type(";
+ if (T->getSizeExpr())
+ T->getSizeExpr()->printPretty(OS, nullptr, Policy);
+ OS << "))) ";
+ printBefore(T->getElementType(), OS);
+ break;
+ case VectorType::GenericVector: {
+ // FIXME: We prefer to print the size directly here, but have no way
+ // to get the size of the type.
+ OS << "__attribute__((__vector_size__(";
+ if (T->getSizeExpr())
+ T->getSizeExpr()->printPretty(OS, nullptr, Policy);
+ OS << " * sizeof(";
+ print(T->getElementType(), OS, StringRef());
+ OS << ")))) ";
+ printBefore(T->getElementType(), OS);
+ break;
+ }
+ }
+}
+
+void AdjustedTypePrinter::printDependentVectorAfter(
+ const DependentVectorType *T, raw_ostream &OS) {
+ printAfter(T->getElementType(), OS);
+}
+#endif
void AdjustedTypePrinter::printExtVectorBefore(const ExtVectorType *T,
raw_ostream &OS) {
@@ -740,11 +813,13 @@ void AdjustedTypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_5_0_0
printFunctionAfter(Info, OS);
+#if CLANG_VERSION_NUMBER < VERSION_NUMBER_9_0_0 // Clang 9.0.0 port in progress
if (unsigned quals = T->getTypeQuals()) {
OS << ' ';
AppendTypeQualList(OS, quals, Policy.Restrict);
}
-
+#endif // Clang 9.0.0 port in progress
+
switch (T->getRefQualifier()) {
case RQ_None:
break;
@@ -869,6 +944,11 @@ void AdjustedTypePrinter::printFunctionAfter(const clang::FunctionType::ExtInfo
<< Info.getRegParm() << ")))";
if (Info.getNoCallerSavedRegs())
OS << " __attribute__((no_caller_saved_registers))";
+//AC++: added if
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_7_0_0
+ if (Info.getNoCfCheck())
+ OS << " __attribute__((nocf_check))";
+#endif
}
#else
if (Info.getNoReturn())
@@ -1336,6 +1416,20 @@ void AdjustedTypePrinter::printInjectedClassNameAfter(const InjectedClassNameTyp
void AdjustedTypePrinter::printElaboratedBefore(const ElaboratedType *T,
raw_ostream &OS) {
//AC++: added #if for backward compatibility
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_7_0_0
+ if (Policy.IncludeTagDefinition && T->getOwnedTagDecl()) {
+ TagDecl *OwnedTagDecl = T->getOwnedTagDecl();
+ assert(OwnedTagDecl->getTypeForDecl() == T->getNamedType().getTypePtr() &&
+ "OwnedTagDecl expected to be a declaration for the type");
+ PrintingPolicy SubPolicy = Policy;
+ SubPolicy.IncludeTagDefinition = false;
+ OwnedTagDecl->print(OS, SubPolicy, Indentation);
+ spaceBeforePlaceHolder(OS);
+ return;
+ }
+#endif
+
+//AC++: added #if for backward compatibility
#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_3_9_1
if (Policy.IncludeTagDefinition && isa<TagType>(T->getNamedType()))
#else
@@ -1361,6 +1455,11 @@ void AdjustedTypePrinter::printElaboratedBefore(const ElaboratedType *T,
}
void AdjustedTypePrinter::printElaboratedAfter(const ElaboratedType *T,
raw_ostream &OS) {
+ //AC++: added #if for backward compatibility
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_7_0_0
+ if (Policy.IncludeTagDefinition && T->getOwnedTagDecl())
+ return;
+#endif
//AC++: commented out:
//ElaboratedTypePolicyRAII PolicyRAII(Policy);
printAfter(T->getNamedType(), OS);
@@ -1430,6 +1529,8 @@ void AdjustedTypePrinter::printPackExpansionAfter(const PackExpansionType *T,
void AdjustedTypePrinter::printAttributedBefore(const AttributedType *T,
raw_ostream &OS) {
+#if CLANG_VERSION_NUMBER < VERSION_NUMBER_9_0_0 // Clang 9.0.0 port in progress
+
// Prefer the macro forms of the GC and ownership qualifiers.
if (T->getAttrKind() == AttributedType::attr_objc_gc ||
T->getAttrKind() == AttributedType::attr_objc_ownership)
@@ -1465,10 +1566,12 @@ void AdjustedTypePrinter::printAttributedBefore(const AttributedType *T,
spaceBeforePlaceHolder(OS);
}
#endif
+#endif // Clang 9.0.0 port in progress
}
void AdjustedTypePrinter::printAttributedAfter(const AttributedType *T,
raw_ostream &OS) {
+#if CLANG_VERSION_NUMBER < VERSION_NUMBER_9_0_0 // Clang 9.0.0 port in progress
// Prefer the macro forms of the GC and ownership qualifiers.
if (T->getAttrKind() == AttributedType::attr_objc_gc ||
T->getAttrKind() == AttributedType::attr_objc_ownership)
@@ -1529,11 +1632,37 @@ void AdjustedTypePrinter::printAttributedAfter(const AttributedType *T,
}
#endif
+ //AC++: added #if for backward compatibility
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_7_0_0
+ if (T->getAttrKind() == AttributedType::attr_lifetimebound) {
+ OS << " [[clang::lifetimebound]]";
+ return;
+ }
+#endif
+
//AC++: added if:
if(!remove_attributes) {
OS << " __attribute__((";
switch (T->getAttrKind()) {
+//AC++: added #if for backward compatibility
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_7_0_0
+ case AttributedType::attr_lifetimebound:
+ case AttributedType::attr_nonnull:
+ case AttributedType::attr_nullable:
+ case AttributedType::attr_null_unspecified:
+ case AttributedType::attr_objc_gc:
+ case AttributedType::attr_objc_inert_unsafe_unretained:
+ case AttributedType::attr_objc_kindof:
+ case AttributedType::attr_objc_ownership:
+ case AttributedType::attr_ptr32:
+ case AttributedType::attr_ptr64:
+ case AttributedType::attr_sptr:
+ case AttributedType::attr_uptr:
+ llvm_unreachable("This attribute should have been handled already");
+#else
default: llvm_unreachable("This attribute should have been handled already");
+#endif
+
case AttributedType::attr_address_space:
OS << "address_space(";
//AC++: added #if for backward compatibility
@@ -1584,6 +1713,8 @@ void AdjustedTypePrinter::printAttributedAfter(const AttributedType *T,
break;
}
+//AC++: added #if
+#if CLANG_VERSION_NUMBER < VERSION_NUMBER_7_0_0
case AttributedType::attr_objc_gc: {
OS << "objc_gc(";
@@ -1613,6 +1744,7 @@ void AdjustedTypePrinter::printAttributedAfter(const AttributedType *T,
}
OS << ')';
break;
+#endif
//AC++: added #if
#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_5_0_0
@@ -1624,10 +1756,18 @@ void AdjustedTypePrinter::printAttributedAfter(const AttributedType *T,
// FIXME: When Sema learns to form this AttributedType, avoid printing the
// attribute again in printFunctionProtoAfter.
case AttributedType::attr_noreturn: OS << "noreturn"; break;
+//AC++: added #if
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_7_0_0
+ case AttributedType::attr_nocf_check: OS << "nocf_check"; break;
+#endif
case AttributedType::attr_cdecl: OS << "cdecl"; break;
case AttributedType::attr_fastcall: OS << "fastcall"; break;
case AttributedType::attr_stdcall: OS << "stdcall"; break;
+//AC++: added #if
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_6_0_0
+ case AttributedType::attr_swiftcall: OS << "swiftcall"; break;
+#endif
case AttributedType::attr_thiscall: OS << "thiscall"; break;
//AC++: added if
#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_3_6_2
@@ -1657,9 +1797,19 @@ void AdjustedTypePrinter::printAttributedAfter(const AttributedType *T,
case AttributedType::attr_pnaclcall: OS << "pnaclcall"; break;
#endif
case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break;
+//AC++: added #if for backward compatibility
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_6_0_0
+ case AttributedType::attr_preserve_most:
+ OS << "preserve_most";
+ break;
+ case AttributedType::attr_preserve_all:
+ OS << "preserve_all";
+ break;
+#endif
}
OS << "))";
}
+#endif // Clang 9.0.0 port in progress
}
void AdjustedTypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,
@@ -2082,7 +2232,7 @@ void AdjustedTypePrinter::adjusted_NamedDecl_printQualifiedName(const NamedDecl*
//AC++: do not collect contexts if we should not print qualifiers/nested name specifiers/contexts
if(!(absolute_qualified == TSEF_DISABLE)) {
- // Collect contexts.
+ // Collect named contexts.
while (Ctx) {
if(isa<LinkageSpecDecl>(Ctx)) {
// Decl specifying the linkage (e.g. extern "C" or extern "C" { }). This are not part of the qualified name
@@ -2528,4 +2678,5 @@ void AdjustedTypePrinter::adjusted_NestedNameSpecifier_print(const NestedNameSpe
OS << "::";
}
-//#endif
+
+#endif // CLANG_VERSION_NUMBER < VERSION_NUMBER_9_0_0
diff --git a/AspectC++/ClangAdjustedTypePrinter.h b/AspectC++/ClangAdjustedTypePrinter.h
index 8ba554d..8125f78 100644
--- a/AspectC++/ClangAdjustedTypePrinter.h
+++ b/AspectC++/ClangAdjustedTypePrinter.h
@@ -20,7 +20,8 @@
#ifndef __ClangAdjustedTypePrinter_h__
#define __ClangAdjustedTypePrinter_h__
#include "version.h"
-//#if CLANG_VERSION_NUMBER < VERSION_NUMBER_6_0_0
+#include "ClangTransformInfo.h"
+#if CLANG_VERSION_NUMBER < VERSION_NUMBER_7_0_0
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
@@ -34,17 +35,44 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
+#else
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <string>
+#endif
+
//AC++: commented out: using namespace clang;
//AC++: commented out: namespace {
-//#endif
-//AC++: enum added:
-enum TriStateEnableFeature {
- TSEF_ENABLE = true,
- TSEF_DISABLE = false,
- TSEF_DONOTCHANGE = 2,
-};
-//#if CLANG_VERSION_NUMBER < VERSION_NUMBER_6_0_0
+
//AC++: added "clang::" nested name specifier to every clang type
/// \brief RAII object that enables printing of the ARC __strong lifetime
@@ -181,5 +209,4 @@ enum TriStateEnableFeature {
//AC++: continuation in ClangAdjustedTypePrinter.cc
//AC++: Added include guard:
-//#endif
#endif // __ClangAdjustedTypePrinter_h__
diff --git a/AspectC++/ClangBinding.cc b/AspectC++/ClangBinding.cc
index 00fc0d4..4ddf90a 100644
--- a/AspectC++/ClangBinding.cc
+++ b/AspectC++/ClangBinding.cc
@@ -1,6 +1,7 @@
#include "clang/Basic/Version.h"
#if CLANG_VERSION_MAJOR == 3 && CLANG_VERSION_MINOR == 5 && CLANG_VERSION_PATCHLEVEL == 0
+#elif CLANG_VERSION_MAJOR == 3 && CLANG_VERSION_MINOR == 5 && CLANG_VERSION_PATCHLEVEL == 2
#elif CLANG_VERSION_MAJOR == 3 && CLANG_VERSION_MINOR == 6 && CLANG_VERSION_PATCHLEVEL == 2
#elif CLANG_VERSION_MAJOR == 3 && CLANG_VERSION_MINOR == 7 && CLANG_VERSION_PATCHLEVEL == 1
#elif CLANG_VERSION_MAJOR == 3 && CLANG_VERSION_MINOR == 8 && CLANG_VERSION_PATCHLEVEL == 0
@@ -10,10 +11,12 @@
#elif CLANG_VERSION_MAJOR == 4 && CLANG_VERSION_MINOR == 0 && CLANG_VERSION_PATCHLEVEL == 1
#elif CLANG_VERSION_MAJOR == 5 && CLANG_VERSION_MINOR == 0 && CLANG_VERSION_PATCHLEVEL == 0
#elif CLANG_VERSION_MAJOR == 5 && CLANG_VERSION_MINOR == 0 && CLANG_VERSION_PATCHLEVEL == 1
+#elif CLANG_VERSION_MAJOR == 5 && CLANG_VERSION_MINOR == 0 && CLANG_VERSION_PATCHLEVEL == 2
#elif CLANG_VERSION_MAJOR == 6 && CLANG_VERSION_MINOR == 0 && CLANG_VERSION_PATCHLEVEL == 0
#elif CLANG_VERSION_MAJOR == 6 && CLANG_VERSION_MINOR == 0 && CLANG_VERSION_PATCHLEVEL == 1
+#elif CLANG_VERSION_MAJOR == 9 && CLANG_VERSION_MINOR == 0 && CLANG_VERSION_PATCHLEVEL == 0
#else
-#warning "Invalid clang version used! Only 3.5.0, 3.6.2, 3.7.1, 3.8.0, 3.8.1, 3.9.1, 4.0.0, 4.0.1, 5.0.0, 5.0.1, 6.0.0, and 6.0.1 are supported by this code."
+#warning "Invalid clang version used! Only 3.5.0, 3.5.2, 3.6.2, 3.7.1, 3.8.0, 3.8.1, 3.9.1, 4.0.0, 4.0.1, 5.0.0, 5.0.1, 5.0.2, 6.0.0, 6.0.1, and 9.0.0 are supported by this code."
#endif
#include "ClangIntroSema.h"
@@ -87,7 +90,12 @@ GEN_SEMA_WRAPPER_WITH_RESULT(clang::Decl*, ActOnStartOfFunctionDef, _ZN5clang4Se
#endif
// wrapper for Sema::ActOnStartNamespaceDef
-#if FRONTEND_CLANG >= 38
+#if FRONTEND_CLANG >= 90
+GEN_SEMA_WRAPPER_WITH_RESULT(clang::Decl*, ActOnStartNamespaceDef, _ZN5clang4Sema22ActOnStartNamespaceDefEPNS_5ScopeENS_14SourceLocationES3_S3_PNS_14IdentifierInfoES3_RKNS_20ParsedAttributesViewERPNS_18UsingDirectiveDeclE, \
+ (clang::Sema &that, clang::Scope *S, clang::SourceLocation InlineLoc, clang::SourceLocation NamespaceLoc,
+ clang::SourceLocation IdentLoc, clang::IdentifierInfo *Ident, clang::SourceLocation LBrace, const clang::ParsedAttributesView &AttrList, clang::UsingDirectiveDecl * &UsingDecl), \
+ S, InlineLoc, NamespaceLoc, IdentLoc, Ident, LBrace, AttrList, UsingDecl)
+#elif FRONTEND_CLANG >= 38
GEN_SEMA_WRAPPER_WITH_RESULT(clang::Decl*, ActOnStartNamespaceDef, _ZN5clang4Sema22ActOnStartNamespaceDefEPNS_5ScopeENS_14SourceLocationES3_S3_PNS_14IdentifierInfoES3_PNS_13AttributeListERPNS_18UsingDirectiveDeclE, \
(clang::Sema &that, clang::Scope *S, clang::SourceLocation InlineLoc, clang::SourceLocation NamespaceLoc,
clang::SourceLocation IdentLoc, clang::IdentifierInfo *Ident, clang::SourceLocation LBrace, clang::AttributeList *AttrList, clang::UsingDirectiveDecl * &UsingDecl), \
@@ -100,7 +108,17 @@ GEN_SEMA_WRAPPER_WITH_RESULT(clang::Decl*, ActOnStartNamespaceDef, _ZN5clang4Sem
#endif
// wrapper for Decl *Sema::ActOnTag
-#if FRONTEND_CLANG >= 50
+#if FRONTEND_CLANG >= 90
+GEN_SEMA_WRAPPER_WITH_RESULT(clang::Decl*, ActOnTag, \
+ _ZN5clang4Sema8ActOnTagEPNS_5ScopeEjNS0_10TagUseKindENS_14SourceLocationERNS_12CXXScopeSpecEPNS_14IdentifierInfoES4_RKNS_20ParsedAttributesViewENS_15AccessSpecifierES4_N4llvm15MutableArrayRefIPNS_21TemplateParameterListEEERbSI_S4_bNS_12ActionResultINS_9OpaquePtrINS_8QualTypeEEELb0EEEbbPNS0_12SkipBodyInfoE, \
+ (clang::Sema &that, clang::Scope *S, unsigned TagSpec, clang::Sema::TagUseKind TUK, clang::SourceLocation KWLoc, clang::CXXScopeSpec &SS, \
+ clang::IdentifierInfo *Name, clang::SourceLocation NameLoc, const clang::ParsedAttributesView &Attr, clang::AccessSpecifier AS, \
+ clang::SourceLocation ModulePrivateLoc, clang::MultiTemplateParamsArg TemplateParameterLists, \
+ bool &OwnedDecl, bool &IsDependent, clang::SourceLocation ScopedEnumKWLoc, \
+ bool ScopedEnumUsesClassTag, clang::TypeResult UnderlyingType, bool IsTypeSpecifier, bool IsTemplateParamOrArg, clang::Sema::SkipBodyInfo *SkipBody), \
+ S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attr, AS, ModulePrivateLoc, TemplateParameterLists, \
+ OwnedDecl, IsDependent, ScopedEnumKWLoc, ScopedEnumUsesClassTag, UnderlyingType, IsTypeSpecifier, IsTemplateParamOrArg, SkipBody)
+#elif FRONTEND_CLANG >= 50
GEN_SEMA_WRAPPER_WITH_RESULT(clang::Decl*, ActOnTag, \
_ZN5clang4Sema8ActOnTagEPNS_5ScopeEjNS0_10TagUseKindENS_14SourceLocationERNS_12CXXScopeSpecEPNS_14IdentifierInfoES4_PNS_13AttributeListENS_15AccessSpecifierES4_N4llvm15MutableArrayRefIPNS_21TemplateParameterListEEERbSH_S4_bNS_12ActionResultINS_9OpaquePtrINS_8QualTypeEEELb0EEEbbPNS0_12SkipBodyInfoE, \
(clang::Sema &that, clang::Scope *S, unsigned TagSpec, clang::Sema::TagUseKind TUK, clang::SourceLocation KWLoc, clang::CXXScopeSpec &SS, \
@@ -143,11 +161,19 @@ GEN_SEMA_WRAPPER_WITH_RESULT(clang::Decl*, ActOnTag, \
#endif
// wrapper for Sema::ActOnFinishCXXMemberSpecification
+#if FRONTEND_CLANG >= 90
+GEN_SEMA_WRAPPER_NO_RESULT(ActOnFinishCXXMemberSpecification, \
+ _ZN5clang4Sema33ActOnFinishCXXMemberSpecificationEPNS_5ScopeENS_14SourceLocationEPNS_4DeclES3_S3_RKNS_20ParsedAttributesViewE, \
+ (clang::Sema &that, clang::Scope* S, clang::SourceLocation RLoc, Decl *TagDecl, \
+ clang::SourceLocation LBrac, clang::SourceLocation RBrac, const clang::ParsedAttributesView &AttrList), \
+ S, RLoc, TagDecl, LBrac, RBrac, AttrList)
+#else
GEN_SEMA_WRAPPER_NO_RESULT(ActOnFinishCXXMemberSpecification, \
_ZN5clang4Sema33ActOnFinishCXXMemberSpecificationEPNS_5ScopeENS_14SourceLocationEPNS_4DeclES3_S3_PNS_13AttributeListE, \
(clang::Sema &that, clang::Scope* S, clang::SourceLocation RLoc, Decl *TagDecl, \
clang::SourceLocation LBrac, clang::SourceLocation RBrac, clang::AttributeList *AttrList), \
S, RLoc, TagDecl, LBrac, RBrac, AttrList)
+#endif
// wrapper for Sema::ActOnEndOfTranslationUnit
GEN_SEMA_WRAPPER_NO_RESULT_NO_ARG(ActOnEndOfTranslationUnit, _ZN5clang4Sema25ActOnEndOfTranslationUnitEv)
@@ -183,9 +209,13 @@ GEN_SEMA_WRAPPER_WITH_RESULT(clang::Decl*, ActOnDeclarator, _ZN5clang4Sema15ActO
(clang::Sema &that, clang::Scope *S, clang::Declarator &D), S, D)
// wrapper for Sema::ProcessStmtAttributes
+#if FRONTEND_CLANG >= 90
+GEN_SEMA_WRAPPER_WITH_RESULT(clang::StmtResult, ProcessStmtAttributes, _ZN5clang4Sema21ProcessStmtAttributesEPNS_4StmtERKNS_20ParsedAttributesViewENS_11SourceRangeE, \
+ (clang::Sema &that, clang::Stmt *S, const clang::ParsedAttributesView &AttrList, clang::SourceRange Range), S, AttrList, Range)
+#else
GEN_SEMA_WRAPPER_WITH_RESULT(clang::StmtResult, ProcessStmtAttributes, _ZN5clang4Sema21ProcessStmtAttributesEPNS_4StmtEPNS_13AttributeListENS_11SourceRangeE, \
(clang::Sema &that, clang::Stmt *S, clang::AttributeList *AttrList, clang::SourceRange Range), S, AttrList, Range)
-
+#endif
// Special wrapper for Preprocessor::Lex
WeaverBase *macro_recorder = 0;
diff --git a/AspectC++/ClangBinding.h b/AspectC++/ClangBinding.h
index 6df1f61..3d33cdb 100644
--- a/AspectC++/ClangBinding.h
+++ b/AspectC++/ClangBinding.h
@@ -68,7 +68,12 @@ clang::Decl* RealActOnStartOfFunctionDef(clang::Sema &that, clang::Scope *S,
clang::Declarator &D);
#endif
-#if FRONTEND_CLANG >= 38
+#if FRONTEND_CLANG >= 90
+clang::Decl* RealActOnStartNamespaceDef (
+ clang::Sema &that, clang::Scope *S, clang::SourceLocation InlineLoc, clang::SourceLocation NamespaceLoc,
+ clang::SourceLocation IdentLoc, clang::IdentifierInfo *Ident, clang::SourceLocation LBrace,
+ const clang::ParsedAttributesView &AttrList, clang::UsingDirectiveDecl * &UsingDecl);
+#elif FRONTEND_CLANG >= 38
clang::Decl* RealActOnStartNamespaceDef (
clang::Sema &that, clang::Scope *S, clang::SourceLocation InlineLoc, clang::SourceLocation NamespaceLoc,
clang::SourceLocation IdentLoc, clang::IdentifierInfo *Ident, clang::SourceLocation LBrace,
@@ -80,7 +85,15 @@ clang::Decl* RealActOnStartNamespaceDef (
clang::AttributeList *AttrList);
#endif
-#if FRONTEND_CLANG >= 50
+#if FRONTEND_CLANG >= 90
+clang::Decl* RealActOnTag(
+ clang::Sema &that, clang::Scope *S, unsigned TagSpec, clang::Sema::TagUseKind TUK, clang::SourceLocation KWLoc, clang::CXXScopeSpec &SS,
+ clang::IdentifierInfo *Name, clang::SourceLocation NameLoc, const clang::ParsedAttributesView &Attr, clang::AccessSpecifier AS,
+ clang::SourceLocation ModulePrivateLoc, clang::MultiTemplateParamsArg TemplateParameterLists,
+ bool &OwnedDecl, bool &IsDependent, clang::SourceLocation ScopedEnumKWLoc,
+ bool ScopedEnumUsesClassTag, clang::TypeResult UnderlyingType, bool IsTypeSpecifier, bool IsTemplateParamOrArg,
+ clang::Sema::SkipBodyInfo *SkipBody);
+#elif FRONTEND_CLANG >= 50
clang::Decl* RealActOnTag(
clang::Sema &that, clang::Scope *S, unsigned TagSpec, clang::Sema::TagUseKind TUK, clang::SourceLocation KWLoc, clang::CXXScopeSpec &SS,
clang::IdentifierInfo *Name, clang::SourceLocation NameLoc, clang::AttributeList *Attr, clang::AccessSpecifier AS,
@@ -111,9 +124,15 @@ clang::Decl* RealActOnTag(
bool ScopedEnumUsesClassTag, clang::TypeResult UnderlyingType);
#endif
+#if FRONTEND_CLANG >= 90
+void RealActOnFinishCXXMemberSpecification (clang::Sema &that, clang::Scope* S,
+ clang::SourceLocation RLoc, clang::Decl *TagDecl, clang::SourceLocation LBrac,
+ clang::SourceLocation RBrac, const clang::ParsedAttributesView &AttrList);
+#else
void RealActOnFinishCXXMemberSpecification (clang::Sema &that, clang::Scope* S,
clang::SourceLocation RLoc, clang::Decl *TagDecl, clang::SourceLocation LBrac,
clang::SourceLocation RBrac, clang::AttributeList *AttrList);
+#endif
void RealActOnEndOfTranslationUnit(clang::Sema &that);
@@ -127,7 +146,11 @@ clang::NamedDecl* RealActOnCXXMemberDeclarator(clang::Sema &that, clang::Scope *
clang::Decl* RealActOnDeclarator(clang::Sema &that, clang::Scope *S, clang::Declarator &D);
+#if FRONTEND_CLANG >= 90
+clang::StmtResult RealProcessStmtAttributes(clang::Sema &that, clang::Stmt *S, const clang::ParsedAttributesView &AttrList, clang::SourceRange Range);
+#else
clang::StmtResult RealProcessStmtAttributes(clang::Sema &that, clang::Stmt *S, clang::AttributeList *AttrList, clang::SourceRange Range);
+#endif
// if macro_recorder points to a WeaverBase instance, each token that is
// return by clang::Preprocessor::Lex will also be passed to the recorder.
diff --git a/AspectC++/ClangFlowAnalysis.cc b/AspectC++/ClangFlowAnalysis.cc
index d779efb..cd2512f 100644
--- a/AspectC++/ClangFlowAnalysis.cc
+++ b/AspectC++/ClangFlowAnalysis.cc
@@ -230,9 +230,21 @@ static bool referencesSameObject(clang::Stmt* stmt1, clang::Stmt* stmt2) {
Stmt::child_iterator it1 = stmt1->child_begin();
Stmt::child_iterator it2 = stmt2->child_begin();
for( ; (it1 != stmt1->child_end()) && (it2 != stmt2->child_end()); it1++, it2++) {
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ Stmt *stmt1 = *it1;
+ Stmt *stmt2 = *it2;
+ if (dyn_cast_or_null<Expr>(stmt1))
+ stmt1 = (static_cast<Expr*>(stmt1))->IgnoreImplicit();
+ if (dyn_cast_or_null<Expr>(stmt2))
+ stmt2 = (static_cast<Expr*>(stmt2))->IgnoreImplicit();
+ if ( referencesSameObject(stmt1, stmt2) == false ) {
+ return false;
+ }
+#else
if ( referencesSameObject((*it1)->IgnoreImplicit(), (*it2)->IgnoreImplicit()) == false ) {
return false;
}
+#endif
}
return true;
}
@@ -616,7 +628,12 @@ bool TransferFunctions::VisitUnaryOperator(UnaryOperator* UO) {
unsigned int TransferFunctions::lookup_target_obj_lid(clang::Expr* expr) {
clang::Stmt* stmt = expr;
while (stmt) {
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ if (dyn_cast_or_null<Expr>(stmt))
+ stmt = (static_cast<Expr*>(stmt))->IgnoreImplicit();
+#else
stmt = stmt->IgnoreImplicit();
+#endif
if( clang::DeclRefExpr* DRF = dyn_cast<DeclRefExpr>(stmt) ) {
// non-member variable
clang::VarDecl* VD = dyn_cast_or_null<VarDecl>(DRF->getDecl());
@@ -719,8 +736,13 @@ unsigned int TransferFunctions::lookup_target_obj_lid(clang::Expr* expr) {
void TransferFunctions::update(clang::Stmt* stmt, unsigned int new_id) {
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ if (dyn_cast_or_null<Expr>(stmt))
+ stmt = (static_cast<Expr*>(stmt))->IgnoreImplicit();
+#else
stmt = stmt->IgnoreImplicit();
-
+#endif
+
if( clang::DeclRefExpr* DRF = dyn_cast<DeclRefExpr>(stmt) ) {
clang::VarDecl* VD = dyn_cast_or_null<VarDecl>(DRF->getDecl());
_dfvals.update_variable(VD, DRF, new_id);
diff --git a/AspectC++/ClangInclusionRewriter.cc b/AspectC++/ClangInclusionRewriter.cc
index a37c848..f10d278 100644
--- a/AspectC++/ClangInclusionRewriter.cc
+++ b/AspectC++/ClangInclusionRewriter.cc
@@ -75,7 +75,11 @@ private:
const FileEntry *File,
StringRef SearchPath,
StringRef RelativePath,
- const Module *Imported);
+ const Module *Imported
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ , SrcMgr::CharacteristicKind FileType
+#endif
+ );
void WriteLineInfo(const char *Filename, int Line,
SrcMgr::CharacteristicKind FileType,
StringRef EOL, StringRef Extra = StringRef());
@@ -168,7 +172,7 @@ void InclusionRewriter::FileChanged(SourceLocation Loc,
/// Called whenever an inclusion is skipped due to canonical header protection
/// macros.
void InclusionRewriter::FileSkipped(const FileEntry &/*ParentFile*/,
- const Token &/*FilenameTok*/,
+ const Token &FilenameTok,
SrcMgr::CharacteristicKind /*FileType*/) {
assert(LastInsertedFileChange != FileChanges.end() && "A file, that wasn't "
"found via an inclusion directive, was skipped");
@@ -189,7 +193,11 @@ void InclusionRewriter::InclusionDirective(SourceLocation HashLoc,
const FileEntry * /*File*/,
StringRef /*SearchPath*/,
StringRef /*RelativePath*/,
- const Module *Imported) {
+ const Module *Imported
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ , SrcMgr::CharacteristicKind FileType
+#endif
+ ) {
assert(LastInsertedFileChange == FileChanges.end() && "Another inclusion "
"directive was found before the previous one was processed");
std::pair<FileChangeMap::iterator, bool> p = FileChanges.insert(
@@ -397,6 +405,11 @@ bool InclusionRewriter::HandleHasInclude(
// , bool *IsMapped,
, nullptr
#endif // Clang 5.0.0
+// Clang >= 9.0.0 has another additional argument:
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ // , bool *IsFrameworkFound
+ , nullptr
+#endif // Clang 9.0.0
);
FileExists = File != 0;
return true;
diff --git a/AspectC++/ClangIntroParser.cc b/AspectC++/ClangIntroParser.cc
index f221aa7..a31d377 100644
--- a/AspectC++/ClangIntroParser.cc
+++ b/AspectC++/ClangIntroParser.cc
@@ -38,10 +38,14 @@ void ClangIntroParser::ParseCXXClassBody(Decl *TagDecl) {
if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||
Tok.is(tok::kw___if_not_exists))) {
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, AccessAttrs, CurAS);
+#else
ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS);
+#endif
continue;
}
-
+
// Check for extraneous top-level semicolon.
if (Tok.is(tok::semi)) {
ConsumeExtraSemi(InsideStruct, TagType);
@@ -120,17 +124,28 @@ void ClangIntroParser::ParseCXXClassBody(Decl *TagDecl) {
<< (CurAS == AS_protected);
}
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ if (Actions.ActOnAccessSpecifier(AS, ASLoc, EndLoc,
+ AccessAttrs)) {
+ // found another attribute than only annotations
+ AccessAttrs.clear();
+ }
+#else
if (Actions.ActOnAccessSpecifier(AS, ASLoc, EndLoc,
AccessAttrs.getList())) {
// found another attribute than only annotations
AccessAttrs.clear();
}
-
+#endif
continue;
}
// Parse all the comma separated declarators.
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ ParseCXXClassMemberDeclaration(CurAS, AccessAttrs);
+#else
ParseCXXClassMemberDeclaration(CurAS, AccessAttrs.getList());
+#endif
}
}
diff --git a/AspectC++/ClangIntroSema.cc b/AspectC++/ClangIntroSema.cc
index 4f39581..8108a4d 100644
--- a/AspectC++/ClangIntroSema.cc
+++ b/AspectC++/ClangIntroSema.cc
@@ -16,6 +16,9 @@
using namespace clang;
+#if FRONTEND_CLANG >= 90 // Clang 9.0.0 port in progress
+
+#else
// remove all attributes that have namespace "AC::" in its name from the
// attribute list 'in' and put them into 'hidden'
void hideACAttrs(clang::AttributeList * &in, clang::AttributeList *&hidden) {
@@ -97,6 +100,7 @@ clang::AttributedStmt* injectAttrs(clang::SourceLocation AttrLoc, clang::Attribu
clang::AttributedStmt *LS = clang::AttributedStmt::Create(context, AttrLoc, Attrs, SubStmt);
return LS;
}
+#endif // Clang 9.0.0 port
ClangIntroSema::ClangIntroSema(ClangIntroducer &introducer,
Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
@@ -152,7 +156,15 @@ void ClangIntroSema::ActOnBaseSpecifiers (Decl *ClassDecl,
}
#endif
-#if FRONTEND_CLANG >= 38
+#if FRONTEND_CLANG >= 90
+clang::Decl* ClangIntroSema::ActOnStartOfFunctionDef(
+ clang::Scope *S, clang::Declarator &D,
+ clang::MultiTemplateParamsArg TemplateParamLists,
+ clang::Sema::SkipBodyInfo *SkipBody) {
+ clang::Decl *decl = RealActOnStartOfFunctionDef(*this, S, D, TemplateParamLists, SkipBody);
+ return decl; // TODO Clang 9.0.0 port in progress
+}
+#elif FRONTEND_CLANG >= 38
clang::Decl* ClangIntroSema::ActOnStartOfFunctionDef(
clang::Scope *S, clang::Declarator &D,
clang::MultiTemplateParamsArg TemplateParamLists,
@@ -192,7 +204,24 @@ clang::Decl* ClangIntroSema::ActOnStartOfFunctionDef(
}
#endif
-#if FRONTEND_CLANG >= 38
+#if FRONTEND_CLANG >= 90
+clang::Decl* ClangIntroSema::ActOnStartNamespaceDef (
+ clang::Scope *S, clang::SourceLocation InlineLoc, clang::SourceLocation NamespaceLoc,
+ clang::SourceLocation IdentLoc, clang::IdentifierInfo *Ident, clang::SourceLocation LBrace,
+ const clang::ParsedAttributesView &AttrList, clang::UsingDirectiveDecl * &UsingDecl) {
+ std::cout << "ActOnNamespaceDef! TO BE FIXED" << std::endl;
+ // clang::AttributeList *hidden_attrs = 0;
+ // hideACAttrs (AttrList, hidden_attrs);
+ clang::Decl *decl = RealActOnStartNamespaceDef(*this, S, InlineLoc, NamespaceLoc, IdentLoc, Ident, LBrace, AttrList, UsingDecl);
+ // injectAttrs(decl, this->getASTContext(), hidden_attrs);
+ // decl->dump();
+ // clang::NamespaceDecl *nsdecl = clang::dyn_cast<clang::NamespaceDecl>(decl);
+ // if (nsdecl)
+ // _introducer->namespace_start(nsdecl);
+ // restoreACAttrs(AttrList, hidden_attrs);
+ return decl;
+}
+#elif FRONTEND_CLANG >= 38
clang::Decl* ClangIntroSema::ActOnStartNamespaceDef (
clang::Scope *S, clang::SourceLocation InlineLoc, clang::SourceLocation NamespaceLoc,
clang::SourceLocation IdentLoc, clang::IdentifierInfo *Ident, clang::SourceLocation LBrace,
@@ -228,7 +257,27 @@ clang::Decl* ClangIntroSema::ActOnStartNamespaceDef (
}
#endif
-#if FRONTEND_CLANG >= 50
+#if FRONTEND_CLANG >= 90
+clang::Decl* ClangIntroSema::ActOnTag (
+ clang::Scope *S, unsigned TagSpec, clang::Sema::TagUseKind TUK, clang::SourceLocation KWLoc, clang::CXXScopeSpec &SS,
+ clang::IdentifierInfo *Name, clang::SourceLocation NameLoc, const clang::ParsedAttributesView &Attr, clang::AccessSpecifier AS,
+ clang::SourceLocation ModulePrivateLoc, clang::MultiTemplateParamsArg TemplateParameterLists,
+ bool &OwnedDecl, bool &IsDependent, clang::SourceLocation ScopedEnumKWLoc,
+ bool ScopedEnumUsesClassTag, clang::TypeResult UnderlyingType, bool IsTypeSpecifier, bool IsTemplateParamOrArg, clang::Sema::SkipBodyInfo *SkipBody) {
+ std::cout << "ActOnTag! TO BE FIXED" << std::endl;
+ // clang::AttributeList *hidden_attrs = 0;
+ // hideACAttrs (Attr, hidden_attrs);
+ clang::Decl *decl = RealActOnTag(*this, S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attr, AS, ModulePrivateLoc, TemplateParameterLists,
+ OwnedDecl, IsDependent, ScopedEnumKWLoc, ScopedEnumUsesClassTag, UnderlyingType, IsTypeSpecifier, IsTemplateParamOrArg, SkipBody);
+ // injectAttrs(decl, this->getASTContext(), hidden_attrs);
+// decl->dump();
+ // clang::TagDecl *tdecl = clang::dyn_cast<clang::TagDecl>(decl);
+ // if (tdecl)
+ // _introducer->tag_start(tdecl);
+ // restoreACAttrs(Attr, hidden_attrs);
+ return decl;
+}
+#elif FRONTEND_CLANG >= 50
clang::Decl* ClangIntroSema::ActOnTag (
clang::Scope *S, unsigned TagSpec, clang::Sema::TagUseKind TUK, clang::SourceLocation KWLoc, clang::CXXScopeSpec &SS,
clang::IdentifierInfo *Name, clang::SourceLocation NameLoc, clang::AttributeList *Attr, clang::AccessSpecifier AS,
@@ -310,6 +359,15 @@ clang::Decl* ClangIntroSema::ActOnTag (
}
#endif
+#if FRONTEND_CLANG >= 90
+void ClangIntroSema::ActOnFinishCXXMemberSpecification (Scope* S,
+ SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac,
+ SourceLocation RBrac, const clang::ParsedAttributesView &AttrList) {
+ _introducer->class_end (TagDecl, RBrac);
+ RealActOnFinishCXXMemberSpecification(*this, S, RLoc, TagDecl, LBrac, RBrac,
+ AttrList);
+}
+#else
void ClangIntroSema::ActOnFinishCXXMemberSpecification (Scope* S,
SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac,
SourceLocation RBrac, AttributeList *AttrList) {
@@ -317,6 +375,7 @@ void ClangIntroSema::ActOnFinishCXXMemberSpecification (Scope* S,
RealActOnFinishCXXMemberSpecification(*this, S, RLoc, TagDecl, LBrac, RBrac,
AttrList);
}
+#endif
void ClangIntroSema::ActOnEndOfTranslationUnit () {
if (_nested_tu_end == 0) {
@@ -353,14 +412,20 @@ clang::NamedDecl *ClangIntroSema::ActOnCXXMemberDeclarator(clang::Scope *S, clan
clang::Expr *BitfieldWidth, const clang::VirtSpecifiers &VS,
clang::InClassInitStyle InitStyle){
// std::cout << "ActOnCXXMemberDeclarator!" << std::endl;
+#if FRONTEND_CLANG >= 90
+#else
clang::AttributeList *declspec_attrs = 0, *declarator_attrs = 0;
hideACAttrs (D.getMutableDeclSpec().getAttributes().getListRef(), declspec_attrs);
hideACAttrs (D.getAttrListRef(), declarator_attrs);
+#endif
clang::NamedDecl *ndecl = RealActOnCXXMemberDeclarator(*this, S, AS, D, TemplateParameterLists,
BitfieldWidth, VS, InitStyle);
// std::cout << " name " << ndecl->getNameAsString() << std::endl;
+#if FRONTEND_CLANG >= 90
+#else
injectAttrs(ndecl, this->getASTContext(), declspec_attrs);
injectAttrs(ndecl, this->getASTContext(), declarator_attrs);
+#endif
clang::DeclaratorDecl *ddecl = clang::dyn_cast<clang::DeclaratorDecl>(ndecl);
clang::FunctionDecl *fdecl = clang::dyn_cast<clang::FunctionDecl>(ndecl);
if (fdecl)
@@ -368,27 +433,39 @@ clang::NamedDecl *ClangIntroSema::ActOnCXXMemberDeclarator(clang::Scope *S, clan
else if (ddecl)
_introducer->declarator_start(ddecl);
// ndecl->dump();
+#if FRONTEND_CLANG >= 90
+#else
restoreACAttrs(D.getMutableDeclSpec().getAttributes().getListRef(), declspec_attrs);
restoreACAttrs(D.getAttrListRef(), declarator_attrs);
+#endif
return ndecl;
}
clang::Decl *ClangIntroSema::ActOnDeclarator(clang::Scope *S, clang::Declarator &D) {
// std::cout << "ActOnDeclarator!" << std::endl;
+#if FRONTEND_CLANG >= 90
+#else
clang::AttributeList *declspec_attrs = 0, *declarator_attrs = 0;
hideACAttrs (D.getMutableDeclSpec().getAttributes().getListRef(), declspec_attrs);
hideACAttrs (D.getAttrListRef(), declarator_attrs);
+#endif
clang::Decl *decl = RealActOnDeclarator(*this, S, D);
+#if FRONTEND_CLANG >= 90
+#else
injectAttrs(decl, this->getASTContext(), declspec_attrs);
injectAttrs(decl, this->getASTContext(), declarator_attrs);
+#endif
clang::DeclaratorDecl *ddecl = clang::dyn_cast<clang::DeclaratorDecl>(decl);
clang::FunctionDecl *fdecl = clang::dyn_cast<clang::FunctionDecl>(decl);
if (fdecl) // must be check first, because a FunctionDecl is also a DeclaratorDecl
_introducer->function_start(fdecl);
else if (ddecl)
_introducer->declarator_start(ddecl);
+#if FRONTEND_CLANG >= 90
+#else
restoreACAttrs(D.getMutableDeclSpec().getAttributes().getListRef(), declspec_attrs);
restoreACAttrs(D.getAttrListRef(), declarator_attrs);
+#endif
return decl;
}
@@ -399,8 +476,15 @@ clang::Decl *ClangIntroSema::ActOnDeclarator(clang::Scope *S, clang::Declarator
* We then have to inject our hidden attributes into whatever statement we get back.
* After that, we restore the attributes into the AttrList, although this may be unnecessary (but just to be safe).
*/
+#if FRONTEND_CLANG >= 90
+clang::StmtResult ClangIntroSema::ProcessStmtAttributes(clang::Stmt *S, const clang::ParsedAttributesView &AttrList,
+ clang::SourceRange Range) {
+ // TODO: fix this code; Clang 9.0.0 port in progress
+ return RealProcessStmtAttributes(*this, S, AttrList, Range);
+}
+#else
clang::StmtResult ClangIntroSema::ProcessStmtAttributes(clang::Stmt *S, clang::AttributeList *AttrList,
- clang::SourceRange Range) {
+ clang::SourceRange Range) {
clang::AttributeList *stmt_attrs = 0;
hideACAttrs (AttrList, stmt_attrs);
clang::StmtResult stmtResult = RealProcessStmtAttributes(*this, S, AttrList, Range);
@@ -410,3 +494,4 @@ clang::StmtResult ClangIntroSema::ProcessStmtAttributes(clang::Stmt *S, clang::A
restoreACAttrs(AttrList, stmt_attrs);
return attributedStmt;
}
+#endif
diff --git a/AspectC++/ClangIntroSema.h b/AspectC++/ClangIntroSema.h
index 193134a..e8a2789 100644
--- a/AspectC++/ClangIntroSema.h
+++ b/AspectC++/ClangIntroSema.h
@@ -44,7 +44,12 @@ public:
clang::Scope *S, clang::Declarator &D);
#endif
-#if FRONTEND_CLANG >= 38
+#if FRONTEND_CLANG >= 90
+ clang::Decl* ActOnStartNamespaceDef (
+ clang::Scope *S, clang::SourceLocation InlineLoc, clang::SourceLocation NamespaceLoc,
+ clang::SourceLocation IdentLoc, clang::IdentifierInfo *Ident, clang::SourceLocation LBrace,
+ const clang::ParsedAttributesView &AttrList, clang::UsingDirectiveDecl * &UsingDecl);
+#elif FRONTEND_CLANG >= 38
clang::Decl* ActOnStartNamespaceDef (
clang::Scope *S, clang::SourceLocation InlineLoc, clang::SourceLocation NamespaceLoc,
clang::SourceLocation IdentLoc, clang::IdentifierInfo *Ident, clang::SourceLocation LBrace,
@@ -56,7 +61,15 @@ public:
clang::AttributeList *AttrList);
#endif
-#if FRONTEND_CLANG >= 50
+#if FRONTEND_CLANG >= 90
+clang::Decl* ActOnTag (
+ clang::Scope *S, unsigned TagSpec, clang::Sema::TagUseKind TUK, clang::SourceLocation KWLoc, clang::CXXScopeSpec &SS,
+ clang::IdentifierInfo *Name, clang::SourceLocation NameLoc, const clang::ParsedAttributesView &Attr, clang::AccessSpecifier AS,
+ clang::SourceLocation ModulePrivateLoc, clang::MultiTemplateParamsArg TemplateParameterLists,
+ bool &OwnedDecl, bool &IsDependent, clang::SourceLocation ScopedEnumKWLoc,
+ bool ScopedEnumUsesClassTag, clang::TypeResult UnderlyingType, bool IsTypeSpecifier, bool IsTemplateParamOrArg,
+ clang::Sema::SkipBodyInfo *SkipBody);
+#elif FRONTEND_CLANG >= 50
clang::Decl* ActOnTag (
clang::Scope *S, unsigned TagSpec, clang::Sema::TagUseKind TUK, clang::SourceLocation KWLoc, clang::CXXScopeSpec &SS,
clang::IdentifierInfo *Name, clang::SourceLocation NameLoc, clang::AttributeList *Attr, clang::AccessSpecifier AS,
@@ -87,10 +100,16 @@ clang::Decl* ActOnTag (
bool ScopedEnumUsesClassTag, clang::TypeResult UnderlyingType);
#endif
+#if FRONTEND_CLANG >= 90
void ActOnFinishCXXMemberSpecification (clang::Scope* S,
clang::SourceLocation RLoc, clang::Decl *TagDecl, clang::SourceLocation LBrac,
+ clang::SourceLocation RBrac, const clang::ParsedAttributesView &AttrList);
+#else
+ void ActOnFinishCXXMemberSpecification (clang::Scope* S,
+ clang::SourceLocation RLoc, clang::Decl *TagDecl, clang::SourceLocation LBrac,
clang::SourceLocation RBrac, clang::AttributeList *AttrList);
-
+#endif
+
void ActOnEndOfTranslationUnit ();
bool canSkipFunctionBody(clang::Decl *FctDecl);
@@ -102,8 +121,11 @@ clang::Decl* ActOnTag (
clang::Decl *ActOnDeclarator(clang::Scope *S, clang::Declarator &D);
+#if FRONTEND_CLANG >= 90
+ clang::StmtResult ProcessStmtAttributes(clang::Stmt *S, const clang::ParsedAttributesView &AttrList, clang::SourceRange Range);
+#else
clang::StmtResult ProcessStmtAttributes(clang::Stmt *S, clang::AttributeList *AttrList, clang::SourceRange Range);
-
+#endif
};
#endif // __ClangIntroSema_h__
diff --git a/AspectC++/ClangIntroducer.cc b/AspectC++/ClangIntroducer.cc
index 4c6bfa2..06e8028 100644
--- a/AspectC++/ClangIntroducer.cc
+++ b/AspectC++/ClangIntroducer.cc
@@ -349,6 +349,7 @@ std::string ClangIntroducer::insert_introspection_code(clang::CXXRecordDecl *cd,
// generate member_name => the name of attribute i
unit << "static const char *name () { return \"" << *dd << "\"; }\n";
unit << " };\n";
+ unit << " typedef Member<" << e << "> Member_" << dd->getName() << ";\n";
e++;
}
unit << " enum { MEMBERS = " << e << " };\n";
@@ -390,6 +391,8 @@ std::string ClangIntroducer::insert_introspection_code(clang::CXXRecordDecl *cd,
unit << " enum { DESTRUCTORS = " << destructors << " };\n";
unit << " };\n";
+ if (precedence == -1)
+ unit << " typedef __TI __TI_" << cd->getName() << ";\n";
#if 0
// paste a #line directive
LineDirectiveMgr &lmgr = _code_weaver.line_directive_mgr ();
@@ -615,7 +618,9 @@ void ClangIntroducer::parse (clang::Parser *parser, const std::string &source_co
int pos = 0;
for (list<clang::Token>::const_iterator i = tokens.begin(); i != tokens.end(); ++i)
input[pos++] = *i;
-#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_3_9_1
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ PP.EnterTokenStream(std::move(input), tokens.size(), true, false);
+#elif CLANG_VERSION_NUMBER >= VERSION_NUMBER_3_9_1
PP.EnterTokenStream(std::move(input), tokens.size(), true);
#else
PP.EnterTokenStream(input, tokens.size(), true, true);
@@ -635,8 +640,11 @@ void ClangIntroducer::class_end (clang::Decl *decl, clang::SourceLocation rbrac)
bool needs_introspection = _conf.introspection(); // --introspection given?
if (td) {
- if (td->getName () == "__TI" || td->getName ().startswith("__TJP"))
- return;
+ for (clang::TagDecl* cur = td; cur != 0; cur = llvm::dyn_cast_or_null<clang::TagDecl>(cur->getParent())) {
+ if (cur->getName () == "__TI" || cur->getName ().startswith("__TJP"))
+ return;
+ if (cur != td) break; // check one level of nesting only: skip loop after 2nd iteration
+ }
update_base_classes (decl);
@@ -986,7 +994,7 @@ void ClangIntroducer::handle_includes(set<ACFileID> &units,
_code_weaver.close_namespace (inc, inscls);
// inspos should be infront of the class
- clang::SourceLocation inspos = inscls->getLocStart();
+ clang::SourceLocation inspos = CLANG_GET_LOC_START(inscls);
// This is what gets parsed. We don't care about namespaces here.
ostringstream includes;
@@ -1357,14 +1365,14 @@ void ClangIntroducer::tag_start (clang::TagDecl *decl) {
// check and register attributes in the project model
// cout << "tag_start " << decl->getQualifiedNameAsString() << endl;
if (decl->hasAttrs())
- inject_attribute_check(decl->getLocStart(), decl->getAttrs(), decl->getLexicalDeclContext());
+ inject_attribute_check(CLANG_GET_LOC_START(decl), decl->getAttrs(), decl->getLexicalDeclContext());
}
void ClangIntroducer::namespace_start (clang::NamespaceDecl *decl) {
// check and register attributes in the project model
// cout << "namespace_start " << decl->getQualifiedNameAsString() << endl;
if (decl->hasAttrs())
- inject_attribute_check(decl->getLocStart(), decl->getAttrs(), decl->getLexicalDeclContext());
+ inject_attribute_check(CLANG_GET_LOC_START(decl), decl->getAttrs(), decl->getLexicalDeclContext());
}
void ClangIntroducer::function_start (clang::FunctionDecl *decl) {
@@ -1381,18 +1389,18 @@ void ClangIntroducer::function_start (clang::FunctionDecl *decl) {
TransformInfo::replace_in_string(def, " __ac_attr1_", " __ac_attr_");
// parse code on-the-fly in forced C++ 11 mode and in the current lexical context
- parse(_parser, def, decl->getLocStart(), decl->getLexicalDeclContext(), true);
+ parse(_parser, def, CLANG_GET_LOC_START(decl), decl->getLexicalDeclContext(), true);
// Delete the function declaration from the code the back-end compiler will see
// FIXME: using the current parser token here is a hack! We assume that it is the
// semi colon.
- _code_weaver.kill (_code_weaver.weave_pos(decl->getLocStart(), WeavePos::WP_BEFORE),
+ _code_weaver.kill (_code_weaver.weave_pos(CLANG_GET_LOC_START(decl), WeavePos::WP_BEFORE),
_code_weaver.weave_pos(_parser->getCurToken().getEndLoc(), WeavePos::WP_AFTER));
}
else {
// check and register attributes in the project model
if (decl->hasAttrs())
- inject_attribute_check(decl->getLocStart(), decl->getAttrs(), decl->getLexicalDeclContext());
+ inject_attribute_check(CLANG_GET_LOC_START(decl), decl->getAttrs(), decl->getLexicalDeclContext());
}
}
@@ -1400,7 +1408,7 @@ void ClangIntroducer::declarator_start (clang::DeclaratorDecl *decl) {
// check and register attributes in the project model
// cout << "declarator_start " << decl->getQualifiedNameAsString() << endl;
if (decl->hasAttrs())
- inject_attribute_check(decl->getLocStart(), decl->getAttrs(), decl->getLexicalDeclContext());
+ inject_attribute_check(CLANG_GET_LOC_START(decl), decl->getAttrs(), decl->getLexicalDeclContext());
}
void ClangIntroducer::attributed_stmt_start (clang::AttributedStmt *stmt) {
@@ -1409,6 +1417,6 @@ void ClangIntroducer::attributed_stmt_start (clang::AttributedStmt *stmt) {
clang::AttrVec attrs;
for (const clang::Attr *attr : stmt->getAttrs())
attrs.push_back((clang::Attr*)attr);
- inject_attribute_check(stmt->getLocStart(), attrs, _ci->getSema().CurContext);
+ inject_attribute_check(CLANG_GET_LOC_START(stmt), attrs, _ci->getSema().CurContext);
}
diff --git a/AspectC++/ClangModelBuilder.cc b/AspectC++/ClangModelBuilder.cc
index 7828c2a..5c25036 100644
--- a/AspectC++/ClangModelBuilder.cc
+++ b/AspectC++/ClangModelBuilder.cc
@@ -1192,7 +1192,7 @@ TU_Builtin* ClangModelBuilder::register_builtin_operator_call(clang::Expr* built
model_operator_call->origin(lexical_parent_decl);
// Add the source-location:
- add_source_loc(model_operator_call, built_in_operator->getLocStart(), built_in_operator->getLocEnd(), SLK_NONE);
+ add_source_loc(model_operator_call, CLANG_GET_LOC_START(built_in_operator), CLANG_GET_LOC_END(built_in_operator), SLK_NONE);
// Insert the operator-call into the model as children of the lexical-model-parent-node:
if (lexical_parent_function_decl && stmt)
@@ -1238,7 +1238,7 @@ ACM_Access *ClangModelBuilder::register_call (clang::FunctionDecl *called,
else {
lexical = register_variable (vd_caller);
if (!lexical) {
- _err << Puma::sev_warning << call_node->getLocStart ()
+ _err << Puma::sev_warning << CLANG_GET_LOC_START(call_node)
<< "location of function call invalid" << Puma::endMessage;
return 0;
}
@@ -1575,12 +1575,12 @@ void ClangModelBuilder::add_source_loc (ACM_Any *name, ClangToken token, ClangTo
void ClangModelBuilder::add_source_loc (ACM_Any *name, clang::Decl *tree,
SourceLocKind kind) {
- add_source_loc(name, tree->getLocStart(), tree->getLocEnd(), kind);
+ add_source_loc(name, CLANG_GET_LOC_START(tree), CLANG_GET_LOC_END(tree), kind);
}
void ClangModelBuilder::add_source_loc (ACM_Any *name, clang::Stmt *tree,
SourceLocKind kind) {
- add_source_loc(name, tree->getLocStart(), tree->getLocEnd(), kind);
+ add_source_loc(name, CLANG_GET_LOC_START(tree), CLANG_GET_LOC_END(tree), kind);
}
void ClangModelBuilder::add_source_loc(ACM_Any *name, clang::SourceLocation location,
diff --git a/AspectC++/ClangSyntacticContext.h b/AspectC++/ClangSyntacticContext.h
index 902297c..7a5252f 100644
--- a/AspectC++/ClangSyntacticContext.h
+++ b/AspectC++/ClangSyntacticContext.h
@@ -115,13 +115,13 @@ public:
// First case: this is a call in a variable declaration:
const clang::VarDecl *vd = clang::dyn_cast<clang::VarDecl>(_decl);
if (vd)
- return wb.weave_pos(vd->getLocStart (), WeavePos::WP_BEFORE);
+ return wb.weave_pos(CLANG_GET_LOC_START(vd), WeavePos::WP_BEFORE);
// Second case: a function ...
- clang::SourceLocation loc = llvm::cast<clang::FunctionDecl>(_decl)->getLocStart();
+ clang::SourceLocation loc = CLANG_GET_LOC_START(llvm::cast<clang::FunctionDecl>(_decl));
const clang::LinkageSpecDecl *lsd =
llvm::dyn_cast<clang::LinkageSpecDecl>(llvm::cast<clang::FunctionDecl>(_decl)->getDeclContext ());
if (lsd && !lsd->hasBraces ())
- loc = lsd->getLocStart ();
+ loc = CLANG_GET_LOC_START(lsd);
if (_decl->hasAttrs()) {
clang::SourceManager &source_manager = wb.getRewriter ().getSourceMgr();
@@ -139,22 +139,22 @@ public:
}
const WeavePos &fct_body_start_pos (WeaverBase &wb) const {
- clang::SourceLocation loc = llvm::cast<clang::FunctionDecl>(_decl)->getBody()->getLocStart();
+ clang::SourceLocation loc = CLANG_GET_LOC_START(llvm::cast<clang::FunctionDecl>(_decl)->getBody());
return wb.weave_pos(loc, WeavePos::WP_BEFORE);
}
const WeavePos &fct_body_end_pos (WeaverBase &wb) const {
- clang::SourceLocation loc = llvm::cast<clang::FunctionDecl>(_decl)->getLocEnd();
+ clang::SourceLocation loc = CLANG_GET_LOC_END(llvm::cast<clang::FunctionDecl>(_decl));
return wb.weave_pos(loc, WeavePos::WP_BEFORE);
}
const WeavePos &objdecl_start_pos (WeaverBase &wb) const {
- clang::SourceLocation loc = _decl->getLocStart();
+ clang::SourceLocation loc = CLANG_GET_LOC_START(_decl);
return wb.weave_pos(loc, WeavePos::WP_BEFORE);
}
const WeavePos &objdecl_end_pos (WeaverBase &wb) const {
- clang::SourceLocation loc = _decl->getLocEnd();
+ clang::SourceLocation loc = CLANG_GET_LOC_END(_decl);
if (llvm::isa<clang::FieldDecl>(_decl)) {
const clang::LangOptions &options = wb.getRewriter ().getLangOpts ();
clang::SourceManager &source_manager = wb.getRewriter ().getSourceMgr();
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
diff --git a/AspectC++/ClangWeaverBase.cc b/AspectC++/ClangWeaverBase.cc
index 068ed4a..ab8eb04 100644
--- a/AspectC++/ClangWeaverBase.cc
+++ b/AspectC++/ClangWeaverBase.cc
@@ -320,7 +320,9 @@ void WeaverBase::lex_and_filter_attr(clang::Preprocessor &PP, clang::Token &resu
int pos = 0;
for (list<clang::Token>::const_iterator i = reinsert_tokens.begin(); i != reinsert_tokens.end(); ++i)
input[pos++] = *i;
-#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_3_9_1
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ PP.EnterTokenStream(std::move(input), reinsert_tokens.size(), true, false);
+#elif CLANG_VERSION_NUMBER >= VERSION_NUMBER_3_9_1
PP.EnterTokenStream(std::move(input), reinsert_tokens.size(), true);
#else
PP.EnterTokenStream(input, reinsert_tokens.size(), true, true);
@@ -472,8 +474,14 @@ void WeaverBase::commit_kill (clang::SourceLocation from, clang::SourceLocation
_rewriter->RemoveText(clang::CharSourceRange::getCharRange(loc1, macro_end));
clang::SourceLocation somewhere_inside = macro_info->second._somewhere_inside;
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ clang::CharSourceRange source_range = SM.getExpansionRange(somewhere_inside);
+ std::pair<clang::SourceLocation, clang::SourceLocation> range =
+ std::pair<clang::SourceLocation, clang::SourceLocation> (source_range.getBegin(), source_range.getEnd());
+#else
std::pair<clang::SourceLocation, clang::SourceLocation> range =
SM.getExpansionRange(somewhere_inside);
+#endif
unsigned len = _rewriter->getRangeSize(clang::SourceRange(range.second, range.second));
_rewriter->RemoveText(clang::CharSourceRange::getCharRange(
range.second.getLocWithOffset(len), loc2), opts);
@@ -488,8 +496,14 @@ void WeaverBase::commit_kill (clang::SourceLocation from, clang::SourceLocation
_rewriter->RemoveText(clang::CharSourceRange::getCharRange(macro_start, loc2));
clang::SourceLocation somewhere_inside = macro_info->second._somewhere_inside;
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ clang::CharSourceRange source_range = SM.getExpansionRange(somewhere_inside);
+ std::pair<clang::SourceLocation, clang::SourceLocation> range =
+ std::pair<clang::SourceLocation, clang::SourceLocation> (source_range.getBegin(), source_range.getEnd());
+#else
std::pair<clang::SourceLocation, clang::SourceLocation> range =
SM.getExpansionRange(somewhere_inside);
+#endif
_rewriter->RemoveText(clang::CharSourceRange::getCharRange(
loc1, range.first), opts);
}
@@ -518,13 +532,25 @@ void WeaverBase::commit_kill (clang::SourceLocation from, clang::SourceLocation
// remove from first macro expansion end to second macro expansion begin
clang::SourceLocation somewhere_inside1 = macro_info1->second._somewhere_inside;
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ clang::CharSourceRange source_range1 = SM.getExpansionRange(somewhere_inside1);
+ std::pair<clang::SourceLocation, clang::SourceLocation> range1 =
+ std::pair<clang::SourceLocation, clang::SourceLocation> (source_range1.getBegin(), source_range1.getEnd());
+#else
std::pair<clang::SourceLocation, clang::SourceLocation> range1 =
SM.getExpansionRange(somewhere_inside1);
+#endif
unsigned len = _rewriter->getRangeSize(clang::SourceRange(range1.second, range1.second));
clang::SourceLocation somewhere_inside2 = macro_info2->second._somewhere_inside;
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ clang::CharSourceRange source_range2 = SM.getExpansionRange(somewhere_inside2);
+ std::pair<clang::SourceLocation, clang::SourceLocation> range2 =
+ std::pair<clang::SourceLocation, clang::SourceLocation> (source_range2.getBegin(), source_range2.getEnd());
+#else
std::pair<clang::SourceLocation, clang::SourceLocation> range2 =
SM.getExpansionRange(somewhere_inside2);
+#endif
_rewriter->RemoveText(clang::CharSourceRange::getCharRange(
range1.second.getLocWithOffset(len), range2.first), opts);
@@ -623,8 +649,14 @@ void WeaverBase::resolve_macros() {
// cout << mm_iter->second._expanded_macro_text << endl;
// expand macro
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+ clang::CharSourceRange source_range = SM.getExpansionRange(somewhere_inside);
+ std::pair<clang::SourceLocation, clang::SourceLocation> range =
+ std::pair<clang::SourceLocation, clang::SourceLocation> (source_range.getBegin(), source_range.getEnd());
+#else
std::pair<clang::SourceLocation, clang::SourceLocation> range =
SM.getExpansionRange(somewhere_inside);
+#endif
const clang::RewriteBuffer *RB = _rewriter->getRewriteBufferFor(fid);
if (!RB) {
cout << "fatal: Rewrite buffer not found" << endl;
diff --git a/AspectC++/CodeWeaver.cc b/AspectC++/CodeWeaver.cc
index 6d9a374..4d9c85a 100644
--- a/AspectC++/CodeWeaver.cc
+++ b/AspectC++/CodeWeaver.cc
@@ -2655,7 +2655,7 @@ void CodeWeaver::expand_arrow_operator_chain(TI_CommonCall &ti, const WeavePos &
return;
clang::Expr *expr = ti.target_expr();
while (true) {
- expr = expr->IgnoreImpCasts();
+ expr = expr->IgnoreImplicit();
// check if this an unseen operator->() call
clang::CXXOperatorCallExpr *call_expr = clang::dyn_cast_or_null<clang::CXXOperatorCallExpr>(expr);
@@ -3621,11 +3621,11 @@ void CodeWeaver::rename(const clang::ParmVarDecl *arg, const string &new_name) {
// name.
// ... we would like to use this ...
- // replace(weave_pos(arg->getLocStart(), WeavePos::WP_BEFORE),
- // get_pos_after_loc(arg->getLocEnd()), os.str());
- // ... but the result of getLocEnd with the current Clang version is nonsense
+ // replace(weave_pos(arg->getBeginLoc(), WeavePos::WP_BEFORE),
+ // get_pos_after_loc(arg->getEndLoc()), os.str());
+ // ... but the result of getEndLoc with the current Clang version is nonsense
// workaround:
- replace(weave_pos(arg->getLocStart(), WeavePos::WP_BEFORE),
+ replace(weave_pos(CLANG_GET_LOC_START(arg), WeavePos::WP_BEFORE),
get_pos_after_loc(arg->getTypeSourceInfo()->getTypeLoc().getSourceRange().getEnd()),
os.str ());
} else {
@@ -3633,8 +3633,8 @@ void CodeWeaver::rename(const clang::ParmVarDecl *arg, const string &new_name) {
// of the default parameter. Then insert the new type and argument. Since we
// kill the equals sign, generate a new one.
os << " = ";
- replace(weave_pos(arg->getLocStart(), WeavePos::WP_BEFORE),
- weave_pos(arg->getInit()->getLocStart(), WeavePos::WP_AFTER),
+ replace(weave_pos(CLANG_GET_LOC_START(arg), WeavePos::WP_BEFORE),
+ weave_pos(CLANG_GET_LOC_START(arg->getInit()), WeavePos::WP_AFTER),
os.str());
}
}
diff --git a/AspectC++/Makefile b/AspectC++/Makefile
index 44bf49a..4064448 100644
--- a/AspectC++/Makefile
+++ b/AspectC++/Makefile
@@ -64,6 +64,10 @@ LDFLAGS += $(LIBXML2_LIB)
ifneq ($(FRONTEND),Puma)
ifneq ($(_TARGET),macosx_x86_64)
LDFLAGS += -lclangRewriteFrontend -lclangRewrite -lclangFrontend -lclangSerialization -lclangDriver -lclangParse -lclangSema -lclangAnalysis -lclangEdit -lclangAST -lclangLex -lclangBasic -lLLVMAsmParser -lLLVMMCParser -lLLVMBitReader -lLLVMTransformUtils -lLLVMCore -lLLVMMC -lLLVMOption -lLLVMSupport
+ ifneq ($(filter 9.0%, $(LLVM_VERSION)),)
+ LDFLAGS += -lLLVMBitstreamReader -lLLVMBinaryFormat -lLLVMRemarks -lLLVMProfileData -lLLVMSupport -lLLVMDemangle
+ endif
+# LDFLAGS += `$(LLVMCONF) --libs`
LDFLAGS += $(patsubst %,-Xlinker --wrap=%,$(LLVM_SYMBOLS))
else
# Mac OS X is special, we patch the clang libraries below.
diff --git a/AspectC++/ThisJoinPoint.cc b/AspectC++/ThisJoinPoint.cc
index e1cbdbe..c4114ae 100644
--- a/AspectC++/ThisJoinPoint.cc
+++ b/AspectC++/ThisJoinPoint.cc
@@ -195,6 +195,28 @@ void ThisJoinPoint::gen_tjp_struct (ostream &code, ACM_Code *loc,
types << " typedef " << ( array_defined( loc ) ? "Array" : "TEntity" ) << " TTarget::* MemberPtr;" << endl;
else // use void * for non member entities (function returns 0)
types << " typedef void * MemberPtr;" << endl;
+
+ // generate EntityInfo, which refers to the introspection API
+ if (has_entity_var(*loc)) { // restrict to variables, otherwise use has_entity(...)
+ ACM_Name *entity = get_entity(*loc);
+ if (entity) {
+ ACM_Class *defining_cls = 0; // the class where the entity has been declared
+ if (entity->get_parent() && ((static_cast<ACM_Node*>(entity->get_parent()))->type_val() & JPT_Class))
+ defining_cls = static_cast<ACM_Class*>(entity->get_parent());
+
+ // generate a default EntityInfo (void), for example, if the entity is unknown or if introspection code is unavailable
+ types << " template<typename T, int HAVE=AC::HasTypeInfo<T>::RET, int __D=0> struct __EntityInfo { typedef void EntityInfo; };" << endl;
+ if (defining_cls) {
+ // generate the actual EntityInfo
+ types << " template<typename T, int __D> struct __EntityInfo<T, 1, __D> { "
+ << "typedef typename TTarget::__TI_"
+ << defining_cls->get_name()
+ << "::Member_" << entity->get_name()
+ << " EntityInfo; };" << endl;
+ }
+ types << " typedef typename __EntityInfo<TTarget>::EntityInfo EntityInfo;" << endl;
+ }
+ }
}
#endif
diff --git a/AspectC++/Transformer.cc b/AspectC++/Transformer.cc
index ed783b1..28a93b1 100644
--- a/AspectC++/Transformer.cc
+++ b/AspectC++/Transformer.cc
@@ -155,13 +155,13 @@ void Transformer::reinitializeSourceManager(clang::CompilerInstance *ci,
}
}
-// // print all buffers (for debugging code transformations, especially in phase 1)
-// for (clang::SourceManager::fileinfo_iterator fi = NewSM->fileinfo_begin(),
-// fe = NewSM->fileinfo_end();
-// fi != fe; ++fi) {
-// const llvm::MemoryBuffer *buf = fi->second->getRawBuffer();
-// cout << "BUF: " << buf->getBuffer().str() << endl;
-// }
+ // // print all buffers (for debugging code transformations, especially in phase 1)
+ // for (clang::SourceManager::fileinfo_iterator fi = NewSM->fileinfo_begin(),
+ // fe = NewSM->fileinfo_end();
+ // fi != fe; ++fi) {
+ // const llvm::MemoryBuffer *buf = fi->second->getRawBuffer();
+ // cout << "BUF: " << buf->getBuffer().str() << endl;
+ // }
// Now insert the new source manager and initialize it.
ci->resetAndLeakSourceManager ();
@@ -812,8 +812,8 @@ void Transformer::cleanup (ModelBuilder &jpm) {
#else
if (clang::Decl *decl = TI_Pointcut::of (pct)->decl())
_code_weaver.kill(
- _code_weaver.weave_pos(decl->getLocStart(), WeavePos::WP_BEFORE),
- _code_weaver.weave_pos(decl->getLocEnd().getLocWithOffset(1),
+ _code_weaver.weave_pos(CLANG_GET_LOC_START(decl), WeavePos::WP_BEFORE),
+ _code_weaver.weave_pos(CLANG_GET_LOC_END(decl).getLocWithOffset(1),
WeavePos::WP_AFTER));
#endif
}
diff --git a/AspectC++/config/clang-3.5.2.mk b/AspectC++/config/clang-3.5.2.mk
new file mode 100644
index 0000000..7f9f265
--- /dev/null
+++ b/AspectC++/config/clang-3.5.2.mk
@@ -0,0 +1 @@
+LLVM_SYMBOLS := _ZN5clang4Sema31ActOnStartCXXMemberDeclarationsEPNS_5ScopeEPNS_4DeclENS_14SourceLocationEbS5_ _ZN5clang4Sema33ActOnFinishCXXMemberSpecificationEPNS_5ScopeENS_14SourceLocationEPNS_4DeclES3_S3_PNS_13AttributeListE _ZN5clang4Sema25ActOnEndOfTranslationUnitEv _ZN5clang4Sema19canSkipFunctionBodyEPNS_4DeclE _ZN5clang4Sema24ActOnCXXMemberDeclaratorEPNS_5ScopeENS_15AccessSpecifierERNS_10DeclaratorEN4llvm15MutableArrayRefIPNS_21TemplateParameterListEEEPNS_4ExprERKNS_14VirtSpecifiersENS_16InClassInitStyleE _ZN5clang4Sema15ActOnDeclaratorEPNS_5ScopeERNS_10DeclaratorE _ZN5clang12Preprocessor3LexERNS_5TokenE _ZN5clang12Preprocessor9PeekAheadEj _ZN5clang4Sema19ActOnBaseSpecifiersEPNS_4DeclEPPNS_16CXXBaseSpecifierEj _ZN5clang4Sema8ActOnTagEPNS_5ScopeEjNS0_10TagUseKindENS_14SourceLocationERNS_12CXXScopeSpecEPNS_14IdentifierInfoES4_PNS_13AttributeListENS_15AccessSpecifierES4_N4llvm15MutableArrayRefIPNS_21TemplateParameterListEEERbSH_S4_bNS_12ActionResultINS_9OpaquePtrINS_8QualTypeEEELb0EEEb _ZN5clang4Sema22ActOnStartNamespaceDefEPNS_5ScopeENS_14SourceLocationES3_S3_PNS_14IdentifierInfoES3_PNS_13AttributeListE _ZN5clang4Sema23ActOnStartOfFunctionDefEPNS_5ScopeERNS_10DeclaratorE _ZN5clang4Sema21ProcessStmtAttributesEPNS_4StmtEPNS_13AttributeListENS_11SourceRangeE
diff --git a/AspectC++/config/clang-5.0.2.mk b/AspectC++/config/clang-5.0.2.mk
new file mode 100644
index 0000000..577e312
--- /dev/null
+++ b/AspectC++/config/clang-5.0.2.mk
@@ -0,0 +1 @@
+LLVM_SYMBOLS := _ZN5clang4Sema31ActOnStartCXXMemberDeclarationsEPNS_5ScopeEPNS_4DeclENS_14SourceLocationEbS5_ _ZN5clang4Sema33ActOnFinishCXXMemberSpecificationEPNS_5ScopeENS_14SourceLocationEPNS_4DeclES3_S3_PNS_13AttributeListE _ZN5clang4Sema25ActOnEndOfTranslationUnitEv _ZN5clang4Sema19canSkipFunctionBodyEPNS_4DeclE _ZN5clang4Sema24ActOnCXXMemberDeclaratorEPNS_5ScopeENS_15AccessSpecifierERNS_10DeclaratorEN4llvm15MutableArrayRefIPNS_21TemplateParameterListEEEPNS_4ExprERKNS_14VirtSpecifiersENS_16InClassInitStyleE _ZN5clang4Sema15ActOnDeclaratorEPNS_5ScopeERNS_10DeclaratorE _ZN5clang12Preprocessor3LexERNS_5TokenE _ZN5clang12Preprocessor9PeekAheadEj _ZN5clang4Sema19ActOnBaseSpecifiersEPNS_4DeclEN4llvm15MutableArrayRefIPNS_16CXXBaseSpecifierEEE _ZN5clang4Sema8ActOnTagEPNS_5ScopeEjNS0_10TagUseKindENS_14SourceLocationERNS_12CXXScopeSpecEPNS_14IdentifierInfoES4_PNS_13AttributeListENS_15AccessSpecifierES4_N4llvm15MutableArrayRefIPNS_21TemplateParameterListEEERbSH_S4_bNS_12ActionResultINS_9OpaquePtrINS_8QualTypeEEELb0EEEbbPNS0_12SkipBodyInfoE _ZN5clang4Sema22ActOnStartNamespaceDefEPNS_5ScopeENS_14SourceLocationES3_S3_PNS_14IdentifierInfoES3_PNS_13AttributeListERPNS_18UsingDirectiveDeclE _ZN5clang4Sema23ActOnStartOfFunctionDefEPNS_5ScopeERNS_10DeclaratorEN4llvm15MutableArrayRefIPNS_21TemplateParameterListEEEPNS0_12SkipBodyInfoE _ZN5clang4Sema21ProcessStmtAttributesEPNS_4StmtEPNS_13AttributeListENS_11SourceRangeE
diff --git a/AspectC++/config/clang-9.0.0.mk b/AspectC++/config/clang-9.0.0.mk
new file mode 100644
index 0000000..e788d9c
--- /dev/null
+++ b/AspectC++/config/clang-9.0.0.mk
@@ -0,0 +1 @@
+LLVM_SYMBOLS := _ZN5clang4Sema31ActOnStartCXXMemberDeclarationsEPNS_5ScopeEPNS_4DeclENS_14SourceLocationEbS5_ _ZN5clang4Sema33ActOnFinishCXXMemberSpecificationEPNS_5ScopeENS_14SourceLocationEPNS_4DeclES3_S3_RKNS_20ParsedAttributesViewE _ZN5clang4Sema25ActOnEndOfTranslationUnitEv _ZN5clang4Sema19canSkipFunctionBodyEPNS_4DeclE _ZN5clang4Sema24ActOnCXXMemberDeclaratorEPNS_5ScopeENS_15AccessSpecifierERNS_10DeclaratorEN4llvm15MutableArrayRefIPNS_21TemplateParameterListEEEPNS_4ExprERKNS_14VirtSpecifiersENS_16InClassInitStyleE _ZN5clang4Sema15ActOnDeclaratorEPNS_5ScopeERNS_10DeclaratorE _ZN5clang12Preprocessor3LexERNS_5TokenE _ZN5clang12Preprocessor9PeekAheadEj _ZN5clang4Sema19ActOnBaseSpecifiersEPNS_4DeclEN4llvm15MutableArrayRefIPNS_16CXXBaseSpecifierEEE _ZN5clang4Sema8ActOnTagEPNS_5ScopeEjNS0_10TagUseKindENS_14SourceLocationERNS_12CXXScopeSpecEPNS_14IdentifierInfoES4_RKNS_20ParsedAttributesViewENS_15AccessSpecifierES4_N4llvm15MutableArrayRefIPNS_21TemplateParameterListEEERbSI_S4_bNS_12ActionResultINS_9OpaquePtrINS_8QualTypeEEELb0EEEbbPNS0_12SkipBodyInfoE _ZN5clang4Sema22ActOnStartNamespaceDefEPNS_5ScopeENS_14SourceLocationES3_S3_PNS_14IdentifierInfoES3_RKNS_20ParsedAttributesViewERPNS_18UsingDirectiveDeclE _ZN5clang4Sema23ActOnStartOfFunctionDefEPNS_5ScopeERNS_10DeclaratorEN4llvm15MutableArrayRefIPNS_21TemplateParameterListEEEPNS0_12SkipBodyInfoE _ZN5clang4Sema21ProcessStmtAttributesEPNS_4StmtERKNS_20ParsedAttributesViewENS_11SourceRangeE
diff --git a/AspectC++/config/clang.mk b/AspectC++/config/clang.mk
index fa8ccad..45f4ee0 100644
--- a/AspectC++/config/clang.mk
+++ b/AspectC++/config/clang.mk
@@ -15,7 +15,10 @@ endif
include config/clang-$(LLVM_VERSION).mk
# determine relevant interface variants
-LLVM_INTERFACE := 50 # latest is default
+LLVM_INTERFACE := 90 # latest is default
+ifneq ($(filter 9.0%, $(LLVM_VERSION)),)
+ LLVM_INTERFACE := 90
+else
ifneq ($(filter 3.5%, $(LLVM_VERSION))$(filter 3.6%, $(LLVM_VERSION)),)
LLVM_INTERFACE := 35
else
@@ -30,6 +33,7 @@ ifneq ($(filter 5.0%, $(LLVM_VERSION))$(filter 6.0%, $(LLVM_VERSION)),)
endif
endif
endif
+endif
ifeq ($(_TARGET),macosx_x86_64) # on macOS the symbols have an additional '_'
LLVM_SYMBOLS := $(patsubst %, _%, $(LLVM_SYMBOLS))
diff --git a/AspectC++/tests/EntityInfo/JPTL.h b/AspectC++/tests/EntityInfo/JPTL.h
new file mode 100644
index 0000000..c7eba70
--- /dev/null
+++ b/AspectC++/tests/EntityInfo/JPTL.h
@@ -0,0 +1,893 @@
+// This file is part of the JoinPoint Template Library (JPTL)
+//
+// JPTL is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// JPTL is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with JPTL. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright (C) 2012-2014 Christoph Borchert
+
+#ifndef __JPTL_H__
+#define __JPTL_H__
+
+namespace JPTL {
+
+
+namespace SFINAE_CHECK {
+
+namespace EXEC {
+// static check, whether <T> has an attribute 'EXEC'
+template<typename T> long ttest(...); // overload resolution matches always
+template<typename T> char ttest(typename T::EXEC const volatile *); // preferred by overload resolution
+
+template<typename T, unsigned hasEXEC = ((sizeof(ttest<T>(0))==sizeof(char))?1:0) >
+struct GET {
+ typedef typename T::EXEC Type;
+};
+template<typename T>
+struct GET<T, 0> {
+ typedef void Type;
+};
+} // namespace EXEC
+
+// For looking up EXEC, use this dummy ones if the real one has no members/functions
+// FIXME: this needs maintenance if future ac++ versions change this structures
+template <int __D=0> struct DummyMember { typedef char Type; typedef AC::Referred<Type>::type ReferredType; static const AC::Protection prot = AC::PROT_PRIVATE; static const AC::Specifiers spec = AC::SPEC_NONE; static ReferredType *pointer (const void* const obj = 0) { return 0; } static const char *name () { return "null"; } };
+template <int __D=0> struct DummyFunction { static const AC::Protection prot = AC::PROT_PRIVATE; static const AC::Specifiers spec = AC::SPEC_NONE; };
+template <int __D=0> struct DummyConstructor { static const AC::Protection prot = AC::PROT_PRIVATE; static const AC::Specifiers spec = AC::SPEC_NONE; };
+template <int __D=0> struct DummyDestructor { static const AC::Protection prot = AC::PROT_PRIVATE; static const AC::Specifiers spec = AC::SPEC_NONE; };
+
+template<typename TypeInfo, unsigned MEMBERS=TypeInfo::MEMBERS>
+struct GetFirstMember {
+ typedef typename TypeInfo::template Member<0> MemberInfo;
+};
+template<typename TypeInfo>
+struct GetFirstMember<TypeInfo, 0> {
+ typedef DummyMember<> MemberInfo;
+};
+
+template<typename TypeInfo, unsigned FUNCTIONS=TypeInfo::FUNCTIONS>
+struct GetFirstFunction {
+ typedef typename TypeInfo::template Function<0> FunctionInfo;
+};
+template<typename TypeInfo>
+struct GetFirstFunction<TypeInfo, 0> {
+ typedef DummyFunction<> FunctionInfo;
+};
+
+template<typename TypeInfo, unsigned CONSTRUCTORS=TypeInfo::CONSTRUCTORS>
+struct GetFirstConstructor {
+ typedef typename TypeInfo::template Constructor<0> ConstructorInfo;
+};
+template<typename TypeInfo>
+struct GetFirstConstructor<TypeInfo, 0> {
+ typedef DummyConstructor<> ConstructorInfo;
+};
+
+template<typename TypeInfo, unsigned DESTRUCTORS=TypeInfo::DESTRUCTORS>
+struct GetFirstDestructor {
+ typedef typename TypeInfo::template Destructor<0> DestructorInfo;
+};
+template<typename TypeInfo>
+struct GetFirstDestructor<TypeInfo, 0> {
+ typedef DummyDestructor<> DestructorInfo;
+};
+
+} // namespace SFINAE_CHECK
+
+//-------------------------------------------------------------------------------------------------------------------------------
+
+#ifndef __acweaving
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=typename SFINAE_CHECK::EXEC::GET< Action<TypeInfo, void> >::Type, // look for EXEC in Action<...> //TODO: improve readability of this particular feature
+ unsigned I=TypeInfo::BASECLASSES>
+struct BaseIterator {
+
+ //base type information
+ typedef typename TypeInfo::template BaseClass<I-1>::Type BASE_TYPE;
+ typedef AC::TypeInfo<BASE_TYPE> BASE_TYPE_INFO;
+
+ // try to cast (a pointer) from TypeInfo::That* to BASE_TYPE*
+ // if that fails, return the original value
+ template<typename T>
+ __attribute__((always_inline)) inline static T base_cast(T arg) { return arg; }
+ __attribute__((always_inline)) inline static BASE_TYPE* base_cast(typename TypeInfo::That* arg) {
+ return (BASE_TYPE*)arg;
+ }
+ __attribute__((always_inline)) inline static const BASE_TYPE* base_cast(const typename TypeInfo::That* arg) {
+ return (const BASE_TYPE*)arg;
+ }
+ __attribute__((always_inline)) inline static volatile BASE_TYPE* base_cast(volatile typename TypeInfo::That* arg) {
+ return (volatile BASE_TYPE*)arg;
+ }
+ __attribute__((always_inline)) inline static const volatile BASE_TYPE* base_cast(const volatile typename TypeInfo::That* arg) {
+ return (const volatile BASE_TYPE*)arg;
+ }
+
+ // calculation of the context type
+ typedef typename BaseIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::EXEC PREV_EXEC; // recursion to the current base class
+ typedef typename BaseIterator<TypeInfo, Action, PREV_EXEC, I-1>::EXEC EXEC; // process next base class
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() { // rule: I > 0
+ BaseIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec(); // recursion to the current base class
+ BaseIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(); // process next base class
+ }
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) { // rule: I > 0
+ BaseIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec( base_cast(arg0) ); // recursion to the current base class
+ BaseIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(arg0); // process next base class
+ }
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) { // rule: I > 0
+ BaseIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec( base_cast(arg0) , base_cast(arg1) ); // recursion to the current base class
+ BaseIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(arg0, arg1); // process next base class
+ }
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) { // rule: I > 0
+ BaseIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec( base_cast(arg0) , base_cast(arg1) , base_cast(arg2) ); // recursion to the current base class
+ BaseIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(arg0, arg1, arg2); // process next base class
+ }
+};
+
+// Specialization for I=0
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC>
+struct BaseIterator<TypeInfo, Action, LAST_EXEC, 0> {
+
+ // calculation of the context type
+ typedef typename SFINAE_CHECK::EXEC::GET< Action<TypeInfo, LAST_EXEC> >::Type EXEC;
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {
+ Action<TypeInfo, LAST_EXEC>::exec();
+ }
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {
+ Action<TypeInfo, LAST_EXEC>::exec(arg0);
+ }
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {
+ Action<TypeInfo, LAST_EXEC>::exec(arg0, arg1);
+ }
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {
+ Action<TypeInfo, LAST_EXEC>::exec(arg0, arg1, arg2);
+ }
+};
+
+//-------------------------------------------------------------------------------------------------------------------------------
+
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=typename SFINAE_CHECK::EXEC::GET< Action<typename SFINAE_CHECK::GetFirstMember<TypeInfo>::MemberInfo, void> >::Type, // look for EXEC in Action<...> //TODO: improve readability of this particular feature
+ unsigned I=TypeInfo::MEMBERS>
+struct MemberIterator {
+
+ //member type info
+ typedef typename TypeInfo::template Member<I-1> MEMBER_TYPE_INFO;
+
+ // calculation of the context type
+ typedef typename MemberIterator<TypeInfo, Action, LAST_EXEC, I-1>::EXEC PREV_EXEC;
+ typedef typename SFINAE_CHECK::EXEC::GET< Action<MEMBER_TYPE_INFO, PREV_EXEC> >::Type EXEC;
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {
+ MemberIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec();
+ Action<MEMBER_TYPE_INFO, PREV_EXEC>::exec();
+ }
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {
+ MemberIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec(arg0);
+ Action<MEMBER_TYPE_INFO, PREV_EXEC>::exec(arg0);
+ }
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {
+ MemberIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec(arg0, arg1);
+ Action<MEMBER_TYPE_INFO, PREV_EXEC>::exec(arg0, arg1);
+ }
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {
+ MemberIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec(arg0, arg1, arg2);
+ Action<MEMBER_TYPE_INFO, PREV_EXEC>::exec(arg0, arg1, arg2);
+ }
+};
+
+// Specialization for I=0 (end of recursion)
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC>
+struct MemberIterator<TypeInfo, Action, LAST_EXEC, 0> {
+
+ // calculation of the context type
+ typedef LAST_EXEC EXEC;
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {}
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {}
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {}
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {}
+};
+
+//-------------------------------------------------------------------------------------------------------------------------------
+
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=typename SFINAE_CHECK::EXEC::GET< Action<typename SFINAE_CHECK::GetFirstFunction<TypeInfo>::FunctionInfo, void> >::Type, // look for EXEC in Action<...> //TODO: improve readability of this particular feature
+ unsigned I=TypeInfo::FUNCTIONS>
+struct FunctionIterator {
+
+ //member type info
+ typedef typename TypeInfo::template Function<I-1> FUNCTION_INFO;
+
+ // calculation of the context type
+ typedef typename FunctionIterator<TypeInfo, Action, LAST_EXEC, I-1>::EXEC PREV_EXEC;
+ typedef typename SFINAE_CHECK::EXEC::GET< Action<FUNCTION_INFO, PREV_EXEC> >::Type EXEC;
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {
+ FunctionIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec();
+ Action<FUNCTION_INFO, PREV_EXEC>::exec();
+ }
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {
+ FunctionIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec(arg0);
+ Action<FUNCTION_INFO, PREV_EXEC>::exec(arg0);
+ }
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {
+ FunctionIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec(arg0, arg1);
+ Action<FUNCTION_INFO, PREV_EXEC>::exec(arg0, arg1);
+ }
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {
+ FunctionIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec(arg0, arg1, arg2);
+ Action<FUNCTION_INFO, PREV_EXEC>::exec(arg0, arg1, arg2);
+ }
+};
+
+// Specialization for I=0 (end of recursion)
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC>
+struct FunctionIterator<TypeInfo, Action, LAST_EXEC, 0> {
+
+ // calculation of the context type
+ typedef LAST_EXEC EXEC;
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {}
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {}
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {}
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {}
+};
+
+//-------------------------------------------------------------------------------------------------------------------------------
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=typename SFINAE_CHECK::EXEC::GET< Action<typename SFINAE_CHECK::GetFirstConstructor<TypeInfo>::ConstructorInfo, void> >::Type, // look for EXEC in Action<...> //TODO: improve readability of this particular feature
+ unsigned I=TypeInfo::CONSTRUCTORS>
+struct ConstructorIterator {
+
+ //member type info
+ typedef typename TypeInfo::template Constructor<I-1> CONSTRUCTOR_INFO;
+
+ // calculation of the context type
+ typedef typename ConstructorIterator<TypeInfo, Action, LAST_EXEC, I-1>::EXEC PREV_EXEC;
+ typedef typename SFINAE_CHECK::EXEC::GET< Action<CONSTRUCTOR_INFO, PREV_EXEC> >::Type EXEC;
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {
+ ConstructorIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec();
+ Action<CONSTRUCTOR_INFO, PREV_EXEC>::exec();
+ }
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {
+ ConstructorIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec(arg0);
+ Action<CONSTRUCTOR_INFO, PREV_EXEC>::exec(arg0);
+ }
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {
+ ConstructorIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec(arg0, arg1);
+ Action<CONSTRUCTOR_INFO, PREV_EXEC>::exec(arg0, arg1);
+ }
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {
+ ConstructorIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec(arg0, arg1, arg2);
+ Action<CONSTRUCTOR_INFO, PREV_EXEC>::exec(arg0, arg1, arg2);
+ }
+};
+
+// Specialization for I=0 (end of recursion)
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC>
+struct ConstructorIterator<TypeInfo, Action, LAST_EXEC, 0> {
+
+ // calculation of the context type
+ typedef LAST_EXEC EXEC;
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {}
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {}
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {}
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {}
+};
+
+//-------------------------------------------------------------------------------------------------------------------------------
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=typename SFINAE_CHECK::EXEC::GET< Action<typename SFINAE_CHECK::GetFirstDestructor<TypeInfo>::DestructorInfo, void> >::Type, // look for EXEC in Action<...> //TODO: improve readability of this particular feature
+ unsigned I=TypeInfo::DESTRUCTORS>
+struct DestructorIterator {
+
+ //member type info
+ typedef typename TypeInfo::template Destructor<I-1> DESTRUCTOR_INFO;
+
+ // calculation of the context type
+ typedef typename DestructorIterator<TypeInfo, Action, LAST_EXEC, I-1>::EXEC PREV_EXEC;
+ typedef typename SFINAE_CHECK::EXEC::GET< Action<DESTRUCTOR_INFO, PREV_EXEC> >::Type EXEC;
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {
+ DestructorIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec();
+ Action<DESTRUCTOR_INFO, PREV_EXEC>::exec();
+ }
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {
+ DestructorIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec(arg0);
+ Action<DESTRUCTOR_INFO, PREV_EXEC>::exec(arg0);
+ }
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {
+ DestructorIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec(arg0, arg1);
+ Action<DESTRUCTOR_INFO, PREV_EXEC>::exec(arg0, arg1);
+ }
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {
+ DestructorIterator<TypeInfo, Action, LAST_EXEC, I-1>::exec(arg0, arg1, arg2);
+ Action<DESTRUCTOR_INFO, PREV_EXEC>::exec(arg0, arg1, arg2);
+ }
+};
+
+// Specialization for I=0 (end of recursion)
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC>
+struct DestructorIterator<TypeInfo, Action, LAST_EXEC, 0> {
+
+ // calculation of the context type
+ typedef LAST_EXEC EXEC;
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {}
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {}
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {}
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {}
+};
+
+//-------------------------------------------------------------------------------------------------------------------------------
+
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=typename SFINAE_CHECK::EXEC::GET< Action<typename SFINAE_CHECK::GetFirstMember<TypeInfo>::MemberInfo, void> >::Type, // look for EXEC in Action<...> //TODO: improve readability of this particular feature
+ unsigned I=TypeInfo::BASECLASSES>
+struct BaseMemberIterator {
+
+ //base type information
+ typedef typename TypeInfo::template BaseClass<I-1>::Type BASE_TYPE;
+ typedef AC::TypeInfo<BASE_TYPE> BASE_TYPE_INFO;
+
+ // try to cast (a pointer) from TypeInfo::That* to BASE_TYPE*
+ // if that fails, return the original value
+ template<typename T>
+ __attribute__((always_inline)) inline static T base_cast(T arg) { return arg; }
+ __attribute__((always_inline)) inline static BASE_TYPE* base_cast(typename TypeInfo::That* arg) {
+ return (BASE_TYPE*)arg;
+ }
+ __attribute__((always_inline)) inline static const BASE_TYPE* base_cast(const typename TypeInfo::That* arg) {
+ return (const BASE_TYPE*)arg;
+ }
+ __attribute__((always_inline)) inline static volatile BASE_TYPE* base_cast(volatile typename TypeInfo::That* arg) {
+ return (volatile BASE_TYPE*)arg;
+ }
+ __attribute__((always_inline)) inline static const volatile BASE_TYPE* base_cast(const volatile typename TypeInfo::That* arg) {
+ return (const volatile BASE_TYPE*)arg;
+ }
+
+ // calculation of the context type
+ typedef typename BaseMemberIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::EXEC PREV_EXEC; // recursion to the current base class
+ typedef typename BaseMemberIterator<TypeInfo, Action, PREV_EXEC, I-1>::EXEC EXEC; // process next base class
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() { // rule: I > 0
+ BaseMemberIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec(); // recursion to the current base class
+ BaseMemberIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(); // process next base class
+ }
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) { // rule: I > 0
+ BaseMemberIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec( base_cast(arg0) ); // recursion to the current base class
+ BaseMemberIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(arg0); // process next base class
+ }
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) { // rule: I > 0
+ BaseMemberIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec( base_cast(arg0) , base_cast(arg1) ); // recursion to the current base class
+ BaseMemberIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(arg0, arg1); // process next base class
+ }
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) { // rule: I > 0
+ BaseMemberIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec( base_cast(arg0) , base_cast(arg1) , base_cast(arg2) ); // recursion to the current base class
+ BaseMemberIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(arg0, arg1, arg2); // process next base class
+ }
+};
+
+// Specialization for I=0
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC>
+struct BaseMemberIterator<TypeInfo, Action, LAST_EXEC, 0> {
+
+ // use the MemberIterator for now, as we reached a child node
+ typedef MemberIterator<TypeInfo, Action, LAST_EXEC> MIT;
+
+ // calculation of the context type
+ typedef typename MIT::EXEC EXEC;
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {
+ MIT::exec();
+ }
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {
+ MIT::exec(arg0);
+ }
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {
+ MIT::exec(arg0, arg1);
+ }
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {
+ MIT::exec(arg0, arg1, arg2);
+ }
+};
+
+//-------------------------------------------------------------------------------------------------------------------------------
+
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=typename SFINAE_CHECK::EXEC::GET< Action<typename SFINAE_CHECK::GetFirstFunction<TypeInfo>::FunctionInfo, void> >::Type, // look for EXEC in Action<...> //TODO: improve readability of this particular feature
+ unsigned I=TypeInfo::BASECLASSES>
+struct BaseFunctionIterator {
+
+ //base type information
+ typedef typename TypeInfo::template BaseClass<I-1>::Type BASE_TYPE;
+ typedef AC::TypeInfo<BASE_TYPE> BASE_TYPE_INFO;
+
+ // try to cast (a pointer) from TypeInfo::That* to BASE_TYPE*
+ // if that fails, return the original value
+ template<typename T>
+ __attribute__((always_inline)) inline static T base_cast(T arg) { return arg; }
+ __attribute__((always_inline)) inline static BASE_TYPE* base_cast(typename TypeInfo::That* arg) {
+ return (BASE_TYPE*)arg;
+ }
+ __attribute__((always_inline)) inline static const BASE_TYPE* base_cast(const typename TypeInfo::That* arg) {
+ return (const BASE_TYPE*)arg;
+ }
+ __attribute__((always_inline)) inline static volatile BASE_TYPE* base_cast(volatile typename TypeInfo::That* arg) {
+ return (volatile BASE_TYPE*)arg;
+ }
+ __attribute__((always_inline)) inline static const volatile BASE_TYPE* base_cast(const volatile typename TypeInfo::That* arg) {
+ return (const volatile BASE_TYPE*)arg;
+ }
+
+ // calculation of the context type
+ typedef typename BaseFunctionIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::EXEC PREV_EXEC; // recursion to the current base class
+ typedef typename BaseFunctionIterator<TypeInfo, Action, PREV_EXEC, I-1>::EXEC EXEC; // process next base class
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() { // rule: I > 0
+ BaseFunctionIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec(); // recursion to the current base class
+ BaseFunctionIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(); // process next base class
+ }
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) { // rule: I > 0
+ BaseFunctionIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec( base_cast(arg0) ); // recursion to the current base class
+ BaseFunctionIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(arg0); // process next base class
+ }
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) { // rule: I > 0
+ BaseFunctionIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec( base_cast(arg0) , base_cast(arg1) ); // recursion to the current base class
+ BaseFunctionIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(arg0, arg1); // process next base class
+ }
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) { // rule: I > 0
+ BaseFunctionIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec( base_cast(arg0) , base_cast(arg1) , base_cast(arg2) ); // recursion to the current base class
+ BaseFunctionIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(arg0, arg1, arg2); // process next base class
+ }
+};
+
+// Specialization for I=0
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC>
+struct BaseFunctionIterator<TypeInfo, Action, LAST_EXEC, 0> {
+
+ // use the FunctionIterator for now, as we reached a child node
+ typedef FunctionIterator<TypeInfo, Action, LAST_EXEC> FIT;
+
+ // calculation of the context type
+ typedef typename FIT::EXEC EXEC;
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {
+ FIT::exec();
+ }
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {
+ FIT::exec(arg0);
+ }
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {
+ FIT::exec(arg0, arg1);
+ }
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {
+ FIT::exec(arg0, arg1, arg2);
+ }
+};
+
+//-------------------------------------------------------------------------------------------------------------------------------
+
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=typename SFINAE_CHECK::EXEC::GET< Action<typename SFINAE_CHECK::GetFirstConstructor<TypeInfo>::ConstructorInfo, void> >::Type, // look for EXEC in Action<...> //TODO: improve readability of this particular feature
+ unsigned I=TypeInfo::BASECLASSES>
+struct BaseConstructorIterator {
+
+ //base type information
+ typedef typename TypeInfo::template BaseClass<I-1>::Type BASE_TYPE;
+ typedef AC::TypeInfo<BASE_TYPE> BASE_TYPE_INFO;
+
+ // try to cast (a pointer) from TypeInfo::That* to BASE_TYPE*
+ // if that fails, return the original value
+ template<typename T>
+ __attribute__((always_inline)) inline static T base_cast(T arg) { return arg; }
+ __attribute__((always_inline)) inline static BASE_TYPE* base_cast(typename TypeInfo::That* arg) {
+ return (BASE_TYPE*)arg;
+ }
+ __attribute__((always_inline)) inline static const BASE_TYPE* base_cast(const typename TypeInfo::That* arg) {
+ return (const BASE_TYPE*)arg;
+ }
+ __attribute__((always_inline)) inline static volatile BASE_TYPE* base_cast(volatile typename TypeInfo::That* arg) {
+ return (volatile BASE_TYPE*)arg;
+ }
+ __attribute__((always_inline)) inline static const volatile BASE_TYPE* base_cast(const volatile typename TypeInfo::That* arg) {
+ return (const volatile BASE_TYPE*)arg;
+ }
+
+ // calculation of the context type
+ typedef typename BaseConstructorIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::EXEC PREV_EXEC; // recursion to the current base class
+ typedef typename BaseConstructorIterator<TypeInfo, Action, PREV_EXEC, I-1>::EXEC EXEC; // process next base class
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() { // rule: I > 0
+ BaseConstructorIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec(); // recursion to the current base class
+ BaseConstructorIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(); // process next base class
+ }
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) { // rule: I > 0
+ BaseConstructorIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec( base_cast(arg0) ); // recursion to the current base class
+ BaseConstructorIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(arg0); // process next base class
+ }
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) { // rule: I > 0
+ BaseConstructorIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec( base_cast(arg0) , base_cast(arg1) ); // recursion to the current base class
+ BaseConstructorIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(arg0, arg1); // process next base class
+ }
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) { // rule: I > 0
+ BaseConstructorIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec( base_cast(arg0) , base_cast(arg1) , base_cast(arg2) ); // recursion to the current base class
+ BaseConstructorIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(arg0, arg1, arg2); // process next base class
+ }
+};
+
+// Specialization for I=0
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC>
+struct BaseConstructorIterator<TypeInfo, Action, LAST_EXEC, 0> {
+
+ // use the FunctionIterator for now, as we reached a child node
+ typedef ConstructorIterator<TypeInfo, Action, LAST_EXEC> CIT;
+
+ // calculation of the context type
+ typedef typename CIT::EXEC EXEC;
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {
+ CIT::exec();
+ }
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {
+ CIT::exec(arg0);
+ }
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {
+ CIT::exec(arg0, arg1);
+ }
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {
+ CIT::exec(arg0, arg1, arg2);
+ }
+};
+
+//-------------------------------------------------------------------------------------------------------------------------------
+
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=typename SFINAE_CHECK::EXEC::GET< Action<typename SFINAE_CHECK::GetFirstDestructor<TypeInfo>::DestructorInfo, void> >::Type, // look for EXEC in Action<...> //TODO: improve readability of this particular feature
+ unsigned I=TypeInfo::BASECLASSES>
+struct BaseDestructorIterator {
+
+ //base type information
+ typedef typename TypeInfo::template BaseClass<I-1>::Type BASE_TYPE;
+ typedef AC::TypeInfo<BASE_TYPE> BASE_TYPE_INFO;
+
+ // try to cast (a pointer) from TypeInfo::That* to BASE_TYPE*
+ // if that fails, return the original value
+ template<typename T>
+ __attribute__((always_inline)) inline static T base_cast(T arg) { return arg; }
+ __attribute__((always_inline)) inline static BASE_TYPE* base_cast(typename TypeInfo::That* arg) {
+ return (BASE_TYPE*)arg;
+ }
+ __attribute__((always_inline)) inline static const BASE_TYPE* base_cast(const typename TypeInfo::That* arg) {
+ return (const BASE_TYPE*)arg;
+ }
+ __attribute__((always_inline)) inline static volatile BASE_TYPE* base_cast(volatile typename TypeInfo::That* arg) {
+ return (volatile BASE_TYPE*)arg;
+ }
+ __attribute__((always_inline)) inline static const volatile BASE_TYPE* base_cast(const volatile typename TypeInfo::That* arg) {
+ return (const volatile BASE_TYPE*)arg;
+ }
+
+ // calculation of the context type
+ typedef typename BaseDestructorIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::EXEC PREV_EXEC; // recursion to the current base class
+ typedef typename BaseDestructorIterator<TypeInfo, Action, PREV_EXEC, I-1>::EXEC EXEC; // process next base class
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() { // rule: I > 0
+ BaseDestructorIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec(); // recursion to the current base class
+ BaseDestructorIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(); // process next base class
+ }
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) { // rule: I > 0
+ BaseDestructorIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec( base_cast(arg0) ); // recursion to the current base class
+ BaseDestructorIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(arg0); // process next base class
+ }
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) { // rule: I > 0
+ BaseDestructorIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec( base_cast(arg0) , base_cast(arg1) ); // recursion to the current base class
+ BaseDestructorIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(arg0, arg1); // process next base class
+ }
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) { // rule: I > 0
+ BaseDestructorIterator<BASE_TYPE_INFO, Action, LAST_EXEC>::exec( base_cast(arg0) , base_cast(arg1) , base_cast(arg2) ); // recursion to the current base class
+ BaseDestructorIterator<TypeInfo, Action, PREV_EXEC, I-1>::exec(arg0, arg1, arg2); // process next base class
+ }
+};
+
+// Specialization for I=0
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC>
+struct BaseDestructorIterator<TypeInfo, Action, LAST_EXEC, 0> {
+
+ // use the FunctionIterator for now, as we reached a child node
+ typedef DestructorIterator<TypeInfo, Action, LAST_EXEC> DIT;
+
+ // calculation of the context type
+ typedef typename DIT::EXEC EXEC;
+
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {
+ DIT::exec();
+ }
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {
+ DIT::exec(arg0);
+ }
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {
+ DIT::exec(arg0, arg1);
+ }
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {
+ DIT::exec(arg0, arg1, arg2);
+ }
+};
+
+#else // __acweaving
+
+// These are dummy iterators to speed up the weaving phase (no recursion).
+// Thus, the real iterators get only instantiated once during the final compilation.
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=void,
+ unsigned I=0>
+struct BaseIterator {
+ typedef typename SFINAE_CHECK::EXEC::GET< Action<TypeInfo, LAST_EXEC> >::Type EXEC;
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {}
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {}
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {}
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {}
+};
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=void,
+ unsigned I=0>
+struct MemberIterator {
+ typedef typename SFINAE_CHECK::EXEC::GET< Action<typename SFINAE_CHECK::DummyMember<>, LAST_EXEC> >::Type EXEC;
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {}
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {}
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {}
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {}
+};
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=void,
+ unsigned I=0>
+struct FunctionIterator {
+ typedef typename SFINAE_CHECK::EXEC::GET< Action<typename SFINAE_CHECK::DummyFunction<>, LAST_EXEC> >::Type EXEC;
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {}
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {}
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {}
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {}
+};
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=void,
+ unsigned I=0>
+struct ConstructorIterator {
+ typedef typename SFINAE_CHECK::EXEC::GET< Action<typename SFINAE_CHECK::DummyConstructor<>, LAST_EXEC> >::Type EXEC;
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {}
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {}
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {}
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {}
+};
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=void,
+ unsigned I=0>
+struct DestructorIterator {
+ typedef typename SFINAE_CHECK::EXEC::GET< Action<typename SFINAE_CHECK::DummyDestructor<>, LAST_EXEC> >::Type EXEC;
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {}
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {}
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {}
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {}
+};
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=void,
+ unsigned I=0>
+struct BaseMemberIterator {
+ typedef typename MemberIterator<TypeInfo, Action, LAST_EXEC>::EXEC EXEC;
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {}
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {}
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {}
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {}
+};
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=void,
+ unsigned I=0>
+struct BaseFunctionIterator {
+ typedef typename FunctionIterator<TypeInfo, Action, LAST_EXEC>::EXEC EXEC;
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {}
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {}
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {}
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {}
+};
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=void,
+ unsigned I=0>
+struct BaseConstructorIterator {
+ typedef typename ConstructorIterator<TypeInfo, Action, LAST_EXEC>::EXEC EXEC;
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {}
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {}
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {}
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {}
+};
+
+template<typename TypeInfo,
+ template <typename, typename> class Action,
+ typename LAST_EXEC=void,
+ unsigned I=0>
+struct BaseDestructorIterator {
+ typedef typename DestructorIterator<TypeInfo, Action, LAST_EXEC>::EXEC EXEC;
+ // the exec(...) function
+ __attribute__((always_inline)) inline static void exec() {}
+ template<typename ARG_0>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0) {}
+ template<typename ARG_0, typename ARG_1>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1) {}
+ template<typename ARG_0, typename ARG_1, typename ARG_2>
+ __attribute__((always_inline)) inline static void exec(ARG_0 arg0, ARG_1 arg1, ARG_2 arg2) {}
+};
+#endif // __acweaving
+
+} // namespace JPTL
+
+#endif // __JPTL_H__
+
diff --git a/AspectC++/tests/EntityInfo/Makefile b/AspectC++/tests/EntityInfo/Makefile
new file mode 100644
index 0000000..b75c633
--- /dev/null
+++ b/AspectC++/tests/EntityInfo/Makefile
@@ -0,0 +1,2 @@
+ACFLAGS ?= --builtin_operators --data_joinpoints --introspection
+include ../Makefile.generic
diff --git a/AspectC++/tests/EntityInfo/feature.ref b/AspectC++/tests/EntityInfo/feature.ref
new file mode 100644
index 0000000..963a401
--- /dev/null
+++ b/AspectC++/tests/EntityInfo/feature.ref
@@ -0,0 +1,17 @@
+ JoinPoint::signature() JoinPoint::EntityInfo::name()
+ ====================== =============================
+ int A::y A::y
+ int A::foo[42] A::foo
+ char A::z A::z
+ char A::z A::z
+ int A::foo[42] A::foo
+ short int A::global A::global
+ short int A::global A::global
+ short int A::global A::global
+ short int A::global A::global
+ short int A::global A::global
+ int C::c C::c
+ int stat <unknown>::<unknown>
+ int stat <unknown>::<unknown>
+ int stat <unknown>::<unknown>
+ int var <unknown>::<unknown>
diff --git a/AspectC++/tests/EntityInfo/main.cc b/AspectC++/tests/EntityInfo/main.cc
new file mode 100644
index 0000000..8cbfb74
--- /dev/null
+++ b/AspectC++/tests/EntityInfo/main.cc
@@ -0,0 +1,122 @@
+#include <iostream>
+#include <iomanip>
+#include "JPTL.h"
+
+
+template<typename MemberInfo, typename CONTEXT>
+struct MemberLookup {
+ // helper template for checking if two types are the same
+ template<typename T, typename U>
+ struct TypeCompare {
+ enum { IS_SAME = 0 };
+ };
+ template<typename T>
+ struct TypeCompare<T,T> {
+ enum { IS_SAME = 1 };
+ };
+ // the actual EXEC struct for use with JPTL::MemberIterator<...>
+ struct EXEC {
+ typedef typename CONTEXT::EntityInfo EntityInfo; // pass through
+ enum { FOUND = (TypeCompare<EntityInfo, MemberInfo>::IS_SAME == 1) ? 1 : CONTEXT::FOUND,
+ INDEX = (FOUND == 1) ? CONTEXT::INDEX : CONTEXT::INDEX + 1 }; // stop counting if found
+ };
+};
+template<typename T>
+struct MemberLookupInit {
+ // initial EXEC
+ typedef T EntityInfo;
+ enum { FOUND = 0, INDEX = 0 };
+};
+
+template<typename TypeInfo, typename CONTEXT>
+struct EntityInfoLookup {
+ // helper template for conditional type selection
+ template<typename T, typename U, unsigned int USE_FIRST>
+ struct TypeSelect {
+ typedef T Type;
+ };
+ template<typename T, typename U>
+ struct TypeSelect<T, U, 0> {
+ typedef U Type;
+ };
+ // the actual EXEC struct for use with JPTL::BaseIterator<...>
+ struct EXEC {
+ typedef typename CONTEXT::EntityInfo EntityInfo; // pass through
+ typedef JPTL::MemberIterator<TypeInfo, MemberLookup, MemberLookupInit<EntityInfo> > MIT;
+ enum { FOUND = MIT::EXEC::FOUND ? 1 : 0 }; // do we have a positive lookup for this base class?
+
+ typedef typename TypeSelect<typename TypeInfo::That, typename CONTEXT::TargetClass, FOUND>::Type TargetClass;
+ enum { INDEX = (FOUND == 1) ? static_cast<unsigned int>(MIT::EXEC::INDEX) : static_cast<unsigned int>(CONTEXT::INDEX) };
+ };
+};
+template<typename T>
+struct EntityInfoLookupInit {
+ // initial EXEC
+ typedef T EntityInfo;
+ typedef void TargetClass;
+ enum { INDEX = 0 };
+};
+
+
+// ---- some pretty printing stuff ---
+template<typename T, unsigned int INDEX, int AVAIL=AC::TypeInfo<T>::AVAILABLE>
+struct Printer {
+ static const char* signature() { return AC::TypeInfo<T>::signature(); }
+ static const char* name() { return AC::TypeInfo<T>::template Member<INDEX>::name(); }
+};
+template<typename T, unsigned int INDEX>
+struct Printer<T, INDEX, 0> {
+ static const char* signature() { return "<unknown>"; }
+ static const char* name() { return "<unknown>"; }
+};
+
+// ---- the test code ---
+class A {
+public:
+ int x;
+ int y;
+ char z;
+ int foo[42];
+ static short global;
+};
+
+short A::global = 0;
+
+class B : public A {};
+
+class C : public A { public: int c; };
+
+class D : public B, public C {};
+
+static int stat = 0;
+int var = 1;
+
+int main() {
+ std::cout << std::setw(30) << "JoinPoint::signature()" << "\t\tJoinPoint::EntityInfo::name()" << std::endl
+ << std::setw(30) << "======================" << "\t\t=============================" << std::endl;
+ C c;
+ c.y = 42;
+ c.foo[0] = 3;
+ c.foo[4] = c.A::z++;
+ A::global++;
+ c.global--;
+ A::global = 5;
+ c.c = 5;
+
+ var = ++stat;
+
+ int *p = &c.y;
+ *p = 0;
+ return 0;
+};
+
+aspect EntityInfoPrinter {
+ advice get("% ...::%") || set("% ...::%") : before() {
+ typedef typename JPTL::BaseIterator<AC::TypeInfo<JoinPoint::Target>, EntityInfoLookup, EntityInfoLookupInit<typename JoinPoint::EntityInfo> >::EXEC Lookup;
+
+ std::cout << std::setw(30) << JoinPoint::signature() << "\t\t"
+ << Printer<typename Lookup::TargetClass, Lookup::INDEX>::signature() << "::"
+ << Printer<typename Lookup::TargetClass, Lookup::INDEX>::name() << std::endl;
+ }
+};
+
diff --git a/AspectC++/tests/Makefile b/AspectC++/tests/Makefile
index 0a6d9a6..968ce6b 100644
--- a/AspectC++/tests/Makefile
+++ b/AspectC++/tests/Makefile
@@ -39,7 +39,8 @@ ACTESTS += SimpleGetAdvice SimpleSetAdvice CompoundGetSetAdvice FunctionEntity \
SimpleRefAdvice SimpleAliasAccessMember SimpleGetSetFuncPtr \
ArrayAccessAdvice MatchScope GetBaseDerived \
Bug-Typenames DefaultArgs2 CallViaADN Bug574 GetConditional Bug576 \
- Bug567 Bug568 Bug548 Bug589 Bug594 Bug598 CallRef Float128Basic
+ Bug567 Bug568 Bug548 Bug589 Bug594 Bug598 CallRef Float128Basic \
+ EntityInfo TypePrinting_FunctionPointers
ACTESTS += Attribute_basic Attribute_inMacro Attribute_removeAttrs
#Attribute_pointcuts Attribute_params Attribute_paramEvaluation \
#Attribute_paramsIntrospection Attribute_stringParam
diff --git a/AspectC++/tests/TypePrinting_FunctionPointers/Makefile b/AspectC++/tests/TypePrinting_FunctionPointers/Makefile
new file mode 100644
index 0000000..01d074c
--- /dev/null
+++ b/AspectC++/tests/TypePrinting_FunctionPointers/Makefile
@@ -0,0 +1,2 @@
+ACFLAGS += --builtin_operators --data_joinpoints
+include ../Makefile.generic
diff --git a/AspectC++/tests/TypePrinting_FunctionPointers/feature.ref b/AspectC++/tests/TypePrinting_FunctionPointers/feature.ref
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/AspectC++/tests/TypePrinting_FunctionPointers/feature.ref
diff --git a/AspectC++/tests/TypePrinting_FunctionPointers/main.cc b/AspectC++/tests/TypePrinting_FunctionPointers/main.cc
new file mode 100644
index 0000000..479a31b
--- /dev/null
+++ b/AspectC++/tests/TypePrinting_FunctionPointers/main.cc
@@ -0,0 +1,56 @@
+// getFullyQualifiedType does not support function pointers in clang=9.0.0. As a result the type
+// of foo's argument is not fully qualified in woven code. This result in invalid woven code.
+
+// See Bug568 testcase for more type printing tests
+
+namespace N {
+ class N {
+ class C {
+ class C2 { };
+ };
+ };
+
+ class C {
+ public:
+ class C2 { };
+ };
+
+ void foo(C::C2& (*a)(C*, C::C2&)) { }
+
+ void bar(int i) {
+ // To successfully weave this call, ::N::C is necessary
+ foo(nullptr);
+ }
+
+ template<typename T1>
+ class B {
+ void mf(T1 ma) { }
+ };
+
+ template<typename T1>
+ void goocar(T1 a) { }
+}
+
+int main() {
+ // Indirectly call foo in a scope where N::C names the wrong class and ::N::C is absolutely necessary.
+ N::bar(42);
+
+ // In this scope, N::C is sufficient (i.e., the global namespace specifier is not necessary). Interestingly, also N's specifier is missing.
+ N::foo(nullptr);
+
+ // This must also work (function pointer type as template argument type). With clang=9.0.0 getFullyQualifiedType *removes* all specifier from
+ // the function pointer type inside the template argument.
+ using namespace N;
+ B<C::C2& (*)(C*, C::C2&)> b;
+ goocar<>(b);
+}
+
+aspect Asp {
+ advice call("% ...::%(...)") || builtin("% ...::%(...)") || set("% ...::%") : before() {
+ tjp->arg<0>(); // All matchable functions have exactly one argument.
+ }
+
+ advice get("% ...::%") : around() {
+ tjp->proceed();
+ }
+};
diff --git a/AspectC++/tests/make_testall_multiple_clang_versions.sh b/AspectC++/tests/make_testall_multiple_clang_versions.sh
new file mode 100755
index 0000000..795992f
--- /dev/null
+++ b/AspectC++/tests/make_testall_multiple_clang_versions.sh
@@ -0,0 +1,125 @@
+#!/bin/bash
+# This script allows to automatically build and test AspectC++ with multiple clang versions. It produces a compact
+# report about AspectC++'s status in terms of supported clang versions.
+
+### Optional arguments ###
+# $1 clang_version_array (see below)
+# $2 clang_dir_path_prefix (see below)
+# $3 build target, i.e., make's TARGET argument
+if [ $# -gt 3 ]
+then
+ echo "Error: Max. 3 arguments allowed."
+ exit 1
+fi
+
+### Config ###
+
+# Array of version strings. For each string, the corresponding clang version is used for testing AspectC++. Pre-built
+# binaries/libraries can be downloaded from http://releases.llvm.org/download.html.
+clang_version_array=${1:-"9.0.0 6.0.1 5.0.2 4.0.1 3.9.1 3.8.1 3.7.1 3.6.2 3.5.2"}
+
+# Path to directory containing clang binary/library directories plus the prefix of all clang binary/library directory
+# names.
+# When concatenated with a version from the version array, it must result in a path to the root of a clang
+# binary/library directory. From that path, "./bin/llvm-config" should point to llvm-config binary.
+# For example, extract all downloaded pre-built binary/library files to your home and rename each extracted root
+# directory to llvm-<version>. In this case, clang_dir_path_prefix should be "$HOME/llvm-"
+# Note: Please provide absolute paths. Tilde (~) is not supported.
+clang_dir_path_prefix=${2:-"$HOME/llvm-"}
+
+# Number of cpus to use for building:
+cpu_count_to_use=$(grep -c ^processor /proc/cpuinfo)
+
+# AspectC++ build command without LLVMCONF argument:
+build_target=${3:-"linux-debug"}
+acpp_base_build_command="make SHARED=1 TARGET=$build_target -j$cpu_count_to_use FRONTEND=Clang"
+
+### End of config ######################################################################################################
+########################################################################################################################
+
+
+run_command() {
+ # $1 = command description
+ # $2 = command to run
+ # $3 = whether to continue on non-zero exit code (1) or not (0)
+
+ echo -e "\n------------------------------\n$1 ($2) ..."
+ # Run command:
+ # Since we run two piped commands below, force bash to set the exit status $? to a non-zero exit code if any of the
+ # commands fail:
+ set -o pipefail
+ # Direct command output to stdout/stderr while additionally storing stdout in the variable:
+ exec 9>&1 # Duplicates &1 to 9 (9 is a mostly arbitrary chosen number)
+ output=$($2 | tee >(cat - >&9))
+ # Store the last exit code:
+ exit_code=$?
+ if [ $exit_code -ne 0 ]
+ then
+ echo "Error: $1 failed with exit code $exit_code."
+ if [ -n "$3" ] && [ "$3" -eq 1 ] # if $3 is not empty ("-n" ^= "! -z") and equals 1
+ then
+ echo "... but continuing anyway."
+ else
+ exit $exit_code
+ fi
+ else
+ echo "Done."
+ fi
+}
+
+# If PUMA_CONFIG is not set and a default config from aspectc++ package is available, set PUMA_CONFIG to the default:
+if [ -z "$PUMA_CONFIG" ] && [ -f "/etc/puma.config" ]
+then
+ export PUMA_CONFIG="/etc/puma.config"
+ echo "Set PUMA_CONFIG to default config $PUMA_CONFIG."
+fi
+
+# Show a warning if tests are likely to fail:
+if [ -z "$PUMA_CONFIG" ]
+then
+ echo "----------------------------------------------------------------"
+ echo "WARNING: Neither /etc/puma.config exists nor PUMA_CONFIG is set."
+ echo " This may lead to failing tests due to failing includes."
+ echo " See README for more information."
+ echo "----------------------------------------------------------------"
+ sleep 2
+fi
+
+echo -e "Testing AspectC++ with clang versions $clang_version_array ..."
+
+for clang_version in $clang_version_array
+do
+ echo -e "\n------------------------------\n| AspectC++ with Clang $clang_version |\n------------------------------"
+ # In each loop, try to build and test with the current clang version. In all cases, clang_version_result_string
+ # contains either the test results or a message explaining why the build failed.
+
+ # Construct llvm-config path:
+ llvm_conf_path="${clang_dir_path_prefix}$clang_version/bin/llvm-config"
+ if [ ! -f "$llvm_conf_path" ]
+ then
+ echo "Error: Could not find Clang $clang_version llvm-config binary in $llvm_conf_path. Please check your clang directory paths and the config on top of this file. Skipping tests ..."
+ clang_version_result_string="Unable to build AspectC++: $llvm_conf_path does not exist."
+ else
+ # clang/llvm binaries/libraries are available. Construct build, clean and test commands:
+ acpp_build_command="$acpp_base_build_command LLVMCONF=$llvm_conf_path"
+ acpp_clean_command="$acpp_build_command clean"
+ acpp_testall_command="$acpp_build_command testall"
+ # Try building AspectC++:
+ run_command "Cleaning with Clang $clang_version" "$acpp_clean_command"
+ run_command "Building with Clang $clang_version" "$acpp_build_command" "1" # do not exit script on non-zero exit code
+ if [ $exit_code -ne 0 ]
+ then
+ clang_version_result_string="Unable to build AspectC++: Build command exited with non-zero exit code $exit_code."
+ else
+ # Build was successful: Run the tests:
+ run_command "Running tests with Clang $clang_version" "$acpp_testall_command" "1"
+ # Extract the test result summary line:
+ clang_version_result_string=$(echo "$output" | sed -n 2p) # second line of test output only
+ fi
+ fi
+ # Construct a string holding all clang versions' test result summaries:
+ overall_test_results="$overall_test_results\n$clang_version: $clang_version_result_string"
+
+ echo -e "\nTest results so far:$overall_test_results"
+done
+echo -e "\nOverall test results:$overall_test_results"
diff --git a/AspectC++/version.h b/AspectC++/version.h
index adbdb30..eae6960 100644
--- a/AspectC++/version.h
+++ b/AspectC++/version.h
@@ -47,6 +47,20 @@ static inline const char *ac_program() {return "ac++";}
#define VERSION_NUMBER_4_0_0 GET_VERSION_NUMBER(4, 0, 0)
#define VERSION_NUMBER_5_0_0 GET_VERSION_NUMBER(5, 0, 0)
#define VERSION_NUMBER_6_0_0 GET_VERSION_NUMBER(6, 0, 0)
+#define VERSION_NUMBER_7_0_0 GET_VERSION_NUMBER(7, 0, 0)
+#define VERSION_NUMBER_9_0_0 GET_VERSION_NUMBER(9, 0, 0)
+
+// StartLoc and EndLoc API change
+#if CLANG_VERSION_NUMBER >= VERSION_NUMBER_9_0_0
+#define CLANG_GET_LOC_END(ptr) ((ptr)->getEndLoc())
+#define CLANG_GET_START_LOC(ptr) ((ptr)->getBeginLoc())
+#define CLANG_GET_LOC_START(ptr) ((ptr)->getBeginLoc())
+#else
+#define CLANG_GET_LOC_END(ptr) ((ptr)->getLocEnd())
+#define CLANG_GET_START_LOC(ptr) ((ptr)->getStartLoc())
+#define CLANG_GET_LOC_START(ptr) ((ptr)->getLocStart())
+#endif
+
#endif // FRONTEND_CLANG
#endif // __version_h__
diff --git a/Puma/src/common/Config.cc b/Puma/src/common/Config.cc
index b9af574..76ff861 100644
--- a/Puma/src/common/Config.cc
+++ b/Puma/src/common/Config.cc
@@ -108,6 +108,8 @@ OptsParser::Option pumaOpts[] = {
{Config::SET_OPTION_ARG, NULL, "ptrdiff-type", "Set type for ptrdiff_t", OptsParser::AT_MANDATORY},
{Config::SET_OPTION_ARG, NULL, "target", "Set target triple, which determines sizes and alignments for built-in types", OptsParser::AT_MANDATORY},
{Config::SET_OPTION_ARG, NULL, "isystem", "Add a system include directory", OptsParser::AT_MANDATORY},
+ {Config::SET_OPTION_ARG, NULL, "isysroot", "Add a sysroot directory", OptsParser::AT_MANDATORY},
+ {Config::SET_OPTION_ARG, "F", NULL, "Add a framework include directory", OptsParser::AT_MANDATORY}, // macOS
{0, 0, 0, 0, OptsParser::AT_NONE}
};
diff --git a/Puma/src/compile.mk b/Puma/src/compile.mk
index 35e0004..8ac3392 100644
--- a/Puma/src/compile.mk
+++ b/Puma/src/compile.mk
@@ -82,7 +82,7 @@ $(OBJDIR)/%.o : %.c
$(DEPDIR)/%.d : %.cc
@echo "Generating dependencies for $(notdir $<)..."
@$(CXX) $(CPPFLAGS) -MM $(filter %.cc,$^) | \
- sed -e "s@$(*F)\.o@$(OBJDIR)/& $(DEPDIR)/$(*F).d@g" > $@
+ sed -e "s|$(*F)\.o|$(OBJDIR)/& $(DEPDIR)/$(*F).d|g" > $@
.PHONY: all showinfo