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 "llvm/Support/Casting.h"
47#include "llvm/Support/raw_ostream.h"
48#include "llvm/ADT/APSInt.h"
49#include "llvm/ADT/APFloat.h"
50
51using namespace clang;
52
53namespace {
54 static bool IsRelevantKind(clang::Decl::Kind DK)
55 {
56 return DK == clang::Decl::Field || DK == clang::Decl::EnumConstant || DK == clang::Decl::Var;
57 }
58}
59
60bool TClingDataMemberIter::ShouldSkip(const clang::Decl *D) const
61{
63 return true;
64
65 if (const auto *ND = llvm::dyn_cast<NamedDecl>(D)) {
66 // Skip unnamed declarations, e.g. in
67 // struct S {
68 // struct { int i; }
69 // };
70 // the inner struct corresponds to an unnamed member variable,
71 // where only `S::i` should be exposed.
72 if (!ND->getIdentifier())
73 return true;
74 } else {
75 // TClingDataMemberIter only cares about NamedDecls.
76 return true;
77 }
78
79 return !IsRelevantKind(D->getKind());
80}
81
82bool TClingDataMemberIter::ShouldSkip(const clang::UsingShadowDecl *USD) const
83{
85 return true;
86
87 if (auto *VD = llvm::dyn_cast<clang::ValueDecl>(USD->getTargetDecl())) {
88 return !IsRelevantKind(VD->getKind());
89 }
90
91 // TODO: handle multi-level UsingShadowDecls.
92 return true;
93}
94
98: TClingDeclInfo(nullptr), fInterp(interp)
99{
100
102
103 if (ci) {
104 fClassInfo = *ci;
105 } else {
107 }
108
109 if (!ci || !ci->IsValid()) {
110 return;
111 }
112
113 auto *DC = llvm::dyn_cast<clang::DeclContext>(ci->GetDecl());
114
116 fIter.Init();
117}
118
120 const clang::ValueDecl *ValD,
122: TClingDeclInfo(ValD), fInterp(interp)
123{
124
125 if (ci) {
126 fClassInfo = *ci;
127 } else {
129 }
130
131 using namespace llvm;
132 const auto DC = ValD->getDeclContext();
133 (void)DC;
135 ((DC->isTransparentContext() || DC->isInlineNamespace()) && isa<TranslationUnitDecl>(DC->getParent()) ) ||
136 isa<EnumConstantDecl>(ValD)) && "Not TU?");
137 assert(IsRelevantKind(ValD->getKind()) &&
138 "The decl should be either VarDecl or FieldDecl or EnumConstDecl");
139
140}
141
143{
144 // Three cases:
145 // 1) 00: none to be checked
146 // 2) 01: type to be checked
147 // 3) 10: none to be checked
148 // 4) 11: both to be checked
149 unsigned int code = fIoType.empty() + (int(fIoName.empty()) << 1);
150
151 if (code == 0) return;
152
153 const Decl* decl = GetTargetValueDecl();
154
155 if (code == 3 || code == 2) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,"ioname",fIoName);
156 if (code == 3 || code == 1) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,"iotype",fIoType);
157
158}
159
161{
162 if (!IsValid()) {
163 return TDictionary::DeclId_t();
164 }
165 if (auto *VD = GetAsValueDecl())
166 return (const clang::Decl*)(VD->getCanonicalDecl());
167 return (const clang::Decl*)(GetAsUsingShadowDecl()->getCanonicalDecl());
168}
169
170const clang::ValueDecl *TClingDataMemberInfo::GetAsValueDecl() const
171{
173}
174
175const clang::UsingShadowDecl *TClingDataMemberInfo::GetAsUsingShadowDecl() const
176{
178}
179
180const clang::ValueDecl *TClingDataMemberInfo::GetTargetValueDecl() const
181{
182 const Decl *D = GetDecl();
183 do {
184 if (auto VD = dyn_cast<ValueDecl>(D))
185 return VD;
186 } while ((D = dyn_cast<UsingShadowDecl>(D)->getTargetDecl()));
187 return nullptr;
188}
189
190const clang::Type *TClingDataMemberInfo::GetClassAsType() const {
191 return fClassInfo.GetType();
192}
193
195{
196 if (!IsValid()) {
197 return -1;
198 }
199 const clang::ValueDecl *VD = GetTargetValueDecl();
200 // Sanity check the current data member.
201 clang::Decl::Kind DK = VD->getKind();
202 if (
203 (DK != clang::Decl::Field) &&
204 (DK != clang::Decl::Var) &&
205 (DK != clang::Decl::EnumConstant)
206 ) {
207 // Error, was not a data member, variable, or enumerator.
208 return -1;
209 }
210 if (DK == clang::Decl::EnumConstant) {
211 // We know that an enumerator value does not have array type.
212 return 0;
213 }
214 // To get this information we must count the number
215 // of array type nodes in the canonical type chain.
216 clang::QualType QT = VD->getType().getCanonicalType();
217 int cnt = 0;
218 while (1) {
219 if (QT->isArrayType()) {
220 ++cnt;
221 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
222 continue;
223 }
224 else if (QT->isReferenceType()) {
225 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
226 continue;
227 }
228 else if (QT->isPointerType()) {
229 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
230 continue;
231 }
232 else if (QT->isMemberPointerType()) {
233 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
234 continue;
235 }
236 break;
237 }
238 return cnt;
239}
240
242{
243 if (!IsValid()) {
244 return -1;
245 }
246 const clang::ValueDecl *VD = GetTargetValueDecl();
247 // Sanity check the current data member.
248 clang::Decl::Kind DK = GetDecl()->getKind();
249 if (
250 (DK != clang::Decl::Field) &&
251 (DK != clang::Decl::Var) &&
252 (DK != clang::Decl::EnumConstant)
253 ) {
254 // Error, was not a data member, variable, or enumerator.
255 return -1;
256 }
257 if (DK == clang::Decl::EnumConstant) {
258 // We know that an enumerator value does not have array type.
259 return 0;
260 }
261 // To get this information we must count the number
262 // of array type nodes in the canonical type chain.
263 clang::QualType QT = VD->getType().getCanonicalType();
264 int paran = ArrayDim();
265 if ((dim < 0) || (dim >= paran)) {
266 // Passed dimension is out of bounds.
267 return -1;
268 }
269 int cnt = dim;
270 int max = 0;
271 while (1) {
272 if (QT->isArrayType()) {
273 if (cnt == 0) {
274 if (const clang::ConstantArrayType *CAT =
275 llvm::dyn_cast<clang::ConstantArrayType>(QT)
276 ) {
277 max = static_cast<int>(CAT->getSize().getZExtValue());
278 }
279 else if (llvm::dyn_cast<clang::IncompleteArrayType>(QT)) {
280 max = INT_MAX;
281 }
282 else {
283 max = -1;
284 }
285 break;
286 }
287 --cnt;
288 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
289 continue;
290 }
291 else if (QT->isReferenceType()) {
292 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
293 continue;
294 }
295 else if (QT->isPointerType()) {
296 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
297 continue;
298 }
299 else if (QT->isMemberPointerType()) {
300 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
301 continue;
302 }
303 break;
304 }
305 return max;
306}
307
309{
310 assert(!fDecl && "This is a single decl, not an iterator!");
311
312 ClearNames();
313
314 if (!fFirstTime && !fIter.IsValid()) {
315 // Iterator is already invalid.
316 return 0;
317 }
318 // Advance to the next decl.
319 if (fFirstTime) {
320 // The cint semantics are weird.
321 fFirstTime = false;
322 } else {
323 fIter.Next();
324 }
325 return fIter.IsValid();
326}
327
329{
330 using namespace clang;
331
332 if (!IsValid()) {
333 return -1L;
334 }
335
336 const ValueDecl *D = GetTargetValueDecl();
337 ASTContext& C = D->getASTContext();
338 if (const FieldDecl *FldD = dyn_cast<FieldDecl>(D)) {
339 // The current member is a non-static data member.
340
341 // getASTRecordLayout() might deserialize.
342 cling::Interpreter::PushTransactionRAII RAII(fInterp);
343 const clang::RecordDecl *RD = FldD->getParent();
344 const clang::ASTRecordLayout &Layout = C.getASTRecordLayout(RD);
345 uint64_t bits = Layout.getFieldOffset(FldD->getFieldIndex());
346 int64_t offset = C.toCharUnitsFromBits(bits).getQuantity();
347 return static_cast<Longptr_t>(offset);
348 }
349 else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
350 // Could trigger deserialization of decls, in particular in case
351 // of constexpr, like:
352 // static constexpr Long64_t something = std::numeric_limits<Long64_t>::max();
353 cling::Interpreter::PushTransactionRAII RAII(fInterp);
354
355 // We can't reassign constexpr or const variables. We can compute the
356 // initializer.
357 if (VD->hasInit() && (VD->isConstexpr() || VD->getType().isConstQualified())) {
358 if (const APValue* val = VD->evaluateValue()) {
359 if (VD->getType()->isIntegralType(C)) {
360 return reinterpret_cast<Longptr_t>(val->getInt().getRawData());
361 } else {
362 // The VD stores the init value; its lifetime should the lifetime of
363 // this offset.
364 switch (val->getKind()) {
365 case APValue::Int: {
366 if (val->getInt().isSigned())
367 fConstInitVal.fLong = (Longptr_t)val->getInt().getSExtValue();
368 else
369 fConstInitVal.fLong = (Longptr_t)val->getInt().getZExtValue();
370 return (Longptr_t) &fConstInitVal.fLong;
371 }
372 case APValue::Float:
373 if (&val->getFloat().getSemantics()
374 == (const llvm::fltSemantics*)&llvm::APFloat::IEEEsingle()) {
375 fConstInitVal.fFloat = val->getFloat().convertToFloat();
376 return (Longptr_t)&fConstInitVal.fFloat;
377 } else if (&val->getFloat().getSemantics()
378 == (const llvm::fltSemantics*) &llvm::APFloat::IEEEdouble()) {
379 fConstInitVal.fDouble = val->getFloat().convertToDouble();
380 return (Longptr_t)&fConstInitVal.fDouble;
381 }
382 // else fall-through
383 default:
384 ;// fall-through
385 };
386 // fall-through
387 } // not integral type
388 } // have an APValue
389 } // have an initializing value
390
391 // Try the slow operation.
392 if (Longptr_t addr = reinterpret_cast<Longptr_t>(fInterp->getAddressOfGlobal(GlobalDecl(VD))))
393 return addr;
394 }
395 // FIXME: We have to explicitly check for not enum constant because the
396 // implementation of getAddressOfGlobal relies on mangling the name and in
397 // clang there is misbehaviour in MangleContext::shouldMangleDeclName.
398 // enum constants are essentially numbers and don't get addresses. However
399 // ROOT expects the address to the enum constant initializer to be returned.
400 else if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) {
401 // The raw data is stored as a long long, so we need to find the 'long'
402 // part.
403
404 // The memory leak for `EnumConstantDecl` was fixed in:
405 // https://github.com/llvm/llvm-project/pull/78311
406 // We were relying on the leak to provide the address for EnumConstantDecl.
407 // Now store the data value as a member instead.
408 fEnumValue = ECD->getInitVal().getExtValue();
409 return reinterpret_cast<Longptr_t>(&fEnumValue);
410 }
411 return -1L;
412}
413
415{
416 if (!IsValid()) {
417 return 0L;
418 }
419 long property = 0L;
420
421 // If the declaration is public in a private nested struct, make the declaration
422 // private nonetheless, as for outside access (e.g. ROOT I/O) it's private:
423 // NOTE: this uses `GetDecl()`, to capture the access of the UsingShadowDecl,
424 // which is defined in the derived class and might differ from the access of the decl
425 // in the base class.
426 // TODO: move this somewhere such that TClingMethodInfo can use this, too.
427 const Decl *thisDecl = GetDecl();
428 clang::AccessSpecifier strictestAccess = thisDecl->getAccess();
429 const DeclContext *nonTransparentDC = thisDecl->getDeclContext();
430
432 const Decl *declOrParent = thisDecl;
433 for (const auto *Parent = declOrParent->getDeclContext(); !llvm::isa<TranslationUnitDecl>(Parent);
434 Parent = declOrParent->getDeclContext()) {
435 if (!Parent->isTransparentContext()) {
436 if (const auto *RD = llvm::dyn_cast<clang::RecordDecl>(Parent)) {
437 if (!RD->isAnonymousStructOrUnion()) {
439 break;
440 }
441 } else {
442 nonTransparentDC = Parent;
443 break;
444 }
445 }
446
447 declOrParent = llvm::dyn_cast<clang::Decl>(Parent);
448 if (!declOrParent)
449 break;
451 strictestAccess = declOrParent->getAccess();
452 }
453 }
454 };
455
457 // TODO: Now that we have the kIsNotReacheable we could return the property
458 // to be reflecting the local information. However it is unclear if the
459 // information is used as-is (it appears to not be used in ROOT proper)
460 switch (strictestAccess) {
461 case clang::AS_public:
462 property |= kIsPublic;
463 break;
464 case clang::AS_protected:
465 property |= kIsProtected | kIsNotReacheable;
466 break;
467 case clang::AS_private:
468 property |= kIsPrivate | kIsNotReacheable;
469 break;
470 case clang::AS_none: //?
471 property |= kIsPublic;
472 break;
473 default:
474 // IMPOSSIBLE
475 assert(false && "Unexpected value for the access property value in Clang");
476 break;
477 }
478 if (llvm::isa<clang::UsingShadowDecl>(thisDecl))
479 property |= kIsUsing;
480
481 const clang::ValueDecl *vd = GetTargetValueDecl();
482 if (const clang::VarDecl *vard = llvm::dyn_cast<clang::VarDecl>(vd)) {
483 if (vard->isConstexpr())
484 property |= kIsConstexpr;
485 if (vard->getStorageClass() == clang::SC_Static) {
486 property |= kIsStatic;
487 } else if (nonTransparentDC->isNamespace()) {
488 // Data members of a namespace are global variable which were
489 // considered to be 'static' in the CINT (and thus ROOT) scheme.
490 property |= kIsStatic;
491 }
492 } else if (llvm::isa<clang::EnumConstantDecl>(vd)) {
493 // Enumeration constant are considered to be 'static' data member in
494 // the CINT (and thus ROOT) scheme.
495 property |= kIsStatic;
496 }
497 clang::QualType qt = vd->getType();
498 if (llvm::isa<clang::TypedefType>(qt)) {
499 property |= kIsTypedef;
500 }
501 qt = qt.getCanonicalType();
503 const clang::TagType *tt = qt->getAs<clang::TagType>();
504 if (tt) {
505 // tt->getDecl() might deserialize.
506 cling::Interpreter::PushTransactionRAII RAII(fInterp);
507 const clang::TagDecl *td = tt->getDecl();
508 if (td->isClass()) {
509 property |= kIsClass;
510 }
511 else if (td->isStruct()) {
512 property |= kIsStruct;
513 }
514 else if (td->isUnion()) {
515 property |= kIsUnion;
516 }
517 else if (td->isEnum()) {
518 property |= kIsEnum;
519 }
520 }
521
522 if (const auto *RD = llvm::dyn_cast<RecordDecl>(thisDecl->getDeclContext())) {
523 if (RD->isUnion())
524 property |= kIsUnionMember;
525 }
526 // We can't be a namespace, can we?
527 // if (dc->isNamespace() && !dc->isTranslationUnit()) {
528 // property |= kIsNamespace;
529 // }
530 return property;
531}
532
534{
535 if (!IsValid()) {
536 return 0L;
537 }
538 const clang::ValueDecl *vd = GetTargetValueDecl();
539 clang::QualType qt = vd->getType();
541}
542
544{
545 if (!IsValid()) {
546 return -1;
547 }
548
549 const clang::ValueDecl *vd = GetTargetValueDecl();
550 // Sanity check the current data member.
551 clang::Decl::Kind dk = vd->getKind();
552 if ((dk != clang::Decl::Field) && (dk != clang::Decl::Var) &&
553 (dk != clang::Decl::EnumConstant)) {
554 // Error, was not a data member, variable, or enumerator.
555 return -1;
556 }
557 clang::QualType qt = vd->getType();
558 if (qt->isIncompleteType()) {
559 // We cannot determine the size of forward-declared types.
560 return -1;
561 }
562 clang::ASTContext &context = GetDecl()->getASTContext();
563 // Truncate cast to fit to cint interface.
564 return static_cast<int>(context.getTypeSizeInChars(qt).getQuantity());
565}
566
568{
569 if (!IsValid()) {
570 return nullptr;
571 }
572
574 if (!fIoType.empty()) return fIoType.c_str();
575
576 // Note: This must be static because we return a pointer inside it!
577 static std::string buf;
578 buf.clear();
579 const clang::ValueDecl *vd = GetTargetValueDecl();
580 clang::QualType vdType = vd->getType();
581 // In CINT's version, the type name returns did *not* include any array
582 // information, ROOT's existing code depends on it.
583 while (vdType->isArrayType()) {
584 vdType = GetDecl()->getASTContext().getQualifiedType(vdType->getBaseElementTypeUnsafe(),vdType.getQualifiers());
585 }
586
587 // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
589
591
592 return buf.c_str();
593}
594
596{
597 if (!IsValid()) {
598 return nullptr;
599 }
600
602 if (!fIoType.empty()) return fIoType.c_str();
603
604 // Note: This must be static because we return a pointer inside it!
605 static std::string buf;
606 buf.clear();
607 const clang::ValueDecl *vd = GetTargetValueDecl();
608 // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
609 clang::QualType vdType = ROOT::TMetaUtils::ReSubstTemplateArg(vd->getType(), GetClassAsType());
610
612
613 // In CINT's version, the type name returns did *not* include any array
614 // information, ROOT's existing code depends on it.
615 // This might become part of the implementation of GetNormalizedName.
616 while (buf.length() && buf[buf.length()-1] == ']') {
617 size_t last = buf.rfind('['); // if this is not the bracket we are looking, the type is malformed.
618 if (last != std::string::npos) {
619 buf.erase(last);
620 }
621 }
622 return buf.c_str();
623}
624
625const char *TClingDataMemberInfo::Name() const
626{
627 if (!IsValid()) {
628 return nullptr;
629 }
630
632 if (!fIoName.empty()) return fIoName.c_str();
633
634 return TClingDeclInfo::Name();
635}
636
638{
639 if (!IsValid()) {
640 return nullptr;
641 }
642
643 //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
644 //if (fTitle.size())
645 // return fTitle.c_str();
646
647 bool titleFound=false;
648 // Try to get the comment either from the annotation or the header file if present
649 std::string attribute_s;
650 const Decl* decl = GetTargetValueDecl();
651 for (Decl::attr_iterator attrIt = decl->attr_begin();
652 attrIt!=decl->attr_end() && !titleFound ;++attrIt){
654 attribute_s.find(ROOT::TMetaUtils::propNames::separator) == std::string::npos){
656 titleFound=true;
657 }
658 }
659
660 if (!titleFound && !decl->isFromASTFile()) {
661 // Try to get the comment from the header file if present
662 // but not for decls from AST file, where rootcling would have
663 // created an annotation
665 }
666
667 return fTitle.c_str();
668}
669
670// ValidArrayIndex return a static string (so use it or copy it immediately, do not
671// call GrabIndex twice in the same expression) containing the size of the
672// array data member.
674{
675 if (!IsValid()) {
676 return llvm::StringRef();
677 }
678 const clang::DeclaratorDecl *FD = llvm::dyn_cast<clang::DeclaratorDecl>(GetTargetValueDecl());
679 if (FD)
681 return {};
682}
683
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