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 const auto DC = ValD->getDeclContext();
87 assert((ci || isa<TranslationUnitDecl>(DC) ||
88 ((DC->isTransparentContext() || DC->isInlineNamespace()) && isa<TranslationUnitDecl>(DC->getParent()) ) ||
89 isa<EnumConstantDecl>(ValD)) &&
"Not TU?");
90 assert((isa<VarDecl>(ValD) ||
91 isa<FieldDecl>(ValD) ||
92 isa<EnumConstantDecl>(ValD) ||
93 isa<IndirectFieldDecl>(ValD)) &&
94 "The decl should be either VarDecl or FieldDecl or EnumConstDecl");
105 unsigned int code =
fIoType.empty() + (int(
fIoName.empty()) << 1);
107 if (code == 0)
return;
111 if (code == 3 || code == 2) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,
"ioname",
fIoName);
112 if (code == 3 || code == 1) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,
"iotype",
fIoType);
121 return (
const clang::Decl*)(
GetDecl()->getCanonicalDecl());
130 clang::Decl::Kind DK =
GetDecl()->getKind();
132 (DK != clang::Decl::Field) &&
134 (DK != clang::Decl::EnumConstant)
139 if (DK == clang::Decl::EnumConstant) {
145 const clang::ValueDecl *VD = llvm::dyn_cast<clang::ValueDecl>(
GetDecl());
146 clang::QualType QT = VD->getType().getCanonicalType();
149 if (QT->isArrayType()) {
151 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
154 else if (QT->isReferenceType()) {
155 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
158 else if (QT->isPointerType()) {
159 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
162 else if (QT->isMemberPointerType()) {
163 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
177 clang::Decl::Kind DK =
GetDecl()->getKind();
179 (DK != clang::Decl::Field) &&
181 (DK != clang::Decl::EnumConstant)
186 if (DK == clang::Decl::EnumConstant) {
192 const clang::ValueDecl *VD = llvm::dyn_cast<clang::ValueDecl>(
GetDecl());
193 clang::QualType QT = VD->getType().getCanonicalType();
195 if ((dim < 0) || (dim >= paran)) {
202 if (QT->isArrayType()) {
204 if (
const clang::ConstantArrayType *CAT =
205 llvm::dyn_cast<clang::ConstantArrayType>(QT)
207 max =
static_cast<int>(CAT->getSize().getZExtValue());
209 else if (llvm::dyn_cast<clang::IncompleteArrayType>(QT)) {
218 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
221 else if (QT->isReferenceType()) {
222 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
225 else if (QT->isPointerType()) {
226 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
229 else if (QT->isMemberPointerType()) {
230 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
241 &&
"This is a single decl, not an iterator!");
244 bool increment =
true;
251 else if (increment) {
274 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
275 fIter = dc->decls_begin();
284 clang::Decl::Kind DK =
fIter->getKind();
285 if (DK == clang::Decl::Enum) {
289 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
290 fIter = llvm::dyn_cast<clang::DeclContext>(*fIter)->decls_begin();
294 if ((DK == clang::Decl::Field) || (DK == clang::Decl::EnumConstant) ||
301 if (
auto NS = dyn_cast<NamespaceDecl>(*
fIter)) {
302 if (NS->getDeclContext()->isTranslationUnit() && NS->isInlineNamespace())
311 using namespace clang;
318 ASTContext&
C = D->getASTContext();
319 if (
const FieldDecl *FldD = dyn_cast<FieldDecl>(D)) {
321 const clang::RecordDecl *RD = FldD->getParent();
322 const clang::ASTRecordLayout &
Layout =
C.getASTRecordLayout(RD);
323 uint64_t bits =
Layout.getFieldOffset(FldD->getFieldIndex());
324 int64_t offset =
C.toCharUnitsFromBits(bits).getQuantity();
325 return static_cast<long>(offset);
327 else if (
const VarDecl *VD = dyn_cast<VarDecl>(D)) {
331 cling::Interpreter::PushTransactionRAII RAII(
fInterp);
333 if (
long addr =
reinterpret_cast<long>(
fInterp->getAddressOfGlobal(GlobalDecl(VD))))
335 auto evalStmt = VD->ensureEvaluatedStmt();
336 if (evalStmt && evalStmt->Value) {
337 if (
const APValue* val = VD->evaluateValue()) {
338 if (VD->getType()->isIntegralType(
C)) {
339 return reinterpret_cast<long>(val->getInt().getRawData());
343 switch (val->getKind()) {
345 if (val->getInt().isSigned())
352 if (&val->getFloat().getSemantics()
353 == (
const llvm::fltSemantics*)&llvm::APFloat::IEEEsingle()) {
356 }
else if (&val->getFloat().getSemantics()
357 == (
const llvm::fltSemantics*) &llvm::APFloat::IEEEdouble()) {
375 else if (
const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
380 return reinterpret_cast<long>(ECD->getInitVal().getRawData());
383 return reinterpret_cast<long>(((
char*)ECD->getInitVal().getRawData())+
sizeof(
long) );
394 const clang::Decl *declaccess =
GetDecl();
395 if (declaccess->getDeclContext()->isTransparentContext()) {
396 declaccess = llvm::dyn_cast<clang::Decl>(declaccess->getDeclContext());
397 if (!declaccess) declaccess =
GetDecl();
399 switch (declaccess->getAccess()) {
400 case clang::AS_public:
403 case clang::AS_protected:
406 case clang::AS_private:
410 if (declaccess->getDeclContext()->isNamespace()) {
420 if (
const clang::VarDecl *vard = llvm::dyn_cast<clang::VarDecl>(
GetDecl())) {
421 if (vard->isConstexpr())
423 if (vard->getStorageClass() == clang::SC_Static) {
425 }
else if (declaccess->getDeclContext()->isNamespace()) {
431 if (llvm::isa<clang::EnumConstantDecl>(
GetDecl())) {
436 const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(
GetDecl());
437 clang::QualType qt = vd->getType();
438 if (llvm::isa<clang::TypedefType>(qt)) {
441 qt = qt.getCanonicalType();
442 if (qt.isConstQualified()) {
446 if (qt->isArrayType()) {
448 qt = llvm::cast<clang::ArrayType>(qt)->getElementType();
451 else if (qt->isReferenceType()) {
453 qt = llvm::cast<clang::ReferenceType>(qt)->getPointeeType();
456 else if (qt->isPointerType()) {
458 if (qt.isConstQualified()) {
461 qt = llvm::cast<clang::PointerType>(qt)->getPointeeType();
464 else if (qt->isMemberPointerType()) {
465 qt = llvm::cast<clang::MemberPointerType>(qt)->getPointeeType();
470 if (qt->isBuiltinType()) {
473 if (qt.isConstQualified()) {
476 const clang::TagType *
tt = qt->getAs<clang::TagType>();
478 const clang::TagDecl *td =
tt->getDecl();
482 else if (td->isStruct()) {
485 else if (td->isUnion()) {
488 else if (td->isEnum()) {
504 const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(
GetDecl());
505 clang::QualType qt = vd->getType();
516 clang::Decl::Kind dk =
GetDecl()->getKind();
518 (dk != clang::Decl::EnumConstant)) {
522 const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(
GetDecl());
523 clang::QualType qt = vd->getType();
524 if (qt->isIncompleteType()) {
528 clang::ASTContext &context =
GetDecl()->getASTContext();
530 return static_cast<int>(context.getTypeSizeInChars(qt).getQuantity());
543 static std::string buf;
545 if (
const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(
GetDecl())) {
546 clang::QualType vdType = vd->getType();
549 while (vdType->isArrayType()) {
550 vdType =
GetDecl()->getASTContext().getQualifiedType(vdType->getBaseElementTypeUnsafe(),vdType.getQualifiers());
556 ROOT::TMetaUtils::GetFullyQualifiedTypeName(buf, vdType, *
fInterp);
573 static std::string buf;
575 if (
const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(
GetDecl())) {
577 clang::QualType vdType = ROOT::TMetaUtils::ReSubstTemplateArg(vd->getType(),
fClassInfo->
GetType());
584 while (buf.length() && buf[buf.length()-1] ==
']') {
585 size_t last = buf.rfind(
'[');
586 if (last != std::string::npos) {
617 bool titleFound=
false;
619 std::string attribute_s;
621 for (Decl::attr_iterator attrIt = decl->attr_begin();
622 attrIt!=decl->attr_end() && !titleFound ;++attrIt){
623 if (0 == ROOT::TMetaUtils::extractAttrString(*attrIt, attribute_s) &&
624 attribute_s.find(ROOT::TMetaUtils::propNames::separator) == std::string::npos){
630 if (!titleFound && !
GetDecl()->isFromASTFile()) {
646 return llvm::StringRef();
648 const clang::DeclaratorDecl *FD = llvm::dyn_cast<clang::DeclaratorDecl>(
GetDecl());
649 if (FD)
return ROOT::TMetaUtils::DataMemberInfo__ValidArrayIndex(*FD);
650 else return llvm::StringRef();
typedef void((*Func_t)())
Emulation of the CINT ClassInfo class.
const clang::Type * GetType() const
const char * TypeName() const
clang::DeclContext::decl_iterator fIter
const clang::Decl * GetDecl() const override
union TClingDataMemberInfo::@26 fConstInitVal
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