From 7e7bfe7c9572e843e2ec2bef299053ec173d76b3 Mon Sep 17 00:00:00 2001 From: Axel Naumann <Axel.Naumann@cern.ch> Date: Mon, 19 May 2014 20:46:34 +0200 Subject: [PATCH] Also store typedefs in ROOT PCM. --- core/meta/src/TCling.cxx | 10 +- core/utils/src/rootcling.cxx | 253 +++++++++++++++-------------- core/utils/src/rootclingTCling.cxx | 25 ++- core/utils/src/rootclingTCling.h | 1 + 4 files changed, 163 insertions(+), 126 deletions(-) diff --git a/core/meta/src/TCling.cxx b/core/meta/src/TCling.cxx index db02a63e571..192fb1cb0f0 100644 --- a/core/meta/src/TCling.cxx +++ b/core/meta/src/TCling.cxx @@ -1017,8 +1017,16 @@ bool TCling::LoadPCM(TString pcmFileName, if (protoClasses) for(auto proto : *protoClasses) TClassTable::Add((TProtoClass*)proto); - protoClasses->Clear(); // Owner ship was transfered to TClassTable. + protoClasses->Clear(); // Ownership was transfered to TClassTable. delete protoClasses; + + TObjArray *dataTypes; + pcmFile->GetObject("__Typedefs", dataTypes); + if (dataTypes) + for (auto typedf: *dataTypes) + gROOT->GetListOfTypes()->Add(typedf); + dataTypes->Clear(); // Ownership was transfered to TListOfTypes. + delete dataTypes; delete pcmFile; gDebug = oldDebug; diff --git a/core/utils/src/rootcling.cxx b/core/utils/src/rootcling.cxx index 5da7f230922..a8814050721 100644 --- a/core/utils/src/rootcling.cxx +++ b/core/utils/src/rootcling.cxx @@ -281,8 +281,12 @@ static void EmitStreamerInfo(const char* normName) { AddStreamerInfoToROOTFile(normName); } +static void EmitTypedefs(const std::vector<clang::TypedefNameDecl*>& tdvec) { + for (const auto td: tdvec) + AddTypedefToROOTFile(td->getQualifiedNameAsString().c_str()); +} #else -static bool EmitStreamerInfo(const char*) { return true; } +static void EmitStreamerInfo(const char*) { } #endif //______________________________________________________________________________ @@ -379,12 +383,12 @@ void AnnotateFieldDecl(clang::FieldDecl& decl, for(iter = attrMap.begin();iter!=attrMap.end();iter++){ const std::string& name = iter->first; const std::string& value = iter->second; - + if (name == propNames::name) continue; - - /* This test is here since in ROOT5, when using genreflex, + + /* This test is here since in ROOT5, when using genreflex, * for pods, iotype is ignored */ - + if (name == propNames::iotype && ( decl.getType()->isArrayType() || decl.getType()->isPointerType() ) ){ const char* msg="Data member \"%s\" is an array or a pointer. " @@ -393,10 +397,10 @@ void AnnotateFieldDecl(clang::FieldDecl& decl, "which are not pointers or arrays.\n"; ROOT::TMetaUtils::Error("AnnotateFieldDecl", msg, varName.c_str(), value.c_str() ); - continue; + continue; } - - + + // These lines are here to use the root pcms. Indeed we need to annotate the AST // before persisting the ProtoClasses in the root pcms. // BEGIN ROOT PCMS @@ -795,7 +799,7 @@ void ParseRootMapFileNewFormat(ifstream& file, map<string,string>& autoloads) // For "class ", "namespace " and "typedef " respectively const std::unordered_map<char, unsigned int> keyLenMap = {{'c',6},{'n',10},{'t',8}}; - + while (getline(file, line, '\n')) { if (line == "{ decls }") { while (getline(file, line, '\n')) { @@ -1314,9 +1318,9 @@ void WriteClassFunctions(const clang::CXXRecordDecl *cl, std::ostream& dictStrea enclSpaceNesting = ROOT::TMetaUtils::WriteNamespaceHeader(dictStream, cl); } - if (autoLoad) + if (autoLoad) dictStream << "#include \"TInterpreter.h\"\n"; - + dictStream << "//_______________________________________" << "_______________________________________" << std::endl; if (add_template_keyword) dictStream << "template <> "; @@ -1362,7 +1366,7 @@ void WriteClassFunctions(const clang::CXXRecordDecl *cl, std::ostream& dictStrea dictStream << "TClass *" << clsname << "::Class()" << std::endl << "{" << std::endl; if (autoLoad){ dictStream << " Dictionary();\n"; - } + } else{ dictStream << " if (!fgIsA) fgIsA = ::ROOT::GenerateInitInstanceLocal((const ::"; dictStream << fullname << "*)0x0)->GetClass();" << std::endl; @@ -2045,7 +2049,7 @@ void GenerateLinkdef(int *argc, char **argv, int firstInputFile, } code_for_parser += "\n#endif\n"; - + } //______________________________________________________________________________ @@ -2173,7 +2177,7 @@ static int GenerateModule(TModuleGenerator& modGen, modGen.WriteRegistrationSource(dictStream, - inlineInputHeader, + inlineInputHeader, fwdDeclnArgsToKeepString, headersClassesMapString); @@ -2310,7 +2314,7 @@ void AddPlatformDefines(std::vector<std::string>& clingArgs) //______________________________________________________________________________ void ExtractFileName(const std::string& path, std::string& filename) { - // Extract the filename from a fullpath + // Extract the filename from a fullpath filename = llvm::sys::path::filename (path); } @@ -2444,7 +2448,7 @@ void ManipForRootmap(std::string& name) // * "*const" becomes "*-const" ReplaceAll(name,"*const","*-const"); - + // * "short int" becomes "short" ReplaceAll(name,"short int","short"); @@ -2509,7 +2513,7 @@ int CreateRootMapFile(const std::string& rootmapFileName, // The number used to have the same alignment of ROOT5 const int alignment=49; - + // Loop on selected classes and insert them in the rootmap std::string thisClassName; for (std::list<std::string>::const_iterator classNameIt=classesNames.begin(); @@ -2604,7 +2608,7 @@ int CreateNewRootMapFile(const std::string& rootmapFileName, rootmapFile << "namespace " << nsName << std::endl; } } - + // And typedefs. These are used just to trigger the autoload mechanism if (!typedefDecls.empty()){ rootmapFile << "# List of selected typedefs\n"; @@ -2645,14 +2649,14 @@ int PrepareArgsForFwdDecl(std::string& templateArgs, // E.g. template <template <typename> class T> class container { }; static const char* paramPackWarning="Template parameter pack found: autoload of variadic templates is not supported yet.\n"; - + templateArgs="<"; for (clang::TemplateParameterList::const_iterator prmIt = tmplParamList.begin(); - prmIt != tmplParamList.end(); prmIt++){ - + prmIt != tmplParamList.end(); prmIt++){ + if (prmIt != tmplParamList.begin()) templateArgs += ", "; - + clang::NamedDecl* nDecl = *prmIt; std::string typeName; @@ -2669,7 +2673,7 @@ int PrepareArgsForFwdDecl(std::string& templateArgs, else if (const clang::NonTypeTemplateParmDecl* nttpd = llvm::dyn_cast<clang::NonTypeTemplateParmDecl>(nDecl)){ const clang::QualType &theType = nttpd->getType(); // If this is an enum, use int as it is impossible to fwd declare and - // this makes sense since it is not a type... + // this makes sense since it is not a type... if (theType.getAsString().find("enum") != std::string::npos){ std::string astDump; llvm::raw_string_ostream ostream(astDump); @@ -2695,7 +2699,7 @@ int PrepareArgsForFwdDecl(std::string& templateArgs, return 1; } } - + templateArgs += typeName; } @@ -2711,10 +2715,10 @@ void EncloseInNamespaces(const clang::Decl& decl, // definition string. // For example, if the definition string is "myClass" which is enclosed by // the namespaces ns1 and ns2, one would get: - // namespace ns2{ namespace ns1 { class myClass; } } - + // namespace ns2{ namespace ns1 { class myClass; } } + // Before everyting - + std::list<std::pair<std::string,bool> > enclosingNamespaces; ROOT::TMetaUtils::ExtractEnclosingNameSpaces(decl,enclosingNamespaces); // Check if we have enclosing namespaces @@ -2732,16 +2736,16 @@ int ExtractNamespacesDefinition(const clang::RecordDecl& rDecl, std::string& definitionStr) { // Extract the namespace definition for rDecl - + const clang::RecordDecl* definition = rDecl.getDefinition(); if (!definition) return 1; EncloseInNamespaces(*definition, definitionStr); - + return 0; } - + //______________________________________________________________________________ int ExtractDefinitionFromRecordDecl(const clang::RecordDecl& rDecl, cling::Interpreter& interpreter, @@ -2749,7 +2753,7 @@ int ExtractDefinitionFromRecordDecl(const clang::RecordDecl& rDecl, { // Detect if the rDecl is a template instance. const clang::ClassTemplateSpecializationDecl* tmplSpecDecl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (&rDecl); - if (!tmplSpecDecl){ + if (!tmplSpecDecl){ return 1; } @@ -2772,12 +2776,12 @@ int ExtractTemplateDefinition(const clang::TemplateDecl& templDecl, { // Operate on the template declaration in order to get its forward declaration - + const clang::TemplateParameterList *tmplParamList= templDecl.getTemplateParameters(); if (!tmplParamList){ // Should never happen TMetaUtils::Error(0, "Cannot extract template parameter list for %s", templDecl.getNameAsString().c_str()); return 1; - } + } std::string templateArgs; @@ -2787,20 +2791,20 @@ int ExtractTemplateDefinition(const clang::TemplateDecl& templDecl, TMetaUtils::Warning(0, "Problems encountered while preparing arguments for forward declaration of class %s", templDecl.getNameAsString().c_str()); return retCode; } - + definitionStr="template "+templateArgs+" class "+templDecl.getNameAsString(); // iterate over the nested namespaces and complete the definition if (definition){ definitionStr += " ;"; - + // Check if we have enclosing namespaces - // FIXME: this should be active also for classes + // FIXME: this should be active also for classes EncloseInNamespaces(*definition, definitionStr); } - + return 0; } @@ -2830,7 +2834,7 @@ int ExtractSelectedClassesAndTemplateDefs(RScanner& scan, // An unordered_set to keep track of the existing classes. // We want to avoid duplicates there as they may hint to a serious corruption std::unordered_set<std::string> classesSet; - + std::string attrName,attrValue; bool isClassSelected; // Loop on selected classes and put them in a list @@ -2839,13 +2843,13 @@ int ExtractSelectedClassesAndTemplateDefs(RScanner& scan, isClassSelected = true; std::string normalizedName(selClassesIter->GetNormalizedName()); if (normalizedName.size()!=0 && !classesSet.insert(normalizedName).second){ - std::cerr << "FATAL: A class with normalized name " << normalizedName + std::cerr << "FATAL: A class with normalized name " << normalizedName << " was already selected. This means that two different instances of" << " clang::RecordDecl had the same name, which is not possible." << " This can be a hint of a serious problem in the class selection." << " In addition, the generated dictionary would not even compile.\n"; return 1; - } + } classesList.push_back(normalizedName); const clang::RecordDecl* rDecl = selClassesIter->GetRecordDecl(); @@ -2907,9 +2911,9 @@ int GenerateFullDict(std::ostream& dictStream, RScanner::ClassColl_t::const_iterator end = scan.fSelectedClasses.end(); bool needsCollectionProxy = false; - + if (!onepcm) { - + // // We will loop over all the classes several times. // In order we will call @@ -2965,6 +2969,7 @@ int GenerateFullDict(std::ostream& dictStream, } #ifndef ROOT_STAGE1_BUILD + EmitTypedefs(scan.fSelectedTypedefs); // Make up for skipping RegisterModule, now that dictionary parsing // is done and these headers cannot be selected anymore. interp.parseForModule("#include \"TStreamerInfo.h\"\n" @@ -3067,7 +3072,7 @@ int GenerateFullDict(std::ostream& dictStream, // coverity[fun_call_w_exception] - that's just fine. ROOT::RStl::Instance().WriteClassInit(dictStream, interp, normCtxt, ctorTypes, needsCollectionProxy); } - + return 0; } @@ -3109,7 +3114,7 @@ void CreateDictHeader(std::ostream& dictStream, const std::string& main_dictname #ifndef R__SOLARIS dictStream << "// Since CINT ignores the std namespace, we need to do so in this file.\n" << "namespace std {} using namespace std;\n\n"; - #endif + #endif } //______________________________________________________________________________ @@ -3192,7 +3197,7 @@ public: std::ifstream ifile(tmpName); if (!ifile) ROOT::TMetaUtils::Error(0, "Cannot find %s!\n", tmpName); - + if ( 0 != std::remove( tmpName )){ ROOT::TMetaUtils::Error(0, "Removing %s!\n", tmpName); retval++; @@ -3200,7 +3205,7 @@ public: } return retval; } - + //______________________________________________ int commit(){ int retval=0; @@ -3263,15 +3268,15 @@ void CheckForMinusW(const char* arg, // Transform -W statements in diagnostic pragmas for cling reacting on "-Wno-" // For example // -Wno-deprecated-declarations --> #pragma clang diagnostic ignored "-Wdeprecated-declarations" - + const std::string pattern("-Wno-"); - + std::string localArg(arg); if ( localArg.find(pattern) != 0 ) return; - + ReplaceAll(localArg,pattern,"#pragma clang diagnostic ignored \"-W"); localArg+="\""; - diagnosticPragmas.push_back(localArg); + diagnosticPragmas.push_back(localArg); } //______________________________________________________________________________ @@ -3279,7 +3284,7 @@ std::string GetFwdDeclnArgsToKeepString(const ROOT::TMetaUtils::TNormalizedCtxt& cling::Interpreter& interp) { std::string fwdDecl; - std::string initStr("{"); + std::string initStr("{"); auto& fwdDeclnArgsToSkipColl = normCtxt.GetTemplNargsToKeepMap(); for (auto& strigNargsToKeepPair : fwdDeclnArgsToSkipColl){ auto& clTemplDecl = *strigNargsToKeepPair.first; @@ -3287,7 +3292,7 @@ std::string GetFwdDeclnArgsToKeepString(const ROOT::TMetaUtils::TNormalizedCtxt& interp, fwdDecl); fwdDecl+=" ;"; - EncloseInNamespaces(clTemplDecl,fwdDecl); + EncloseInNamespaces(clTemplDecl,fwdDecl); initStr+="{\""+ fwdDecl+"\", " +std::to_string(strigNargsToKeepPair.second) @@ -3295,9 +3300,9 @@ std::string GetFwdDeclnArgsToKeepString(const ROOT::TMetaUtils::TNormalizedCtxt& } if (!fwdDeclnArgsToSkipColl.empty()) initStr.pop_back(); - initStr+="}"; + initStr+="}"; return initStr; -} +} //______________________________________________________________________________ clang::QualType GetPointeeTypeIfPossible(const clang::QualType& qt) @@ -3317,29 +3322,29 @@ clang::QualType GetPointeeTypeIfPossible(const clang::QualType& qt) std::list<std::string> RecordDecl2Headers(const clang::CXXRecordDecl& rcd, const cling::Interpreter& interp, std::set<const clang::CXXRecordDecl*>& visitedDecls) -{ - // Extract the list of headers necessary for the Decl - std::list<std::string> headers; - +{ + // Extract the list of headers necessary for the Decl + std::list<std::string> headers; + // Avoid infinite recursion if (!visitedDecls.insert(rcd.getCanonicalDecl()).second) - return headers; - + return headers; + // If this is a template if (const clang::ClassTemplateSpecializationDecl* tsd = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&rcd)){ - + // Loop on the template args for (auto& tArg : tsd->getTemplateArgs().asArray()){ if (clang::TemplateArgument::ArgKind::Type != tArg.getKind()) continue; auto tArgQualType = GetPointeeTypeIfPossible(tArg.getAsType()); - if (tArgQualType.isNull()) continue; + if (tArgQualType.isNull()) continue; if (const clang::CXXRecordDecl* tArgCxxRcd = tArgQualType->getAsCXXRecordDecl()){ headers.splice(headers.end(), RecordDecl2Headers(*tArgCxxRcd, interp, visitedDecls)); } - } - + } + if(!ROOT::TMetaUtils::IsStdClass(rcd) && rcd.hasDefinition()){ - + // Loop on base classes - with a newer llvm, range based possible for (auto baseIt=tsd->bases_begin();baseIt!=tsd->bases_end();baseIt++){ auto baseQualType = GetPointeeTypeIfPossible(baseIt->getType()); @@ -3347,20 +3352,20 @@ std::list<std::string> RecordDecl2Headers(const clang::CXXRecordDecl& rcd, if (const clang::CXXRecordDecl* baseRcdPtr = baseQualType->getAsCXXRecordDecl()){ headers.splice(headers.end(), RecordDecl2Headers(*baseRcdPtr, interp, visitedDecls)); } - } - + } + // Loop on the data members - with a newer llvm, range based possible for (auto declIt = tsd->decls_begin(); declIt != tsd->decls_end(); ++declIt) { if (const clang::FieldDecl* fieldDecl = llvm::dyn_cast<clang::FieldDecl>(*declIt)){ auto fieldQualType = GetPointeeTypeIfPossible(fieldDecl->getType()); - if (fieldQualType.isNull() ) continue ; + if (fieldQualType.isNull() ) continue ; if (const clang::CXXRecordDecl* fieldCxxRcd = fieldQualType->getAsCXXRecordDecl()){ if (fieldCxxRcd->hasDefinition()) headers.splice(headers.end(), RecordDecl2Headers(*fieldCxxRcd, interp, visitedDecls)); } } } - + // Loop on methods for (auto methodIt = tsd->method_begin(); methodIt!=tsd->method_end();++methodIt){ // Check arguments @@ -3378,17 +3383,17 @@ std::list<std::string> RecordDecl2Headers(const clang::CXXRecordDecl& rcd, if (const clang::CXXRecordDecl* retCxxRcd = retQualType->getAsCXXRecordDecl()){ if (retCxxRcd->hasDefinition()) headers.splice(headers.end(), RecordDecl2Headers(*retCxxRcd, interp, visitedDecls)); - } + } } } - + } // End template instance - - std::string header = ROOT::TMetaUtils::GetFileName(rcd, interp); + + std::string header = ROOT::TMetaUtils::GetFileName(rcd, interp); headers.emplace_back(header); headers.reverse(); return headers; - + } //______________________________________________________________________________ @@ -3399,9 +3404,9 @@ void ExtractHeadersForClasses(const RScanner::ClassColl_t& annotatedRcds, { std::set<const clang::CXXRecordDecl*> visitedDecls; std::unordered_set<std::string> buffer; - // Add some manip of headers + // Add some manip of headers for (auto& annotatedRcd : annotatedRcds){ - if (const clang::CXXRecordDecl* cxxRcd = + if (const clang::CXXRecordDecl* cxxRcd = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(annotatedRcd.GetRecordDecl())){ visitedDecls.clear(); std::list<std::string> headers (RecordDecl2Headers(*cxxRcd,interp,visitedDecls)); @@ -3428,9 +3433,9 @@ void ExtractHeadersForClasses(const RScanner::ClassColl_t& annotatedRcds, const std::string GenerateStringFromHeadersForClasses (const HeadersClassesMap_t& headersClassesMap, const std::string& detectedUmbrella) { - // Generate a string for the dictionary from the headers-classes map. + // Generate a string for the dictionary from the headers-classes map. std::string headerName; - + if (genreflex::verbose) std::cout << "Class-headers Mapping:\n"; std::string headersClassesMapString="static const char* classesHeaders[]={\n"; @@ -3439,13 +3444,13 @@ const std::string GenerateStringFromHeadersForClasses (const HeadersClassesMap_t std::cout << " o " << classHeaders.first << " --> "; headersClassesMapString+="\""; headersClassesMapString+=classHeaders.first+"\""; - for (auto& header : classHeaders.second){ + for (auto& header : classHeaders.second){ headerName = (detectedUmbrella==header) ? "payloadCode" : "\""+header+"\""; - headersClassesMapString+=", "+ headerName; + headersClassesMapString+=", "+ headerName; if (genreflex::verbose) std::cout << ", " << headerName; } - if (genreflex::verbose) + if (genreflex::verbose) std::cout << std::endl; headersClassesMapString+=", \"@\",\n"; } @@ -3678,7 +3683,7 @@ int RootCling(int argc, // Collect the diagnostic pragmas linked to the usage of -W // Workaround for ROOT-5656 std::list<std::string> diagnosticPragmas; - + int nextStart = 0; while (ic < argc) { if (*argv[ic] == '-' || *argv[ic] == '+') { @@ -3723,22 +3728,22 @@ int RootCling(int argc, interpreteronly = true; ic+=1; continue; - } + } if (strcmp("-split", argv[ic]) == 0) { // Split the dict doSplit = true; ic+=1; continue; - } + } if (strcmp("-noDictSelection", argv[ic]) == 0) { // Disable selection dictSelection = false; ic+=1; continue; - } - + } + if (strcmp("-s", argv[ic]) == 0 && (ic+1) < argc) { // Target shared library name sharedLibraryPathName = argv[ic+1]; @@ -3752,8 +3757,8 @@ int RootCling(int argc, baseModules.push_back(argv[ic+1]); ic+=2; continue; - } - + } + if (strcmp("+P", argv[ic]) == 0 || strcmp("+V", argv[ic]) == 0 || strcmp("+STUB", argv[ic]) == 0) { @@ -3984,12 +3989,12 @@ int RootCling(int argc, string incCurDir = "-I"; incCurDir += currentDirectory; pcmArgs.push_back(incCurDir); - - TModuleGenerator modGen(interp.getCI(), + + TModuleGenerator modGen(interp.getCI(), sharedLibraryPathName.c_str()); - + interp.declare("#pragma clang diagnostic ignored \"-Wdeprecated-declarations\""); - + // Add the diagnostic pragmas distilled from the -Wno-xyz for (std::list<std::string>::iterator dPrIt = diagnosticPragmas.begin(); dPrIt != diagnosticPragmas.end(); dPrIt++){ @@ -4074,16 +4079,16 @@ int RootCling(int argc, return 1; } } - + // Exclude string not to re-generatre the dictionary std::vector<std::pair<std::string,std::string>> namesForExclusion; if (!buildingROOT){ namesForExclusion.push_back(std::make_pair(ROOT::TMetaUtils::propNames::name,"std::string")); namesForExclusion.push_back(std::make_pair(ROOT::TMetaUtils::propNames::pattern,"ROOT::Meta::Selection*")); } - + SelectionRules selectionRules(interp,normCtxt,namesForExclusion); - + std::string extraIncludes; ROOT::TMetaUtils::RConstructorTypes constructorTypes; @@ -4092,7 +4097,7 @@ int RootCling(int argc, clang::CompilerInstance* CI = interp.getCI(); if(dictSelection && !onepcm) DictSelectionReader dictSelReader (selectionRules,CI->getASTContext()); - + bool isSelXML = IsSelectionXml(linkdefFilename.c_str()); if (requestAllSymbols && !isSelXML) { @@ -4193,7 +4198,7 @@ int RootCling(int argc, selectionRules.SearchNames(interp); int scannerVerbLevel = 0; - { + { using namespace ROOT::TMetaUtils; scannerVerbLevel = (gErrorIgnoreLevel == kInfo || (isGenreflex && gErrorIgnoreLevel != kFatal)) ? 1:0; } @@ -4204,13 +4209,13 @@ int RootCling(int argc, scanType = RScanner::EScanType::kOnePCM; if (dictSelection) scanType = RScanner::EScanType::kTwoPasses; - + RScanner scan(selectionRules, scanType, interp, normCtxt, scannerVerbLevel); - + // If needed initialize the autoloading hook if (liblistPrefix.length()) { LoadLibraryMap(liblistPrefix + ".in", gAutoloads); @@ -4258,7 +4263,7 @@ int RootCling(int argc, // Be a little bit makefile friendly and remove the dictionary in case of error. // We could add an option -k to keep the file even in case of error. exit(1); - } + } //--------------------------------------------------------------------------- // Write all the necessary #include @@ -4281,7 +4286,7 @@ int RootCling(int argc, InitializeStreamerInfoROOTFile(modGen.GetModuleFileName().c_str()); #endif } - + int retCode = GenerateFullDict(splitDictStream, interp, scan, @@ -4296,7 +4301,7 @@ int RootCling(int argc, } if (doSplit && splitDictStreamPtr) delete splitDictStreamPtr; - + // Now we have done all our looping and thus all the possible // annotation, let's write the pcms. HeadersClassesMap_t headersClassesMap; @@ -4305,14 +4310,14 @@ int RootCling(int argc, ExtractHeadersForClasses(scan.fSelectedClasses, scan.fSelectedTypedefs, headersClassesMap, - interp); - + interp); + std::string detectedUmbrella; for (auto& arg : pcmArgs){ if (inlineInputHeader && !IsLinkdefFile(arg.c_str()) && IsHeaderName(arg)){ detectedUmbrella=arg; break; - } + } } const std::string headersClassesMapString = GenerateStringFromHeadersForClasses(headersClassesMap,detectedUmbrella); @@ -4351,11 +4356,11 @@ int RootCling(int argc, // Create rootmap and capabilities files - std::string rootmapLibName = std::accumulate(rootmapLibNames.begin(), + std::string rootmapLibName = std::accumulate(rootmapLibNames.begin(), rootmapLibNames.end(), - std::string(), + std::string(), [](const std::string& a, const std::string& b){return a+" "+b;}); - + bool rootMapNeeded = !rootmapFileName.empty() || !rootmapLibName.empty(); bool capaNeeded=!capaFileName.empty(); @@ -4367,16 +4372,16 @@ int RootCling(int argc, classesNames, classesNamesForRootmap, classesDefsList, - interp); + interp); if (0!=retCode) return retCode; // Create the rootmapfile if needed - if (rootMapNeeded){ - + if (rootMapNeeded){ + std::list<std::string> nsNames; - + ExtractSelectedNamespaces(scan,nsNames); - + AdjustRootMapNames(rootmapFileName, rootmapLibName); @@ -4387,7 +4392,7 @@ int RootCling(int argc, tmpCatalog.addFileName(rootmapFileName); int rmStatusCode = 0; if (useNewRmfFormat){ - + rmStatusCode = CreateNewRootMapFile(rootmapFileName, rootmapLibName, classesDefsList, @@ -4425,7 +4430,7 @@ int RootCling(int argc, } namespace genreflex{ - + //______________________________________________________________________________ bool endsWith(const std::string& theString, const std::string& theSubstring) { @@ -4657,7 +4662,7 @@ int invokeRootCling(const std::string& verbosity, // Split dictionaries if (doSplit) argvVector.push_back(string2charptr("-split")); - + // Targetlib if (!targetLibName.empty()){ argvVector.push_back(string2charptr("-s")); @@ -5001,7 +5006,7 @@ int GenReflex(int argc, char **argv) "" , "split", option::Arg::None, "--split\tSplit the dictionary in two, isolating the part with ClassDef related functions in a separate file\n"}, - + {PCMFILENAME, STRING , "m" , "" , @@ -5061,8 +5066,8 @@ int GenReflex(int argc, char **argv) STRING , "W" , "" , option::FullArg::Required, - ""}, - + ""}, + // Options that rise warnings {NOMEMBERTYPEDEFS, STRING , @@ -5139,9 +5144,9 @@ int GenReflex(int argc, char **argv) // // Warn if a selection file is not present and exit // if (NULL==options[SELECTIONFILENAME].arg){ // ROOT::TMetaUtils::Warning(0,"The usage of genreflex without a selection file is not yet supported.\n"); -// return 1; +// return 1; // } - + // Set the parameters for the rootmap file. If the libname is not set, // it will be set according to the header in invokeRootCling. @@ -5185,7 +5190,7 @@ int GenReflex(int argc, char **argv) bool doSplit = false; if (options[SPLIT]) doSplit=true; - + // Add the .so extension to the rootmap lib if not there if (!rootmapLibName.empty() && !endsWith(rootmapLibName,gLibraryExtension)){ rootmapLibName+=gLibraryExtension; @@ -5209,10 +5214,10 @@ int GenReflex(int argc, char **argv) // Includes std::vector<std::string> includes; extractMultipleOptions(options,INCLUDE, includes); - + // Warnings std::vector<std::string> warnings; - extractMultipleOptions(options, WARNING, warnings); + extractMultipleOptions(options, WARNING, warnings); // The outputfilename(s) // There are two cases: diff --git a/core/utils/src/rootclingTCling.cxx b/core/utils/src/rootclingTCling.cxx index 1d25f98d891..87f2059b737 100644 --- a/core/utils/src/rootclingTCling.cxx +++ b/core/utils/src/rootclingTCling.cxx @@ -22,6 +22,7 @@ std::string gPCMFilename; std::vector<std::string> gClassesToStore; +std::vector<std::string> gTypedefsToStore; std::vector<std::string> gAncestorPCMsNames; extern "C" @@ -53,6 +54,12 @@ void AddStreamerInfoToROOTFile(const char* normName) gClassesToStore.emplace_back(normName); } +extern "C" +void AddTypedefToROOTFile(const char* tdname) +{ + gTypedefsToStore.push_back(tdname); +} + extern "C" void AddAncestorPCMROOTFile(const char* pcmName) { @@ -68,7 +75,7 @@ bool CloseStreamerInfoROOTFile() TVirtualStreamerInfo::SetFactory(new TStreamerInfo()); TObjArray protoClasses; - for (const auto& normName: gClassesToStore) { + for (const auto normName: gClassesToStore) { TClass* cl = TClass::GetClass(normName.c_str(), kTRUE /*load*/); if (!cl) { std::cerr << "ERROR in CloseStreamerInfoROOTFile(): cannot find class " @@ -85,6 +92,21 @@ bool CloseStreamerInfoROOTFile() protoClasses.AddLast(new TProtoClass(cl)); } + TObjArray typedefs; + for (const auto dtname: gTypedefsToStore) { + TDataType* dt = (TDataType*)gROOT->GetListOfTypes()->FindObject(dtname.c_str()); + if (!dt) { + std::cerr << "ERROR in CloseStreamerInfoROOTFile(): cannot find class " + << dtname << '\n'; + return false; + } + if (dt->GetType() == -1) { + dt->Property(); // Force initialization of the bits and property fields. + dt->GetTypeName(); // Force caching of type name. + typedefs.AddLast(dt); + } + } + // Don't use TFile::Open(); we don't need plugins. TFile dictFile(gPCMFilename.c_str(), "RECREATE"); if (dictFile.IsZombie()) @@ -92,6 +114,7 @@ bool CloseStreamerInfoROOTFile() // Instead of plugins: protoClasses.Write("__ProtoClasses", TObject::kSingleKey); protoClasses.Delete(); + typedefs.Write("__Typedefs", TObject::kSingleKey); dictFile.WriteObjectAny(&gAncestorPCMsNames, "std::vector<std::string>", "__AncestorPCMsNames"); diff --git a/core/utils/src/rootclingTCling.h b/core/utils/src/rootclingTCling.h index 20d3936de7a..414a7ca5aac 100644 --- a/core/utils/src/rootclingTCling.h +++ b/core/utils/src/rootclingTCling.h @@ -24,6 +24,7 @@ extern "C" { cling::Interpreter* TCling__GetInterpreter(); void InitializeStreamerInfoROOTFile(const char* filename); void AddStreamerInfoToROOTFile(const char* normName); + void AddTypedefToROOTFile(const char* tdname); void AddAncestorPCMROOTFile(const char* pcmName); bool CloseStreamerInfoROOTFile(); } -- GitLab