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);
46inline static bool IsElementPresent(
const std::vector<T> &
v,
const T &el){
47 return std::find(
v.begin(),
v.end(),el) !=
v.end();
51inline static bool IsElementPresent(
const std::vector<const T*> &
v,
T *el){
52 return std::find(
v.begin(),
v.end(),el) !=
v.end();
60extern cling::Interpreter *
gInterp;
78 const cling::Interpreter &interpret,
79 ROOT::TMetaUtils::TNormalizedCtxt &normCtxt,
83 fInterpreter(interpret),
84 fRecordDeclCallback(0),
86 fSelectionRules(rules),
123 if (
auto M = D->getOwningModule()) {
141 return *num.getRawData();
148 return *num.getRawData();
155 return num.toString(10,
true);
162 std::string txt =
"";
171 std::ostringstream stream;
178inline std::string
Message(
const std::string &msg,
const std::string &location)
180 std::string loc = location;
185 return loc +
" " + msg;
192 const std::string message =
Message(msg, location);
193 std::cout << message << std::endl;
200 const std::string message =
Message(msg, location);
201 std::cout << message << std::endl;
208 const std::string message =
Message(msg, location);
209 std::cout << message << std::endl;
216 std::string loc = location;
226 std::string location =
"";
227 llvm::raw_string_ostream stream(location);
242 std::string location =
"";
243 llvm::raw_string_ostream stream(location);
253 std::string
name =
"";
256 if (clang::NamedDecl* ND = dyn_cast <clang::NamedDecl> (D)) {
257 name = ND->getQualifiedNameAsString();
278 std::string kind = D->getDeclKindName();
280 ShowInfo(
"Scan: " + kind +
" declaration " +
name, location);
289 std::string kind = D->getDeclKindName();
300 std::string kind = D->getDeclKindName();
311 std::string kind = D->getDeclKindName();
328 clang::Decl::Kind k = D->getKind();
341 std::string kind = D->getDeclKindName();
343 std::string msg =
"Unimplemented ";
345 msg +=
"declaration";
362 std::string kind = qual_type.getTypePtr()->getTypeClassName();
363 ShowWarning(
"Unknown " + kind +
" type " + qual_type.getAsString(), location);
371 std::string kind = qual_type.getTypePtr()->getTypeClassName();
372 ShowWarning(
"Unsupported " + kind +
" type " + qual_type.getAsString(), location);
379 std::string enum_name = D->getQualifiedNameAsString();
381 if (! D->getDeclName ()) {
403 clang::LangOptions lang_opts;
404 clang::PrintingPolicy print_opts(lang_opts);
406 std::string
text =
"";
407 llvm::raw_string_ostream stream(
text);
409 expr->printPretty(stream, NULL, print_opts);
418 clang::LangOptions lang_opts;
419 clang::PrintingPolicy print_opts(lang_opts);
421 std::string
text =
"";
422 llvm::raw_string_ostream stream(
text);
424 N.print(stream, print_opts);
433 std::string result =
"";
435 for (clang::FunctionDecl::param_iterator
I = D->param_begin(),
E = D->param_end();
I !=
E; ++
I) {
436 clang::ParmVarDecl*
P = *
I;
441 std::string
type =
P->getType().getAsString();
442 std::string
name =
P->getNameAsString();
448 std::string init_value =
ExprToStr(
P->getDefaultArg());
449 result +=
"=" + init_value;
460 std::string result =
"";
462 for (clang::FunctionDecl::param_iterator
I = D->param_begin(),
E = D->param_end();
I !=
E; ++
I) {
463 clang::ParmVarDecl*
P = *
I;
468 std::string
type =
P->getType().getAsString();
472 return "(" + result +
")";
489 if((
N &&
N->isImplicit()) || !
N){
498 clang::DeclContext* primary_ctxt =
N->getPrimaryContext();
499 clang::NamespaceDecl* primary = llvm::dyn_cast<clang::NamespaceDecl>(primary_ctxt);
501 RPredicateIsSameNamespace pred(primary);
506 std::string qual_name;
509 std::cout<<
"\tSelected namespace -> " << qual_name <<
"\n";
536 const clang::RecordDecl* recordDecl,
537 const std::string& attr_name,
538 const clang::TypedefNameDecl* typedefNameDecl,
539 unsigned int indexOffset)
544 if (recordDecl->isUnion() &&
545 0 != ROOT::TMetaUtils::GetClassVersion(recordDecl,
fInterpreter)) {
546 std::string normName;
548 recordDecl->getASTContext().getTypeDeclType(recordDecl),
551 ROOT::TMetaUtils::Error(0,
"Union %s has been selected for I/O. This is not supported. Interactive usage of unions is supported, as all C++ entities, without the need of dictionaries.\n",normName.c_str());
580 std::string qual_name;
582 std::string normName;
584 recordDecl->getASTContext().getTypeDeclType(recordDecl),
587 std::string typedef_qual_name;
588 std::string typedefMsg;
589 if (typedefNameDecl){
591 typedefMsg =
"(through typedef/alias " + typedef_qual_name +
") ";
594 std::cout <<
"Selected class "
620 const clang::RecordDecl* recordDecl = clang::dyn_cast<clang::RecordDecl>(typeDecl);
621 const clang::TypedefNameDecl* typedefNameDecl = clang::dyn_cast<clang::TypedefNameDecl>(typeDecl);
624 if (!recordDecl && typedefNameDecl) {
625 recordDecl = ROOT::TMetaUtils::GetUnderlyingRecordDecl(typedefNameDecl->getUnderlyingType());
631 "Could not cast typeDecl either to RecordDecl or could not get RecordDecl underneath typedef.\n");
636 if (!recordDecl->getIdentifier())
640 if (recordDecl->isDependentType())
661 if(recordDecl->isImplicit() || !recordDecl->isCompleteDefinition()) {
666 const clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(recordDecl);
667 if (cxxdecl && cxxdecl->getDescribedClassTemplate ()) {
675 const ClassSelectionRule *selected = typedefNameDecl ? selectedFromTypedef : selectedFromRecDecl;
677 if (! selected)
return true;
680 bool excludedFromRecDecl =
false;
681 if ( selectedFromRecDecl )
688 if (selectedFromTypedef){
703 "Typedef is selected %s.\n", typedefNameDecl->getNameAsString().c_str());
711 if (recordDecl->getName() ==
"pair") {
712 const clang::NamespaceDecl *nsDecl = llvm::dyn_cast<clang::NamespaceDecl>(recordDecl->getDeclContext());
715 "Cannot convert context of RecordDecl called pair into a namespace.\n");
718 const clang::NamespaceDecl *nsCanonical = nsDecl->getCanonicalDecl();
719 if (nsCanonical && nsCanonical ==
fInterpreter.getCI()->getSema().getStdNamespace()) {
728 bool rcrdDeclNotAlreadySelected =
fselectedRecordDecls.insert((RecordDecl*)recordDecl->getCanonicalDecl()).second;
729 if (!
fFirstPass && !rcrdDeclNotAlreadySelected) {
731 auto declSelRuleMapIt =
fDeclSelRuleMap.find(recordDecl->getCanonicalDecl());
733 declSelRuleMapIt->second != selected) {
734 std::string normName;
736 recordDecl->getASTContext().getTypeDeclType(recordDecl),
741 int previouslineno = previouslyMatchingRule->GetLineNumber();
743 std::string cleanFileName = llvm::sys::path::filename(selected->
GetSelFileName());
746 if (!rulesAreCompatible){
747 std::stringstream message;
748 if (lineno > 1) message <<
"Selection file " << cleanFileName <<
", lines "
749 << lineno <<
" and " << previouslineno <<
". ";
750 message <<
"Attempt to select a class "<< normName <<
" with two rules which have incompatible attributes. "
751 <<
"The attributes such as transiency might not be correctly propagated to the typesystem of ROOT.\n";
752 selected->
Print(message);
753 message <<
"Conflicting rule already matched:\n";
754 previouslyMatchingRule->Print(message);
762 if (!rcrdDeclNotAlreadySelected ||
fFirstPass)
769 if (recordDecl->getAccess() == AS_private || recordDecl->getAccess() == AS_protected) {
774 if (!isFileSelection) {
775 std::string normName;
777 recordDecl->getASTContext().getTypeDeclType(recordDecl),
780 auto msg =
"Class or struct %s was selected but its dictionary cannot be generated: "
781 "this is a private or protected class and this is not supported. No direct "
782 "I/O operation of %s instances will be possible.\n";
793 clang::QualType thisType(req_type, 0);
801 if (
auto CTSD = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(recordDecl)) {
811 const clang::Type *thisType = info.fSelected->GetRequestedType();
813 thisType = info.fDecl->getTypeForDecl();
814 const clang::CXXRecordDecl *recordDecl = info.fDecl;
815 auto nameTypeForIO = ROOT::TMetaUtils::GetNameTypeForIO(clang::QualType(thisType, 0),
fInterpreter,
fNormCtxt);
816 auto typeForIO = nameTypeForIO.second;
819 if (typeForIO.getTypePtr() == thisType)
821 if (
auto recordDeclForIO = typeForIO->getAsCXXRecordDecl()) {
822 const auto canRecordDeclForIO = recordDeclForIO->getCanonicalDecl();
825 recordDecl = canRecordDeclForIO;
827 thisType = typeForIO.getTypePtr();
831 nameTypeForIO.first, info.fTypedefNameDecl, 1000);
850 const clang::DeclContext *ctx = D->getDeclContext();
854 const clang::NamedDecl *parent = llvm::dyn_cast<clang::NamedDecl> (ctx);
855 isInStd = parent && 0 == parent->getQualifiedNameAsString().compare(0,5,
"std::");
858 if (ROOT::TMetaUtils::GetUnderlyingRecordDecl(D->getUnderlyingType()) &&
888 if (!D->hasGlobalStorage() ||
935 if(clang::FunctionDecl::TemplatedKind::TK_FunctionTemplate == D->getTemplatedKind())
954 clang::Decl* D = dyn_cast<clang::Decl>(DC);
956 if (D && D->isImplicit()){
961 const clang::NamespaceDecl *parent = llvm::dyn_cast<clang::NamespaceDecl> (DC);
962 if (parent && 0 == parent->getQualifiedNameAsString().compare(0,5,
"std::"))
966 for (DeclContext::decl_iterator Child = DC->decls_begin(), ChildEnd = DC->decls_end();
967 ret && (Child != ChildEnd); ++Child) {
968 ret=TraverseDecl(*Child);
979 clang::NamedDecl*
N = dyn_cast<clang::NamedDecl> (D);
982 name =
N->getNameAsString();
995 auto N = dyn_cast<const clang::NamedDecl> (D);
998 llvm::raw_string_ostream stream(qual_name);
999 N->getNameForDiagnostic(stream,D->getASTContext().getPrintingPolicy(),
true);
1014 clang::FunctionDecl*
F = dyn_cast<clang::FunctionDecl> (D);
1019 for (clang::FunctionDecl::param_iterator
I =
F->param_begin(),
E =
F->param_end();
I !=
E; ++
I) {
1020 clang::ParmVarDecl*
P = *
I;
1022 if (prototype !=
"")
1026 std::string
type =
P->getType().getAsString();
1027 if (
type.at(
type.length()-1) ==
'*') {
1034 prototype =
"(" + prototype +
")";
1038 ShowWarning(
"can't convert Decl to FunctionDecl",
"");
1052 std::cout<<
"File name detected"<<std::endl;
1056 TraverseDecl(
C.getTranslationUnitDecl());
1064 TraverseDecl(
C.getTranslationUnitDecl());
std::string IntToStr(int num)
long APIntToLong(const llvm::APInt &num)
cling::Interpreter * gInterp
std::string AddSpace(const std::string &txt)
size_t APIntToSize(const llvm::APInt &num)
void * ToDeclProp(clang::Decl *item)
std::string APIntToStr(const llvm::APInt &num)
std::string IntToStd(int num)
std::string Message(const std::string &msg, const std::string &location)
void Info(const char *location, const char *msgfmt,...)
void Error(const char *location, const char *msgfmt,...)
void Warning(const char *location, const char *msgfmt,...)
TRObject operator()(const T1 &t1) const
bool HasAttributeFileName() const
bool HasAttributePattern() const
const std::string & GetAttributePattern() const
bool HasAttributeFilePattern() const
const std::string & GetAttributeName() const
const clang::Type * GetRequestedType() const
long GetLineNumber() const
ESelect GetSelected() const
bool HasAttributeName() const
bool IsFromTypedef() const
const char * GetSelFileName() const
bool RequestNoStreamer() const
bool RequestStreamerInfo() const
bool RequestNoInputOperator() const
int RequestedVersionNumber() const
void Print(std::ostream &out) const
bool RequestOnlyTClass() const
std::string GetLocation(clang::Decl *D) const
void Scan(const clang::ASTContext &C)
void UnknownDecl(clang::Decl *D, const std::string &txt="") const
unknown - this kind of declaration was not known to programmer
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'.
ROOT::TMetaUtils::TNormalizedCtxt & fNormCtxt
DeclCallback fRecordDeclCallback
void UnsupportedDecl(clang::Decl *D, const std::string &txt="") const
unsupported - this kind of declaration is probably not used (in current version of C++)
static std::map< clang::Decl *, std::string > fgAnonymousEnumMap
void UnimportantDecl(clang::Decl *D, const std::string &txt="") const
unimportant - this kind of declaration is not stored into reflex
void AddDelayedAnnotatedRecordDecls()
const clang::SourceManager * fSourceManager
static const int fgDeclLast
FunctionColl_t fSelectedFunctions
bool VisitFieldDecl(clang::FieldDecl *D)
Nothing to be done here.
void ShowInfo(const std::string &msg, const std::string &location="") const
bool TreatRecordDeclOrTypedefNameDecl(clang::TypeDecl *typeDecl)
static int fgAnonymousClassCounter
std::string FuncParameters(clang::FunctionDecl *D) const
bool fTypeTable[fgTypeLast+1]
void ShowTemplateInfo(const std::string &msg, const std::string &location="") const
std::string GetEnumName(clang::EnumDecl *D) const
NamespaceColl_t fSelectedNamespaces
bool GetFunctionPrototype(clang::Decl *D, std::string &prototype) const
std::set< clang::RecordDecl * > fselectedRecordDecls
std::string ConvTemplateName(clang::TemplateName &N) const
static int fgBadClassCounter
void UnimplementedDecl(clang::Decl *D, const std::string &txt="")
information about item, that should be implemented
bool VisitVarDecl(clang::VarDecl *D)
TypedefColl_t fSelectedTypedefs
std::string GetSrcLocation(clang::SourceLocation L) const
void(* DeclCallback)(const clang::RecordDecl *)
void UnsupportedType(clang::QualType qual_type) const
const cling::Interpreter & fInterpreter
DeclCallback SetRecordDeclCallback(DeclCallback callback)
Set the callback to the RecordDecl and return the previous one.
bool VisitNamespaceDecl(clang::NamespaceDecl *D)
This method visits a namespace node.
void ShowWarning(const std::string &msg, const std::string &location="") const
std::string GetName(clang::Decl *D) const
static int fgAnonymousEnumCounter
static const char * fgClangFuncKey
void ShowError(const std::string &msg, const std::string &location="") const
void UnexpectedDecl(clang::Decl *D, const std::string &txt="") const
unexpected - this kind of declaration is unexpected (in concrete place)
EnumColl_t fSelectedEnums
int AddAnnotatedRecordDecl(const ClassSelectionRule *, const clang::Type *, const clang::RecordDecl *, const std::string &, const clang::TypedefNameDecl *, unsigned int indexOffset=0)
std::vector< DelayedAnnotatedRecordDeclInfo > fDelayedAnnotatedRecordDecls
bool VisitEnumDecl(clang::EnumDecl *D)
static std::map< clang::Decl *, std::string > fgAnonymousClassMap
std::string FuncParameterList(clang::FunctionDecl *D) const
static bool GetDeclQualName(const clang::Decl *D, std::string &qual_name)
std::string ExprToStr(clang::Expr *expr) const
static const int fgTypeLast
SelectionRules & fSelectionRules
static const char * fgClangDeclKey
bool VisitRecordDecl(clang::RecordDecl *D)
void UnknownType(clang::QualType qual_type) const
bool fDeclTable[fgDeclLast+1]
VariableColl_t fSelectedVariables
bool VisitFunctionDecl(clang::FunctionDecl *D)
DeclsSelRulesMap_t fDeclSelRuleMap
unsigned int fVerboseLevel
bool GetDeclName(clang::Decl *D, std::string &name) const
bool TraverseDeclContextHelper(clang::DeclContext *DC)
ClassColl_t fSelectedClasses
void DeclInfo(clang::Decl *D) const
bool shouldVisitDecl(clang::NamedDecl *D)
Whether we can actually visit this declaration, i.e.
bool VisitTypedefNameDecl(clang::TypedefNameDecl *D)
Visitor for every TypedefNameDecl, i.e.
The class representing the collection of selection rules.
const ClassSelectionRule * IsDeclSelected(const clang::RecordDecl *D) const
bool GetHasFileNameRule() const
bool IsSelectionXMLFile() const
Type
enumeration specifying the integration types.
bool areEqual< ClassSelectionRule >(const ClassSelectionRule *r1, const ClassSelectionRule *r2, bool moduloNameOrPattern)
bool IsStdClass(const char *type)
return true if the class belongs to the std namespace
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
static constexpr double L
constexpr Double_t E()
Base of natural log: