diff --git a/core/meta/inc/TClass.h b/core/meta/inc/TClass.h index d434ed68a3d0deeb82ab2471f243535ddf8cb32c..e6512c63004e244538b1d9d8182cac23c216ee97 100644 --- a/core/meta/inc/TClass.h +++ b/core/meta/inc/TClass.h @@ -258,6 +258,9 @@ private: protected: TVirtualStreamerInfo *FindStreamerInfo(TObjArray* arr, UInt_t checksum) const; static THashTable *GetClassTypedefHash(); + void GetMissingDictionariesForBaseClasses(TCollection& result, bool recurse); + void GetMissingDictionariesForMembers(TCollection& result, bool recurse); + void GetMissingDictionariesWithRecursionCheck(TCollection& result, bool recurse); public: TClass(); @@ -372,7 +375,7 @@ public: TVirtualStreamerInfo *FindStreamerInfoAbstractEmulated(UInt_t checksum) const; const type_info *GetTypeInfo() const { return fTypeInfo; }; Bool_t HasDictionary(); - void GetMissingDictionaries(TObjArray& result, bool recurse = false); + void GetMissingDictionaries(THashTable& result, bool recurse = false); void IgnoreTObjectStreamer(Bool_t ignore=kTRUE); Bool_t InheritsFrom(const char *cl) const; Bool_t InheritsFrom(const TClass *cl) const; diff --git a/core/meta/inc/TInterpreter.h b/core/meta/inc/TInterpreter.h index a2db7281c5ba1b827487dd9ad15688e46e434b4b..d313526da482bd98b02bbfcbbda793bdb56ce737 100644 --- a/core/meta/inc/TInterpreter.h +++ b/core/meta/inc/TInterpreter.h @@ -120,8 +120,6 @@ public: virtual const char *GetIncludePath() = 0; virtual const char *GetSTLIncludePath() const { return ""; } virtual TObjArray *GetRootMapFiles() const = 0; - virtual Bool_t HasDictionary(TClass* cl) = 0; - virtual void GetMissingDictionaries(TClass* cl, TObjArray& result, bool recurse = false) = 0; virtual void Initialize() = 0; virtual void InspectMembers(TMemberInspector&, const void* obj, const TClass* cl, Bool_t isTransient) = 0; virtual Bool_t IsLoaded(const char *filename) const = 0; diff --git a/core/meta/src/TClass.cxx b/core/meta/src/TClass.cxx index 36903902b3c30cfa60f691c49f4d70be042f5473..275a851ce37e76cff6cd5f9907393c737c4f2589 100644 --- a/core/meta/src/TClass.cxx +++ b/core/meta/src/TClass.cxx @@ -3369,20 +3369,137 @@ void TClass::GetMenuItems(TList *list) } } +//______________________________________________________________________________ Bool_t TClass::HasDictionary() { // Check whether a class has a dictionary or not. - return gInterpreter->HasDictionary(this); + if (gClassTable->GetDict(fName)) return true; + + return false; +} + +//______________________________________________________________________________ +void TClass::GetMissingDictionariesForBaseClasses(TCollection& result, bool recurse) +{ + // Verify the base classes always. + + TList* lb = GetListOfBases(); + if (!lb) return; + TIter nextBase(lb); + TBaseClass* base = 0; + while ((base = (TBaseClass*)nextBase())) { + TClass* baseCl = base->Class(); + if (baseCl) { + baseCl->GetMissingDictionariesWithRecursionCheck(result, recurse); + } + } +} + +//______________________________________________________________________________ +void TClass::GetMissingDictionariesForMembers(TCollection& result, bool recurse) +{ + // Verify the Data Members. + + TListOfDataMembers* ldm = (TListOfDataMembers*)GetListOfDataMembers(); + if (!ldm) return ; + TIter nextMemb(ldm); + TDataMember * dm = 0; + while ((dm = (TDataMember*)nextMemb())) { + // If it is a built-in data type. + TClass* dmTClass = 0; + if (dm->GetDataType()) { + dmTClass = dm->GetDataType()->Class(); + // Otherwise get the string representing the type. + } else if (dm->GetTypeName()) { + dmTClass = TClass::GetClass(dm->GetTypeName()); + } + if (dmTClass) { + dmTClass->GetMissingDictionariesWithRecursionCheck(result, recurse); + } + } +} + +//______________________________________________________________________________ +void TClass::GetMissingDictionariesWithRecursionCheck(TCollection& result, bool recurse) +{ + // From the second level of recursion onwards it is different state check. + + if (result.FindObject(this)) return; + + static TClassRef sCIString("string"); + if (this == sCIString) return; + + if (strncmp(fName, "pair<", 5) == 0) return; + + if (!HasDictionary()) { + result.Add(this); + } + //Check whether a custom streamer + if (!TestBit(TClass::kHasCustomStreamerMember)) { + if (GetCollectionProxy()) { + // We need to look at the collection's content + // The collection has different kind of elements the check would be required. + TClass* t = 0; + if ((t = GetCollectionProxy()->GetValueClass())) { + if (!t->HasDictionary()) { + if (recurse) { + t->GetMissingDictionariesWithRecursionCheck(result, recurse); + } else { + result.Add(this); + } + } + } + } else { + if (recurse) { + GetMissingDictionariesForMembers(result, recurse); + } + GetMissingDictionariesForBaseClasses(result, recurse); + } + } } -void TClass::GetMissingDictionaries(TObjArray& result, bool recurse) +//______________________________________________________________________________ +void TClass::GetMissingDictionaries(THashTable& result, bool recurse) { - // Get the classes that have a missing dictionary. - // Recurse over the data members using the flag recurse. - // By default is is not recursing on the data members. + // Get the classes that have a missing dictionary starting from this one. + // With recurse = false the classes checked for missing dictionaries are: + // the class itself, all base classes, direct data members, + // and for collection proxies the container's + // elements without iterating over the element's data members; + // With recurse = true the classes checked for missing dictionaries are: + // the class itself, all base classes, recursing on the data members, + // and for the collection proxies recursiong on the elements of the + // collection and iterating over the element's data members. + + // Top level recursion it different from the following levels of recursion. + + if (result.FindObject(this)) return; - gInterpreter->GetMissingDictionaries(this, result, recurse); + static TClassRef sCIString("string"); + if (this == sCIString) return; + + if (strncmp(fName, "pair<", 5) == 0) return; + + if (!HasDictionary()) { + result.Add(this); + } + //Check whether a custom streamer + if (!TestBit(TClass::kHasCustomStreamerMember)) { + if (GetCollectionProxy()) { + // We need to look at the collection's content + // The collection has different kind of elements the check would be required. + TClass* t = 0; + if ((t = GetCollectionProxy()->GetValueClass())) { + if (!t->HasDictionary()) { + t->GetMissingDictionariesWithRecursionCheck(result, recurse); + } + } + } else { + GetMissingDictionariesForMembers(result, recurse); + GetMissingDictionariesForBaseClasses(result, recurse); + } + } } //______________________________________________________________________________ diff --git a/core/meta/src/TCling.cxx b/core/meta/src/TCling.cxx index 192fb1cb0f0ca4c9b6b1f0e6e8df49d18d5c854c..6d09670e5f0444b07d55d0fc3c44cabb1f1b871a 100644 --- a/core/meta/src/TCling.cxx +++ b/core/meta/src/TCling.cxx @@ -3409,154 +3409,6 @@ void TCling::GetInterpreterTypeName(const char* name, std::string &output, Bool_ return; } -//______________________________________________________________________________ -Bool_t TCling::HasDictionary(TClass* cl) -{ - // Check whether a class has a dictionary or not. - - // Get the Decl and Type for the class. - TClingClassInfo* cli = (TClingClassInfo*)cl->GetClassInfo(); - if (!cli) return false; - const clang::Decl* D = cli->GetDecl(); - const clang::Type* T = cli->GetType(); - - // Convert to RecordDecl. - if (llvm::isa<clang::RecordDecl>(D)) { - - // Get the name of the class - std::string buf; - ROOT::TMetaUtils::GetNormalizedName(buf, QualType(T, 0), *fInterpreter, *fNormalizedCtxt); - const char* name = buf.c_str(); - - // Check for the dictionary of the curent class. - if (gClassTable->GetDict(name)) - return true; - } - return false; -} - -//______________________________________________________________________________ -bool TCling::InsertMissingDictionaryDecl(const clang::Decl* D, std::set<std::string> &netD, clang::QualType qType, bool recurse) -{ - - // Utility function to insert a type pointer to a decl that does not have a dictionary - // In the set of pointer for the classes without dictionaries. - - // Get the name of the class. - - // If we deal with a std::string we do not need to recurse and we do not need to get the normalized name - // because we want to now if it is a std string or not. - if (strcmp(qType.getAsString().c_str(), "std::string")==0) return false; - std::string buf; - ROOT::TMetaUtils::GetNormalizedName(buf, qType, *fInterpreter, *fNormalizedCtxt); - const char* name = buf.c_str(); - - // Check whether the type pointer is not already in the set. - std::set<std::string>::iterator it = netD.find(name); - if (it != netD.end()) return false; - - // Check for the dictionary of the curent class. - if (TClass* t = TClass::GetClass(name)) { - //Check whether a custom streamer - if (t->TestBit(TClass::kHasCustomStreamerMember)) return false; - // Deal with proxies. - if (t->GetCollectionProxy()) { - // We need to make sure the collection proxy is not emulated - if ((t->GetCollectionProxy()->GetProperties() & TVirtualCollectionProxy::kIsEmulated) != 0) { - // oups we are missing the dictionary for the collection. - netD.insert(name); - return false; - } else { - // We need to *not* look at t but instead at its content - // The collection has different kind of elements the check would be required. - if ((t = t->GetCollectionProxy()->GetValueClass())) { - if (TClingClassInfo* ti = (TClingClassInfo*)t->GetClassInfo()) { - if(const clang::Type* elemType = ti->GetType()) { - // Get the name of the class. - std::string elemBuf; - ROOT::TMetaUtils::GetNormalizedName(elemBuf, QualType(elemType, 0), *fInterpreter, *fNormalizedCtxt); - const char* elemName = elemBuf.c_str(); - if (!gClassTable->GetDict(elemName)) { - std::set<std::string>::iterator it = netD.find(elemName); - if (it != netD.end()) return false; - netD.insert(elemName); - } - } - } - } - return true; - } - } - } - if (!gClassTable->GetDict(name)) { - netD.insert(name); - } - - return true; -} -//______________________________________________________________________________ -void TCling::GetMissingDictionariesForDecl(const clang::Decl* D, std::set<std::string> &netD, clang::QualType qType, bool recurse) -{ - // Utility function to get the missing dictionaries for a record decl. - // Checks all the data members and if the recurse flag is true it recurses over contents of the data members. - - // Insert this Type pointer in the set if it is not already there and it does not have a dictionary. - if (!InsertMissingDictionaryDecl(D, netD, qType, recurse)) return; - - // Verify the Data members. - if (const clang::CXXRecordDecl* RD = llvm::dyn_cast<clang::CXXRecordDecl>(D)) { - for (clang::RecordDecl::field_iterator iField = RD->field_begin(), - eField = RD->field_end(); iField != eField; ++iField) { - - clang::QualType fieldQualType = (*iField)->getType(); - if (!fieldQualType.isNull()) { - // Check if not NullType. - //if (const clang::TypedefType* TD = dyn_cast<clang::TypedefType>(fieldQualType.getTypePtr())) { - if (const clang::Type* fieldType = ROOT::TMetaUtils::GetUnderlyingType(fieldQualType)) { - clang::Decl* FD = fieldType->getAsCXXRecordDecl(); - if (FD) { - if(recurse) { - GetMissingDictionariesForDecl(FD, netD, QualType(fieldType, 0), recurse); - } else { - InsertMissingDictionaryDecl(FD, netD, QualType(fieldType, 0), recurse); - } - } - } - } - } - } -} - -//______________________________________________________________________________ -void TCling::GetMissingDictionaries(TClass* cl, TObjArray& result, bool recurse /*recurse*/) -{ - // Get the missing dictionaries for a given TClass cl. - - // Get the Decl and Type for the class. - TClingClassInfo* cli = (TClingClassInfo*)cl->GetClassInfo(); - if (!cli){ - return; - } - const clang::Decl* D = cli->GetDecl(); - const clang::Type* T = cli->GetType(); - - // Set containing all the decls of the classes that do not have a dictionary. - std::set<std::string> netD; - clang::QualType qType = QualType(T, 0); - GetMissingDictionariesForDecl(D, netD, qType, recurse); - - // Convert set<std::string> to TObjArray. - for (std::set<std::string>::const_iterator I = netD.begin(), - E = netD.end(); I != E; ++I) { - - if (TClass* clMissingDict = TClass::GetClass((*I).c_str())) { - result.Add(clMissingDict); - } else { - Error("TCling::GetMissingDictionaries", "The class %s missing dictionary was not found.", (*I).c_str()); - } - } -} - //______________________________________________________________________________ void TCling::Execute(const char* function, const char* params, int* error) { diff --git a/core/meta/src/TCling.h b/core/meta/src/TCling.h index 692f06328bdefbae77f09a60a143f0c6de13e14e..ea861b01d7f2e13cca6775e1d20e28b461abdc83 100644 --- a/core/meta/src/TCling.h +++ b/core/meta/src/TCling.h @@ -170,8 +170,6 @@ public: // Public Interface const char* GetIncludePath(); virtual const char* GetSTLIncludePath() const; TObjArray* GetRootMapFiles() const { return fRootmapFiles; } - Bool_t HasDictionary(TClass* cl); - void GetMissingDictionaries(TClass* cl, TObjArray& result, bool recurse); unsigned long long GetInterpreterStateMarker() const { return fTransactionCount;} virtual void Initialize(); void InspectMembers(TMemberInspector&, const void* obj, const TClass* cl, Bool_t isTransient); @@ -503,8 +501,6 @@ private: // Private Utility Functions bool LoadPCM(TString pcmFileName, const char** headers, void (*triggerFunc)()) const; - void GetMissingDictionariesForDecl(const clang::Decl* D, std::set<std::string> &netD, clang::QualType qType, bool recurse); - bool InsertMissingDictionaryDecl(const clang::Decl* D, std::set<std::string> &netD, clang::QualType qType, bool recurse); void InitRootmapFile(const char *name); int ReadRootmapFile(const char *rootmapfile); Bool_t HandleNewTransaction(const cling::Transaction &T); diff --git a/core/metautils/src/TClassEdit.cxx b/core/metautils/src/TClassEdit.cxx index f61cf0a23324bf929fa413b0c42695e5e17b5231..966a2960bcec41b322e6ad13c9969ac342951fa2 100644 --- a/core/metautils/src/TClassEdit.cxx +++ b/core/metautils/src/TClassEdit.cxx @@ -336,7 +336,12 @@ void TClassEdit::TSplitType::ShortType(std::string &answ, int mode) answ += '>'; } } - if (fNestedLocation) answ += fElements[fNestedLocation]; + if (fNestedLocation) { + // Treat X pf A<B>::X + fElements[fNestedLocation] = TClassEdit::ShortType(fElements[fNestedLocation].c_str(),mode); + answ += fElements[fNestedLocation]; + } + // tail is not a type name, just [2], &, * etc. if (tailLoc) answ += fElements[tailLoc]; }