31 #include "cling/Interpreter/Interpreter.h"
32 #include "cling/Interpreter/Transaction.h"
35 #include "clang/AST/ASTContext.h"
36 #include "clang/AST/Decl.h"
37 #include "clang/AST/DeclCXX.h"
38 #include "clang/AST/PrettyPrinter.h"
39 #include "clang/AST/RecordLayout.h"
40 #include "clang/AST/Type.h"
41 #include "clang/AST/CXXInheritance.h"
44 #include "llvm/Support/Casting.h"
45 #include "llvm/Support/raw_ostream.h"
46 #include "llvm/ExecutionEngine/ExecutionEngine.h"
47 #include "llvm/IR/Module.h"
54 using namespace clang;
59 : fInterp(interp), fClassInfo(0), fFirstTime(true), fDescend(
false),
60 fDecl(0), fIter(0), fBaseInfo(0), fOffset(0
L), fClassInfoOwnership(true)
72 const clang::CXXRecordDecl* CRD =
80 fIter = CRD->bases_begin();
86 : fInterp(interp), fClassInfo(0), fFirstTime(true), fDescend(
false),
87 fDecl(0), fIter(0), fBaseInfo(0), fOffset(0
L), fClassInfoOwnership(
false)
94 const clang::CXXRecordDecl* CRD =
95 llvm::dyn_cast<clang::CXXRecordDecl>(derived->
GetDecl());
96 const clang::CXXRecordDecl* BaseCRD =
97 llvm::dyn_cast<clang::CXXRecordDecl>(base->
GetDecl());
98 if (!CRD || !BaseCRD) {
108 clang::CXXBasePaths Paths;
109 if (!CRD->isDerivedFrom(BaseCRD, Paths)) {
115 fIter = CRD->bases_end();
119 : fInterp(rhs.fInterp), fClassInfo(0), fFirstTime(rhs.fFirstTime),
120 fDescend(rhs.fDescend), fDecl(rhs.fDecl), fIter(rhs.fIter), fBaseInfo(0),
121 fIterStack(rhs.fIterStack), fOffset(rhs.fOffset), fClassInfoOwnership(true)
160 void* address,
bool isDerivedObject)
const
168 if (
fInterp->isInSyntaxOnlyMode())
172 const clang::RecordDecl* fromDerivedDecl
173 = dyn_cast<clang::RecordDecl>(fromDerivedClass->
GetDecl());
174 if (!fromDerivedDecl) {
175 Error(
"TClingBaseClassInfo::GenerateBaseOffsetFunction",
176 "Offset of non-class %s is ill-defined!", fromDerivedClass->
Name());
179 const clang::RecordDecl* toBaseDecl
180 = dyn_cast<clang::RecordDecl>(toBaseClass->
GetDecl());
182 Error(
"TClingBaseClassInfo::GenerateBaseOffsetFunction",
183 "Offset of non-class %s is ill-defined!", toBaseClass->
Name());
191 buf <<
"h" << fromDerivedDecl;
193 buf <<
"h" << toBaseDecl;
194 wrapper_name = buf.str();
198 if (!
fInterp->getAddressOfGlobal(wrapper_name)) {
200 string fromDerivedClassName;
201 clang::QualType QTDerived(fromDerivedClass->
GetType(), 0);
204 string toBase_class_name;
205 clang::QualType QTtoBase(toBaseClass->
GetType(), 0);
209 llvm::raw_string_ostream buf(code);
210 buf <<
"extern \"C\" long " + wrapper_name +
"(void* address, bool isDerivedObject) {\n"
212 <<
" " << fromDerivedClassName <<
" *fromDerived;"
213 <<
" if (isDerivedObject) {"
214 <<
" fromDerived = (" << fromDerivedClassName <<
"*)address;\n"
216 <<
" fromDerived = dynamic_cast<" << fromDerivedClassName <<
"*>((" << toBase_class_name <<
"*)address);\n"
218 <<
" if (!fromDerived) {\n"
221 <<
" " << toBase_class_name <<
" *toBase = fromDerived;\n"
222 <<
" return ((long)toBase - (long)fromDerived);\n}\n";
226 void*
f =
fInterp->compileFunction(wrapper_name, code,
true ,
229 Error(
"TClingBaseClassInfo::GenerateBaseOffsetFunction",
230 "Compilation failed!");
254 (
fIter == llvm::dyn_cast<clang::CXXRecordDecl>(
fDecl)->bases_end())) {
269 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
271 const clang::RecordType *Ty =
fIter->getType()->
272 getAs<clang::RecordType>();
275 clang::CXXRecordDecl *Base = llvm::cast<clang::CXXRecordDecl>(
276 Ty->getDecl()->getDefinition());
277 clang::ASTContext &
Context = Base->getASTContext();
278 const clang::RecordDecl *RD = llvm::dyn_cast<clang::RecordDecl>(
fDecl);
279 const clang::ASTRecordLayout &
Layout = Context.getASTRecordLayout(RD);
280 int64_t offset = Layout.getBaseClassOffset(Base).getQuantity();
281 fOffset +=
static_cast<long>(offset);
283 static_cast<long>(offset)));
285 fIter = Base->bases_begin();
293 (
fIter == llvm::dyn_cast<clang::CXXRecordDecl>(
fDecl)->bases_end()) &&
304 if (
fIter == llvm::dyn_cast<clang::CXXRecordDecl>(
fDecl)->bases_end()) {
313 const clang::TagType *Ty =
fIter->getType()->getAs<clang::TagType>();
319 const clang::CXXRecordDecl *Base =
320 llvm::cast_or_null<clang::CXXRecordDecl>(Ty->getDecl()->
328 if (!onlyDirect && Base->getNumBases()) {
353 const clang::CXXRecordDecl *Src,
354 const clang::CXXRecordDecl *Dst,
355 cling::Interpreter* interp)
357 clang::CXXBasePaths Paths(
true,
true,
362 if (!Dst->isDerivedFrom(Src, Paths))
363 return clang::CharUnits::fromQuantity(-2ULL);
365 unsigned NumPublicPaths = 0;
369 for (clang::CXXBasePaths::paths_iterator
I = Paths.begin(),
E = Paths.end();
374 for (clang::CXXBasePath::iterator J =
I->begin(), JE =
I->end(); J != JE; ++J) {
377 if (J->Base->isVirtual())
378 return clang::CharUnits::fromQuantity(-1ULL);
380 if (NumPublicPaths > 1)
384 cling::Interpreter::PushTransactionRAII RAII(interp);
385 const clang::ASTRecordLayout &
L = Context.getASTRecordLayout(J->Class);
386 Offset += L.getBaseClassOffset(J->Base->getType()->getAsCXXRecordDecl());
391 if (NumPublicPaths == 0)
392 return clang::CharUnits::fromQuantity(-2ULL);
395 if (NumPublicPaths > 1)
396 return clang::CharUnits::fromQuantity(-3ULL);
411 const clang::CXXRecordDecl* Base =
419 clang::ASTContext&
Context = Base->getASTContext();
420 const clang::CXXRecordDecl* RD = llvm::dyn_cast<clang::CXXRecordDecl>(
fDecl);
426 if (clang_val == -2 || clang_val == -3) {
435 getPrintingPolicy());
436 llvm::raw_string_ostream stream(buf);
438 ->getNameForDiagnostic(stream, Policy,
true);
444 ->getNameForDiagnostic(stream, Policy,
true);
448 if (clang_val == -2) {
449 Error(
"TClingBaseClassInfo::Offset",
450 "The class %s does not derive from the base %s.",
451 derivedName.
Data(), baseName.
Data());
454 Error(
"TClingBaseClassInfo::Offset",
455 "There are multiple paths from derived class %s to base class %s.",
456 derivedName.
Data(), baseName.
Data());
465 Error(
"TClingBaseClassInfo::Offset",
"The address of the object for virtual base offset calculation is not valid.");
471 if (executableFunc) {
473 return (*executableFunc)(address, isDerivedObject);
491 const clang::CXXRecordDecl* CRD
492 = llvm::dyn_cast<CXXRecordDecl>(
fDecl);
493 const clang::CXXRecordDecl* BaseCRD
495 if (!CRD || !BaseCRD) {
496 Error(
"TClingBaseClassInfo::Property",
497 "The derived class or the base class do not have a CXXRecordDecl.");
501 clang::CXXBasePaths Paths(
false,
true,
503 if (!CRD->isDerivedFrom(BaseCRD, Paths)) {
506 Error(
"TClingBaseClassInfo",
"Class not derived from given base.");
508 if (Paths.getDetectedVirtual()) {
512 clang::AccessSpecifier AS = clang::AS_public;
514 for (clang::CXXBasePaths::const_paths_iterator IB = Paths.begin(), EB = Paths.end();
515 AS != clang::AS_private && IB != EB; ++IB) {
516 switch (IB->Access) {
518 case clang::AS_public:
break;
519 case clang::AS_protected: AS = clang::AS_protected;
break;
520 case clang::AS_private: AS = clang::AS_private;
break;
521 case clang::AS_none:
break;
525 case clang::AS_public:
528 case clang::AS_protected:
531 case clang::AS_private:
OffsetPtrFunc_t GenerateBaseOffsetFunction(const TClingClassInfo *derivedClass, TClingClassInfo *targetClass, void *address, bool isDerivedObject) const
RooCmdArg Offset(Bool_t flag=kTRUE)
void AddBaseOffsetValue(const clang::Decl *decl, ptrdiff_t offset)
const char * Name() const
RooArgList L(const RooAbsArg &v1)
std::vector< std::pair< std::pair< const clang::Decl *, clang::CXXRecordDecl::base_class_const_iterator >, long > > fIterStack
Small helper to keep current directory context.
static clang::CharUnits computeOffsetHint(clang::ASTContext &Context, const clang::CXXRecordDecl *Src, const clang::CXXRecordDecl *Dst, cling::Interpreter *interp)
const char * Name() const
void FullName(std::string &output, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
TClingBaseClassInfo & operator=(const TClingBaseClassInfo &)
ClassImp(TIterator) Bool_t TIterator return false
Compare two iterator objects.
const clang::Type * GetType() const
TClingBaseClassInfo(cling::Interpreter *, TClingClassInfo *)
const char * Data() const
ptrdiff_t(* OffsetPtrFunc_t)(void *, bool)
TClingClassInfo * fBaseInfo
int InternalNext(int onlyDirect)
void Error(const char *location, const char *msgfmt,...)
const char * TmpltName() const
const char * TmpltName() const
TClingClassInfo * GetBase() const
Emulation of the CINT BaseClassInfo class.
ptrdiff_t Offset(void *address=0, bool isDerivedObject=true) const
const clang::Decl * GetDecl() const
const clang::Decl * fDecl
void FullName(std::string &output, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
Emulation of the CINT ClassInfo class.
cling::Interpreter * fInterp
RooCmdArg Layout(Double_t xmin, Double_t xmax=0.99, Double_t ymin=0.95)
clang::CXXRecordDecl::base_class_const_iterator fIter
static void output(int code)
TClingClassInfo * fClassInfo
void AddBaseOffsetFunction(const clang::Decl *decl, OffsetPtrFunc_t func)