27#include "TClingUtils.h"
31#include "clang/AST/Attr.h"
32#include "clang/AST/ASTContext.h"
33#include "clang/AST/Decl.h"
34#include "clang/AST/GlobalDecl.h"
35#include "clang/AST/Expr.h"
36#include "clang/AST/ExprCXX.h"
37#include "clang/AST/PrettyPrinter.h"
38#include "clang/AST/RecordLayout.h"
39#include "clang/AST/Type.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/raw_ostream.h"
43#include "llvm/ADT/APSInt.h"
44#include "llvm/ADT/APFloat.h"
50:
TClingDeclInfo(nullptr), fInterp(interp), fClassInfo(0), fFirstTime(true), fTitle(
""), fContextIdx(0U), fIoType(
""), fIoName(
"")
61 clang::DeclContext *dc = llvm::cast<clang::DeclContext>(D);
65 cling::Interpreter::PushTransactionRAII RAII(interp);
66 fIter = llvm::cast<clang::DeclContext>(D)->decls_begin();
67 const TagDecl *TD = ROOT::TMetaUtils::GetAnnotatedRedeclarable(llvm::dyn_cast<TagDecl>(D));
69 fIter = TD->decls_begin();
79 const clang::ValueDecl *ValD,
82 fTitle(
""), fContextIdx(0U), fIoType(
""), fIoName(
""){
85 assert((ci || isa<TranslationUnitDecl>(ValD->getDeclContext()) ||
86 (ValD->getDeclContext()->isTransparentContext() && isa<TranslationUnitDecl>(ValD->getDeclContext()->getParent()) ) ||
87 isa<EnumConstantDecl>(ValD)) &&
"Not TU?");
88 assert((isa<VarDecl>(ValD) ||
89 isa<FieldDecl>(ValD) ||
90 isa<EnumConstantDecl>(ValD) ||
91 isa<IndirectFieldDecl>(ValD)) &&
92 "The decl should be either VarDecl or FieldDecl or EnumConstDecl");
103 unsigned int code =
fIoType.empty() + (int(
fIoName.empty()) << 1);
105 if (code == 0)
return;
109 if (code == 3 || code == 2) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,
"ioname",
fIoName);
110 if (code == 3 || code == 1) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,
"iotype",
fIoType);
119 return (
const clang::Decl*)(
GetDecl()->getCanonicalDecl());
128 clang::Decl::Kind DK =
GetDecl()->getKind();
130 (DK != clang::Decl::Field) &&
132 (DK != clang::Decl::EnumConstant)
137 if (DK == clang::Decl::EnumConstant) {
143 const clang::ValueDecl *VD = llvm::dyn_cast<clang::ValueDecl>(
GetDecl());
144 clang::QualType QT = VD->getType().getCanonicalType();
147 if (QT->isArrayType()) {
149 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
152 else if (QT->isReferenceType()) {
153 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
156 else if (QT->isPointerType()) {
157 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
160 else if (QT->isMemberPointerType()) {
161 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
175 clang::Decl::Kind DK =
GetDecl()->getKind();
177 (DK != clang::Decl::Field) &&
179 (DK != clang::Decl::EnumConstant)
184 if (DK == clang::Decl::EnumConstant) {
190 const clang::ValueDecl *VD = llvm::dyn_cast<clang::ValueDecl>(
GetDecl());
191 clang::QualType QT = VD->getType().getCanonicalType();
193 if ((dim < 0) || (dim >= paran)) {
200 if (QT->isArrayType()) {
202 if (
const clang::ConstantArrayType *CAT =
203 llvm::dyn_cast<clang::ConstantArrayType>(QT)
205 max =
static_cast<int>(CAT->getSize().getZExtValue());
207 else if (llvm::dyn_cast<clang::IncompleteArrayType>(QT)) {
216 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
219 else if (QT->isReferenceType()) {
220 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
223 else if (QT->isPointerType()) {
224 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
227 else if (QT->isMemberPointerType()) {
228 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
239 &&
"This is a single decl, not an iterator!");
242 bool increment =
true;
249 else if (increment) {
272 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
273 fIter = dc->decls_begin();
282 clang::Decl::Kind DK =
fIter->getKind();
283 if (DK == clang::Decl::Enum) {
287 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
288 fIter = llvm::dyn_cast<clang::DeclContext>(*fIter)->decls_begin();
292 if ((DK == clang::Decl::Field) || (DK == clang::Decl::EnumConstant) ||
304 using namespace clang;
311 ASTContext&
C = D->getASTContext();
312 if (
const FieldDecl *FldD = dyn_cast<FieldDecl>(D)) {
314 const clang::RecordDecl *RD = FldD->getParent();
315 const clang::ASTRecordLayout &
Layout =
C.getASTRecordLayout(RD);
316 uint64_t bits =
Layout.getFieldOffset(FldD->getFieldIndex());
317 int64_t offset =
C.toCharUnitsFromBits(bits).getQuantity();
318 return static_cast<long>(offset);
320 else if (
const VarDecl *VD = dyn_cast<VarDecl>(D)) {
324 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
326 if (
long addr =
reinterpret_cast<long>(
fInterp->getAddressOfGlobal(GlobalDecl(VD))))
328 auto evalStmt = VD->ensureEvaluatedStmt();
329 if (evalStmt && evalStmt->Value) {
330 if (
const APValue* val = VD->evaluateValue()) {
331 if (VD->getType()->isIntegralType(
C)) {
332 return reinterpret_cast<long>(val->getInt().getRawData());
336 switch (val->getKind()) {
338 if (val->getInt().isSigned())
345 if (&val->getFloat().getSemantics()
346 == (
const llvm::fltSemantics*)&llvm::APFloat::IEEEsingle()) {
349 }
else if (&val->getFloat().getSemantics()
350 == (
const llvm::fltSemantics*) &llvm::APFloat::IEEEdouble()) {
368 else if (
const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
373 return reinterpret_cast<long>(ECD->getInitVal().getRawData());
376 return reinterpret_cast<long>(((
char*)ECD->getInitVal().getRawData())+
sizeof(
long) );
387 const clang::Decl *declaccess =
GetDecl();
388 if (declaccess->getDeclContext()->isTransparentContext()) {
389 declaccess = llvm::dyn_cast<clang::Decl>(declaccess->getDeclContext());
390 if (!declaccess) declaccess =
GetDecl();
392 switch (declaccess->getAccess()) {
393 case clang::AS_public:
396 case clang::AS_protected:
399 case clang::AS_private:
403 if (declaccess->getDeclContext()->isNamespace()) {
413 if (
const clang::VarDecl *vard = llvm::dyn_cast<clang::VarDecl>(
GetDecl())) {
414 if (vard->getStorageClass() == clang::SC_Static) {
416 }
else if (declaccess->getDeclContext()->isNamespace()) {
422 if (llvm::isa<clang::EnumConstantDecl>(
GetDecl())) {
427 const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(
GetDecl());
428 clang::QualType qt = vd->getType();
429 if (llvm::isa<clang::TypedefType>(qt)) {
432 qt = qt.getCanonicalType();
433 if (qt.isConstQualified()) {
437 if (qt->isArrayType()) {
439 qt = llvm::cast<clang::ArrayType>(qt)->getElementType();
442 else if (qt->isReferenceType()) {
444 qt = llvm::cast<clang::ReferenceType>(qt)->getPointeeType();
447 else if (qt->isPointerType()) {
449 if (qt.isConstQualified()) {
452 qt = llvm::cast<clang::PointerType>(qt)->getPointeeType();
455 else if (qt->isMemberPointerType()) {
456 qt = llvm::cast<clang::MemberPointerType>(qt)->getPointeeType();
461 if (qt->isBuiltinType()) {
464 if (qt.isConstQualified()) {
467 const clang::TagType *
tt = qt->getAs<clang::TagType>();
469 const clang::TagDecl *td =
tt->getDecl();
473 else if (td->isStruct()) {
476 else if (td->isUnion()) {
479 else if (td->isEnum()) {
495 const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(
GetDecl());
496 clang::QualType qt = vd->getType();
507 clang::Decl::Kind dk =
GetDecl()->getKind();
509 (dk != clang::Decl::EnumConstant)) {
513 const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(
GetDecl());
514 clang::QualType qt = vd->getType();
515 if (qt->isIncompleteType()) {
519 clang::ASTContext &context =
GetDecl()->getASTContext();
521 return static_cast<int>(context.getTypeSizeInChars(qt).getQuantity());
534 static std::string buf;
536 if (
const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(
GetDecl())) {
537 clang::QualType vdType = vd->getType();
540 while (vdType->isArrayType()) {
541 vdType =
GetDecl()->getASTContext().getQualifiedType(vdType->getBaseElementTypeUnsafe(),vdType.getQualifiers());
547 ROOT::TMetaUtils::GetFullyQualifiedTypeName(buf, vdType, *
fInterp);
564 static std::string buf;
566 if (
const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(
GetDecl())) {
568 clang::QualType vdType = ROOT::TMetaUtils::ReSubstTemplateArg(vd->getType(),
fClassInfo->
GetType());
575 while (buf.length() && buf[buf.length()-1] ==
']') {
576 size_t last = buf.rfind(
'[');
577 if (last != std::string::npos) {
608 bool titleFound=
false;
610 std::string attribute_s;
612 for (Decl::attr_iterator attrIt = decl->attr_begin();
613 attrIt!=decl->attr_end() && !titleFound ;++attrIt){
614 if (0 == ROOT::TMetaUtils::extractAttrString(*attrIt, attribute_s) &&
615 attribute_s.find(ROOT::TMetaUtils::propNames::separator) == std::string::npos){
621 if (!titleFound && !
GetDecl()->isFromASTFile()) {
637 return llvm::StringRef();
639 const clang::DeclaratorDecl *FD = llvm::dyn_cast<clang::DeclaratorDecl>(
GetDecl());
640 if (FD)
return ROOT::TMetaUtils::DataMemberInfo__ValidArrayIndex(*FD);
641 else return llvm::StringRef();
Emulation of the CINT ClassInfo class.
const clang::Type * GetType() const
const char * TypeName() const
union TClingDataMemberInfo::@30 fConstInitVal
clang::DeclContext::decl_iterator fIter
const clang::Decl * GetDecl() const override
const char * TypeTrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
void CheckForIoTypeAndName() const
const char * Name() override
int MaxIndex(int dim) const
TClingClassInfo * fClassInfo
std::vector< clang::DeclContext::decl_iterator > fIterStack
TClingDataMemberInfo(cling::Interpreter *interp)
cling::Interpreter * fInterp
llvm::SmallVector< clang::DeclContext *, 2 > fContexts
llvm::StringRef ValidArrayIndex() const
long TypeProperty() const
DeclId_t GetDeclId() const
const clang::Decl * fDecl
virtual const char * Name()
virtual bool IsValid() const
virtual const clang::Decl * GetDecl() const
Emulation of the CINT TypeInfo class.
double Var(const RVec< T > &v)
Get the variance of the elements of an RVec.
RooCmdArg Layout(Double_t xmin, Double_t xmax=0.99, Double_t ymin=0.95)
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
static constexpr double L