Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TClingDataMemberInfo.cxx
Go to the documentation of this file.
1// @(#)root/core/meta:$Id$
2// Author: Paul Russo 30/07/2012
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TClingDataMemberInfo
13
14Emulation of the CINT DataMemberInfo class.
15
16The CINT C++ interpreter provides an interface to metadata about
17the data members of a class through the DataMemberInfo class. This
18class provides the same functionality, using an interface as close
19as possible to DataMemberInfo but the data member metadata comes
20from the Clang C++ compiler, not CINT.
21*/
22
24
25#include "TDictionary.h"
26#include "TClingClassInfo.h"
27#include "TClingTypeInfo.h"
28#include "TClingUtils.h"
29#include "TClassEdit.h"
30#include "TError.h"
31#include "TInterpreter.h"
32#include "TVirtualMutex.h"
33
34#include "cling/Interpreter/Interpreter.h"
35
36#include "clang/AST/Attr.h"
37#include "clang/AST/ASTContext.h"
38#include "clang/AST/Decl.h"
39#include "clang/AST/GlobalDecl.h"
40#include "clang/AST/Expr.h"
41#include "clang/AST/ExprCXX.h"
42#include "clang/AST/PrettyPrinter.h"
43#include "clang/AST/RecordLayout.h"
44#include "clang/AST/Type.h"
45
46#include "clang/Interpreter/CppInterOp.h"
47
48#include "llvm/Support/Casting.h"
49#include "llvm/Support/raw_ostream.h"
50#include "llvm/ADT/APSInt.h"
51#include "llvm/ADT/APFloat.h"
52
53using namespace clang;
54
55namespace {
56 static bool IsRelevantKind(clang::Decl::Kind DK)
57 {
58 return DK == clang::Decl::Field || DK == clang::Decl::EnumConstant || DK == clang::Decl::Var;
59 }
60}
61
62bool TClingDataMemberIter::ShouldSkip(const clang::Decl *D) const
63{
65 return true;
66
67 if (const auto *ND = llvm::dyn_cast<NamedDecl>(D)) {
68 // Skip unnamed declarations, e.g. in
69 // struct S {
70 // struct { int i; }
71 // };
72 // the inner struct corresponds to an unnamed member variable,
73 // where only `S::i` should be exposed.
74 if (!ND->getIdentifier())
75 return true;
76 } else {
77 // TClingDataMemberIter only cares about NamedDecls.
78 return true;
79 }
80
81 return !IsRelevantKind(D->getKind());
82}
83
84bool TClingDataMemberIter::ShouldSkip(const clang::UsingShadowDecl *USD) const
85{
87 return true;
88
89 if (auto *VD = llvm::dyn_cast<clang::ValueDecl>(USD->getTargetDecl())) {
90 return !IsRelevantKind(VD->getKind());
91 }
92
93 // TODO: handle multi-level UsingShadowDecls.
94 return true;
95}
96
100: TClingDeclInfo(nullptr), fInterp(interp)
101{
102
104
105 if (ci) {
106 fClassInfo = *ci;
107 } else {
109 }
110
111 if (!ci || !ci->IsValid()) {
112 return;
113 }
114
115 auto *DC = llvm::dyn_cast<clang::DeclContext>(ci->GetDecl());
116
118 fIter.Init();
119}
120
122 const clang::ValueDecl *ValD,
124: TClingDeclInfo(ValD), fInterp(interp)
125{
126
127 if (ci) {
128 fClassInfo = *ci;
129 } else {
131 }
132
133 using namespace llvm;
134 const auto DC = ValD->getDeclContext();
135 (void)DC;
137 ((DC->isTransparentContext() || DC->isInlineNamespace()) && isa<TranslationUnitDecl>(DC->getParent()) ) ||
138 isa<EnumConstantDecl>(ValD)) && "Not TU?");
139 assert(IsRelevantKind(ValD->getKind()) &&
140 "The decl should be either VarDecl or FieldDecl or EnumConstDecl");
141
142}
143
145{
146 // Three cases:
147 // 1) 00: none to be checked
148 // 2) 01: type to be checked
149 // 3) 10: none to be checked
150 // 4) 11: both to be checked
151 unsigned int code = fIoType.empty() + (int(fIoName.empty()) << 1);
152
153 if (code == 0) return;
154
155 const Decl* decl = GetTargetValueDecl();
156
157 if (code == 3 || code == 2) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,"ioname",fIoName);
158 if (code == 3 || code == 1) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,"iotype",fIoType);
159
160}
161
163{
164 if (!IsValid()) {
165 return TDictionary::DeclId_t();
166 }
167 if (auto *VD = GetAsValueDecl())
168 return (const clang::Decl*)(VD->getCanonicalDecl());
169 return (const clang::Decl*)(GetAsUsingShadowDecl()->getCanonicalDecl());
170}
171
172const clang::ValueDecl *TClingDataMemberInfo::GetAsValueDecl() const
173{
175}
176
177const clang::UsingShadowDecl *TClingDataMemberInfo::GetAsUsingShadowDecl() const
178{
180}
181
182const clang::ValueDecl *TClingDataMemberInfo::GetTargetValueDecl() const
183{
184 const Decl *D = GetDecl();
185 do {
186 if (auto VD = dyn_cast<ValueDecl>(D))
187 return VD;
188 } while ((D = dyn_cast<UsingShadowDecl>(D)->getTargetDecl()));
189 return nullptr;
190}
191
192const clang::Type *TClingDataMemberInfo::GetClassAsType() const {
193 return fClassInfo.GetType();
194}
195
197{
198 if (!IsValid()) {
199 return -1;
200 }
201 const clang::ValueDecl *VD = GetTargetValueDecl();
202 // Sanity check the current data member.
203 clang::Decl::Kind DK = VD->getKind();
204 if (
205 (DK != clang::Decl::Field) &&
206 (DK != clang::Decl::Var) &&
207 (DK != clang::Decl::EnumConstant)
208 ) {
209 // Error, was not a data member, variable, or enumerator.
210 return -1;
211 }
212 if (DK == clang::Decl::EnumConstant) {
213 // We know that an enumerator value does not have array type.
214 return 0;
215 }
216 // To get this information we must count the number
217 // of array type nodes in the canonical type chain.
218 clang::QualType QT = VD->getType().getCanonicalType();
219 int cnt = 0;
220 while (1) {
221 if (QT->isArrayType()) {
222 ++cnt;
223 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
224 continue;
225 }
226 else if (QT->isReferenceType()) {
227 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
228 continue;
229 }
230 else if (QT->isPointerType()) {
231 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
232 continue;
233 }
234 else if (QT->isMemberPointerType()) {
235 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
236 continue;
237 }
238 break;
239 }
240 return cnt;
241}
242
244{
245 if (!IsValid()) {
246 return -1;
247 }
248 const clang::ValueDecl *VD = GetTargetValueDecl();
249 // Sanity check the current data member.
250 clang::Decl::Kind DK = GetDecl()->getKind();
251 if (
252 (DK != clang::Decl::Field) &&
253 (DK != clang::Decl::Var) &&
254 (DK != clang::Decl::EnumConstant)
255 ) {
256 // Error, was not a data member, variable, or enumerator.
257 return -1;
258 }
259 if (DK == clang::Decl::EnumConstant) {
260 // We know that an enumerator value does not have array type.
261 return 0;
262 }
263 // To get this information we must count the number
264 // of array type nodes in the canonical type chain.
265 clang::QualType QT = VD->getType().getCanonicalType();
266 int paran = ArrayDim();
267 if ((dim < 0) || (dim >= paran)) {
268 // Passed dimension is out of bounds.
269 return -1;
270 }
271 int cnt = dim;
272 int max = 0;
273 while (1) {
274 if (QT->isArrayType()) {
275 if (cnt == 0) {
276 if (const clang::ConstantArrayType *CAT =
277 llvm::dyn_cast<clang::ConstantArrayType>(QT)
278 ) {
279 max = static_cast<int>(CAT->getSize().getZExtValue());
280 }
281 else if (llvm::dyn_cast<clang::IncompleteArrayType>(QT)) {
282 max = INT_MAX;
283 }
284 else {
285 max = -1;
286 }
287 break;
288 }
289 --cnt;
290 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
291 continue;
292 }
293 else if (QT->isReferenceType()) {
294 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
295 continue;
296 }
297 else if (QT->isPointerType()) {
298 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
299 continue;
300 }
301 else if (QT->isMemberPointerType()) {
302 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
303 continue;
304 }
305 break;
306 }
307 return max;
308}
309
311{
312 assert(!fDecl && "This is a single decl, not an iterator!");
313
314 ClearNames();
315
316 if (!fFirstTime && !fIter.IsValid()) {
317 // Iterator is already invalid.
318 return 0;
319 }
320 // Advance to the next decl.
321 if (fFirstTime) {
322 // The cint semantics are weird.
323 fFirstTime = false;
324 } else {
325 fIter.Next();
326 }
327 return fIter.IsValid();
328}
329
331{
332 using namespace clang;
333
334 if (!IsValid()) {
335 return -1L;
336 }
337
338 const ValueDecl *D = GetTargetValueDecl();
339 ASTContext& C = D->getASTContext();
340 if (const FieldDecl *FldD = dyn_cast<FieldDecl>(D)) {
341 // The current member is a non-static data member.
342
343 // getASTRecordLayout() might deserialize.
344 cling::Interpreter::PushTransactionRAII RAII(fInterp);
345 const clang::RecordDecl *RD = FldD->getParent();
346 const clang::ASTRecordLayout &Layout = C.getASTRecordLayout(RD);
347 uint64_t bits = Layout.getFieldOffset(FldD->getFieldIndex());
348 int64_t offset = C.toCharUnitsFromBits(bits).getQuantity();
349 return static_cast<Longptr_t>(offset);
350 }
351 else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
352 // Could trigger deserialization of decls, in particular in case
353 // of constexpr, like:
354 // static constexpr Long64_t something = std::numeric_limits<Long64_t>::max();
355 cling::Interpreter::PushTransactionRAII RAII(fInterp);
356
357 // We can't reassign constexpr or const variables. We can compute the
358 // initializer.
359 if (VD->hasInit() && (VD->isConstexpr() || VD->getType().isConstQualified())) {
360 if (const APValue* val = VD->evaluateValue()) {
361 if (VD->getType()->isIntegralType(C)) {
362 return reinterpret_cast<Longptr_t>(val->getInt().getRawData());
363 } else {
364 // The VD stores the init value; its lifetime should the lifetime of
365 // this offset.
366 switch (val->getKind()) {
367 case APValue::Int: {
368 if (val->getInt().isSigned())
369 fConstInitVal.fLong = (Longptr_t)val->getInt().getSExtValue();
370 else
371 fConstInitVal.fLong = (Longptr_t)val->getInt().getZExtValue();
372 return (Longptr_t) &fConstInitVal.fLong;
373 }
374 case APValue::Float:
375 if (&val->getFloat().getSemantics()
376 == (const llvm::fltSemantics*)&llvm::APFloat::IEEEsingle()) {
377 fConstInitVal.fFloat = val->getFloat().convertToFloat();
378 return (Longptr_t)&fConstInitVal.fFloat;
379 } else if (&val->getFloat().getSemantics()
380 == (const llvm::fltSemantics*) &llvm::APFloat::IEEEdouble()) {
381 fConstInitVal.fDouble = val->getFloat().convertToDouble();
382 return (Longptr_t)&fConstInitVal.fDouble;
383 }
384 // else fall-through
385 default:
386 ;// fall-through
387 };
388 // fall-through
389 } // not integral type
390 } // have an APValue
391 } // have an initializing value
392
393 // Try the slow operation.
394 if (Longptr_t addr = reinterpret_cast<Longptr_t>(fInterp->getAddressOfGlobal(GlobalDecl(VD))))
395 return addr;
396 }
397 // FIXME: We have to explicitly check for not enum constant because the
398 // implementation of getAddressOfGlobal relies on mangling the name and in
399 // clang there is misbehaviour in MangleContext::shouldMangleDeclName.
400 // enum constants are essentially numbers and don't get addresses. However
401 // ROOT expects the address to the enum constant initializer to be returned.
402 else if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) {
403 // The raw data is stored as a long long, so we need to find the 'long'
404 // part.
405
406 // The memory leak for `EnumConstantDecl` was fixed in:
407 // https://github.com/llvm/llvm-project/pull/78311
408 // We were relying on the leak to provide the address for EnumConstantDecl.
409 // Now store the data value as a member instead.
410 fEnumValue = ECD->getInitVal().getExtValue();
411 return reinterpret_cast<Longptr_t>(&fEnumValue);
412 }
413 return -1L;
414}
415
417{
418 if (!IsValid()) {
419 return 0L;
420 }
421 long property = 0L;
422
423 // If the declaration is public in a private nested struct, make the declaration
424 // private nonetheless, as for outside access (e.g. ROOT I/O) it's private:
425 // NOTE: this uses `GetDecl()`, to capture the access of the UsingShadowDecl,
426 // which is defined in the derived class and might differ from the access of the decl
427 // in the base class.
428 // TODO: move this somewhere such that TClingMethodInfo can use this, too.
429 const Decl *thisDecl = GetDecl();
430 clang::AccessSpecifier strictestAccess = thisDecl->getAccess();
431 const DeclContext *nonTransparentDC = thisDecl->getDeclContext();
432
434 const Decl *declOrParent = thisDecl;
435 for (const auto *Parent = declOrParent->getDeclContext(); !llvm::isa<TranslationUnitDecl>(Parent);
436 Parent = declOrParent->getDeclContext()) {
437 if (!Parent->isTransparentContext()) {
438 if (const auto *RD = llvm::dyn_cast<clang::RecordDecl>(Parent)) {
439 if (!RD->isAnonymousStructOrUnion()) {
441 break;
442 }
443 } else {
444 nonTransparentDC = Parent;
445 break;
446 }
447 }
448
449 declOrParent = llvm::dyn_cast<clang::Decl>(Parent);
450 if (!declOrParent)
451 break;
453 strictestAccess = declOrParent->getAccess();
454 }
455 }
456 };
457
459 // TODO: Now that we have the kIsNotReacheable we could return the property
460 // to be reflecting the local information. However it is unclear if the
461 // information is used as-is (it appears to not be used in ROOT proper)
462 switch (strictestAccess) {
463 case clang::AS_public:
464 property |= kIsPublic;
465 break;
466 case clang::AS_protected:
467 property |= kIsProtected | kIsNotReacheable;
468 break;
469 case clang::AS_private:
470 property |= kIsPrivate | kIsNotReacheable;
471 break;
472 case clang::AS_none: //?
473 property |= kIsPublic;
474 break;
475 default:
476 // IMPOSSIBLE
477 assert(false && "Unexpected value for the access property value in Clang");
478 break;
479 }
480 if (llvm::isa<clang::UsingShadowDecl>(thisDecl))
481 property |= kIsUsing;
482
483 const clang::ValueDecl *vd = GetTargetValueDecl();
484 if (const clang::VarDecl *vard = llvm::dyn_cast<clang::VarDecl>(vd)) {
485 if (vard->isConstexpr())
486 property |= kIsConstexpr;
487 if (vard->getStorageClass() == clang::SC_Static) {
488 property |= kIsStatic;
489 } else if (nonTransparentDC->isNamespace()) {
490 // Data members of a namespace are global variable which were
491 // considered to be 'static' in the CINT (and thus ROOT) scheme.
492 property |= kIsStatic;
493 }
494 } else if (llvm::isa<clang::EnumConstantDecl>(vd)) {
495 // Enumeration constant are considered to be 'static' data member in
496 // the CINT (and thus ROOT) scheme.
497 property |= kIsStatic;
498 }
499 clang::QualType qt = vd->getType();
500 if (llvm::isa<clang::TypedefType>(qt)) {
501 property |= kIsTypedef;
502 }
503 qt = qt.getCanonicalType();
505 const clang::TagType *tt = qt->getAs<clang::TagType>();
506 if (tt) {
507 // tt->getDecl() might deserialize.
508 cling::Interpreter::PushTransactionRAII RAII(fInterp);
509 const clang::TagDecl *td = tt->getDecl();
510 if (td->isClass()) {
511 property |= kIsClass;
512 }
513 else if (td->isStruct()) {
514 property |= kIsStruct;
515 }
516 else if (td->isUnion()) {
517 property |= kIsUnion;
518 }
519 else if (td->isEnum()) {
520 property |= kIsEnum;
521 }
522 }
523
524 if (const auto *RD = llvm::dyn_cast<RecordDecl>(thisDecl->getDeclContext())) {
525 if (RD->isUnion())
526 property |= kIsUnionMember;
527 }
528 // We can't be a namespace, can we?
529 // if (dc->isNamespace() && !dc->isTranslationUnit()) {
530 // property |= kIsNamespace;
531 // }
532 return property;
533}
534
536{
537 if (!IsValid()) {
538 return 0L;
539 }
540 const clang::ValueDecl *vd = GetTargetValueDecl();
541 clang::QualType qt = vd->getType();
543}
544
546{
547 if (!IsValid()) {
548 return -1;
549 }
550
551 const clang::ValueDecl *vd = GetTargetValueDecl();
552 // Sanity check the current data member.
553 clang::Decl::Kind dk = vd->getKind();
554 if ((dk != clang::Decl::Field) && (dk != clang::Decl::Var) &&
555 (dk != clang::Decl::EnumConstant)) {
556 // Error, was not a data member, variable, or enumerator.
557 return -1;
558 }
559 return Cpp::GetSizeOfType(vd->getType().getAsOpaquePtr());
560}
561
563{
564 if (!IsValid()) {
565 return nullptr;
566 }
567
569 if (!fIoType.empty()) return fIoType.c_str();
570
571 // Note: This must be static because we return a pointer inside it!
572 static std::string buf;
573 buf.clear();
574 const clang::ValueDecl *vd = GetTargetValueDecl();
575 clang::QualType vdType = vd->getType();
576 // In CINT's version, the type name returns did *not* include any array
577 // information, ROOT's existing code depends on it.
578 while (vdType->isArrayType()) {
579 vdType = GetDecl()->getASTContext().getQualifiedType(vdType->getBaseElementTypeUnsafe(),vdType.getQualifiers());
580 }
581
582 // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
584
586
587 return buf.c_str();
588}
589
591{
592 if (!IsValid()) {
593 return nullptr;
594 }
595
597 if (!fIoType.empty()) return fIoType.c_str();
598
599 // Note: This must be static because we return a pointer inside it!
600 static std::string buf;
601 buf.clear();
602 const clang::ValueDecl *vd = GetTargetValueDecl();
603 // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
604 clang::QualType vdType = ROOT::TMetaUtils::ReSubstTemplateArg(vd->getType(), GetClassAsType());
605
607
608 // In CINT's version, the type name returns did *not* include any array
609 // information, ROOT's existing code depends on it.
610 // This might become part of the implementation of GetNormalizedName.
611 while (buf.length() && buf[buf.length()-1] == ']') {
612 size_t last = buf.rfind('['); // if this is not the bracket we are looking, the type is malformed.
613 if (last != std::string::npos) {
614 buf.erase(last);
615 }
616 }
617 return buf.c_str();
618}
619
620const char *TClingDataMemberInfo::Name() const
621{
622 if (!IsValid()) {
623 return nullptr;
624 }
625
627 if (!fIoName.empty()) return fIoName.c_str();
628
629 return TClingDeclInfo::Name();
630}
631
633{
634 if (!IsValid()) {
635 return nullptr;
636 }
637
638 //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
639 //if (fTitle.size())
640 // return fTitle.c_str();
641
642 bool titleFound=false;
643 // Try to get the comment either from the annotation or the header file if present
644 std::string attribute_s;
645 const Decl* decl = GetTargetValueDecl();
646 for (Decl::attr_iterator attrIt = decl->attr_begin();
647 attrIt!=decl->attr_end() && !titleFound ;++attrIt){
649 attribute_s.find(ROOT::TMetaUtils::propNames::separator) == std::string::npos){
651 titleFound=true;
652 }
653 }
654
655 if (!titleFound && !decl->isFromASTFile()) {
656 // Try to get the comment from the header file if present
657 // but not for decls from AST file, where rootcling would have
658 // created an annotation
660 }
661
662 return fTitle.c_str();
663}
664
665// ValidArrayIndex return a static string (so use it or copy it immediately, do not
666// call GrabIndex twice in the same expression) containing the size of the
667// array data member.
669{
670 if (!IsValid()) {
671 return llvm::StringRef();
672 }
673 const clang::DeclaratorDecl *FD = llvm::dyn_cast<clang::DeclaratorDecl>(GetTargetValueDecl());
674 if (FD)
676 return {};
677}
678
long Longptr_t
Definition RtypesCore.h:75
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
@ kIsPublic
Definition TDictionary.h:75
@ kIsUnionMember
Definition TDictionary.h:74
@ kIsConstexpr
Definition TDictionary.h:93
@ kIsClass
Definition TDictionary.h:65
@ kIsEnum
Definition TDictionary.h:68
@ kIsPrivate
Definition TDictionary.h:77
@ kIsUsing
Definition TDictionary.h:97
@ kIsStatic
Definition TDictionary.h:80
@ kIsStruct
Definition TDictionary.h:66
@ kIsProtected
Definition TDictionary.h:76
@ kIsUnion
Definition TDictionary.h:67
@ kIsNotReacheable
Definition TDictionary.h:87
@ kIsTypedef
Definition TDictionary.h:69
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t property
R__EXTERN TVirtualMutex * gInterpreterMutex
#define R__LOCKGUARD(mutex)
Emulation of the CINT ClassInfo class.
const clang::Type * GetType() const
const char * TypeName() const
const clang::Type * GetClassAsType() const
const clang::Decl * GetDecl() const override
const char * TypeTrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
union TClingDataMemberInfo::@28 fConstInitVal
const clang::UsingShadowDecl * GetAsUsingShadowDecl() const
TClingDataMemberInfo(cling::Interpreter *interp)
cling::Interpreter * fInterp
const clang::ValueDecl * GetTargetValueDecl() const
Get the ValueDecl, or if this represents a UsingShadowDecl, the underlying target ValueDecl.
const clang::ValueDecl * GetAsValueDecl() const
llvm::StringRef ValidArrayIndex() const
const char * Name() const override
TClingDataMemberIter fIter
Iterate over VarDecl, FieldDecl, EnumConstantDecl, IndirectFieldDecl, and UsingShadowDecls thereof,...
TDictionary::EMemberSelection fSelection
bool ShouldSkip(const clang::Decl *FD) const final
const clang::Decl * fDecl
virtual const char * Name() const
virtual bool IsValid() const
long Property(long property, clang::QualType &qt) const
bool Next()
Advance to next non-skipped; return false if no next decl exists.
virtual bool IsValid() const
Emulation of the CINT TypeInfo class.
long Property() const
static bool WantsRegularMembers(EMemberSelection sel)
EMemberSelection
Kinds of members to include in lists.
static bool WantsUsingDecls(EMemberSelection sel)
const void * DeclId_t
static const std::string separator("@@@")
int extractAttrString(clang::Attr *attribute, std::string &attrString)
Extract attr string.
void GetNormalizedName(std::string &norm_name, const clang::QualType &type, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt)
Return the type name normalized for ROOT, keeping only the ROOT opaque typedef (Double32_t,...
clang::QualType ReSubstTemplateArg(clang::QualType input, const clang::Type *instance)
Check if 'input' or any of its template parameter was substituted when instantiating the class templa...
void GetFullyQualifiedTypeName(std::string &name, const clang::QualType &type, const cling::Interpreter &interpreter)
llvm::StringRef GetComment(const clang::Decl &decl, clang::SourceLocation *loc=nullptr)
Returns the comment (// striped away), annotating declaration in a meaningful for ROOT IO way.
bool ExtractAttrPropertyFromName(const clang::Decl &decl, const std::string &propName, std::string &propValue)
This routine counts on the "propName<separator>propValue" format.
llvm::StringRef DataMemberInfo__ValidArrayIndex(const cling::Interpreter &interp, const clang::DeclaratorDecl &m, int *errnum=nullptr, llvm::StringRef *errstr=nullptr)
ValidArrayIndex return a static string (so use it or copy it immediatly, do not call GrabIndex twice ...
auto * tt
Definition textangle.C:16