13 #include "clang/AST/ASTConsumer.h" 14 #include "clang/Basic/SourceLocation.h" 15 #include "clang/Basic/SourceManager.h" 16 #include "llvm/ADT/SmallSet.h" 17 #include "clang/Sema/Sema.h" 18 #include "clang/Frontend/CompilerInstance.h" 20 #include "cling/Interpreter/Interpreter.h" 21 #include "llvm/Support/Path.h" 32 class RPredicateIsSameNamespace
35 clang::NamespaceDecl *fTarget;
37 RPredicateIsSameNamespace(clang::NamespaceDecl *target) : fTarget(target) {}
41 return (fTarget == element);
46 inline static bool IsElementPresent(
const std::vector<T> &
v,
const T &el){
47 return std::find(v.begin(),v.end(),el) != v.end();
53 using namespace clang;
55 extern cling::Interpreter *
gInterp;
73 const cling::Interpreter &interpret,
76 fVerboseLevel(verbose),
78 fInterpreter(interpret),
79 fRecordDeclCallback(0),
81 fSelectionRules(rules),
99 RScanner::~RScanner ()
115 return *num.getRawData();
122 return *num.getRawData();
129 return num.toString(10,
true);
136 std::string txt =
"";
145 std::ostringstream stream;
152 inline std::string
Message(
const std::string &msg,
const std::string &location)
154 std::string loc = location;
159 return loc +
" " + msg;
166 const std::string message =
Message(msg, location);
167 std::cout << message << std::endl;
174 const std::string message =
Message(msg, location);
175 std::cout << message << std::endl;
182 const std::string message =
Message(msg, location);
183 std::cout << message << std::endl;
190 std::string loc = location;
200 std::string location =
"";
201 llvm::raw_string_ostream stream(location);
216 std::string location =
"";
217 llvm::raw_string_ostream stream(location);
227 std::string
name =
"";
230 if (clang::NamedDecl* ND = dyn_cast <clang::NamedDecl> (D)) {
231 name = ND->getQualifiedNameAsString();
239 inline std::string
AddSpace(
const std::string &txt)
252 std::string kind = D->getDeclKindName();
254 ShowInfo(
"Scan: " + kind +
" declaration " + name, location);
263 std::string kind = D->getDeclKindName();
274 std::string kind = D->getDeclKindName();
276 ShowWarning(
"Unexpected " + kind +
" declaration " + name, location);
285 std::string kind = D->getDeclKindName();
302 clang::Decl::Kind k = D->getKind();
315 std::string kind = D->getDeclKindName();
317 std::string msg =
"Unimplemented ";
319 msg +=
"declaration";
336 std::string kind = qual_type.getTypePtr()->getTypeClassName();
337 ShowWarning(
"Unknown " + kind +
" type " + qual_type.getAsString(), location);
345 std::string kind = qual_type.getTypePtr()->getTypeClassName();
346 ShowWarning(
"Unsupported " + kind +
" type " + qual_type.getAsString(), location);
353 std::string enum_name = D->getQualifiedNameAsString();
355 if (! D->getDeclName ()) {
377 clang::LangOptions lang_opts;
378 clang::PrintingPolicy print_opts(lang_opts);
380 std::string
text =
"";
381 llvm::raw_string_ostream stream(text);
383 expr->printPretty(stream,
NULL, print_opts);
392 clang::LangOptions lang_opts;
393 clang::PrintingPolicy print_opts(lang_opts);
395 std::string
text =
"";
396 llvm::raw_string_ostream stream(text);
398 N.print(stream, print_opts);
409 for (clang::FunctionDecl::param_iterator
I = D->param_begin(),
E = D->param_end();
I !=
E; ++
I) {
410 clang::ParmVarDecl*
P = *
I;
415 std::string
type = P->getType().getAsString();
416 std::string
name = P->getNameAsString();
418 result += type +
" " +
name;
422 std::string init_value =
ExprToStr(P->getDefaultArg());
423 result +=
"=" + init_value;
436 for (clang::FunctionDecl::param_iterator
I = D->param_begin(),
E = D->param_end();
I !=
E; ++
I) {
437 clang::ParmVarDecl*
P = *
I;
442 std::string
type = P->getType().getAsString();
446 return "(" + result +
")";
459 if((N && N->isImplicit()) || !N){
468 clang::DeclContext* primary_ctxt = N->getPrimaryContext();
469 clang::NamespaceDecl* primary = llvm::dyn_cast<clang::NamespaceDecl>(primary_ctxt);
471 RPredicateIsSameNamespace pred(primary);
476 std::string qual_name;
479 std::cout<<
"\tSelected namespace -> " << qual_name <<
"\n";
503 const clang::RecordDecl* recordDecl,
504 const std::string& attr_name,
505 const clang::TypedefNameDecl* typedefNameDecl,
506 unsigned int indexOffset)
533 std::string qual_name;
535 std::string normName;
537 recordDecl->getASTContext().getTypeDeclType(recordDecl),
540 std::string typedef_qual_name;
541 std::string typedefMsg;
542 if (typedefNameDecl){
544 typedefMsg =
"(through typedef/alias " + typedef_qual_name +
") ";
547 std::cout <<
"Selected class " 572 clang::RecordDecl* recordDecl = clang::dyn_cast<clang::RecordDecl>(typeDecl);
573 clang::TypedefNameDecl* typedefNameDecl = clang::dyn_cast<clang::TypedefNameDecl>(typeDecl);
576 if (!recordDecl && typedefNameDecl) {
583 "Could not cast typeDecl either to RecordDecl or could not get RecordDecl underneath typedef.\n");
588 if (!recordDecl->getIdentifier())
605 std::string qual_name;
611 if(recordDecl && (recordDecl->isImplicit() || !recordDecl->isCompleteDefinition()) ) {
616 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(recordDecl);
617 if (cxxdecl && cxxdecl->getDescribedClassTemplate ()) {
625 const ClassSelectionRule *selected = typedefNameDecl ? selectedFromTypedef : selectedFromRecDecl;
627 if (! selected)
return true;
630 bool excludedFromRecDecl =
false;
631 if ( selectedFromRecDecl )
638 if (selectedFromTypedef){
653 "Typedef is selected %s.\n", typedefNameDecl->getNameAsString().c_str());
661 if (recordDecl && recordDecl->getName() ==
"pair") {
662 const clang::NamespaceDecl *nsDecl = llvm::dyn_cast<clang::NamespaceDecl>(recordDecl->getDeclContext());
665 "Cannot convert context of RecordDecl called pair into a namespace.\n");
668 const clang::NamespaceDecl *nsCanonical = nsDecl->getCanonicalDecl();
669 if (nsCanonical && nsCanonical ==
fInterpreter.getCI()->getSema().getStdNamespace()) {
678 bool rcrdDeclNotAlreadySelected =
fselectedRecordDecls.insert((RecordDecl*)recordDecl->getCanonicalDecl()).second;
680 auto declSelRuleMapIt =
fDeclSelRuleMap.find(recordDecl->getCanonicalDecl());
682 !rcrdDeclNotAlreadySelected &&
684 declSelRuleMapIt->second != selected){
685 std::string normName;
687 recordDecl->getASTContext().getTypeDeclType(recordDecl),
692 int previouslineno = previouslyMatchingRule->GetLineNumber();
694 std::string cleanFileName = llvm::sys::path::filename(selected->
GetSelFileName());
697 if (!rulesAreCompatible){
698 std::stringstream message;
699 if (lineno > 1) message <<
"Selection file " << cleanFileName <<
", lines " 700 << lineno <<
" and " << previouslineno <<
". ";
701 message <<
"Attempt to select a class "<< normName <<
" with two rules which have incompatible attributes. " 702 <<
"The attributes such as transiency might not be correctly propagated to the typesystem of ROOT.\n";
703 selected->Print(message);
704 message <<
"Conflicting rule already matched:\n";
705 previouslyMatchingRule->Print(message);
712 if(rcrdDeclNotAlreadySelected &&
723 auto canDeclAccess = recordDecl->getCanonicalDecl()->getAccess();
724 if (!isFileSelection && (AS_protected == canDeclAccess || AS_private == canDeclAccess)){
725 std::string normName;
727 recordDecl->getASTContext().getTypeDeclType(recordDecl),
730 auto msg =
"Class or struct %s was selected but its dictionary cannot be generated: " 731 "this is a private or protected class and this is not supported. No direct " 732 "I/O operation of %s instances will be possible.\n";
742 clang::QualType thisType(req_type, 0);
747 if (llvm::isa<clang::ClassTemplateSpecializationDecl>(recordDecl)) {
749 thisType = recordDecl->getASTContext().getTypeDeclType(recordDecl);
752 auto typeForIO = nameTypeForIO.second;
755 if (!typeForIO->isRecordType())
return true;
756 if (typeForIO.getTypePtr() != thisType.getTypePtr()){
757 if (
auto recordDeclForIO = typeForIO->getAsCXXRecordDecl()) {
758 auto canRecordDeclForIO = recordDeclForIO->getCanonicalDecl();
760 recordDecl = canRecordDeclForIO;
761 fDeclSelRuleMap[recordDecl]=selected;
762 thisType = typeForIO;
764 if (!thisType.isNull()) {
765 req_type = thisType.getTypePtr();
791 const clang::DeclContext *ctx = D->getDeclContext();
795 const clang::NamedDecl *parent = llvm::dyn_cast<clang::NamedDecl> (ctx);
796 isInStd = parent && 0 == parent->getQualifiedNameAsString().compare(0,5,
"std::");
826 if (!D->hasGlobalStorage() ||
867 if(clang::FunctionDecl::TemplatedKind::TK_FunctionTemplate == D->getTemplatedKind())
886 clang::Decl* D = dyn_cast<clang::Decl>(DC);
888 if (D && D->isImplicit()){
893 const clang::NamespaceDecl *parent = llvm::dyn_cast<clang::NamespaceDecl> (DC);
894 if (parent && 0 == parent->getQualifiedNameAsString().compare(0,5,
"std::"))
898 for (DeclContext::decl_iterator Child = DC->decls_begin(), ChildEnd = DC->decls_end();
899 ret && (Child != ChildEnd); ++Child) {
900 ret=TraverseDecl(*Child);
911 clang::NamedDecl*
N = dyn_cast<clang::NamedDecl> (D);
914 name = N->getNameAsString();
927 auto N = dyn_cast<
const clang::NamedDecl> (D);
930 llvm::raw_string_ostream stream(qual_name);
931 N->getNameForDiagnostic(stream,D->getASTContext().getPrintingPolicy(),
true);
946 clang::FunctionDecl*
F = dyn_cast<clang::FunctionDecl> (D);
951 for (clang::FunctionDecl::param_iterator
I = F->param_begin(),
E = F->param_end();
I !=
E; ++
I) {
952 clang::ParmVarDecl*
P = *
I;
958 std::string
type = P->getType().getAsString();
959 if (type.at(type.length()-1) ==
'*') {
960 type.at(type.length()-2) =
'*';
961 type.erase(type.length()-1);
966 prototype =
"(" + prototype +
")";
970 ShowWarning(
"can't convert Decl to FunctionDecl",
"");
984 std::cout<<
"File name detected"<<std::endl;
988 TraverseDecl(C.getTranslationUnitDecl());
996 TraverseDecl(C.getTranslationUnitDecl());
void UnsupportedDecl(clang::Decl *D, const std::string &txt="") const
unsupported - this kind of declaration is probably not used (in current version of C++) ...
bool HasAttributeFileName() const
NamespaceColl_t fSelectedNamespaces
std::string ConvTemplateName(clang::TemplateName &N) const
bool RequestNoInputOperator() const
bool VisitVarDecl(clang::VarDecl *D)
void UnknownDecl(clang::Decl *D, const std::string &txt="") const
unknown - this kind of declaration was not known to programmer
std::string IntToStr(int num)
This namespace contains pre-defined functions to be used in conjuction with TExecutor::Map and TExecu...
cling::Interpreter * gInterp
void UnimportantDecl(clang::Decl *D, const std::string &txt="") const
unimportant - this kind of declaration is not stored into reflex
void UnimplementedDecl(clang::Decl *D, const std::string &txt="")
information about item, that should be implemented
RooArgList L(const RooAbsArg &v1)
std::string GetEnumName(clang::EnumDecl *D) const
ESelect GetSelected() const
static const int fgTypeLast
bool RequestStreamerInfo() const
static std::map< clang::Decl *, std::string > fgAnonymousEnumMap
void(* DeclCallback)(const char *type)
static std::map< clang::Decl *, std::string > fgAnonymousClassMap
bool GetDeclName(clang::Decl *D, std::string &name) const
static int fgAnonymousEnumCounter
ROOT::TMetaUtils::TNormalizedCtxt & fNormCtxt
bool HasAttributeFilePattern() const
bool RequestNoStreamer() const
unsigned int fVerboseLevel
bool GetFunctionPrototype(clang::Decl *D, std::string &prototype) const
bool fDeclTable[fgDeclLast+1]
const char * GetSelFileName() const
const clang::Type * GetRequestedType() const
SelectionRules & fSelectionRules
const std::string & GetAttributePattern() const
bool HasAttributePattern() const
static const char * fgClangDeclKey
VariableColl_t fSelectedVariables
static int fgAnonymousClassCounter
bool VisitTypedefNameDecl(clang::TypedefNameDecl *D)
Visitor for every TypedefNameDecl, i.e.
bool VisitFieldDecl(clang::FieldDecl *D)
Nothing to be done here.
bool GetDeclQualName(const clang::Decl *D, std::string &qual_name) const
bool IsSelectionXMLFile() const
bool GetHasFileNameRule() const
FunctionColl_t fSelectedFunctions
void * ToDeclProp(clang::Decl *item)
The class representing the collection of selection rules.
std::string GetSrcLocation(clang::SourceLocation L) const
DeclCallback SetRecordDeclCallback(DeclCallback callback)
Set the callback to the RecordDecl and return the previous one.
const cling::Interpreter & fInterpreter
RScanner(SelectionRules &rules, EScanType stype, const cling::Interpreter &interpret, ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, unsigned int verbose=0)
Regular constructor setting up the scanner to search for entities matching the 'rules'.
std::string ExprToStr(clang::Expr *expr) const
bool IsFromTypedef() const
std::string APIntToStr(const llvm::APInt &num)
bool RequestOnlyTClass() const
std::string IntToStd(int num)
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
static const int fgDeclLast
long GetLineNumber() const
void ShowTemplateInfo(const std::string &msg, const std::string &location="") const
DeclsSelRulesMap_t fDeclSelRuleMap
size_t APIntToSize(const llvm::APInt &num)
void AddAnnotatedRecordDecl(const ClassSelectionRule *, const clang::Type *, const clang::RecordDecl *, const std::string &, const clang::TypedefNameDecl *, unsigned int indexOffset=0)
std::string GetName(clang::Decl *D) const
ClassColl_t fSelectedClasses
const std::string & GetAttributeName() const
Type
enumeration specifying the integration types.
void ShowError(const std::string &msg, const std::string &location="") const
void Scan(const clang::ASTContext &C)
int RequestedVersionNumber() const
std::string Message(const std::string &msg, const std::string &location)
bool VisitFunctionDecl(clang::FunctionDecl *D)
const clang::SourceManager * fSourceManager
void DeclInfo(clang::Decl *D) const
void ShowWarning(const std::string &msg, const std::string &location="") const
bool VisitEnumDecl(clang::EnumDecl *D)
std::string GetLocation(clang::Decl *D) const
bool VisitRecordDecl(clang::RecordDecl *D)
bool fTypeTable[fgTypeLast+1]
std::string FuncParameterList(clang::FunctionDecl *D) const
std::set< clang::RecordDecl * > fselectedRecordDecls
void UnexpectedDecl(clang::Decl *D, const std::string &txt="") const
unexpected - this kind of declaration is unexpected (in concrete place)
EnumColl_t fSelectedEnums
void UnsupportedType(clang::QualType qual_type) const
std::string FuncParameters(clang::FunctionDecl *D) const
bool TraverseDeclContextHelper(clang::DeclContext *DC)
const ClassSelectionRule * IsDeclSelected(const clang::RecordDecl *D) const
bool VisitNamespaceDecl(clang::NamespaceDecl *D)
This method visits a namespace node.
bool HasAttributeName() const
static const char * fgClangFuncKey
std::string AddSpace(const std::string &txt)
bool areEqual< ClassSelectionRule >(const ClassSelectionRule *r1, const ClassSelectionRule *r2, bool moduloNameOrPattern)
void ShowInfo(const std::string &msg, const std::string &location="") const
long APIntToLong(const llvm::APInt &num)
DeclCallback fRecordDeclCallback
bool TreatRecordDeclOrTypedefNameDecl(clang::TypeDecl *typeDecl)
static int fgBadClassCounter
void UnknownType(clang::QualType qual_type) const
TypedefColl_t fSelectedTypedefs