diff --git a/core/meta/inc/TClass.h b/core/meta/inc/TClass.h index 44a8ae88b6021..797f66c1d6105 100644 --- a/core/meta/inc/TClass.h +++ b/core/meta/inc/TClass.h @@ -33,8 +33,10 @@ #ifndef ROOT_TObjString #include "TObjString.h" #endif + #include #include +#include class TBaseClass; class TBrowser; @@ -308,6 +310,8 @@ friend class ROOT::TGenericClassInfo; TVirtualStreamerInfo *GetStreamerInfo(Int_t version=0) const; TVirtualStreamerInfo *GetStreamerInfoAbstractEmulated(Int_t version=0) const; const type_info *GetTypeInfo() const { return fTypeInfo; }; + Bool_t HasDictionary() const; + void GetMissingDictionaries(bool recurse, TObjArray& result); 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 820ec33caa57f..0adf1f25a1476 100644 --- a/core/meta/inc/TInterpreter.h +++ b/core/meta/inc/TInterpreter.h @@ -26,6 +26,8 @@ #include "TDictionary.h" #endif +#include + class TClass; class TEnv; class TFunction; @@ -73,6 +75,8 @@ class TInterpreter : public TNamed { virtual const char *GetIncludePath() = 0; virtual const char *GetSTLIncludePath() const { return ""; } virtual TObjArray *GetRootMapFiles() const = 0; + virtual Bool_t HasDictionary(TClass* cl) const = 0; + virtual void GetMissingDictionaries(TClass* cl, bool recurse, TObjArray& result) = 0; virtual void Initialize() = 0; virtual void InspectMembers(TMemberInspector&, void* obj, const TClass* cl) = 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 892274ec347b2..f7e9893c21bfe 100644 --- a/core/meta/src/TClass.cxx +++ b/core/meta/src/TClass.cxx @@ -3159,6 +3159,20 @@ void TClass::GetMenuItems(TList *list) } } +Bool_t TClass::HasDictionary() const +{ + // Check whether a class has a dictionary or not. + + return gInterpreter->HasDictionary(this); +} + +void TClass::GetMissingDictionaries(bool recurse, TObjArray& result) +{ + // Get the classes that have a missing dictionary. + + gInterpreter->GetMissingDictionaries(this, recurse, result); +} + //______________________________________________________________________________ Bool_t TClass::IsFolder(void *obj) const { diff --git a/core/meta/src/TCling.cxx b/core/meta/src/TCling.cxx index a34c21fe5b023..401ce04006d47 100644 --- a/core/meta/src/TCling.cxx +++ b/core/meta/src/TCling.cxx @@ -2753,6 +2753,162 @@ const char* TCling::GetInterpreterTypeName(const char* name, Bool_t full) return result.c_str(); } +//______________________________________________________________________________ +Bool_t TCling::HasDictionary(TClass* cl) const +{ + // Check whether a class has a dictionary or not. + + // Get the Decl for the class. + TClingClassInfo* cli = (TClingClassInfo*)cl->GetClassInfo(); + const clang::Decl* D = cli->GetDecl(); + + // Convert to RecordDecl. + if (const clang::RecordDecl* RD = llvm::dyn_cast(D)) { + + // Get the name of the class + std::string buf; + if (const NamedDecl* ND = llvm::dyn_cast(RD)) { + PrintingPolicy Policy(ND->getASTContext().getPrintingPolicy()); + llvm::raw_string_ostream stream(buf); + ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/false); + } + const char* name = buf.c_str(); + + // Check for the dictionary of the curent class. + if (gClassTable->GetDict(name)) + return true; + } + return false; +} + +//______________________________________________________________________________ +namespace { + void GetMissingDictionariesForDataMembers(const clang::Decl* D, std::set &netD, bool recurse); + void GetMissingDictionariesForDecl(const clang::Decl* D, std::set &netD, bool recurse) + { + // Get the data members that do not have a dictionary for a Decl. + + // Get the name of the class + std::string buf; + if (const NamedDecl* ND = llvm::dyn_cast(D)) { + PrintingPolicy Policy(ND->getASTContext().getPrintingPolicy()); + llvm::raw_string_ostream stream(buf); + ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/false); + } + const char* name = buf.c_str(); + + // Check for the dictionary of the curent class. + if (!gClassTable->GetDict(name)){ + std::set::iterator it = netD.find(D); + if (it != netD.end()) return ; + netD.insert(D); + } + if (recurse) { + GetMissingDictionariesForDataMembers(D, netD, recurse); + } + return ; + } + + void GetMissingDictionariesForDataMembers(const clang::Decl* D, std::set &netD, bool recurse) { + + if (const clang::CXXRecordDecl* RD = llvm::dyn_cast(D)) { + // Recurse for the data members. + for (clang::RecordDecl::field_iterator iField = RD->field_begin(), + eField = RD->field_end(); iField != eField; ++iField) { + + clang::QualType qualType = (*iField)->getType(); + if (!qualType.isNull()) { + + //Repetion of code will be fixed with next commit. + //class + if (qualType->isRecordType()) { + if(clang::CXXRecordDecl* FD = qualType->getAsCXXRecordDecl()) { + GetMissingDictionariesForDecl(FD, netD, recurse); + } + } + //pointer to class or to array or reference + if (qualType->isPointerType() || qualType->isReferenceType()) { + QualType pointeeType = qualType->getPointeeType(); + if (pointeeType->isRecordType()) { + if(clang::CXXRecordDecl* FD = pointeeType->getAsCXXRecordDecl()) { + GetMissingDictionariesForDecl(FD, netD, recurse); + } + } + else if(pointeeType->isArrayType()) { + const Type* elementType = pointeeType->getArrayElementTypeNoTypeQual(); + if (elementType->isRecordType()) { + if(clang::CXXRecordDecl* FD = elementType->getAsCXXRecordDecl()) { + GetMissingDictionariesForDecl(FD, netD, recurse); + } + } + } + } + //array of class elements + if (qualType->isArrayType()) { + const Type* elementType = qualType->getArrayElementTypeNoTypeQual(); + if (elementType->isRecordType()) { + clang::CXXRecordDecl* FD = elementType->getAsCXXRecordDecl(); + GetMissingDictionariesForDecl(FD, netD, recurse); + } + } + } + } + } + } +} +//______________________________________________________________________________ +void TCling::GetMissingDictionaries(TClass* cl, bool recurse /*recurse*/, TObjArray& result) +{ + // Get the Tclass-s that do not have a dictionary. + + // Get the Decl for the class. + TClingClassInfo* cli = (TClingClassInfo*)cl->GetClassInfo(); + const clang::Decl* D = cli->GetDecl(); + + // Get the Decls recursively for all data members of TClass cl + + std::set netD; + // Convert to RecordDecl. + if (const clang::RecordDecl* RD = llvm::dyn_cast(D)) { + + // Get the name of the class + std::string buf; + if (const NamedDecl* ND = llvm::dyn_cast(D)) { + PrintingPolicy Policy(ND->getASTContext().getPrintingPolicy()); + llvm::raw_string_ostream stream(buf); + ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/false); + } + const char* name = buf.c_str(); + + // Check for the dictionary of the curent class. + if (!gClassTable->GetDict(name)){ + std::set::iterator it = netD.find(D); + if (it == netD.end()) + netD.insert(D); + } + + GetMissingDictionariesForDataMembers(D, netD, recurse); + } + + //convert set to TObjArray + for (std::set::const_iterator I = netD.begin(), + E = netD.end(); I != E; ++I) { + // Get name of the class. + std::string buf; + if (const NamedDecl* ND = llvm::dyn_cast(*I)) { + PrintingPolicy Policy(ND->getASTContext().getPrintingPolicy()); + llvm::raw_string_ostream stream(buf); + ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true); + } + const char* name = buf.c_str(); + if (TClass* clMissingDict = TClass::GetClass(name)) { + result.Add(clMissingDict); + } else { + Error("TCling::GetMissingDictionaries", "The class %s missing dictionary was not found.", name); + } + } +} + //______________________________________________________________________________ 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 6ea53cd4c93e2..908d2b3283d17 100644 --- a/core/meta/src/TCling.h +++ b/core/meta/src/TCling.h @@ -137,6 +137,8 @@ class TCling : public TInterpreter { const char* GetIncludePath(); virtual const char* GetSTLIncludePath() const; TObjArray* GetRootMapFiles() const { return fRootmapFiles; } + Bool_t HasDictionary(TClass* cl) const; + void GetMissingDictionaries(TClass* cl, bool recurse, TObjArray& result); virtual void Initialize(); void InspectMembers(TMemberInspector&, void* obj, const TClass* cl); Bool_t IsLoaded(const char* filename) const;