diff options
author | Reinhard Tartler <siretart@tauware.de> | 2020-02-29 18:15:17 -0500 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2020-02-29 18:15:17 -0500 |
commit | a4ac05fb82711919d01f98cc350ee817ebf5cfc7 (patch) | |
tree | 4d6abcd6d70502f5f610d32cd7d44c2864c4ece8 | |
parent | 03f550f8322a113f6b430cabfd83125edafcf4c6 (diff) | |
parent | 0a56b56f511f94b12d1ecbf73568332cda107816 (diff) |
Update upstream source from tag 'upstream/2.2+git20200229'
Update to upstream version '2.2+git20200229'
with Debian dir 23d9509c563bc846d67afae0ea41b55655e96a6f
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 |