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"
38 #define FILTER_WARNINGS
55 class RPredicateIsSameNamespace
58 clang::NamespaceDecl *fTarget;
60 RPredicateIsSameNamespace(clang::NamespaceDecl *target) : fTarget(target) {}
64 return (fTarget == element);
69 inline static bool IsElementPresent(
const std::vector<T> &
v,
const T &el){
70 return std::find(v.begin(),v.end(),el) != v.end();
76 using namespace clang;
78 extern cling::Interpreter *
gInterp;
96 const cling::Interpreter &interpret,
99 fVerboseLevel(verbose),
101 fInterpreter(interpret),
102 fRecordDeclCallback(0),
104 fSelectionRules(rules),
138 return *num.getRawData();
145 return *num.getRawData();
152 return num.toString(10,
true);
159 std::string txt =
"";
168 std::ostringstream stream;
175 inline std::string
Message(
const std::string &msg,
const std::string &location)
177 std::string loc = location;
180 int n = loc.length ();
181 while (n > 0 && loc [n] !=
':')
184 loc = loc.substr (0, n) +
":";
190 return loc +
" " + msg;
199 std::cout << message << std::endl;
201 fReporter->Info(
"RScanner:ShowInfo",
"CLR %s", message.Data());
212 std::cout << message << std::endl;
214 fReporter->Warning(
"RScanner:ShowWarning",
"CLR %s", message.Data());
225 std::cout << message << std::endl;
227 fReporter->Error(
"RScanner:ShowError",
"CLR %s", message.Data());
235 #ifdef SHOW_TEMPLATE_INFO
236 std::string loc = location;
247 std::string location =
"";
248 llvm::raw_string_ostream stream(location);
263 std::string location =
"";
264 llvm::raw_string_ostream stream(location);
274 std::string
name =
"";
277 if (clang::NamedDecl* ND = dyn_cast <clang::NamedDecl> (D)) {
278 name = ND->getQualifiedNameAsString();
286 inline std::string
AddSpace(
const std::string &txt)
299 std::string kind = D->getDeclKindName();
301 ShowInfo(
"Scan: " + kind +
" declaration " + name, location);
310 std::string kind = D->getDeclKindName();
321 std::string kind = D->getDeclKindName();
323 ShowWarning(
"Unexpected " + kind +
" declaration " + name, location);
332 std::string kind = D->getDeclKindName();
349 clang::Decl::Kind k = D->getKind();
352 #ifdef FILTER_WARNINGS
364 std::string kind = D->getDeclKindName();
366 std::string msg =
"Unimplemented ";
368 msg +=
"declaration";
385 std::string kind = qual_type.getTypePtr()->getTypeClassName();
386 ShowWarning(
"Unknown " + kind +
" type " + qual_type.getAsString(), location);
394 std::string kind = qual_type.getTypePtr()->getTypeClassName();
395 ShowWarning(
"Unsupported " + kind +
" type " + qual_type.getAsString(), location);
409 clang::Type::TypeClass k = qual_type.getTypePtr()->getTypeClass();
412 #ifdef FILTER_WARNINGS
424 std::string kind = qual_type.getTypePtr()->getTypeClassName();
425 ShowWarning(
"Unimplemented type: " + kind +
" " + qual_type.getAsString(), location);
433 clang::Type::TypeClass k = T->getTypeClass();
436 #ifdef FILTER_WARNINGS
448 std::string kind = T->getTypeClassName ();
449 ShowWarning (
"Unimplemented type: " + kind, location);
457 std::string cls_name = D->getQualifiedNameAsString();
462 if (! D->getDeclName ()) {
484 std::string enum_name = D->getQualifiedNameAsString();
486 if (! D->getDeclName ()) {
508 clang::LangOptions lang_opts;
509 clang::PrintingPolicy print_opts(lang_opts);
511 std::string
text =
"";
512 llvm::raw_string_ostream stream(text);
514 expr->printPretty(stream,
NULL, print_opts);
523 clang::LangOptions lang_opts;
524 clang::PrintingPolicy print_opts(lang_opts);
526 std::string
text =
"";
527 llvm::raw_string_ostream stream(text);
529 N.print(stream, print_opts);
534 #ifdef COMPLETE_TEMPLATES
539 std::string result =
"";
542 for (clang::TemplateParameterList::iterator
I = list->begin(),
E = list->end();
I !=
E; ++
I) {
547 clang::NamedDecl * D = *
I;
549 switch (D->getKind()) {
551 case clang::Decl::TemplateTemplateParm:
552 UnimplementedDecl(dyn_cast <clang::TemplateTemplateParmDecl> (D),
"template parameter");
555 case clang::Decl::TemplateTypeParm:
557 clang::TemplateTypeParmDecl* P = dyn_cast <clang::TemplateTypeParmDecl> (D);
559 if (P->wasDeclaredWithTypename())
560 result +=
"typename ";
564 if (P->isParameterPack())
567 result += P->getNameAsString();
571 case clang::Decl::NonTypeTemplateParm:
573 clang::NonTypeTemplateParmDecl* P = dyn_cast <clang::NonTypeTemplateParmDecl> (D);
574 result += P->getType().getAsString();
576 if (clang::IdentifierInfo*
N = P->getIdentifier()) {
578 std::string s =
N->getName();
582 if (P->hasDefaultArgument())
583 result +=
" = " +
ExprToStr(P->getDefaultArgument());
594 return "<" + result +
">";
608 clang::LangOptions lang_opts;
609 clang::PrintingPolicy print_opts(lang_opts);
610 return clang::TemplateSpecializationType::PrintTemplateArgumentList
611 (list.data(), list.size(), print_opts);
613 #endif // COMPLETE_TEMPLATES
619 std::string result =
"";
621 for (clang::FunctionDecl::param_iterator
I = D->param_begin(),
E = D->param_end();
I !=
E; ++
I) {
622 clang::ParmVarDecl* P = *
I;
627 std::string
type = P->getType().getAsString();
628 std::string
name = P->getNameAsString();
630 result += type +
" " +
name;
634 std::string init_value =
ExprToStr(P->getDefaultArg());
635 result +=
"=" + init_value;
646 std::string result =
"";
648 for (clang::FunctionDecl::param_iterator
I = D->param_begin(),
E = D->param_end();
I !=
E; ++
I) {
649 clang::ParmVarDecl* P = *
I;
654 std::string
type = P->getType().getAsString();
658 return "(" + result +
")";
671 if(N && N->isImplicit()){
680 #ifdef SELECTION_DEBUG
683 clang::DeclContext* primary_ctxt = N->getPrimaryContext();
684 clang::NamespaceDecl* primary = llvm::dyn_cast<clang::NamespaceDecl>(primary_ctxt);
686 RPredicateIsSameNamespace pred(primary);
691 std::string qual_name;
694 std::cout<<
"\tSelected namespace -> " << qual_name <<
"\n";
701 #ifdef SELECTION_DEBUG
736 clang::RecordDecl* recordDecl = clang::dyn_cast<clang::RecordDecl>(typeDecl);
737 clang::TypedefNameDecl* typedefNameDecl = clang::dyn_cast<clang::TypedefNameDecl>(typeDecl);
740 if (!recordDecl && typedefNameDecl) {
747 "Could not cast typeDecl either to RecordDecl or could not get RecordDecl underneath typedef.\n");
752 if (!recordDecl->getIdentifier())
769 std::string qual_name;
775 if(recordDecl && (recordDecl->isImplicit() || !recordDecl->isCompleteDefinition()) ) {
780 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(recordDecl);
781 if (cxxdecl && cxxdecl->getDescribedClassTemplate ()) {
789 const ClassSelectionRule *selected = typedefNameDecl ? selectedFromTypedef : selectedFromRecDecl;
791 if (! selected)
return true;
794 bool excludedFromRecDecl =
false;
795 if ( selectedFromRecDecl )
802 if (selectedFromTypedef){
817 "Typedef is selected %s.\n", typedefNameDecl->getNameAsString().c_str());
825 if (recordDecl && recordDecl->getName() ==
"pair") {
826 const clang::NamespaceDecl *nsDecl = llvm::dyn_cast<clang::NamespaceDecl>(recordDecl->getDeclContext());
829 "Cannot convert context of RecordDecl called pair into a namespace.\n");
832 const clang::NamespaceDecl *nsCanonical = nsDecl->getCanonicalDecl();
833 if (nsCanonical && nsCanonical ==
fInterpreter.getCI()->getSema().getStdNamespace()) {
842 bool rcrdDeclNotAlreadySelected =
fselectedRecordDecls.insert((RecordDecl*)recordDecl->getCanonicalDecl()).second;
844 auto declSelRuleMapIt =
fDeclSelRuleMap.find(recordDecl->getCanonicalDecl());
846 !rcrdDeclNotAlreadySelected &&
848 declSelRuleMapIt->second != selected){
849 std::string normName;
851 recordDecl->getASTContext().getTypeDeclType(recordDecl),
856 int previouslineno = previouslyMatchingRule->GetLineNumber();
861 if (!rulesAreCompatible){
863 if (lineno > 1) message <<
"Selection file " << cleanFileName <<
", lines "
864 << lineno <<
" and " << previouslineno <<
". ";
865 message <<
"Attempt to select a class "<< normName <<
" with two rules which have incompatible attributes. "
866 <<
"The attributes such as transiency might not be correctly propagated to the typesystem of ROOT.\n";
867 selected->Print(message);
868 message <<
"Conflicting rule already matched:\n";
869 previouslyMatchingRule->Print(message);
876 if(rcrdDeclNotAlreadySelected &&
887 auto canDeclAccess = recordDecl->getCanonicalDecl()->getAccess();
888 if (!isFileSelection && (AS_protected == canDeclAccess || AS_private == canDeclAccess)){
889 std::string normName;
891 recordDecl->getASTContext().getTypeDeclType(recordDecl),
894 auto msg =
"Class or struct %s was selected but its dictionary cannot be generated: "
895 "this is a private or protected class and this is not supported. No direct "
896 "I/O operation of %s instances will be possible.\n";
932 std::string qual_name;
934 std::string normName;
936 recordDecl->getASTContext().getTypeDeclType(recordDecl),
939 std::string typedef_qual_name;
940 std::string typedefMsg;
941 if (typedefNameDecl){
943 typedefMsg =
"(through typedef/alias " + typedef_qual_name +
") ";
946 std::cout <<
"Selected class "
975 const clang::DeclContext *ctx = D->getDeclContext();
979 const clang::NamedDecl *parent = llvm::dyn_cast<clang::NamedDecl> (ctx);
980 isInStd = parent && 0 == parent->getQualifiedNameAsString().compare(0,5,
"std::");
1010 if (!D->hasGlobalStorage() ||
1057 if(clang::FunctionDecl::TemplatedKind::TK_FunctionTemplate == D->getTemplatedKind())
1076 clang::Decl* D = dyn_cast<clang::Decl>(DC);
1078 if (D && D->isImplicit()){
1083 const clang::NamespaceDecl *parent = llvm::dyn_cast<clang::NamespaceDecl> (DC);
1084 if (parent && 0 == parent->getQualifiedNameAsString().compare(0,5,
"std::"))
1088 for (DeclContext::decl_iterator Child = DC->decls_begin(), ChildEnd = DC->decls_end();
1089 ret && (Child != ChildEnd); ++Child) {
1090 ret=TraverseDecl(*Child);
1101 clang::NamedDecl*
N=dyn_cast<clang::NamedDecl>(DC);
1103 if(N && (N->getIdentifier()!=
NULL))
1104 ret = N->getNameAsString().c_str();
1113 clang::NamedDecl*
N = dyn_cast<clang::NamedDecl> (D);
1116 name = N->getNameAsString();
1129 clang::NamedDecl*
N = dyn_cast<clang::NamedDecl> (D);
1132 llvm::raw_string_ostream stream(qual_name);
1133 N->getNameForDiagnostic(stream,D->getASTContext().getPrintingPolicy(),
true);
1148 clang::FunctionDecl*
F = dyn_cast<clang::FunctionDecl> (D);
1153 for (clang::FunctionDecl::param_iterator
I = F->param_begin(),
E = F->param_end();
I !=
E; ++
I) {
1154 clang::ParmVarDecl* P = *
I;
1156 if (prototype !=
"")
1160 std::string
type = P->getType().getAsString();
1161 if (type.at(type.length()-1) ==
'*') {
1162 type.at(type.length()-2) =
'*';
1163 type.erase(type.length()-1);
1168 prototype =
"(" + prototype +
")";
1172 ShowWarning(
"can't convert Decl to FunctionDecl",
"");
1186 std::cout<<
"File name detected"<<std::endl;
1190 TraverseDecl(C.getTranslationUnitDecl());
1197 TraverseDecl(C.getTranslationUnitDecl());
std::string ConvTemplateArguments(const clang::TemplateArgumentList &list) const
NamespaceColl_t fSelectedNamespaces
bool VisitVarDecl(clang::VarDecl *D)
void ShowWarning(const std::string &msg, const std::string &location="") const
const ClassSelectionRule * IsDeclSelected(const clang::RecordDecl *D) const
bool HasAttributeName() const
std::string IntToStr(int num)
Namespace for new ROOT classes and functions.
cling::Interpreter * gInterp
bool RequestStreamerInfo() const
bool GetDeclQualName(clang::Decl *D, std::string &qual_name) const
void UnimplementedDecl(clang::Decl *D, const std::string &txt="")
information about item, that should be implemented
std::string GetLocation(clang::Decl *D) const
RooArgList L(const RooAbsArg &v1)
static const int fgTypeLast
bool RequestNoStreamer() const
static std::map< clang::Decl *, std::string > fgAnonymousEnumMap
static const char * filename()
void ShowTemplateInfo(const std::string &msg, const std::string &location="") const
void(* DeclCallback)(const char *type)
static std::map< clang::Decl *, std::string > fgAnonymousClassMap
static int fgAnonymousEnumCounter
ROOT::TMetaUtils::TNormalizedCtxt & fNormCtxt
unsigned int fVerboseLevel
bool RequestNoInputOperator() const
bool fDeclTable[fgDeclLast+1]
SelectionRules & fSelectionRules
void UnexpectedDecl(clang::Decl *D, const std::string &txt="") const
unexpected - this kind of declaration is unexpected (in concrete place)
static const char * fgClangDeclKey
int RequestedVersionNumber() const
VariableColl_t fSelectedVariables
const char Int_t const char TProof Int_t stype
void UnimportantDecl(clang::Decl *D, const std::string &txt="") const
unimportant - this kind of declaration is not stored into reflex
static int fgAnonymousClassCounter
bool VisitTypedefNameDecl(clang::TypedefNameDecl *D)
Visitor for every TypedefNameDecl, i.e.
bool GetFunctionPrototype(clang::Decl *D, std::string &prototype) const
bool VisitFieldDecl(clang::FieldDecl *D)
Nothing to be done here.
std::string FuncParameterList(clang::FunctionDecl *D) const
void UnknownDecl(clang::Decl *D, const std::string &txt="") const
unknown - this kind of declaration was not known to programmer
FunctionColl_t fSelectedFunctions
void * ToDeclProp(clang::Decl *item)
The class representing the collection of selection rules.
std::string GetSrcLocation(clang::SourceLocation L) const
void UnimplementedType(clang::QualType qual_type)
DeclCallback SetRecordDeclCallback(DeclCallback callback)
Set the callback to the RecordDecl and return the previous one.
bool HasAttributeFilePattern() const
const clang::Type * GetRequestedType() const
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 GetName(clang::Decl *D) const
std::string APIntToStr(const llvm::APInt &num)
std::string IntToStd(int num)
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
static const int fgDeclLast
bool IsFromTypedef() const
void ShowError(const std::string &msg, const std::string &location="") const
bool HasAttributeFileName() const
DeclsSelRulesMap_t fDeclSelRuleMap
size_t APIntToSize(const llvm::APInt &num)
ClassColl_t fSelectedClasses
ESelect GetSelected() const
std::string GetEnumName(clang::EnumDecl *D) const
std::string ConvTemplateParams(clang::TemplateDecl *D) const
Type
enumeration specifying the integration types.
const std::string & GetAttributePattern() const
void ShowInfo(const std::string &msg, const std::string &location="") const
void Scan(const clang::ASTContext &C)
const std::string & GetAttributeName() const
TRObject operator()(const T1 &t1) const
std::string ExprToStr(clang::Expr *expr) const
bool HasAttributePattern() const
std::string Message(const std::string &msg, const std::string &location)
const char * GetSelFileName() const
bool VisitFunctionDecl(clang::FunctionDecl *D)
const clang::SourceManager * fSourceManager
void DeclInfo(clang::Decl *D) const
bool VisitEnumDecl(clang::EnumDecl *D)
bool GetHasFileNameRule() const
bool VisitRecordDecl(clang::RecordDecl *D)
std::string ConvTemplateName(clang::TemplateName &N) const
bool fTypeTable[fgTypeLast+1]
std::set< clang::RecordDecl * > fselectedRecordDecls
EnumColl_t fSelectedEnums
bool TraverseDeclContextHelper(clang::DeclContext *DC)
bool IsSelectionXMLFile() const
bool VisitNamespaceDecl(clang::NamespaceDecl *D)
This method visits a namespace node.
long GetLineNumber() const
void UnknownType(clang::QualType qual_type) const
static const char * fgClangFuncKey
std::string AddSpace(const std::string &txt)
bool areEqual< ClassSelectionRule >(const ClassSelectionRule *r1, const ClassSelectionRule *r2, bool moduloNameOrPattern)
std::string FuncParameters(clang::FunctionDecl *D) const
bool GetDeclName(clang::Decl *D, std::string &name) const
long APIntToLong(const llvm::APInt &num)
DeclCallback fRecordDeclCallback
std::string GetClassName(clang::DeclContext *DC) const
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 RequestOnlyTClass() const
bool TreatRecordDeclOrTypedefNameDecl(clang::TypeDecl *typeDecl)
void UnsupportedType(clang::QualType qual_type) const
static int fgBadClassCounter
void UnimportantType(clang::QualType qual_type) const
unimportant - this kind of declaration is not stored into reflex
std::string ConvTemplateParameterList(clang::TemplateParameterList *list) const
TypedefColl_t fSelectedTypedefs