Logo ROOT  
Reference Guide
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), fClassInfo(ci ? new TClingClassInfo(*ci) : new TClingClassInfo(interp))
99{
100
102
103 if (!ci || !ci->IsValid()) {
104 return;
105 }
106
107 auto *DC = llvm::dyn_cast<clang::DeclContext>(ci->GetDecl());
108
109 fIter = TClingDataMemberIter(interp, DC, selection);
110 fIter.Init();
111}
112
114 const clang::ValueDecl *ValD,
115 TClingClassInfo *ci)
116: TClingDeclInfo(ValD), fInterp(interp), fClassInfo(ci ? new TClingClassInfo(*ci) : new TClingClassInfo(interp))
117{
118
119 using namespace llvm;
120 const auto DC = ValD->getDeclContext();
121 (void)DC;
122 assert((ci || isa<TranslationUnitDecl>(DC) ||
123 ((DC->isTransparentContext() || DC->isInlineNamespace()) && isa<TranslationUnitDecl>(DC->getParent()) ) ||
124 isa<EnumConstantDecl>(ValD)) && "Not TU?");
125 assert(IsRelevantKind(ValD->getKind()) &&
126 "The decl should be either VarDecl or FieldDecl or EnumConstDecl");
127
128}
129
131{
132 // Three cases:
133 // 1) 00: none to be checked
134 // 2) 01: type to be checked
135 // 3) 10: none to be checked
136 // 4) 11: both to be checked
137 unsigned int code = fIoType.empty() + (int(fIoName.empty()) << 1);
138
139 if (code == 0) return;
140
141 const Decl* decl = GetTargetValueDecl();
142
143 if (code == 3 || code == 2) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,"ioname",fIoName);
144 if (code == 3 || code == 1) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,"iotype",fIoType);
145
146}
147
149{
150 if (!IsValid()) {
151 return TDictionary::DeclId_t();
152 }
153 if (auto *VD = GetAsValueDecl())
154 return (const clang::Decl*)(VD->getCanonicalDecl());
155 return (const clang::Decl*)(GetAsUsingShadowDecl()->getCanonicalDecl());
156}
157
158const clang::ValueDecl *TClingDataMemberInfo::GetAsValueDecl() const
159{
160 return dyn_cast<ValueDecl>(GetDecl());
161}
162
163const clang::UsingShadowDecl *TClingDataMemberInfo::GetAsUsingShadowDecl() const
164{
165 return dyn_cast<UsingShadowDecl>(GetDecl());
166}
167
168const clang::ValueDecl *TClingDataMemberInfo::GetTargetValueDecl() const
169{
170 const Decl *D = GetDecl();
171 do {
172 if (auto VD = dyn_cast<ValueDecl>(D))
173 return VD;
174 } while ((D = dyn_cast<UsingShadowDecl>(D)->getTargetDecl()));
175 return nullptr;
176}
177
179 return fClassInfo ? fClassInfo->GetType() : nullptr;
180}
181
183{
184 if (!IsValid()) {
185 return -1;
186 }
187 const clang::ValueDecl *VD = GetTargetValueDecl();
188 // Sanity check the current data member.
189 clang::Decl::Kind DK = VD->getKind();
190 if (
191 (DK != clang::Decl::Field) &&
192 (DK != clang::Decl::Var) &&
193 (DK != clang::Decl::EnumConstant)
194 ) {
195 // Error, was not a data member, variable, or enumerator.
196 return -1;
197 }
198 if (DK == clang::Decl::EnumConstant) {
199 // We know that an enumerator value does not have array type.
200 return 0;
201 }
202 // To get this information we must count the number
203 // of array type nodes in the canonical type chain.
204 clang::QualType QT = VD->getType().getCanonicalType();
205 int cnt = 0;
206 while (1) {
207 if (QT->isArrayType()) {
208 ++cnt;
209 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
210 continue;
211 }
212 else if (QT->isReferenceType()) {
213 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
214 continue;
215 }
216 else if (QT->isPointerType()) {
217 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
218 continue;
219 }
220 else if (QT->isMemberPointerType()) {
221 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
222 continue;
223 }
224 break;
225 }
226 return cnt;
227}
228
230{
231 if (!IsValid()) {
232 return -1;
233 }
234 const clang::ValueDecl *VD = GetTargetValueDecl();
235 // Sanity check the current data member.
236 clang::Decl::Kind DK = GetDecl()->getKind();
237 if (
238 (DK != clang::Decl::Field) &&
239 (DK != clang::Decl::Var) &&
240 (DK != clang::Decl::EnumConstant)
241 ) {
242 // Error, was not a data member, variable, or enumerator.
243 return -1;
244 }
245 if (DK == clang::Decl::EnumConstant) {
246 // We know that an enumerator value does not have array type.
247 return 0;
248 }
249 // To get this information we must count the number
250 // of array type nodes in the canonical type chain.
251 clang::QualType QT = VD->getType().getCanonicalType();
252 int paran = ArrayDim();
253 if ((dim < 0) || (dim >= paran)) {
254 // Passed dimension is out of bounds.
255 return -1;
256 }
257 int cnt = dim;
258 int max = 0;
259 while (1) {
260 if (QT->isArrayType()) {
261 if (cnt == 0) {
262 if (const clang::ConstantArrayType *CAT =
263 llvm::dyn_cast<clang::ConstantArrayType>(QT)
264 ) {
265 max = static_cast<int>(CAT->getSize().getZExtValue());
266 }
267 else if (llvm::dyn_cast<clang::IncompleteArrayType>(QT)) {
268 max = INT_MAX;
269 }
270 else {
271 max = -1;
272 }
273 break;
274 }
275 --cnt;
276 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
277 continue;
278 }
279 else if (QT->isReferenceType()) {
280 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
281 continue;
282 }
283 else if (QT->isPointerType()) {
284 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
285 continue;
286 }
287 else if (QT->isMemberPointerType()) {
288 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
289 continue;
290 }
291 break;
292 }
293 return max;
294}
295
297{
298 assert(!fDecl && "This is a single decl, not an iterator!");
299
300 ClearNames();
301
302 if (!fFirstTime && !fIter.IsValid()) {
303 // Iterator is already invalid.
304 return 0;
305 }
306 // Advance to the next decl.
307 if (fFirstTime) {
308 // The cint semantics are weird.
309 fFirstTime = false;
310 } else {
311 fIter.Next();
312 }
313 return fIter.IsValid();
314}
315
317{
318 using namespace clang;
319
320 if (!IsValid()) {
321 return -1L;
322 }
323
324 const ValueDecl *D = GetTargetValueDecl();
325 ASTContext& C = D->getASTContext();
326 if (const FieldDecl *FldD = dyn_cast<FieldDecl>(D)) {
327 // The current member is a non-static data member.
328 const clang::RecordDecl *RD = FldD->getParent();
329 const clang::ASTRecordLayout &Layout = C.getASTRecordLayout(RD);
330 uint64_t bits = Layout.getFieldOffset(FldD->getFieldIndex());
331 int64_t offset = C.toCharUnitsFromBits(bits).getQuantity();
332 return static_cast<long>(offset);
333 }
334 else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
335 // Could trigger deserialization of decls, in particular in case
336 // of constexpr, like:
337 // static constexpr Long64_t something = std::numeric_limits<Long64_t>::max();
338 cling::Interpreter::PushTransactionRAII RAII(fInterp);
339
340 if (long addr = reinterpret_cast<long>(fInterp->getAddressOfGlobal(GlobalDecl(VD))))
341 return addr;
342 auto evalStmt = VD->ensureEvaluatedStmt();
343 if (evalStmt && evalStmt->Value) {
344 if (const APValue* val = VD->evaluateValue()) {
345 if (VD->getType()->isIntegralType(C)) {
346 return reinterpret_cast<long>(val->getInt().getRawData());
347 } else {
348 // The VD stores the init value; its lifetime should the lifetime of
349 // this offset.
350 switch (val->getKind()) {
351 case APValue::Int: {
352 if (val->getInt().isSigned())
353 fConstInitVal.fLong = (long)val->getInt().getSExtValue();
354 else
355 fConstInitVal.fLong = (long)val->getInt().getZExtValue();
356 return (long) &fConstInitVal.fLong;
357 }
358 case APValue::Float:
359 if (&val->getFloat().getSemantics()
360 == (const llvm::fltSemantics*)&llvm::APFloat::IEEEsingle()) {
361 fConstInitVal.fFloat = val->getFloat().convertToFloat();
362 return (long)&fConstInitVal.fFloat;
363 } else if (&val->getFloat().getSemantics()
364 == (const llvm::fltSemantics*) &llvm::APFloat::IEEEdouble()) {
365 fConstInitVal.fDouble = val->getFloat().convertToDouble();
366 return (long)&fConstInitVal.fDouble;
367 }
368 // else fall-through
369 default:
370 ;// fall-through
371 };
372 // fall-through
373 } // not integral type
374 } // have an APValue
375 } // have an initializing value
376 }
377 // FIXME: We have to explicitly check for not enum constant because the
378 // implementation of getAddressOfGlobal relies on mangling the name and in
379 // clang there is misbehaviour in MangleContext::shouldMangleDeclName.
380 // enum constants are essentially numbers and don't get addresses. However
381 // ROOT expects the address to the enum constant initializer to be returned.
382 else if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
383 // The raw data is stored as a long long, so we need to find the 'long'
384 // part.
385#ifdef R__BYTESWAP
386 // In this case at the beginning.
387 return reinterpret_cast<long>(ECD->getInitVal().getRawData());
388#else
389 // In this case in the second part.
390 return reinterpret_cast<long>(((char*)ECD->getInitVal().getRawData())+sizeof(long) );
391#endif
392 return -1L;
393}
394
396{
397 if (!IsValid()) {
398 return 0L;
399 }
400 long property = 0L;
401
402 // If the declaration is public in a private nested struct, make the declaration
403 // private nonetheless, as for outside access (e.g. ROOT I/O) it's private:
404 // NOTE: this uses `GetDecl()`, to capture the access of the UsingShadowDecl,
405 // which is defined in the derived class and might differ from the access of the decl
406 // in the base class.
407 // TODO: move this somewhere such that TClingMethodInfo can use this, too.
408 const Decl *thisDecl = GetDecl();
409 clang::AccessSpecifier strictestAccess = thisDecl->getAccess();
410 const DeclContext *nonTransparentDC = thisDecl->getDeclContext();
411
412 auto getParentAccessAndNonTransparentDC = [&]() {
413 const Decl *declOrParent = thisDecl;
414 for (const auto *Parent = declOrParent->getDeclContext(); !llvm::isa<TranslationUnitDecl>(Parent);
415 Parent = declOrParent->getDeclContext()) {
416 if (!Parent->isTransparentContext()) {
417 if (const auto *RD = llvm::dyn_cast<clang::RecordDecl>(Parent)) {
418 if (!RD->isAnonymousStructOrUnion()) {
419 nonTransparentDC = RD;
420 break;
421 }
422 } else {
423 nonTransparentDC = Parent;
424 break;
425 }
426 }
427
428 declOrParent = llvm::dyn_cast<clang::Decl>(Parent);
429 if (strictestAccess < declOrParent->getAccess()) {
430 strictestAccess = declOrParent->getAccess();
431 }
432 }
433 };
434
435 getParentAccessAndNonTransparentDC();
436
437 switch (strictestAccess) {
438 case clang::AS_public:
439 property |= kIsPublic;
440 break;
441 case clang::AS_protected:
442 property |= kIsProtected;
443 break;
444 case clang::AS_private:
445 property |= kIsPrivate;
446 break;
447 case clang::AS_none: //?
448 property |= kIsPublic;
449 break;
450 default:
451 // IMPOSSIBLE
452 break;
453 }
454 if (llvm::isa<clang::UsingShadowDecl>(thisDecl))
455 property |= kIsUsing;
456
457 const clang::ValueDecl *vd = GetTargetValueDecl();
458 if (const clang::VarDecl *vard = llvm::dyn_cast<clang::VarDecl>(vd)) {
459 if (vard->isConstexpr())
460 property |= kIsConstexpr;
461 if (vard->getStorageClass() == clang::SC_Static) {
462 property |= kIsStatic;
463 } else if (nonTransparentDC->isNamespace()) {
464 // Data members of a namespace are global variable which were
465 // considered to be 'static' in the CINT (and thus ROOT) scheme.
466 property |= kIsStatic;
467 }
468 } else if (llvm::isa<clang::EnumConstantDecl>(vd)) {
469 // Enumeration constant are considered to be 'static' data member in
470 // the CINT (and thus ROOT) scheme.
471 property |= kIsStatic;
472 }
473 clang::QualType qt = vd->getType();
474 if (llvm::isa<clang::TypedefType>(qt)) {
475 property |= kIsTypedef;
476 }
477 qt = qt.getCanonicalType();
478 property = TClingDeclInfo::Property(property, qt);
479 const clang::TagType *tt = qt->getAs<clang::TagType>();
480 if (tt) {
481 const clang::TagDecl *td = tt->getDecl();
482 if (td->isClass()) {
483 property |= kIsClass;
484 }
485 else if (td->isStruct()) {
486 property |= kIsStruct;
487 }
488 else if (td->isUnion()) {
489 property |= kIsUnion;
490 }
491 else if (td->isEnum()) {
492 property |= kIsEnum;
493 }
494 }
495
496 if (const auto *RD = llvm::dyn_cast<RecordDecl>(thisDecl->getDeclContext())) {
497 if (RD->isUnion())
498 property |= kIsUnionMember;
499 }
500 // We can't be a namespace, can we?
501 // if (dc->isNamespace() && !dc->isTranslationUnit()) {
502 // property |= kIsNamespace;
503 // }
504 return property;
505}
506
508{
509 if (!IsValid()) {
510 return 0L;
511 }
512 const clang::ValueDecl *vd = GetTargetValueDecl();
513 clang::QualType qt = vd->getType();
514 return TClingTypeInfo(fInterp, qt).Property();
515}
516
518{
519 if (!IsValid()) {
520 return -1;
521 }
522
523 const clang::ValueDecl *vd = GetTargetValueDecl();
524 // Sanity check the current data member.
525 clang::Decl::Kind dk = vd->getKind();
526 if ((dk != clang::Decl::Field) && (dk != clang::Decl::Var) &&
527 (dk != clang::Decl::EnumConstant)) {
528 // Error, was not a data member, variable, or enumerator.
529 return -1;
530 }
531 clang::QualType qt = vd->getType();
532 if (qt->isIncompleteType()) {
533 // We cannot determine the size of forward-declared types.
534 return -1;
535 }
536 clang::ASTContext &context = GetDecl()->getASTContext();
537 // Truncate cast to fit to cint interface.
538 return static_cast<int>(context.getTypeSizeInChars(qt).getQuantity());
539}
540
542{
543 if (!IsValid()) {
544 return 0;
545 }
546
548 if (!fIoType.empty()) return fIoType.c_str();
549
550 // Note: This must be static because we return a pointer inside it!
551 static std::string buf;
552 buf.clear();
553 const clang::ValueDecl *vd = GetTargetValueDecl();
554 clang::QualType vdType = vd->getType();
555 // In CINT's version, the type name returns did *not* include any array
556 // information, ROOT's existing code depends on it.
557 while (vdType->isArrayType()) {
558 vdType = GetDecl()->getASTContext().getQualifiedType(vdType->getBaseElementTypeUnsafe(),vdType.getQualifiers());
559 }
560
561 // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
563
565
566 return buf.c_str();
567}
568
570{
571 if (!IsValid()) {
572 return 0;
573 }
574
576 if (!fIoType.empty()) return fIoType.c_str();
577
578 // Note: This must be static because we return a pointer inside it!
579 static std::string buf;
580 buf.clear();
581 const clang::ValueDecl *vd = GetTargetValueDecl();
582 // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
583 clang::QualType vdType = ROOT::TMetaUtils::ReSubstTemplateArg(vd->getType(), GetClassAsType());
584
585 ROOT::TMetaUtils::GetNormalizedName(buf, vdType, *fInterp, normCtxt);
586
587 // In CINT's version, the type name returns did *not* include any array
588 // information, ROOT's existing code depends on it.
589 // This might become part of the implementation of GetNormalizedName.
590 while (buf.length() && buf[buf.length()-1] == ']') {
591 size_t last = buf.rfind('['); // if this is not the bracket we are looking, the type is malformed.
592 if (last != std::string::npos) {
593 buf.erase(last);
594 }
595 }
596 return buf.c_str();
597}
598
599const char *TClingDataMemberInfo::Name() const
600{
601 if (!IsValid()) {
602 return 0;
603 }
604
606 if (!fIoName.empty()) return fIoName.c_str();
607
608 return TClingDeclInfo::Name();
609}
610
612{
613 if (!IsValid()) {
614 return 0;
615 }
616
617 //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
618 //if (fTitle.size())
619 // return fTitle.c_str();
620
621 bool titleFound=false;
622 // Try to get the comment either from the annotation or the header file if present
623 std::string attribute_s;
624 const Decl* decl = GetTargetValueDecl();
625 for (Decl::attr_iterator attrIt = decl->attr_begin();
626 attrIt!=decl->attr_end() && !titleFound ;++attrIt){
627 if (0 == ROOT::TMetaUtils::extractAttrString(*attrIt, attribute_s) &&
628 attribute_s.find(ROOT::TMetaUtils::propNames::separator) == std::string::npos){
629 fTitle = attribute_s;
630 titleFound=true;
631 }
632 }
633
634 if (!titleFound && !decl->isFromASTFile()) {
635 // Try to get the comment from the header file if present
636 // but not for decls from AST file, where rootcling would have
637 // created an annotation
639 }
640
641 return fTitle.c_str();
642}
643
644// ValidArrayIndex return a static string (so use it or copy it immediately, do not
645// call GrabIndex twice in the same expression) containing the size of the
646// array data member.
648{
649 if (!IsValid()) {
650 return llvm::StringRef();
651 }
652 const clang::DeclaratorDecl *FD = llvm::dyn_cast<clang::DeclaratorDecl>(GetTargetValueDecl());
654 else return llvm::StringRef();
655}
656
long
Definition: Converters.cxx:858
@ 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
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:41
typedef void((*Func_t)())
#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
const clang::UsingShadowDecl * GetAsUsingShadowDecl() const
int MaxIndex(int dim) const
TClingClassInfo * fClassInfo
TClingDataMemberInfo(cling::Interpreter *interp)
union TClingDataMemberInfo::@29 fConstInitVal
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)
Definition: TDictionary.h:219
EMemberSelection
Kinds of members to include in lists.
Definition: TDictionary.h:214
static bool WantsUsingDecls(EMemberSelection sel)
Definition: TDictionary.h:220
const void * DeclId_t
Definition: TDictionary.h:222
RooCmdArg Layout(Double_t xmin, Double_t xmax=0.99, Double_t ymin=0.95)
Type
enumeration specifying the integration types.
static double C[]
static const std::string separator("@@@")
llvm::StringRef DataMemberInfo__ValidArrayIndex(const clang::DeclaratorDecl &m, int *errnum=0, llvm::StringRef *errstr=0)
ValidArrayIndex return a static string (so use it or copy it immediatly, do not call GrabIndex twice ...
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)
bool ExtractAttrPropertyFromName(const clang::Decl &decl, const std::string &propName, std::string &propValue)
This routine counts on the "propName<separator>propValue" format.
llvm::StringRef GetComment(const clang::Decl &decl, clang::SourceLocation *loc=0)
Returns the comment (// striped away), annotating declaration in a meaningful for ROOT IO way.
double Var(const RVec< T > &v)
Get the variance of the elements of an RVec.
Definition: RVec.hxx:862
static constexpr double L
Definition: TString.h:845
const char * Float
const char * Int
const char * cnt
Definition: TXMLSetup.cxx:74
auto * tt
Definition: textangle.C:16