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 // 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#ifdef R__BYTESWAP
404 // In this case at the beginning.
405 return reinterpret_cast<Longptr_t>(ECD->getInitVal().getRawData());
406#else
407 // In this case in the second part.
408 return reinterpret_cast<Longptr_t>(((char*)ECD->getInitVal().getRawData())+sizeof(Longptr_t) );
409#endif
410 return -1L;
411}
412
414{
415 if (!IsValid()) {
416 return 0L;
417 }
418 long property = 0L;
419
420 // If the declaration is public in a private nested struct, make the declaration
421 // private nonetheless, as for outside access (e.g. ROOT I/O) it's private:
422 // NOTE: this uses `GetDecl()`, to capture the access of the UsingShadowDecl,
423 // which is defined in the derived class and might differ from the access of the decl
424 // in the base class.
425 // TODO: move this somewhere such that TClingMethodInfo can use this, too.
426 const Decl *thisDecl = GetDecl();
427 clang::AccessSpecifier strictestAccess = thisDecl->getAccess();
428 const DeclContext *nonTransparentDC = thisDecl->getDeclContext();
429
430 auto getParentAccessAndNonTransparentDC = [&]() {
431 const Decl *declOrParent = thisDecl;
432 for (const auto *Parent = declOrParent->getDeclContext(); !llvm::isa<TranslationUnitDecl>(Parent);
433 Parent = declOrParent->getDeclContext()) {
434 if (!Parent->isTransparentContext()) {
435 if (const auto *RD = llvm::dyn_cast<clang::RecordDecl>(Parent)) {
436 if (!RD->isAnonymousStructOrUnion()) {
437 nonTransparentDC = RD;
438 break;
439 }
440 } else {
441 nonTransparentDC = Parent;
442 break;
443 }
444 }
445
446 declOrParent = llvm::dyn_cast<clang::Decl>(Parent);
447 if (!declOrParent)
448 break;
449 if (strictestAccess < declOrParent->getAccess()) {
450 strictestAccess = declOrParent->getAccess();
451 }
452 }
453 };
454
455 getParentAccessAndNonTransparentDC();
456
457 switch (strictestAccess) {
458 case clang::AS_public:
459 property |= kIsPublic;
460 break;
461 case clang::AS_protected:
462 property |= kIsProtected;
463 break;
464 case clang::AS_private:
465 property |= kIsPrivate;
466 break;
467 case clang::AS_none: //?
468 property |= kIsPublic;
469 break;
470 default:
471 // IMPOSSIBLE
472 break;
473 }
474 if (llvm::isa<clang::UsingShadowDecl>(thisDecl))
475 property |= kIsUsing;
476
477 const clang::ValueDecl *vd = GetTargetValueDecl();
478 if (const clang::VarDecl *vard = llvm::dyn_cast<clang::VarDecl>(vd)) {
479 if (vard->isConstexpr())
480 property |= kIsConstexpr;
481 if (vard->getStorageClass() == clang::SC_Static) {
482 property |= kIsStatic;
483 } else if (nonTransparentDC->isNamespace()) {
484 // Data members of a namespace are global variable which were
485 // considered to be 'static' in the CINT (and thus ROOT) scheme.
486 property |= kIsStatic;
487 }
488 } else if (llvm::isa<clang::EnumConstantDecl>(vd)) {
489 // Enumeration constant are considered to be 'static' data member in
490 // the CINT (and thus ROOT) scheme.
491 property |= kIsStatic;
492 }
493 clang::QualType qt = vd->getType();
494 if (llvm::isa<clang::TypedefType>(qt)) {
495 property |= kIsTypedef;
496 }
497 qt = qt.getCanonicalType();
498 property = TClingDeclInfo::Property(property, qt);
499 const clang::TagType *tt = qt->getAs<clang::TagType>();
500 if (tt) {
501 // tt->getDecl() might deserialize.
502 cling::Interpreter::PushTransactionRAII RAII(fInterp);
503 const clang::TagDecl *td = tt->getDecl();
504 if (td->isClass()) {
505 property |= kIsClass;
506 }
507 else if (td->isStruct()) {
508 property |= kIsStruct;
509 }
510 else if (td->isUnion()) {
511 property |= kIsUnion;
512 }
513 else if (td->isEnum()) {
514 property |= kIsEnum;
515 }
516 }
517
518 if (const auto *RD = llvm::dyn_cast<RecordDecl>(thisDecl->getDeclContext())) {
519 if (RD->isUnion())
520 property |= kIsUnionMember;
521 }
522 // We can't be a namespace, can we?
523 // if (dc->isNamespace() && !dc->isTranslationUnit()) {
524 // property |= kIsNamespace;
525 // }
526 return property;
527}
528
530{
531 if (!IsValid()) {
532 return 0L;
533 }
534 const clang::ValueDecl *vd = GetTargetValueDecl();
535 clang::QualType qt = vd->getType();
536 return TClingTypeInfo(fInterp, qt).Property();
537}
538
540{
541 if (!IsValid()) {
542 return -1;
543 }
544
545 const clang::ValueDecl *vd = GetTargetValueDecl();
546 // Sanity check the current data member.
547 clang::Decl::Kind dk = vd->getKind();
548 if ((dk != clang::Decl::Field) && (dk != clang::Decl::Var) &&
549 (dk != clang::Decl::EnumConstant)) {
550 // Error, was not a data member, variable, or enumerator.
551 return -1;
552 }
553 clang::QualType qt = vd->getType();
554 if (qt->isIncompleteType()) {
555 // We cannot determine the size of forward-declared types.
556 return -1;
557 }
558 clang::ASTContext &context = GetDecl()->getASTContext();
559 // Truncate cast to fit to cint interface.
560 return static_cast<int>(context.getTypeSizeInChars(qt).getQuantity());
561}
562
564{
565 if (!IsValid()) {
566 return nullptr;
567 }
568
570 if (!fIoType.empty()) return fIoType.c_str();
571
572 // Note: This must be static because we return a pointer inside it!
573 static std::string buf;
574 buf.clear();
575 const clang::ValueDecl *vd = GetTargetValueDecl();
576 clang::QualType vdType = vd->getType();
577 // In CINT's version, the type name returns did *not* include any array
578 // information, ROOT's existing code depends on it.
579 while (vdType->isArrayType()) {
580 vdType = GetDecl()->getASTContext().getQualifiedType(vdType->getBaseElementTypeUnsafe(),vdType.getQualifiers());
581 }
582
583 // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
585
587
588 return buf.c_str();
589}
590
592{
593 if (!IsValid()) {
594 return nullptr;
595 }
596
598 if (!fIoType.empty()) return fIoType.c_str();
599
600 // Note: This must be static because we return a pointer inside it!
601 static std::string buf;
602 buf.clear();
603 const clang::ValueDecl *vd = GetTargetValueDecl();
604 // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
605 clang::QualType vdType = ROOT::TMetaUtils::ReSubstTemplateArg(vd->getType(), GetClassAsType());
606
607 ROOT::TMetaUtils::GetNormalizedName(buf, vdType, *fInterp, normCtxt);
608
609 // In CINT's version, the type name returns did *not* include any array
610 // information, ROOT's existing code depends on it.
611 // This might become part of the implementation of GetNormalizedName.
612 while (buf.length() && buf[buf.length()-1] == ']') {
613 size_t last = buf.rfind('['); // if this is not the bracket we are looking, the type is malformed.
614 if (last != std::string::npos) {
615 buf.erase(last);
616 }
617 }
618 return buf.c_str();
619}
620
621const char *TClingDataMemberInfo::Name() const
622{
623 if (!IsValid()) {
624 return nullptr;
625 }
626
628 if (!fIoName.empty()) return fIoName.c_str();
629
630 return TClingDeclInfo::Name();
631}
632
634{
635 if (!IsValid()) {
636 return nullptr;
637 }
638
639 //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
640 //if (fTitle.size())
641 // return fTitle.c_str();
642
643 bool titleFound=false;
644 // Try to get the comment either from the annotation or the header file if present
645 std::string attribute_s;
646 const Decl* decl = GetTargetValueDecl();
647 for (Decl::attr_iterator attrIt = decl->attr_begin();
648 attrIt!=decl->attr_end() && !titleFound ;++attrIt){
649 if (0 == ROOT::TMetaUtils::extractAttrString(*attrIt, attribute_s) &&
650 attribute_s.find(ROOT::TMetaUtils::propNames::separator) == std::string::npos){
651 fTitle = attribute_s;
652 titleFound=true;
653 }
654 }
655
656 if (!titleFound && !decl->isFromASTFile()) {
657 // Try to get the comment from the header file if present
658 // but not for decls from AST file, where rootcling would have
659 // created an annotation
661 }
662
663 return fTitle.c_str();
664}
665
666// ValidArrayIndex return a static string (so use it or copy it immediately, do not
667// call GrabIndex twice in the same expression) containing the size of the
668// array data member.
670{
671 if (!IsValid()) {
672 return llvm::StringRef();
673 }
674 const clang::DeclaratorDecl *FD = llvm::dyn_cast<clang::DeclaratorDecl>(GetTargetValueDecl());
675 if (FD)
677 return {};
678}
679
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