Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Has dictionary #22

Closed
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions core/meta/inc/TClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@
#ifndef ROOT_TObjString
#include "TObjString.h"
#endif

#include <map>
#include <string>
#include <set>

class TBaseClass;
class TBrowser;
Expand Down Expand Up @@ -308,6 +310,7 @@ 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; };
std::set<TClass*> GetMissingClassDictionaries(bool recurse);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about simply GetMissingDictionaries()?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the advantage of std::set over TObjArray or another of the ROOT collection. Try avoid extra code generation unless really necessary.

Isn't the semantic more akin to 'GetClassesWithMissingDictionary' or 'GetClassesWithoutDictionary'
or maybe GetMissingDictionaries ...

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like GetMissingDictionaries() - of course they are for classes :-) And yes, TObjArray would work. But then use a set<TClass*> for TCling.cxx's GetMissingDictionariesForDecl() to be more performant, and convert the set to the TObjArray in TCling::GetMissingDictionaries(). See comment below. This one should then read
void GetMissingClassDictionaries(bool recurse, TObjArray& result);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also return/use a THashTable .... to avoid the end result copy ... actually I am not sure what is the 'performance' issue the std::set is suppose to resolve ... the number of elements in the resulting list should be 'low' in the general case ...

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mainly about merging duplicates automatically: we don't care how often MyClass is missing its dictionary.

If the set<TClass*> is only in the source it's fine.

void IgnoreTObjectStreamer(Bool_t ignore=kTRUE);
Bool_t InheritsFrom(const char *cl) const;
Bool_t InheritsFrom(const TClass *cl) const;
Expand Down
3 changes: 3 additions & 0 deletions core/meta/inc/TInterpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include "TDictionary.h"
#endif

#include <set>

class TClass;
class TEnv;
class TFunction;
Expand Down Expand Up @@ -73,6 +75,7 @@ class TInterpreter : public TNamed {
virtual const char *GetIncludePath() = 0;
virtual const char *GetSTLIncludePath() const { return ""; }
virtual TObjArray *GetRootMapFiles() const = 0;
virtual std::set<TClass*> GetMissingDictionaries(TClass* cl, bool recurse) = 0;
virtual void Initialize() = 0;
virtual void InspectMembers(TMemberInspector&, void* obj, const TClass* cl) = 0;
virtual Bool_t IsLoaded(const char *filename) const = 0;
Expand Down
8 changes: 8 additions & 0 deletions core/meta/src/TClass.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -3159,6 +3159,14 @@ void TClass::GetMenuItems(TList *list)
}
}

std::set<TClass*> TClass::GetMissingClassDictionaries(bool recurse)
{
//Get the classes that have a missing dictionary.

std::set<TClass*> clMissingDict = gInterpreter->GetMissingDictionaries(this, recurse);
return clMissingDict;
}

//______________________________________________________________________________
Bool_t TClass::IsFolder(void *obj) const
{
Expand Down
116 changes: 116 additions & 0 deletions core/meta/src/TCling.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2753,6 +2753,122 @@ const char* TCling::GetInterpreterTypeName(const char* name, Bool_t full)
return result.c_str();
}

//______________________________________________________________________________
namespace UNNAMED {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once you have removed the declaration in TCling you should be able to remove the "UNNAMED" part of the line above.

void GetMissingDictionariesForDecl(const clang::Decl* D, std::set<const clang::Decl*> &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<NamedDecl>(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<const clang::Decl*>::iterator it = netD.find(D);
if (it != netD.end()) return ;
netD.insert(D);
if(!recurse) return ;
}
else return ;

if (const clang::CXXRecordDecl* RD = llvm::dyn_cast<clang::CXXRecordDecl>(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()) {
clang::CXXRecordDecl* FD = pointeeType->getAsCXXRecordDecl();
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);
}
}
}
}
}
return ;
}
}
//______________________________________________________________________________
std::set<TClass*> TCling::GetMissingDictionaries(TClass* cl, bool recurse /*recurse*/)
{
// 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<const clang::Decl*> netD;
// Convert to RecordDecl.
if (const clang::RecordDecl* RD = llvm::dyn_cast<clang::RecordDecl>(D)) {
UNNAMED::GetMissingDictionariesForDecl(RD, netD, recurse);
}

std::set<TClass*> classesMissingDict;

//convert set<Decl> to set<TClass>
for (std::set<const clang::Decl*>::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<NamedDecl>(*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)) {
classesMissingDict.insert(clMissingDict);
} else {
Error("TCling::GetMissingDictionaries", "The class %s missing dictionary was not found.", name);
}
}

//return the classes the have missing dictionaries

if (netD.empty()) {
classesMissingDict.insert(0);
}
return classesMissingDict;
}

//______________________________________________________________________________
void TCling::Execute(const char* function, const char* params, int* error)
{
Expand Down
2 changes: 2 additions & 0 deletions core/meta/src/TCling.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ class TCling : public TInterpreter {
const char* GetIncludePath();
virtual const char* GetSTLIncludePath() const;
TObjArray* GetRootMapFiles() const { return fRootmapFiles; }
void GetMissingDictionariesForDecl(const clang::Decl* D, std::set<const clang::Decl*> netD, bool recurse);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't declare GetMissingDictionariesForDecl() here; it is only needed by TCling.cxx.

std::set<TClass*> GetMissingDictionaries(TClass* cl, bool recurse);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following Philppe's suggestion maybe better
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;
Expand Down