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 "TClingTypeInfo.h"
27#include "TClingUtils.h"
28#include "TClassEdit.h"
29#include "TError.h"
30
31#include "clang/AST/Attr.h"
32#include "clang/AST/ASTContext.h"
33#include "clang/AST/Decl.h"
34#include "clang/AST/GlobalDecl.h"
35#include "clang/AST/Expr.h"
36#include "clang/AST/ExprCXX.h"
37#include "clang/AST/PrettyPrinter.h"
38#include "clang/AST/RecordLayout.h"
39#include "clang/AST/Type.h"
40
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/raw_ostream.h"
43#include "llvm/ADT/APSInt.h"
44#include "llvm/ADT/APFloat.h"
45
46using namespace clang;
47
50: TClingDeclInfo(nullptr), fInterp(interp), fClassInfo(0), fFirstTime(true), fTitle(""), fContextIdx(0U), fIoType(""), fIoName("")
51{
52 if (!ci) {
53 // We are meant to iterate over the global namespace (well at least CINT did).
54 fClassInfo = new TClingClassInfo(interp);
55 } else {
56 fClassInfo = new TClingClassInfo(*ci);
57 }
58 if (fClassInfo->IsValid()) {
59 Decl *D = const_cast<Decl*>(fClassInfo->GetDecl());
60
61 clang::DeclContext *dc = llvm::cast<clang::DeclContext>(D);
62 dc->collectAllContexts(fContexts);
63
64 // Could trigger deserialization of decls.
65 cling::Interpreter::PushTransactionRAII RAII(interp);
66 fIter = llvm::cast<clang::DeclContext>(D)->decls_begin();
67 const TagDecl *TD = ROOT::TMetaUtils::GetAnnotatedRedeclarable(llvm::dyn_cast<TagDecl>(D));
68 if (TD)
69 fIter = TD->decls_begin();
70
71 // Move to first data member.
73 fFirstTime = true;
74 }
75
76}
77
79 const clang::ValueDecl *ValD,
81: TClingDeclInfo(ValD), fInterp(interp), fClassInfo(ci ? new TClingClassInfo(*ci) : new TClingClassInfo(interp, ValD)), fFirstTime(true),
82 fTitle(""), fContextIdx(0U), fIoType(""), fIoName(""){
83
84 using namespace llvm;
85 const auto DC = ValD->getDeclContext();
86 (void)DC;
87 assert((ci || isa<TranslationUnitDecl>(DC) ||
88 ((DC->isTransparentContext() || DC->isInlineNamespace()) && isa<TranslationUnitDecl>(DC->getParent()) ) ||
89 isa<EnumConstantDecl>(ValD)) && "Not TU?");
90 assert((isa<VarDecl>(ValD) ||
91 isa<FieldDecl>(ValD) ||
92 isa<EnumConstantDecl>(ValD) ||
93 isa<IndirectFieldDecl>(ValD)) &&
94 "The decl should be either VarDecl or FieldDecl or EnumConstDecl");
95
96}
97
99{
100 // Three cases:
101 // 1) 00: none to be checked
102 // 2) 01: type to be checked
103 // 3) 10: none to be checked
104 // 4) 11: both to be checked
105 unsigned int code = fIoType.empty() + (int(fIoName.empty()) << 1);
106
107 if (code == 0) return;
108
109 const Decl* decl = GetDecl();
110
111 if (code == 3 || code == 2) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,"ioname",fIoName);
112 if (code == 3 || code == 1) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,"iotype",fIoType);
113
114}
115
117{
118 if (!IsValid()) {
119 return TDictionary::DeclId_t();
120 }
121 return (const clang::Decl*)(GetDecl()->getCanonicalDecl());
122}
123
125{
126 if (!IsValid()) {
127 return -1;
128 }
129 // Sanity check the current data member.
130 clang::Decl::Kind DK = GetDecl()->getKind();
131 if (
132 (DK != clang::Decl::Field) &&
133 (DK != clang::Decl::Var) &&
134 (DK != clang::Decl::EnumConstant)
135 ) {
136 // Error, was not a data member, variable, or enumerator.
137 return -1;
138 }
139 if (DK == clang::Decl::EnumConstant) {
140 // We know that an enumerator value does not have array type.
141 return 0;
142 }
143 // To get this information we must count the number
144 // of array type nodes in the canonical type chain.
145 const clang::ValueDecl *VD = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
146 clang::QualType QT = VD->getType().getCanonicalType();
147 int cnt = 0;
148 while (1) {
149 if (QT->isArrayType()) {
150 ++cnt;
151 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
152 continue;
153 }
154 else if (QT->isReferenceType()) {
155 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
156 continue;
157 }
158 else if (QT->isPointerType()) {
159 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
160 continue;
161 }
162 else if (QT->isMemberPointerType()) {
163 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
164 continue;
165 }
166 break;
167 }
168 return cnt;
169}
170
172{
173 if (!IsValid()) {
174 return -1;
175 }
176 // Sanity check the current data member.
177 clang::Decl::Kind DK = GetDecl()->getKind();
178 if (
179 (DK != clang::Decl::Field) &&
180 (DK != clang::Decl::Var) &&
181 (DK != clang::Decl::EnumConstant)
182 ) {
183 // Error, was not a data member, variable, or enumerator.
184 return -1;
185 }
186 if (DK == clang::Decl::EnumConstant) {
187 // We know that an enumerator value does not have array type.
188 return 0;
189 }
190 // To get this information we must count the number
191 // of array type nodes in the canonical type chain.
192 const clang::ValueDecl *VD = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
193 clang::QualType QT = VD->getType().getCanonicalType();
194 int paran = ArrayDim();
195 if ((dim < 0) || (dim >= paran)) {
196 // Passed dimension is out of bounds.
197 return -1;
198 }
199 int cnt = dim;
200 int max = 0;
201 while (1) {
202 if (QT->isArrayType()) {
203 if (cnt == 0) {
204 if (const clang::ConstantArrayType *CAT =
205 llvm::dyn_cast<clang::ConstantArrayType>(QT)
206 ) {
207 max = static_cast<int>(CAT->getSize().getZExtValue());
208 }
209 else if (llvm::dyn_cast<clang::IncompleteArrayType>(QT)) {
210 max = INT_MAX;
211 }
212 else {
213 max = -1;
214 }
215 break;
216 }
217 --cnt;
218 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
219 continue;
220 }
221 else if (QT->isReferenceType()) {
222 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
223 continue;
224 }
225 else if (QT->isPointerType()) {
226 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
227 continue;
228 }
229 else if (QT->isMemberPointerType()) {
230 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
231 continue;
232 }
233 break;
234 }
235 return max;
236}
237
239{
240 assert(!fDecl
241 && "This is a single decl, not an iterator!");
242
243 fNameCache.clear(); // invalidate the cache.
244 bool increment = true;
245 // Move to next acceptable data member.
246 while (fFirstTime || *fIter) {
247 // Move to next decl in context.
248 if (fFirstTime) {
249 fFirstTime = false;
250 }
251 else if (increment) {
252 ++fIter;
253 } else {
254 increment = true;
255 }
256
257 // Handle reaching end of current decl context.
258 if (!*fIter) {
259 if (fIterStack.size()) {
260 // End of current decl context, and we have more to go.
261 fIter = fIterStack.back();
262 fIterStack.pop_back();
263 continue;
264 }
265 while (!*fIter) {
266 // Check the next decl context (of namespace)
267 ++fContextIdx;
268 if (fContextIdx >= fContexts.size()) {
269 // Iterator is now invalid.
270 return 0;
271 }
272 clang::DeclContext *dc = fContexts[fContextIdx];
273 // Could trigger deserialization of decls.
274 cling::Interpreter::PushTransactionRAII RAII(fInterp);
275 fIter = dc->decls_begin();
276 if (*fIter) {
277 // Good, a non-empty context.
278 break;
279 }
280 }
281 }
282
283 // Valid decl, recurse into it, accept it, or reject it.
284 clang::Decl::Kind DK = fIter->getKind();
285 if (DK == clang::Decl::Enum) {
286 // We have an enum, recurse into these.
287 // Note: For C++11 we will have to check for a transparent context.
288 fIterStack.push_back(fIter);
289 cling::Interpreter::PushTransactionRAII RAII(fInterp);
290 fIter = llvm::dyn_cast<clang::DeclContext>(*fIter)->decls_begin();
291 increment = false; // avoid the next incrementation
292 continue;
293 }
294 if ((DK == clang::Decl::Field) || (DK == clang::Decl::EnumConstant) ||
295 (DK == clang::Decl::Var)) {
296 // Stop on class data members, enumerator values,
297 // and namespace variable members.
298 return 1;
299 }
300 // Collect internal `__cling_N5xxx' inline namespaces; they will be traversed later
301 if (auto NS = dyn_cast<NamespaceDecl>(*fIter)) {
302 if (NS->getDeclContext()->isTranslationUnit() && NS->isInlineNamespace())
303 fContexts.push_back(NS);
304 }
305 }
306 return 0;
307}
308
310{
311 using namespace clang;
312
313 if (!IsValid()) {
314 return -1L;
315 }
316
317 const Decl *D = GetDecl();
318 ASTContext& C = D->getASTContext();
319 if (const FieldDecl *FldD = dyn_cast<FieldDecl>(D)) {
320 // The current member is a non-static data member.
321 const clang::RecordDecl *RD = FldD->getParent();
322 const clang::ASTRecordLayout &Layout = C.getASTRecordLayout(RD);
323 uint64_t bits = Layout.getFieldOffset(FldD->getFieldIndex());
324 int64_t offset = C.toCharUnitsFromBits(bits).getQuantity();
325 return static_cast<long>(offset);
326 }
327 else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
328 // Could trigger deserialization of decls, in particular in case
329 // of constexpr, like:
330 // static constexpr Long64_t something = std::numeric_limits<Long64_t>::max();
331 cling::Interpreter::PushTransactionRAII RAII(fInterp);
332
333 if (long addr = reinterpret_cast<long>(fInterp->getAddressOfGlobal(GlobalDecl(VD))))
334 return addr;
335 auto evalStmt = VD->ensureEvaluatedStmt();
336 if (evalStmt && evalStmt->Value) {
337 if (const APValue* val = VD->evaluateValue()) {
338 if (VD->getType()->isIntegralType(C)) {
339 return reinterpret_cast<long>(val->getInt().getRawData());
340 } else {
341 // The VD stores the init value; its lifetime should the lifetime of
342 // this offset.
343 switch (val->getKind()) {
344 case APValue::Int: {
345 if (val->getInt().isSigned())
346 fConstInitVal.fLong = (long)val->getInt().getSExtValue();
347 else
348 fConstInitVal.fLong = (long)val->getInt().getZExtValue();
349 return (long) &fConstInitVal.fLong;
350 }
351 case APValue::Float:
352 if (&val->getFloat().getSemantics()
353 == (const llvm::fltSemantics*)&llvm::APFloat::IEEEsingle()) {
354 fConstInitVal.fFloat = val->getFloat().convertToFloat();
355 return (long)&fConstInitVal.fFloat;
356 } else if (&val->getFloat().getSemantics()
357 == (const llvm::fltSemantics*) &llvm::APFloat::IEEEdouble()) {
358 fConstInitVal.fDouble = val->getFloat().convertToDouble();
359 return (long)&fConstInitVal.fDouble;
360 }
361 // else fall-through
362 default:
363 ;// fall-through
364 };
365 // fall-through
366 } // not integral type
367 } // have an APValue
368 } // have an initializing value
369 }
370 // FIXME: We have to explicitly check for not enum constant because the
371 // implementation of getAddressOfGlobal relies on mangling the name and in
372 // clang there is misbehaviour in MangleContext::shouldMangleDeclName.
373 // enum constants are essentially numbers and don't get addresses. However
374 // ROOT expects the address to the enum constant initializer to be returned.
375 else if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
376 // The raw data is stored as a long long, so we need to find the 'long'
377 // part.
378#ifdef R__BYTESWAP
379 // In this case at the beginning.
380 return reinterpret_cast<long>(ECD->getInitVal().getRawData());
381#else
382 // In this case in the second part.
383 return reinterpret_cast<long>(((char*)ECD->getInitVal().getRawData())+sizeof(long) );
384#endif
385 return -1L;
386}
387
389{
390 if (!IsValid()) {
391 return 0L;
392 }
393 long property = 0L;
394 const clang::Decl *declaccess = GetDecl();
395 if (declaccess->getDeclContext()->isTransparentContext()) {
396 declaccess = llvm::dyn_cast<clang::Decl>(declaccess->getDeclContext());
397 if (!declaccess) declaccess = GetDecl();
398 }
399 switch (declaccess->getAccess()) {
400 case clang::AS_public:
401 property |= kIsPublic;
402 break;
403 case clang::AS_protected:
404 property |= kIsProtected;
405 break;
406 case clang::AS_private:
407 property |= kIsPrivate;
408 break;
409 case clang::AS_none:
410 if (declaccess->getDeclContext()->isNamespace()) {
411 property |= kIsPublic;
412 } else {
413 // IMPOSSIBLE
414 }
415 break;
416 default:
417 // IMPOSSIBLE
418 break;
419 }
420 if (const clang::VarDecl *vard = llvm::dyn_cast<clang::VarDecl>(GetDecl())) {
421 if (vard->isConstexpr())
422 property |= kIsConstexpr;
423 if (vard->getStorageClass() == clang::SC_Static) {
424 property |= kIsStatic;
425 } else if (declaccess->getDeclContext()->isNamespace()) {
426 // Data members of a namespace are global variable which were
427 // considered to be 'static' in the CINT (and thus ROOT) scheme.
428 property |= kIsStatic;
429 }
430 }
431 if (llvm::isa<clang::EnumConstantDecl>(GetDecl())) {
432 // Enumeration constant are considered to be 'static' data member in
433 // the CINT (and thus ROOT) scheme.
434 property |= kIsStatic;
435 }
436 const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
437 clang::QualType qt = vd->getType();
438 if (llvm::isa<clang::TypedefType>(qt)) {
439 property |= kIsTypedef;
440 }
441 qt = qt.getCanonicalType();
442 if (qt.isConstQualified()) {
443 property |= kIsConstant;
444 }
445 while (1) {
446 if (qt->isArrayType()) {
447 property |= kIsArray;
448 qt = llvm::cast<clang::ArrayType>(qt)->getElementType();
449 continue;
450 }
451 else if (qt->isReferenceType()) {
452 property |= kIsReference;
453 qt = llvm::cast<clang::ReferenceType>(qt)->getPointeeType();
454 continue;
455 }
456 else if (qt->isPointerType()) {
457 property |= kIsPointer;
458 if (qt.isConstQualified()) {
459 property |= kIsConstPointer;
460 }
461 qt = llvm::cast<clang::PointerType>(qt)->getPointeeType();
462 continue;
463 }
464 else if (qt->isMemberPointerType()) {
465 qt = llvm::cast<clang::MemberPointerType>(qt)->getPointeeType();
466 continue;
467 }
468 break;
469 }
470 if (qt->isBuiltinType()) {
471 property |= kIsFundamental;
472 }
473 if (qt.isConstQualified()) {
474 property |= kIsConstant;
475 }
476 const clang::TagType *tt = qt->getAs<clang::TagType>();
477 if (tt) {
478 const clang::TagDecl *td = tt->getDecl();
479 if (td->isClass()) {
480 property |= kIsClass;
481 }
482 else if (td->isStruct()) {
483 property |= kIsStruct;
484 }
485 else if (td->isUnion()) {
486 property |= kIsUnion;
487 }
488 else if (td->isEnum()) {
489 property |= kIsEnum;
490 }
491 }
492 // We can't be a namespace, can we?
493 // if (dc->isNamespace() && !dc->isTranslationUnit()) {
494 // property |= kIsNamespace;
495 // }
496 return property;
497}
498
500{
501 if (!IsValid()) {
502 return 0L;
503 }
504 const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
505 clang::QualType qt = vd->getType();
506 return TClingTypeInfo(fInterp, qt).Property();
507}
508
510{
511 if (!IsValid()) {
512 return -1;
513 }
514
515 // Sanity check the current data member.
516 clang::Decl::Kind dk = GetDecl()->getKind();
517 if ((dk != clang::Decl::Field) && (dk != clang::Decl::Var) &&
518 (dk != clang::Decl::EnumConstant)) {
519 // Error, was not a data member, variable, or enumerator.
520 return -1;
521 }
522 const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
523 clang::QualType qt = vd->getType();
524 if (qt->isIncompleteType()) {
525 // We cannot determine the size of forward-declared types.
526 return -1;
527 }
528 clang::ASTContext &context = GetDecl()->getASTContext();
529 // Truncate cast to fit to cint interface.
530 return static_cast<int>(context.getTypeSizeInChars(qt).getQuantity());
531}
532
534{
535 if (!IsValid()) {
536 return 0;
537 }
538
540 if (!fIoType.empty()) return fIoType.c_str();
541
542 // Note: This must be static because we return a pointer inside it!
543 static std::string buf;
544 buf.clear();
545 if (const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl())) {
546 clang::QualType vdType = vd->getType();
547 // In CINT's version, the type name returns did *not* include any array
548 // information, ROOT's existing code depends on it.
549 while (vdType->isArrayType()) {
550 vdType = GetDecl()->getASTContext().getQualifiedType(vdType->getBaseElementTypeUnsafe(),vdType.getQualifiers());
551 }
552
553 // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
554 vdType = ROOT::TMetaUtils::ReSubstTemplateArg(vdType, fClassInfo->GetType() );
555
556 ROOT::TMetaUtils::GetFullyQualifiedTypeName(buf, vdType, *fInterp);
557
558 return buf.c_str();
559 }
560 return 0;
561}
562
563const char *TClingDataMemberInfo::TypeTrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
564{
565 if (!IsValid()) {
566 return 0;
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 if (const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl())) {
576 // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
577 clang::QualType vdType = ROOT::TMetaUtils::ReSubstTemplateArg(vd->getType(), fClassInfo->GetType());
578
579 ROOT::TMetaUtils::GetNormalizedName(buf, vdType, *fInterp, normCtxt);
580
581 // In CINT's version, the type name returns did *not* include any array
582 // information, ROOT's existing code depends on it.
583 // This might become part of the implementation of GetNormalizedName.
584 while (buf.length() && buf[buf.length()-1] == ']') {
585 size_t last = buf.rfind('['); // if this is not the bracket we are looking, the type is malformed.
586 if (last != std::string::npos) {
587 buf.erase(last);
588 }
589 }
590 return buf.c_str();
591 }
592 return 0;
593}
594
596{
597 if (!IsValid()) {
598 return 0;
599 }
600
602 if (!fIoName.empty()) return fIoName.c_str();
603
604 return TClingDeclInfo::Name();
605}
606
608{
609 if (!IsValid()) {
610 return 0;
611 }
612
613 //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
614 //if (fTitle.size())
615 // return fTitle.c_str();
616
617 bool titleFound=false;
618 // Try to get the comment either from the annotation or the header file if present
619 std::string attribute_s;
620 const Decl* decl = GetDecl();
621 for (Decl::attr_iterator attrIt = decl->attr_begin();
622 attrIt!=decl->attr_end() && !titleFound ;++attrIt){
623 if (0 == ROOT::TMetaUtils::extractAttrString(*attrIt, attribute_s) &&
624 attribute_s.find(ROOT::TMetaUtils::propNames::separator) == std::string::npos){
625 fTitle = attribute_s;
626 titleFound=true;
627 }
628 }
629
630 if (!titleFound && !GetDecl()->isFromASTFile()) {
631 // Try to get the comment from the header file if present
632 // but not for decls from AST file, where rootcling would have
633 // created an annotation
634 fTitle = ROOT::TMetaUtils::GetComment(*GetDecl()).str();
635 }
636
637 return fTitle.c_str();
638}
639
640// ValidArrayIndex return a static string (so use it or copy it immediately, do not
641// call GrabIndex twice in the same expression) containing the size of the
642// array data member.
644{
645 if (!IsValid()) {
646 return llvm::StringRef();
647 }
648 const clang::DeclaratorDecl *FD = llvm::dyn_cast<clang::DeclaratorDecl>(GetDecl());
649 if (FD) return ROOT::TMetaUtils::DataMemberInfo__ValidArrayIndex(*FD);
650 else return llvm::StringRef();
651}
652
@ kIsPublic
Definition: TDictionary.h:74
@ kIsConstexpr
Definition: TDictionary.h:90
@ kIsPointer
Definition: TDictionary.h:77
@ kIsConstant
Definition: TDictionary.h:86
@ kIsClass
Definition: TDictionary.h:65
@ kIsReference
Definition: TDictionary.h:81
@ kIsEnum
Definition: TDictionary.h:68
@ kIsPrivate
Definition: TDictionary.h:76
@ kIsConstPointer
Definition: TDictionary.h:88
@ kIsFundamental
Definition: TDictionary.h:70
@ kIsArray
Definition: TDictionary.h:78
@ kIsStatic
Definition: TDictionary.h:79
@ kIsStruct
Definition: TDictionary.h:66
@ kIsProtected
Definition: TDictionary.h:75
@ kIsUnion
Definition: TDictionary.h:67
@ kIsTypedef
Definition: TDictionary.h:69
typedef void((*Func_t)())
Emulation of the CINT ClassInfo class.
const clang::Type * GetType() const
const char * TypeName() const
clang::DeclContext::decl_iterator fIter
const clang::Decl * GetDecl() const override
union TClingDataMemberInfo::@26 fConstInitVal
const char * TypeTrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
const char * Name() override
int MaxIndex(int dim) const
TClingClassInfo * fClassInfo
std::vector< clang::DeclContext::decl_iterator > fIterStack
TClingDataMemberInfo(cling::Interpreter *interp)
cling::Interpreter * fInterp
llvm::SmallVector< clang::DeclContext *, 2 > fContexts
llvm::StringRef ValidArrayIndex() const
const clang::Decl * fDecl
virtual const char * Name()
virtual bool IsValid() const
std::string fNameCache
virtual const clang::Decl * GetDecl() const
Emulation of the CINT TypeInfo class.
long Property() const
const void * DeclId_t
Definition: TDictionary.h:209
static double C[]
double Var(const RVec< T > &v)
Get the variance of the elements of an RVec.
Definition: RVec.hxx:861
RooCmdArg Layout(Double_t xmin, Double_t xmax=0.99, Double_t ymin=0.95)
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
Definition: TClassEdit.cxx:832
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