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"
65 if (
const NamedDecl* ND = llvm::dyn_cast<NamedDecl>(decl)) {
66 PrintingPolicy Policy(decl->getASTContext().getPrintingPolicy());
67 llvm::raw_string_ostream stream(buf);
68 ND->getNameForDiagnostic(stream, Policy,
true);
77 TranslationUnitDecl *TU =
78 interp->getCI()->getASTContext().getTranslationUnitDecl();
87 const cling::LookupHelper& lh =
fInterp->getLookupHelper();
88 const Type *
type =
nullptr;
89 const Decl *decl = lh.findScope(
name,
90 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
91 : cling::LookupHelper::NoDiagnostics,
92 &
type, intantiateTemplate);
96 decl = lh.findScope(buf,
97 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
98 : cling::LookupHelper::NoDiagnostics,
99 &
type, intantiateTemplate);
103 const TagType *tagtype =
type->getAs<TagType>();
105 decl = tagtype->getDecl();
110 if (decl && decl->isInvalidDecl()) {
111 Error(
"TClingClassInfo",
"Found an invalid decl for %s.",
name);
119 :
TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(
kTRUE),
120 fIsIter(false), fOffsetCache(0)
127 :
TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(
kTRUE),
128 fIsIter(false), fOffsetCache(0)
140 fOffsetCache[decl] = std::make_pair(offset, executableFunc);
149 const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(
GetDecl());
152 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
164 const CXXRecordDecl *CRD =
165 llvm::dyn_cast<CXXRecordDecl>(
GetDecl());
169 if (CRD->isAbstract()) {
172 if (CRD->hasUserDeclaredConstructor()) {
176 !CRD->hasUserDeclaredConstructor() &&
177 !CRD->hasTrivialDefaultConstructor()
182 CRD->hasUserProvidedDefaultConstructor() ||
183 !CRD->hasTrivialDefaultConstructor()
187 if (CRD->hasUserDeclaredDestructor()) {
190 else if (!CRD->hasTrivialDestructor()) {
193 if (CRD->hasUserDeclaredCopyAssignment()) {
196 if (CRD->isPolymorphic()) {
199 if (CRD->isAggregate() || CRD->isPOD()) {
211 Error(
"TClingClassInfo::Delete()",
"Called while invalid!");
215 Error(
"TClingClassInfo::Delete()",
"Class is not loaded: %s",
236 Error(
"DeleteArray",
"Placement delete of an array is unsupported!\n");
263 const TypedefType *TT = llvm::dyn_cast<TypedefType>(
fType);
265 llvm::StringRef tname(TT->getDecl()->getName());
266 if (tname == fname) {
267 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(
GetDecl());
268 if (ndecl && ndecl->getName() != fname) {
275 const cling::LookupHelper &lh =
fInterp->getLookupHelper();
276 const FunctionTemplateDecl *fd
277 = lh.findFunctionTemplate(
GetDecl(), fname,
278 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
279 : cling::LookupHelper::NoDiagnostics,
false);
280 if (fd)
return fd->getCanonicalDecl();
289 const cling::LookupHelper &lh =
fInterp->getLookupHelper();
292 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
293 : cling::LookupHelper::NoDiagnostics);
294 if (vd)
return llvm::dyn_cast<ValueDecl>(vd->getCanonicalDecl());
310 const TypedefType *TT = llvm::dyn_cast<TypedefType>(
fType);
312 llvm::StringRef tname(TT->getDecl()->getName());
313 if (tname == fname) {
314 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(
GetDecl());
315 if (ndecl && ndecl->getName() != fname) {
317 return GetMethod(ndecl->getName().str().c_str());
322 const cling::LookupHelper &lh =
fInterp->getLookupHelper();
323 const FunctionDecl *fd
324 = lh.findAnyFunction(
GetDecl(), fname,
325 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
326 : cling::LookupHelper::NoDiagnostics,
346 const char *
proto,
bool objectIsConst,
361 const TypedefType *TT = llvm::dyn_cast<TypedefType>(
fType);
363 llvm::StringRef tname(TT->getDecl()->getName());
364 if (tname == fname) {
365 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(
GetDecl());
366 if (ndecl && ndecl->getName() != fname) {
369 objectIsConst,poffset,
376 const cling::LookupHelper& lh =
fInterp->getLookupHelper();
377 const FunctionDecl *fd;
380 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
381 : cling::LookupHelper::NoDiagnostics,
385 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
386 : cling::LookupHelper::NoDiagnostics,
389 Error(
"TClingClassInfo::GetMethod",
390 "The MatchMode %d is not supported.", mode);
408 const clang::DeclContext* ourDC = llvm::dyn_cast<clang::DeclContext>(
GetDecl());
409 if (!fd->getDeclContext()->Equals(ourDC)
410 && !(fd->getDeclContext()->isTransparentContext()
411 && fd->getDeclContext()->getParent()->Equals(ourDC)))
415 if (poffset) *poffset = 0;
419 if (
const CXXMethodDecl *md =
420 llvm::dyn_cast<CXXMethodDecl>(fd)) {
432 const llvm::SmallVectorImpl<clang::QualType> &
proto,
440 const llvm::SmallVectorImpl<clang::QualType> &
proto,
bool objectIsConst,
455 const TypedefType *TT = llvm::dyn_cast<TypedefType>(
fType);
457 llvm::StringRef tname(TT->getDecl()->getName());
458 if (tname == fname) {
459 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(
GetDecl());
460 if (ndecl && ndecl->getName() != fname) {
462 return GetMethod(ndecl->getName().str().c_str(),
proto,objectIsConst,poffset,
469 const cling::LookupHelper& lh =
fInterp->getLookupHelper();
470 const FunctionDecl *fd;
473 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
474 : cling::LookupHelper::NoDiagnostics,
478 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
479 : cling::LookupHelper::NoDiagnostics,
482 Error(
"TClingClassInfo::GetMethod",
483 "The MatchMode %d is not supported.", mode);
494 if (
const CXXMethodDecl *md =
495 llvm::dyn_cast<CXXMethodDecl>(fd)) {
513 const char *arglist,
bool objectIsConst,
521 const TypedefType *TT = llvm::dyn_cast<TypedefType>(
fType);
523 llvm::StringRef tname(TT->getDecl()->getName());
524 if (tname == fname) {
525 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(
GetDecl());
526 if (ndecl && ndecl->getName() != fname) {
528 return GetMethod(ndecl->getName().str().c_str(),arglist,
529 objectIsConst,poffset
543 if (!strcmp(arglist,
")")) {
547 const cling::LookupHelper &lh =
fInterp->getLookupHelper();
548 const FunctionDecl *fd
549 = lh.findFunctionArgs(
GetDecl(), fname, arglist,
550 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
551 : cling::LookupHelper::NoDiagnostics,
560 if (
const CXXMethodDecl *md =
561 llvm::dyn_cast<CXXMethodDecl>(fd)) {
586 clang_val =
static_cast<int>(num_params);
597 const CXXRecordDecl* definer = md->getParent();
598 const CXXRecordDecl* accessor =
599 llvm::cast<CXXRecordDecl>(
GetDecl());
600 if (definer != accessor) {
607 if (bci->
GetDecl() == definer) {
627 std::pair<ptrdiff_t, OffsetPtrFunc_t> offsetCache = (*iter).second;
630 return (*executableFunc)(address, isDerivedObject);
633 Error(
"TClingBaseClassInfo::Offset",
"The address of the object for virtual base offset calculation is not valid.");
638 return offsetCache.first;
646 return binfo.
Offset(address, isDerivedObject);
652 std::vector<std::string> res;
656 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
657 const auto DC = dyn_cast<DeclContext>(
fDecl);
661 clang::PrintingPolicy policy(
fDecl->getASTContext().getPrintingPolicy());
662 for (
auto UD : DC->using_directives()) {
663 NamespaceDecl *NS = UD->getNominatedNamespace();
666 llvm::raw_string_ostream stream(nsName);
668 NS->getNameForDiagnostic(stream, policy,
true);
671 res.push_back(nsName);
694 auto CRD = llvm::dyn_cast<CXXRecordDecl>(
GetDecl());
702 if (type_name) *type_name =
"TRootIOCtor";
708 if (type_name) *type_name =
"__void__";
720 return fInterp->getLookupHelper()
722 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
723 : cling::LookupHelper::NoDiagnostics);
733 fIter = DeclContext::decl_iterator();
737 const cling::LookupHelper& lh =
fInterp->getLookupHelper();
739 : cling::LookupHelper::NoDiagnostics,
744 SetDecl(lh.findScope(buf,
gDebug > 5 ? cling::LookupHelper::WithDiagnostics
745 : cling::LookupHelper::NoDiagnostics,
750 const TagType *tagtype =
fType->getAs<TagType>();
762 fIter = DeclContext::decl_iterator();
770 Fatal(
"TClingClassInfo::Init(tagnum)",
"Should no longer be called");
780 const TagType *tagtype =
fType->getAs<TagType>();
788 QualType qType(
fType,0);
789 static PrintingPolicy printPol(
fInterp->getCI()->getLangOpts());
790 printPol.SuppressScope =
false;
791 Error(
"TClingClassInfo::Init(const Type&)",
792 "The given type %s does not point to a Decl",
793 qType.getAsString(printPol).c_str());
809 const CXXRecordDecl *CRD =
810 llvm::dyn_cast<CXXRecordDecl>(
GetDecl());
816 const CXXRecordDecl *baseCRD =
817 llvm::dyn_cast<CXXRecordDecl>(base.
GetDecl());
818 return CRD->isDerivedFrom(baseCRD);
834 if (
auto *ED = llvm::dyn_cast<clang::EnumDecl>(
GetDecl()))
835 return ED->isScoped();
846 if (
auto ED = llvm::dyn_cast<EnumDecl>(
GetDecl())) {
848 auto Ty = ED->getIntegerType().getTypePtrOrNull();
850 Ty = Ty->getUnqualifiedDesugaredType();
851 if (
auto BTy = llvm::dyn_cast_or_null<BuiltinType>(Ty)) {
852 switch (BTy->getKind()) {
853 case BuiltinType::Bool:
856 case BuiltinType::Char_U:
857 case BuiltinType::UChar:
860 case BuiltinType::Char_S:
861 case BuiltinType::SChar:
864 case BuiltinType::UShort:
866 case BuiltinType::Short:
868 case BuiltinType::UInt:
870 case BuiltinType::Int:
872 case BuiltinType::ULong:
874 case BuiltinType::Long:
876 case BuiltinType::ULongLong:
878 case BuiltinType::LongLong:
904 const CXXRecordDecl *CRD = llvm::dyn_cast<CXXRecordDecl>(
GetDecl());
906 if (!CRD->hasDefinition()) {
910 const TagDecl *TD = llvm::dyn_cast<TagDecl>(
GetDecl());
911 if (TD && TD->getDefinition() ==
nullptr) {
942 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
945 const clang::DeclContext *DC = cast<DeclContext>(
GetDecl());
947 fIter = DC->decls_begin();
949 fIter = DC->noload_decls_begin();
956 if (
const NamedDecl* ND =
957 llvm::dyn_cast<NamedDecl>(
GetDecl())) {
958 PrintingPolicy Policy(
GetDecl()->getASTContext().
959 getPrintingPolicy());
960 llvm::raw_string_ostream stream(buf);
961 ND->getNameForDiagnostic(stream, Policy,
false);
963 Error(
"TClingClassInfo::InternalNext",
964 "Next called but iteration not prepared for %s!", buf.c_str());
966 Error(
"TClingClassInfo::InternalNext",
967 "Next called but iteration not prepared!");
995 DeclContext *DC = llvm::cast<DeclContext>(*
fIter);
997 fIter = DC->decls_begin();
999 fIter = DC->noload_decls_begin();
1019 Decl::Kind DK =
fIter->getKind();
1020 if ((DK == Decl::Namespace) || (DK == Decl::Enum) ||
1021 (DK == Decl::CXXRecord) ||
1022 (DK == Decl::ClassTemplateSpecialization)) {
1023 const TagDecl *TD = llvm::dyn_cast<TagDecl>(*
fIter);
1024 if (TD && !TD->isCompleteDefinition()) {
1028 if (DK == Decl::Namespace) {
1030 if (!
fIter->isCanonicalDecl()) {
1036 if (DK != Decl::Enum) {
1038 DeclContext *DC = llvm::cast<DeclContext>(*
fIter);
1039 if ((
fIterAll && *DC->decls_begin())
1040 || (!
fIterAll && *DC->noload_decls_begin())) {
1050 if (
GetDecl()->isInvalidDecl()) {
1051 Warning(
"TClingClassInfo::Next()",
"Reached an invalid decl.");
1053 if (
const RecordDecl *RD =
1054 llvm::dyn_cast<RecordDecl>(
GetDecl())) {
1055 fType = RD->getASTContext().getRecordType(RD).getTypePtr();
1073 Error(
"TClingClassInfo::New()",
"Called while invalid!");
1077 Error(
"TClingClassInfo::New()",
"Class is not loaded: %s",
1083 std::string type_name;
1087 auto RD = dyn_cast<CXXRecordDecl>(
GetDecl());
1089 Error(
"TClingClassInfo::New()",
"This is a namespace!: %s",
1103 void* obj =
nullptr;
1108 Error(
"TClingClassInfo::New()",
"Call of default constructor "
1109 "failed to return an object for class: %s",
1122 Error(
"TClingClassInfo::New(n)",
"Called while invalid!");
1126 Error(
"TClingClassInfo::New(n)",
"Class is not loaded: %s",
1132 std::string type_name;
1137 auto RD = dyn_cast<CXXRecordDecl>(
GetDecl());
1139 Error(
"TClingClassInfo::New(n)",
"This is a namespace!: %s",
1153 void* obj =
nullptr;
1156 nullptr, (
unsigned long)
n);
1158 Error(
"TClingClassInfo::New(n)",
"Call of default constructor "
1159 "failed to return an array of class: %s",
1173 Error(
"TClingClassInfo::New(n, arena)",
"Called while invalid!");
1177 Error(
"TClingClassInfo::New(n, arena)",
"Class is not loaded: %s",
1183 std::string type_name;
1188 auto RD = dyn_cast<CXXRecordDecl>(
GetDecl());
1190 Error(
"TClingClassInfo::New(n, arena)",
"This is a namespace!: %s",
1204 void* obj =
nullptr;
1208 arena, (
unsigned long)
n);
1218 Error(
"TClingClassInfo::New(arena)",
"Called while invalid!");
1222 Error(
"TClingClassInfo::New(arena)",
"Class is not loaded: %s",
1228 std::string type_name;
1233 auto RD = dyn_cast<CXXRecordDecl>(
GetDecl());
1235 Error(
"TClingClassInfo::New(arena)",
"This is a namespace!: %s",
1249 void* obj =
nullptr;
1269 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
1271 const clang::DeclContext *ctxt =
GetDecl()->getDeclContext();
1272 clang::NamespaceDecl *std_ns =
fInterp->getSema().getStdNamespace();
1273 while (ctxt && ! ctxt->isTranslationUnit()) {
1274 if (ctxt->Equals(std_ns)) {
1278 ctxt = ctxt->getParent();
1280 Decl::Kind DK =
GetDecl()->getKind();
1281 if ((DK == Decl::Namespace) || (DK == Decl::TranslationUnit)) {
1286 const TagDecl *TD = llvm::dyn_cast<TagDecl>(
GetDecl());
1295 const CXXRecordDecl *CRD =
1296 llvm::dyn_cast<CXXRecordDecl>(
GetDecl());
1300 if (CRD->isClass()) {
1302 }
else if (CRD->isStruct()) {
1304 }
else if (CRD->isUnion()) {
1307 if (CRD->hasDefinition() && CRD->isAbstract()) {
1340 Decl::Kind DK =
GetDecl()->getKind();
1341 if (DK == Decl::Namespace) {
1345 else if (DK == Decl::Enum) {
1349 const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(
GetDecl());
1354 if (!RD->getDefinition()) {
1358 ASTContext &Context =
GetDecl()->getASTContext();
1359 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
1360 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1361 int64_t
size = Layout.getSize().getQuantity();
1362 int clang_size =
static_cast<int>(
size);
1384 Decl::Kind DK =
GetDecl()->getKind();
1385 if (DK == Decl::Namespace) {
1387 }
else if (DK == Decl::Enum) {
1390 const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(
GetDecl());
1394 if (!RD->getDefinition()) {
1398 ASTContext &Context =
GetDecl()->getASTContext();
1399 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
1400 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1401 auto align = Layout.getAlignment().getQuantity();
1436 if (
const NamedDecl* ND =
1437 llvm::dyn_cast<NamedDecl>(
GetDecl())) {
1438 PrintingPolicy Policy(
GetDecl()->getASTContext().
1439 getPrintingPolicy());
1440 llvm::raw_string_ostream stream(output);
1441 ND->getNameForDiagnostic(stream, Policy,
true);
1459 if (
const TagDecl *TD = llvm::dyn_cast<TagDecl>(
GetDecl())) {
1461 if (AnnotateAttr *A = TD->getAttr<AnnotateAttr>()) {
1462 std::string attr = A->getAnnotation().str();
1478 const CXXRecordDecl *CRD =
1479 llvm::dyn_cast<CXXRecordDecl>(
GetDecl());
1480 if (CRD && !CRD->isFromASTFile()) {
1495 TTHREAD_TLS_DECL( std::string, buf);
1497 if (
const NamedDecl* ND = llvm::dyn_cast<NamedDecl>(
GetDecl())) {
1499 buf = ND->getNameAsString();
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
long Longptr_t
Integer large enough to hold a pointer (platform-dependent).
bool Bool_t
Boolean (0=false, 1=true) (bool).
static std::string FullyQualifiedName(const Decl *decl)
ptrdiff_t(* OffsetPtrFunc_t)(void *, bool)
Error("WriteTObject","The current directory (%s) is not associated with a file. The object (%s) has not been written.", GetName(), objname)
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
void Fatal(const char *location, const char *msgfmt,...)
Use this function in case of a fatal error. It will abort the program.
externTVirtualMutex * gInterpreterMutex
#define R__LOCKGUARD(mutex)
#define R__WRITE_LOCKGUARD(mutex)
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 * ExecDefaultConstructor(const TClingClassInfo *info, ROOT::TMetaUtils::EIOCtorCategory kind, const std::string &type_name, void *address=nullptr, unsigned long nary=0UL)
void ExecDestructor(const TClingClassInfo *info, void *address=nullptr, unsigned long nary=0UL, bool withFree=true)
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
size_t GetAlignOf() const
Return the alignment of the class in bytes as reported by clang.
std::mutex fOffsetCacheMutex
const char * TmpltName() const
void AddBaseOffsetValue(const clang::Decl *decl, ptrdiff_t offset)
Longptr_t GetOffset(const clang::CXXMethodDecl *md) const
ptrdiff_t GetBaseOffset(TClingClassInfo *toBase, void *address, bool isDerivedObject)
void SetDecl(const clang::Decl *D)
bool IsScopedEnum() const
ROOT::TMetaUtils::EIOCtorCategory HasDefaultConstructor(bool checkio=false, std::string *type_name=nullptr) const
TClingMethodInfo GetMethodWithArgs(const char *fname, const char *arglist, Longptr_t *poffset, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch, EInheritanceMode imode=kWithInheritance) 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 IsValidMethod(const char *method, const char *proto, Bool_t objectIsConst, Longptr_t *offset, 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
TClingMethodInfo GetMethod(const char *fname) const
const clang::ValueDecl * GetDataMember(const char *name) const
int Size() const
Return the size of the class in bytes as reported by clang.
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.
const clang::FunctionDecl * GetTargetFunctionDecl() const
Get the FunctionDecl, or if this represents a UsingShadowDecl, the underlying target FunctionDecl.
void Init(const clang::FunctionDecl *)
constexpr bool IsValidAlignment(std::size_t align) noexcept
Return true if align is a valid C++ alignment value: strictly positive and a power of two.
externTVirtualRWMutex * gCoreMutex
std::string InsertStd(const char *tname)