From c908cba0e35451f8a5fc273b33dfed16cff328f5 Mon Sep 17 00:00:00 2001 From: Axel Naumann Date: Sun, 14 Sep 2014 12:02:09 +0200 Subject: [PATCH] Collect dependencies of forward declarations. --- core/metautils/src/TMetaUtils.cxx | 190 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 184 insertions(+), 6 deletions(-) diff --git a/core/metautils/src/TMetaUtils.cxx b/core/metautils/src/TMetaUtils.cxx index b598a47..5bc0ec5 100644 --- a/core/metautils/src/TMetaUtils.cxx +++ b/core/metautils/src/TMetaUtils.cxx @@ -32,10 +32,11 @@ #include "RStl.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" +#include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" -#include "clang/AST/CXXInheritance.h" -#include "clang/AST/Attr.h" +#include "clang/AST/Type.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/ModuleMap.h" @@ -4555,12 +4556,167 @@ const std::string& ROOT::TMetaUtils::GetPathSeparator() return gPathSeparator; } + +static void addDeclToTransaction(clang::Decl *decl, + cling::Transaction &theTransaction, + std::set &addedDecls); +static void addDeclsToTransactionForType(const clang::Type* typ, + cling::Transaction &theTransaction, + std::set &addedDecls); + +//______________________________________________________________________________ +static void addDeclsToTransactionForNNS(const clang::NestedNameSpecifier* NNS, + cling::Transaction &theTransaction, + std::set &addedDecls) { + if (const clang::NestedNameSpecifier* Prefix = NNS->getPrefix()) + addDeclsToTransactionForNNS(Prefix, theTransaction, addedDecls); + + switch (NNS->getKind()) { + case clang::NestedNameSpecifier::Namespace: + addDeclToTransaction(NNS->getAsNamespace(), theTransaction, addedDecls); + break; + case clang::NestedNameSpecifier::TypeSpec: // fall-through: + case clang::NestedNameSpecifier::TypeSpecWithTemplate: + addDeclsToTransactionForType(NNS->getAsType(), theTransaction, addedDecls); + break; + default: + ROOT::TMetaUtils::Error("addDeclsToTransactionForNNS", "Unexpected kind %d\n", + (int)NNS->getKind()); + break; + + }; +} + +static void addDeclsToTransactionForTemplateName(clang::TemplateName tName, + cling::Transaction &theTransaction, + std::set &addedDecls) { + switch (tName.getKind()) { + case clang::TemplateName::Template: + addDeclToTransaction(tName.getAsTemplateDecl(), theTransaction, addedDecls); + break; + case clang::TemplateName::QualifiedTemplate: + addDeclToTransaction(tName.getAsQualifiedTemplateName()->getTemplateDecl(), theTransaction, addedDecls); + break; + case clang::TemplateName::DependentTemplate: + addDeclsToTransactionForNNS(tName.getAsDependentTemplateName()->getQualifier(), theTransaction, addedDecls); + break; + case clang::TemplateName::SubstTemplateTemplateParm: + addDeclsToTransactionForTemplateName(tName.getAsSubstTemplateTemplateParm()->getReplacement(), theTransaction, addedDecls); + break; + /* needs TemplateArgument handling to be refactored + case clang::TemplateName::SubstTemplateTemplateParmPack: + addDeclsToTransactionForTemplateArgument(tName.getAsSubstTemplateTemplateParmPack()->getArgumentPack(), theTransaction, addedDecls); + break; + */ + default: + ROOT::TMetaUtils::Error("addDeclsToTransactionForTemplateName", "Unexpected kind %s\n", + tName.getKind()); + break; + } +} + +//______________________________________________________________________________ +static void addDeclsToTransactionForType(const clang::Type* typ, + cling::Transaction &theTransaction, + std::set &addedDecls) { + switch (typ->getTypeClass()) { + +#define R__ADD_UNDERLYING(WHAT, HOW) \ + case clang::Type::WHAT: \ + addDeclsToTransactionForType(static_cast(typ)->HOW().getTypePtr(), \ + theTransaction, addedDecls); \ + break + R__ADD_UNDERLYING(ConstantArray, getElementType); + R__ADD_UNDERLYING(DependentSizedArray, getElementType); + R__ADD_UNDERLYING(IncompleteArray, getElementType); + R__ADD_UNDERLYING(VariableArray, getElementType); + R__ADD_UNDERLYING(Atomic, getValueType); + R__ADD_UNDERLYING(Auto, getDeducedType); + R__ADD_UNDERLYING(Decltype, getUnderlyingType); + R__ADD_UNDERLYING(Paren, getInnerType); + R__ADD_UNDERLYING(Pointer, getPointeeType); + R__ADD_UNDERLYING(LValueReference, getPointeeType); + R__ADD_UNDERLYING(RValueReference, getPointeeType); + R__ADD_UNDERLYING(TypeOf, getUnderlyingType); + R__ADD_UNDERLYING(Elaborated, getNamedType); + R__ADD_UNDERLYING(UnaryTransform, getUnderlyingType); +#undef R__ADD_UNDERLYING + + case clang::Type::DependentName: { + const clang::NestedNameSpecifier* NNS = static_cast(typ)->getQualifier(); + addDeclsToTransactionForNNS(NNS, theTransaction, addedDecls); + } + break; + + case clang::Type::MemberPointer: + addDeclsToTransactionForType(static_cast(typ)->getPointeeType().getTypePtr(), + theTransaction, addedDecls); + addDeclsToTransactionForType(static_cast(typ)->getClass(), + theTransaction, addedDecls); + break; + + case clang::Type::Enum: + // intentional fall-through + case clang::Type::Record: + addDeclToTransaction(static_cast(typ)->getDecl(), + theTransaction, addedDecls); + break; + case clang::Type::TemplateSpecialization: { + const clang::TemplateSpecializationType* TST = static_cast(typ); + for (const clang::TemplateArgument& TA: *TST) { + switch (TA.getKind()) { + case clang::TemplateArgument::Type: + addDeclsToTransactionForType(TA.getAsType().getTypePtr(), theTransaction, addedDecls); + break; + case clang::TemplateArgument::Declaration: + addDeclToTransaction(TA.getAsDecl(), theTransaction, addedDecls); + break; + case clang::TemplateArgument::Template: // intentional fall-through: + case clang::TemplateArgument::Pack: + addDeclsToTransactionForTemplateName(TA.getAsTemplateOrTemplatePattern(), theTransaction, addedDecls); + break; + default: + ROOT::TMetaUtils::Error("addDeclsToTransactionForType", "Unexpected TemplateSpecializationType %s\n", + typ->getTypeClassName()); + break; + } + } + addDeclsToTransactionForTemplateName(TST->getTemplateName(), theTransaction, addedDecls); + } + break; + case clang::Type::Typedef: + addDeclToTransaction(static_cast(typ)->getDecl(), + theTransaction, addedDecls); + break; + + case clang::Type::TemplateTypeParm: + addDeclToTransaction(static_cast(typ)->getDecl(), + theTransaction, addedDecls); + break; + + case clang::Type::Builtin: + // Nothing to do. + break; + case clang::Type::TypeOfExpr: + // Nothing to do. + break; + + default: + ROOT::TMetaUtils::Error("addDeclsToTransactionForType", "Unexpected %s\n", + typ->getTypeClassName()); + break; + } + +} + //______________________________________________________________________________ static void addDeclToTransaction(clang::Decl *decl, cling::Transaction &theTransaction, std::set &addedDecls) { if (decl->isFromASTFile()) return; + if (!addedDecls.insert(decl).second) // no duplicates + return; // if (auto *nDecl = llvm::dyn_cast(decl)) { // if (cling::utils::Analyze::IsStdOrCompilerDetails(*nDecl)){ @@ -4568,13 +4724,33 @@ static void addDeclToTransaction(clang::Decl *decl, // } // } - // Templates + // Class template instances if (auto *tsd = llvm::dyn_cast(decl)) { - auto templ = tsd->getSpecializedTemplate(); - if (addedDecls.insert(templ).second) // no duplicates - theTransaction.append(tsd->getSpecializedTemplate()); + addDeclToTransaction(tsd->getSpecializedTemplate(), theTransaction, + addedDecls); + } else if (auto *td = llvm::dyn_cast(decl)) { + // default args of type params might need to be fwd declared, as in + // template > struct Y; + // needs X! + clang::TemplateParameterList &tdPars = *td->getTemplateParameters(); + // iterate over defaults. + for (int iArg = tdPars.getMinRequiredArguments(), + nArgs = tdPars.size(); iArg < nArgs; ++iArg) { + if (auto *ttpd = llvm::dyn_cast(tdPars.getParam(iArg))) { + addDeclToTransaction(ttpd, theTransaction, addedDecls); + } + } + } else if (auto *ttpd = llvm::dyn_cast(decl)) { + if (ttpd->hasDefaultArgument() && !ttpd->defaultArgumentWasInherited()) { + addDeclsToTransactionForType(ttpd->getDefaultArgument().getTypePtr(), + theTransaction, addedDecls); + } + // do not add the "T" of template to the + // transaction. + return; } + // Contexts auto *declForRecursion = decl; while (auto *ctxt = declForRecursion->getDeclContext()) { @@ -4586,6 +4762,8 @@ static void addDeclToTransaction(clang::Decl *decl, break; } } + + theTransaction.append(decl); } //______________________________________________________________________________ -- 1.8.2