31#include "TClingUtils.h"
34#include "cling/Interpreter/Interpreter.h"
35#include "cling/Interpreter/LookupHelper.h"
36#include "cling/Utils/AST.h"
38#include "clang/AST/ASTContext.h"
39#include "clang/AST/Decl.h"
40#include "clang/AST/DeclCXX.h"
41#include "clang/AST/DeclTemplate.h"
42#include "clang/AST/GlobalDecl.h"
43#include "clang/AST/PrettyPrinter.h"
44#include "clang/AST/RecordLayout.h"
45#include "clang/AST/Type.h"
46#include "clang/Basic/Specifiers.h"
47#include "clang/Frontend/CompilerInstance.h"
48#include "clang/Sema/Sema.h"
50#include "llvm/ExecutionEngine/GenericValue.h"
51#include "llvm/Support/Casting.h"
52#include "llvm/Support/raw_ostream.h"
63 if (
const NamedDecl* ND = llvm::dyn_cast<NamedDecl>(decl)) {
64 PrintingPolicy Policy(decl->getASTContext().getPrintingPolicy());
65 llvm::raw_string_ostream stream(buf);
66 ND->getNameForDiagnostic(stream, Policy,
true);
72 :
TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(all),
73 fIsIter(true),
fType(0), fOffsetCache(0)
75 TranslationUnitDecl *TU =
76 interp->getCI()->getASTContext().getTranslationUnitDecl();
83 :
TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(
kTRUE), fIsIter(false),
84 fType(0), fTitle(
""), fOffsetCache(0)
86 const cling::LookupHelper& lh =
fInterp->getLookupHelper();
88 const Decl *decl = lh.findScope(
name,
89 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
90 : cling::LookupHelper::NoDiagnostics,
95 decl = lh.findScope(buf,
96 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
97 : cling::LookupHelper::NoDiagnostics,
102 const TagType *tagtype =
type->getAs<TagType>();
104 decl = tagtype->getDecl();
109 if (decl && decl->isInvalidDecl()) {
110 Error(
"TClingClassInfo",
"Found an invalid decl for %s.",
name);
118 :
TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(
kTRUE),
119 fIsIter(false),
fType(0), fTitle(
""), fOffsetCache(0)
126 :
TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(
kTRUE),
127 fIsIter(false),
fType(0), fTitle(
""), fOffsetCache(0)
138 fOffsetCache[decl] = std::make_pair(offset, executableFunc);
147 const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(
GetDecl());
158 const CXXRecordDecl *CRD =
159 llvm::dyn_cast<CXXRecordDecl>(
GetDecl());
161 if (CRD->isAbstract()) {
164 if (CRD->hasUserDeclaredConstructor()) {
168 !CRD->hasUserDeclaredConstructor() &&
169 !CRD->hasTrivialDefaultConstructor()
174 CRD->hasUserProvidedDefaultConstructor() ||
175 !CRD->hasTrivialDefaultConstructor()
179 if (CRD->hasUserDeclaredDestructor()) {
182 else if (!CRD->hasTrivialDestructor()) {
185 if (CRD->hasUserDeclaredCopyAssignment()) {
188 if (CRD->isPolymorphic()) {
199 Error(
"TClingClassInfo::Delete()",
"Called while invalid!");
203 Error(
"TClingClassInfo::Delete()",
"Class is not loaded: %s",
224 Error(
"DeleteArray",
"Placement delete of an array is unsupported!\n");
251 const TypedefType *TT = llvm::dyn_cast<TypedefType>(
fType);
253 llvm::StringRef tname(TT->getDecl()->getName());
254 if (tname.equals(fname)) {
255 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(
GetDecl());
256 if (ndecl && !ndecl->getName().equals(fname)) {
263 const cling::LookupHelper &lh =
fInterp->getLookupHelper();
264 const FunctionTemplateDecl *fd
265 = lh.findFunctionTemplate(
GetDecl(), fname,
266 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
267 : cling::LookupHelper::NoDiagnostics,
false);
268 if (fd)
return fd->getCanonicalDecl();
277 const cling::LookupHelper &lh =
fInterp->getLookupHelper();
280 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
281 : cling::LookupHelper::NoDiagnostics);
282 if (vd)
return llvm::dyn_cast<ValueDecl>(vd->getCanonicalDecl());
298 const TypedefType *TT = llvm::dyn_cast<TypedefType>(
fType);
300 llvm::StringRef tname(TT->getDecl()->getName());
301 if (tname.equals(fname)) {
302 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(
GetDecl());
303 if (ndecl && !ndecl->getName().equals(fname)) {
305 return GetMethod(ndecl->getName().str().c_str());
310 const cling::LookupHelper &lh =
fInterp->getLookupHelper();
311 const FunctionDecl *fd
312 = lh.findAnyFunction(
GetDecl(), fname,
313 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
314 : cling::LookupHelper::NoDiagnostics,
334 const char *
proto,
bool objectIsConst,
349 const TypedefType *TT = llvm::dyn_cast<TypedefType>(
fType);
351 llvm::StringRef tname(TT->getDecl()->getName());
352 if (tname.equals(fname)) {
353 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(
GetDecl());
354 if (ndecl && !ndecl->getName().equals(fname)) {
357 objectIsConst,poffset,
364 const cling::LookupHelper& lh =
fInterp->getLookupHelper();
365 const FunctionDecl *fd;
368 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
369 : cling::LookupHelper::NoDiagnostics,
373 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
374 : cling::LookupHelper::NoDiagnostics,
377 Error(
"TClingClassInfo::GetMethod",
378 "The MatchMode %d is not supported.", mode);
396 const clang::DeclContext* ourDC = llvm::dyn_cast<clang::DeclContext>(
GetDecl());
397 if (!fd->getDeclContext()->Equals(ourDC)
398 && !(fd->getDeclContext()->isTransparentContext()
399 && fd->getDeclContext()->getParent()->Equals(ourDC)))
403 if (poffset) *poffset = 0;
407 if (
const CXXMethodDecl *md =
408 llvm::dyn_cast<CXXMethodDecl>(fd)) {
420 const llvm::SmallVectorImpl<clang::QualType> &
proto,
428 const llvm::SmallVectorImpl<clang::QualType> &
proto,
bool objectIsConst,
443 const TypedefType *TT = llvm::dyn_cast<TypedefType>(
fType);
445 llvm::StringRef tname(TT->getDecl()->getName());
446 if (tname.equals(fname)) {
447 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(
GetDecl());
448 if (ndecl && !ndecl->getName().equals(fname)) {
450 return GetMethod(ndecl->getName().str().c_str(),
proto,objectIsConst,poffset,
457 const cling::LookupHelper& lh =
fInterp->getLookupHelper();
458 const FunctionDecl *fd;
461 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
462 : cling::LookupHelper::NoDiagnostics,
466 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
467 : cling::LookupHelper::NoDiagnostics,
470 Error(
"TClingClassInfo::GetMethod",
471 "The MatchMode %d is not supported.", mode);
482 if (
const CXXMethodDecl *md =
483 llvm::dyn_cast<CXXMethodDecl>(fd)) {
501 const char *arglist,
bool objectIsConst,
509 const TypedefType *TT = llvm::dyn_cast<TypedefType>(
fType);
511 llvm::StringRef tname(TT->getDecl()->getName());
512 if (tname.equals(fname)) {
513 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(
GetDecl());
514 if (ndecl && !ndecl->getName().equals(fname)) {
516 return GetMethod(ndecl->getName().str().c_str(),arglist,
517 objectIsConst,poffset
531 if (!strcmp(arglist,
")")) {
535 const cling::LookupHelper &lh =
fInterp->getLookupHelper();
536 const FunctionDecl *fd
537 = lh.findFunctionArgs(
GetDecl(), fname, arglist,
538 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
539 : cling::LookupHelper::NoDiagnostics,
548 if (
const CXXMethodDecl *md =
549 llvm::dyn_cast<CXXMethodDecl>(fd)) {
574 clang_val =
static_cast<int>(num_params);
585 const CXXRecordDecl* definer = md->getParent();
586 const CXXRecordDecl* accessor =
587 llvm::cast<CXXRecordDecl>(
GetDecl());
588 if (definer != accessor) {
595 if (bci->
GetDecl() == definer) {
615 std::pair<ptrdiff_t, OffsetPtrFunc_t> offsetCache = (*iter).second;
618 return (*executableFunc)(address, isDerivedObject);
621 Error(
"TClingBaseClassInfo::Offset",
"The address of the object for virtual base offset calculation is not valid.");
626 return offsetCache.first;
634 return binfo.
Offset(address, isDerivedObject);
640 std::vector<std::string> res;
644 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
645 const auto DC = dyn_cast<DeclContext>(
fDecl);
649 clang::PrintingPolicy policy(
fDecl->getASTContext().getPrintingPolicy());
650 for (
auto UD : DC->using_directives()) {
651 NamespaceDecl *NS = UD->getNominatedNamespace();
654 llvm::raw_string_ostream stream(nsName);
656 NS->getNameForDiagnostic(stream, policy,
true);
659 res.push_back(nsName);
679 const CXXRecordDecl* CRD = llvm::dyn_cast<CXXRecordDecl>(
GetDecl());
684 using namespace TMetaUtils;
685 const RConstructorType ioctortype(
"",*
fInterp);
686 return EIOCtorCategory::kAbsent != CheckConstructor(CRD,ioctortype,*
fInterp);
693 return fInterp->getLookupHelper()
695 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
696 : cling::LookupHelper::NoDiagnostics);
706 fIter = DeclContext::decl_iterator();
710 const cling::LookupHelper& lh =
fInterp->getLookupHelper();
712 : cling::LookupHelper::NoDiagnostics,
717 SetDecl(lh.findScope(buf,
gDebug > 5 ? cling::LookupHelper::WithDiagnostics
718 : cling::LookupHelper::NoDiagnostics,
723 const TagType *tagtype =
fType->getAs<TagType>();
735 fIter = DeclContext::decl_iterator();
743 Fatal(
"TClingClassInfo::Init(tagnum)",
"Should no longer be called");
753 const TagType *tagtype =
fType->getAs<TagType>();
761 QualType qType(
fType,0);
762 static PrintingPolicy printPol(
fInterp->getCI()->getLangOpts());
763 printPol.SuppressScope =
false;
764 Error(
"TClingClassInfo::Init(const Type&)",
765 "The given type %s does not point to a Decl",
766 qType.getAsString(printPol).c_str());
782 const CXXRecordDecl *CRD =
783 llvm::dyn_cast<CXXRecordDecl>(
GetDecl());
789 const CXXRecordDecl *baseCRD =
790 llvm::dyn_cast<CXXRecordDecl>(base.
GetDecl());
791 return CRD->isDerivedFrom(baseCRD);
806 if (
auto *ED = llvm::dyn_cast<clang::EnumDecl>(
GetDecl()))
807 return ED->isScoped();
818 if (
auto ED = llvm::dyn_cast<EnumDecl>(
GetDecl())) {
820 auto Ty = ED->getIntegerType().getTypePtrOrNull();
821 if (
auto BTy = llvm::dyn_cast<BuiltinType>(Ty)) {
822 switch (BTy->getKind()) {
826 case BuiltinType::Char_U:
830 case BuiltinType::Char_S:
831 case BuiltinType::SChar:
846 case BuiltinType::ULongLong:
848 case BuiltinType::LongLong:
874 const CXXRecordDecl *CRD = llvm::dyn_cast<CXXRecordDecl>(
GetDecl());
876 if (!CRD->hasDefinition()) {
880 const TagDecl *TD = llvm::dyn_cast<TagDecl>(
GetDecl());
881 if (TD && TD->getDefinition() == 0) {
912 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
915 const clang::DeclContext *DC = cast<DeclContext>(
GetDecl());
917 fIter = DC->decls_begin();
919 fIter = DC->noload_decls_begin();
926 if (
const NamedDecl* ND =
927 llvm::dyn_cast<NamedDecl>(
GetDecl())) {
928 PrintingPolicy Policy(
GetDecl()->getASTContext().
929 getPrintingPolicy());
930 llvm::raw_string_ostream stream(buf);
931 ND->getNameForDiagnostic(stream, Policy,
false);
933 Error(
"TClingClassInfo::InternalNext",
934 "Next called but iteration not prepared for %s!", buf.c_str());
936 Error(
"TClingClassInfo::InternalNext",
937 "Next called but iteration not prepared!");
965 DeclContext *DC = llvm::cast<DeclContext>(*
fIter);
967 fIter = DC->decls_begin();
969 fIter = DC->noload_decls_begin();
989 Decl::Kind DK =
fIter->getKind();
990 if ((DK == Decl::Namespace) || (DK == Decl::Enum) ||
991 (DK == Decl::CXXRecord) ||
992 (DK == Decl::ClassTemplateSpecialization)) {
993 const TagDecl *TD = llvm::dyn_cast<TagDecl>(*
fIter);
994 if (TD && !TD->isCompleteDefinition()) {
998 if (DK == Decl::Namespace) {
1000 if (!
fIter->isCanonicalDecl()) {
1006 if (DK != Decl::Enum) {
1008 DeclContext *DC = llvm::cast<DeclContext>(*
fIter);
1009 if ((
fIterAll && *DC->decls_begin())
1010 || (!
fIterAll && *DC->noload_decls_begin())) {
1020 if (
GetDecl()->isInvalidDecl()) {
1021 Warning(
"TClingClassInfo::Next()",
"Reached an invalid decl.");
1023 if (
const RecordDecl *RD =
1024 llvm::dyn_cast<RecordDecl>(
GetDecl())) {
1025 fType = RD->getASTContext().getRecordType(RD).getTypePtr();
1043 Error(
"TClingClassInfo::New()",
"Called while invalid!");
1047 Error(
"TClingClassInfo::New()",
"Class is not loaded: %s",
1053 const CXXRecordDecl* RD = dyn_cast<CXXRecordDecl>(
GetDecl());
1055 Error(
"TClingClassInfo::New()",
"This is a namespace!: %s",
1070 Error(
"TClingClassInfo::New()",
"Call of default constructor "
1071 "failed to return an object for class: %s",
1084 Error(
"TClingClassInfo::New(n)",
"Called while invalid!");
1088 Error(
"TClingClassInfo::New(n)",
"Class is not loaded: %s",
1096 const CXXRecordDecl* RD = dyn_cast<CXXRecordDecl>(
GetDecl());
1098 Error(
"TClingClassInfo::New(n)",
"This is a namespace!: %s",
1115 Error(
"TClingClassInfo::New(n)",
"Call of default constructor "
1116 "failed to return an array of class: %s",
1130 Error(
"TClingClassInfo::New(n, arena)",
"Called while invalid!");
1134 Error(
"TClingClassInfo::New(n, arena)",
"Class is not loaded: %s",
1141 const CXXRecordDecl* RD = dyn_cast<CXXRecordDecl>(
GetDecl());
1143 Error(
"TClingClassInfo::New(n, arena)",
"This is a namespace!: %s",
1169 Error(
"TClingClassInfo::New(arena)",
"Called while invalid!");
1173 Error(
"TClingClassInfo::New(arena)",
"Class is not loaded: %s",
1180 const CXXRecordDecl* RD = dyn_cast<CXXRecordDecl>(
GetDecl());
1182 Error(
"TClingClassInfo::New(arena)",
"This is a namespace!: %s",
1213 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
1215 const clang::DeclContext *ctxt =
GetDecl()->getDeclContext();
1216 clang::NamespaceDecl *std_ns =
fInterp->getSema().getStdNamespace();
1217 while (! ctxt->isTranslationUnit()) {
1218 if (ctxt->Equals(std_ns)) {
1222 ctxt = ctxt->getParent();
1224 Decl::Kind DK =
GetDecl()->getKind();
1225 if ((DK == Decl::Namespace) || (DK == Decl::TranslationUnit)) {
1230 const TagDecl *TD = llvm::dyn_cast<TagDecl>(
GetDecl());
1239 const CXXRecordDecl *CRD =
1240 llvm::dyn_cast<CXXRecordDecl>(
GetDecl());
1241 if (CRD->isClass()) {
1244 else if (CRD->isStruct()) {
1247 else if (CRD->isUnion()) {
1250 if (CRD->hasDefinition() && CRD->isAbstract()) {
1277 Decl::Kind DK =
GetDecl()->getKind();
1278 if (DK == Decl::Namespace) {
1282 else if (DK == Decl::Enum) {
1286 const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(
GetDecl());
1291 if (!RD->getDefinition()) {
1296 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
1297 const ASTRecordLayout &
Layout =
Context.getASTRecordLayout(RD);
1298 int64_t size =
Layout.getSize().getQuantity();
1299 int clang_size =
static_cast<int>(size);
1308 return reinterpret_cast<long>(
GetDecl());
1333 if (
const NamedDecl* ND =
1334 llvm::dyn_cast<NamedDecl>(
GetDecl())) {
1335 PrintingPolicy Policy(
GetDecl()->getASTContext().
1336 getPrintingPolicy());
1337 llvm::raw_string_ostream stream(
output);
1338 ND->getNameForDiagnostic(stream, Policy,
true);
1356 if (
const TagDecl *TD = llvm::dyn_cast<TagDecl>(
GetDecl())) {
1357 if ( (TD = ROOT::TMetaUtils::GetAnnotatedRedeclarable(TD)) ) {
1358 if (AnnotateAttr *
A = TD->getAttr<AnnotateAttr>()) {
1359 std::string attr =
A->getAnnotation().str();
1360 if (attr.find(TMetaUtils::propNames::separator) != std::string::npos) {
1361 if (TMetaUtils::ExtractAttrPropertyFromName(*TD,TMetaUtils::propNames::comment,attr)) {
1375 const CXXRecordDecl *CRD =
1376 llvm::dyn_cast<CXXRecordDecl>(
GetDecl());
1377 if (CRD && !CRD->isFromASTFile()) {
1378 fTitle = ROOT::TMetaUtils::GetClassComment(*CRD,0,*
fInterp).str();
1392 TTHREAD_TLS_DECL( std::string, buf);
1394 if (
const NamedDecl* ND = llvm::dyn_cast<NamedDecl>(
GetDecl())) {
1396 buf = ND->getNameAsString();
static std::string FullyQualifiedName(const Decl *decl)
ptrdiff_t(* OffsetPtrFunc_t)(void *, bool)
void Error(const char *location, const char *msgfmt,...)
void Warning(const char *location, const char *msgfmt,...)
void Fatal(const char *location, const char *msgfmt,...)
R__EXTERN TVirtualMutex * gInterpreterMutex
#define R__LOCKGUARD(mutex)
#define R__WRITE_LOCKGUARD(mutex)
#define R__READ_LOCKGUARD(mutex)
Small helper to keep current directory context.
Emulation of the CINT BaseClassInfo class.
ptrdiff_t Offset(void *address=0, bool isDerivedObject=true) const
TClingClassInfo * GetBase() const
Emulation of the CINT CallFunc class.
void ExecDestructor(const TClingClassInfo *info, void *address=0, unsigned long nary=0UL, bool withFree=true)
void * ExecDefaultConstructor(const TClingClassInfo *info, void *address=0, unsigned long nary=0UL)
Emulation of the CINT ClassInfo class.
bool HasDefaultConstructor() const
clang::DeclContext::decl_iterator fIter
static bool IsEnum(cling::Interpreter *interp, const char *name)
long ClassProperty() const
void Init(const char *name)
void FullName(std::string &output, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
llvm::DenseMap< const clang::Decl *, std::pair< ptrdiff_t, OffsetPtrFunc_t > > fOffsetCache
EDataType GetUnderlyingType() const
TClingMethodInfo GetMethodWithArgs(const char *fname, const char *arglist, long *poffset, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch, EInheritanceMode imode=kWithInheritance) const
const char * TmpltName() const
void AddBaseOffsetValue(const clang::Decl *decl, ptrdiff_t offset)
ptrdiff_t GetBaseOffset(TClingClassInfo *toBase, void *address, bool isDerivedObject)
void SetDecl(const clang::Decl *D)
bool IsScopedEnum() const
const clang::FunctionTemplateDecl * GetFunctionTemplate(const char *fname) const
int GetMethodNArg(const char *method, const char *proto, Bool_t objectIsConst, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch) const
bool HasMethod(const char *name) const
std::string fDeclFileName
void DeleteArray(void *arena, bool dtorOnly, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
void * New(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
bool IsValidMethod(const char *method, const char *proto, Bool_t objectIsConst, long *offset, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch) const
TClingMethodInfo GetMethod(const char *fname) const
long GetOffset(const clang::CXXMethodDecl *md) const
const clang::ValueDecl * GetDataMember(const char *name) const
void Destruct(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
std::vector< std::string > GetUsingNamespaces()
cling::Interpreter * fInterp
std::vector< clang::DeclContext::decl_iterator > fIterStack
bool IsBase(const char *name) const
const clang::Type * fType
void Delete(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
const clang::Decl * fDecl
virtual bool IsValid() const
virtual const clang::Decl * GetDecl() const
Emulation of the CINT MethodInfo class.
void Init(const clang::FunctionDecl *)
const clang::FunctionDecl * GetMethodDecl() const
Type
enumeration specifying the integration types.
Namespace for new ROOT classes and functions.
R__EXTERN TVirtualRWMutex * gCoreMutex
RooCmdArg Layout(Double_t xmin, Double_t xmax=0.99, Double_t ymin=0.95)
std::string InsertStd(const char *tname)
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
static constexpr double L
static void output(int code)