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 {
106 fClassInfo = TClingClassInfo(interp);
107 }
108
109 if (!ci || !ci->IsValid()) {
110 return;
111 }
112
113 auto *DC = llvm::dyn_cast<clang::DeclContext>(ci->GetDecl());
114
115 fIter = TClingDataMemberIter(interp, DC, selection);
116 fIter.Init();
117}
118
120 const clang::ValueDecl *ValD,
121 TClingClassInfo *ci)
122: TClingDeclInfo(ValD), fInterp(interp)
123{
124
125 if (ci) {
126 fClassInfo = *ci;
127 } else {
128 fClassInfo = TClingClassInfo(interp);
129 }
130
131 using namespace llvm;
132 const auto DC = ValD->getDeclContext();
133 (void)DC;
134 assert((ci || isa<TranslationUnitDecl>(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{
172 return dyn_cast<ValueDecl>(GetDecl());
173}
174
175const clang::UsingShadowDecl *TClingDataMemberInfo::GetAsUsingShadowDecl() const
176{
177 return dyn_cast<UsingShadowDecl>(GetDecl());
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 if (Longptr_t addr = reinterpret_cast<Longptr_t>(fInterp->getAddressOfGlobal(GlobalDecl(VD))))
356 return addr;
357 auto evalStmt = VD->ensureEvaluatedStmt();
358 if (evalStmt && evalStmt->Value) {
359 if (const APValue* val = VD->evaluateValue()) {
360 if (VD->getType()->isIntegralType(C)) {
361 return reinterpret_cast<Longptr_t>(val->getInt().getRawData());
362 } else {
363 // The VD stores the init value; its lifetime should the lifetime of
364 // this offset.
365 switch (val->getKind()) {
366 case APValue::Int: {
367 if (val->getInt().isSigned())
368 fConstInitVal.fLong = (Longptr_t)val->getInt().getSExtValue();
369 else
370 fConstInitVal.fLong = (Longptr_t)val->getInt().getZExtValue();
371 return (Longptr_t) &fConstInitVal.fLong;
372 }
373 case APValue::Float:
374 if (&val->getFloat().getSemantics()
375 == (const llvm::fltSemantics*)&llvm::APFloat::IEEEsingle()) {
376 fConstInitVal.fFloat = val->getFloat().convertToFloat();
377 return (Longptr_t)&fConstInitVal.fFloat;
378 } else if (&val->getFloat().getSemantics()
379 == (const llvm::fltSemantics*) &llvm::APFloat::IEEEdouble()) {
380 fConstInitVal.fDouble = val->getFloat().convertToDouble();
381 return (Longptr_t)&fConstInitVal.fDouble;
382 }
383 // else fall-through
384 default:
385 ;// fall-through
386 };
387 // fall-through
388 } // not integral type
389 } // have an APValue
390 } // have an initializing value
391 }
392 // FIXME: We have to explicitly check for not enum constant because the
393 // implementation of getAddressOfGlobal relies on mangling the name and in
394 // clang there is misbehaviour in MangleContext::shouldMangleDeclName.
395 // enum constants are essentially numbers and don't get addresses. However
396 // ROOT expects the address to the enum constant initializer to be returned.
397 else if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
398 // The raw data is stored as a long long, so we need to find the 'long'
399 // part.
400#ifdef R__BYTESWAP
401 // In this case at the beginning.
402 return reinterpret_cast<Longptr_t>(ECD->getInitVal().getRawData());
403#else
404 // In this case in the second part.
405 return reinterpret_cast<Longptr_t>(((char*)ECD->getInitVal().getRawData())+sizeof(Longptr_t) );
406#endif
407 return -1L;
408}
409
411{
412 if (!IsValid()) {
413 return 0L;
414 }
415 long property = 0L;
416
417 // If the declaration is public in a private nested struct, make the declaration
418 // private nonetheless, as for outside access (e.g. ROOT I/O) it's private:
419 // NOTE: this uses `GetDecl()`, to capture the access of the UsingShadowDecl,
420 // which is defined in the derived class and might differ from the access of the decl
421 // in the base class.
422 // TODO: move this somewhere such that TClingMethodInfo can use this, too.
423 const Decl *thisDecl = GetDecl();
424 clang::AccessSpecifier strictestAccess = thisDecl->getAccess();
425 const DeclContext *nonTransparentDC = thisDecl->getDeclContext();
426
427 auto getParentAccessAndNonTransparentDC = [&]() {
428 const Decl *declOrParent = thisDecl;
429 for (const auto *Parent = declOrParent->getDeclContext(); !llvm::isa<TranslationUnitDecl>(Parent);
430 Parent = declOrParent->getDeclContext()) {
431 if (!Parent->isTransparentContext()) {
432 if (const auto *RD = llvm::dyn_cast<clang::RecordDecl>(Parent)) {
433 if (!RD->isAnonymousStructOrUnion()) {
434 nonTransparentDC = RD;
435 break;
436 }
437 } else {
438 nonTransparentDC = Parent;
439 break;
440 }
441 }
442
443 declOrParent = llvm::dyn_cast<clang::Decl>(Parent);
444 if (!declOrParent)
445 break;
446 if (strictestAccess < declOrParent->getAccess()) {
447 strictestAccess = declOrParent->getAccess();
448 }
449 }
450 };
451
452 getParentAccessAndNonTransparentDC();
453
454 switch (strictestAccess) {
455 case clang::AS_public:
456 property |= kIsPublic;
457 break;
458 case clang::AS_protected:
459 property |= kIsProtected;
460 break;
461 case clang::AS_private:
462 property |= kIsPrivate;
463 break;
464 case clang::AS_none: //?
465 property |= kIsPublic;
466 break;
467 default:
468 // IMPOSSIBLE
469 break;
470 }
471 if (llvm::isa<clang::UsingShadowDecl>(thisDecl))
472 property |= kIsUsing;
473
474 const clang::ValueDecl *vd = GetTargetValueDecl();
475 if (const clang::VarDecl *vard = llvm::dyn_cast<clang::VarDecl>(vd)) {
476 if (vard->isConstexpr())
477 property |= kIsConstexpr;
478 if (vard->getStorageClass() == clang::SC_Static) {
479 property |= kIsStatic;
480 } else if (nonTransparentDC->isNamespace()) {
481 // Data members of a namespace are global variable which were
482 // considered to be 'static' in the CINT (and thus ROOT) scheme.
483 property |= kIsStatic;
484 }
485 } else if (llvm::isa<clang::EnumConstantDecl>(vd)) {
486 // Enumeration constant are considered to be 'static' data member in
487 // the CINT (and thus ROOT) scheme.
488 property |= kIsStatic;
489 }
490 clang::QualType qt = vd->getType();
491 if (llvm::isa<clang::TypedefType>(qt)) {
492 property |= kIsTypedef;
493 }
494 qt = qt.getCanonicalType();
495 property = TClingDeclInfo::Property(property, qt);
496 const clang::TagType *tt = qt->getAs<clang::TagType>();
497 if (tt) {
498 // tt->getDecl() might deserialize.
499 cling::Interpreter::PushTransactionRAII RAII(fInterp);
500 const clang::TagDecl *td = tt->getDecl();
501 if (td->isClass()) {
502 property |= kIsClass;
503 }
504 else if (td->isStruct()) {
505 property |= kIsStruct;
506 }
507 else if (td->isUnion()) {
508 property |= kIsUnion;
509 }
510 else if (td->isEnum()) {
511 property |= kIsEnum;
512 }
513 }
514
515 if (const auto *RD = llvm::dyn_cast<RecordDecl>(thisDecl->getDeclContext())) {
516 if (RD->isUnion())
517 property |= kIsUnionMember;
518 }
519 // We can't be a namespace, can we?
520 // if (dc->isNamespace() && !dc->isTranslationUnit()) {
521 // property |= kIsNamespace;
522 // }
523 return property;
524}
525
527{
528 if (!IsValid()) {
529 return 0L;
530 }
531 const clang::ValueDecl *vd = GetTargetValueDecl();
532 clang::QualType qt = vd->getType();
533 return TClingTypeInfo(fInterp, qt).Property();
534}
535
537{
538 if (!IsValid()) {
539 return -1;
540 }
541
542 const clang::ValueDecl *vd = GetTargetValueDecl();
543 // Sanity check the current data member.
544 clang::Decl::Kind dk = vd->getKind();
545 if ((dk != clang::Decl::Field) && (dk != clang::Decl::Var) &&
546 (dk != clang::Decl::EnumConstant)) {
547 // Error, was not a data member, variable, or enumerator.
548 return -1;
549 }
550 clang::QualType qt = vd->getType();
551 if (qt->isIncompleteType()) {
552 // We cannot determine the size of forward-declared types.
553 return -1;
554 }
555 clang::ASTContext &context = GetDecl()->getASTContext();
556 // Truncate cast to fit to cint interface.
557 return static_cast<int>(context.getTypeSizeInChars(qt).getQuantity());
558}
559
561{
562 if (!IsValid()) {
563 return nullptr;
564 }
565
567 if (!fIoType.empty()) return fIoType.c_str();
568
569 // Note: This must be static because we return a pointer inside it!
570 static std::string buf;
571 buf.clear();
572 const clang::ValueDecl *vd = GetTargetValueDecl();
573 clang::QualType vdType = vd->getType();
574 // In CINT's version, the type name returns did *not* include any array
575 // information, ROOT's existing code depends on it.
576 while (vdType->isArrayType()) {
577 vdType = GetDecl()->getASTContext().getQualifiedType(vdType->getBaseElementTypeUnsafe(),vdType.getQualifiers());
578 }
579
580 // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
582
584
585 return buf.c_str();
586}
587
589{
590 if (!IsValid()) {
591 return nullptr;
592 }
593
595 if (!fIoType.empty()) return fIoType.c_str();
596
597 // Note: This must be static because we return a pointer inside it!
598 static std::string buf;
599 buf.clear();
600 const clang::ValueDecl *vd = GetTargetValueDecl();
601 // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
602 clang::QualType vdType = ROOT::TMetaUtils::ReSubstTemplateArg(vd->getType(), GetClassAsType());
603
604 ROOT::TMetaUtils::GetNormalizedName(buf, vdType, *fInterp, normCtxt);
605
606 // In CINT's version, the type name returns did *not* include any array
607 // information, ROOT's existing code depends on it.
608 // This might become part of the implementation of GetNormalizedName.
609 while (buf.length() && buf[buf.length()-1] == ']') {
610 size_t last = buf.rfind('['); // if this is not the bracket we are looking, the type is malformed.
611 if (last != std::string::npos) {
612 buf.erase(last);
613 }
614 }
615 return buf.c_str();
616}
617
618const char *TClingDataMemberInfo::Name() const
619{
620 if (!IsValid()) {
621 return nullptr;
622 }
623
625 if (!fIoName.empty()) return fIoName.c_str();
626
627 return TClingDeclInfo::Name();
628}
629
631{
632 if (!IsValid()) {
633 return nullptr;
634 }
635
636 //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
637 //if (fTitle.size())
638 // return fTitle.c_str();
639
640 bool titleFound=false;
641 // Try to get the comment either from the annotation or the header file if present
642 std::string attribute_s;
643 const Decl* decl = GetTargetValueDecl();
644 for (Decl::attr_iterator attrIt = decl->attr_begin();
645 attrIt!=decl->attr_end() && !titleFound ;++attrIt){
646 if (0 == ROOT::TMetaUtils::extractAttrString(*attrIt, attribute_s) &&
647 attribute_s.find(ROOT::TMetaUtils::propNames::separator) == std::string::npos){
648 fTitle = attribute_s;
649 titleFound=true;
650 }
651 }
652
653 if (!titleFound && !decl->isFromASTFile()) {
654 // Try to get the comment from the header file if present
655 // but not for decls from AST file, where rootcling would have
656 // created an annotation
658 }
659
660 return fTitle.c_str();
661}
662
663// ValidArrayIndex return a static string (so use it or copy it immediately, do not
664// call GrabIndex twice in the same expression) containing the size of the
665// array data member.
667{
668 if (!IsValid()) {
669 return llvm::StringRef();
670 }
671 const clang::DeclaratorDecl *FD = llvm::dyn_cast<clang::DeclaratorDecl>(GetTargetValueDecl());
672 if (FD)
674 return {};
675}
676
long Longptr_t
Definition RtypesCore.h:82
@ 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
@ 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
virtual const clang::Decl * GetDecl() 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