Logo ROOT   master
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 
14 Emulation of the CINT DataMemberInfo class.
15 
16 The CINT C++ interpreter provides an interface to metadata about
17 the data members of a class through the DataMemberInfo class. This
18 class provides the same functionality, using an interface as close
19 as possible to DataMemberInfo but the data member metadata comes
20 from the Clang C++ compiler, not CINT.
21 */
22 
23 #include "TClingDataMemberInfo.h"
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 
46 using namespace clang;
47 
48 TClingDataMemberInfo::TClingDataMemberInfo(cling::Interpreter *interp,
49  TClingClassInfo *ci)
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.
72  InternalNext();
73  fFirstTime = true;
74  }
75 
76 }
77 
78 TClingDataMemberInfo::TClingDataMemberInfo(cling::Interpreter *interp,
79  const clang::ValueDecl *ValD,
80  TClingClassInfo *ci)
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)
555 
557 
558  return buf.c_str();
559  }
560  return 0;
561 }
562 
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
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());
650  else return llvm::StringRef();
651 }
652 
auto * tt
Definition: textangle.C:16
Definition: TString.h:845
const char * Int
const char * TypeName() const
llvm::StringRef ValidArrayIndex() const
union TClingDataMemberInfo::@26 fConstInitVal
Kind
Chebychev polynomials of first or second kind.
TClingDataMemberInfo(cling::Interpreter *interp)
clang::QualType ReSubstTemplateArg(clang::QualType input, const clang::Type *instance)
Check if &#39;input&#39; or any of its template parameter was substituted when instantiating the class templa...
const char * Name() override
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 ...
virtual bool IsValid() const
void GetFullyQualifiedTypeName(std::string &name, const clang::QualType &type, const cling::Interpreter &interpreter)
double Var(const RVec< T > &v)
Get the variance of the elements of an RVec.
Definition: RVec.hxx:861
clang::DeclContext::decl_iterator fIter
const void * DeclId_t
Definition: TDictionary.h:209
const char * TypeTrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
bool ExtractAttrPropertyFromName(const clang::Decl &decl, const std::string &propName, std::string &propValue)
This routine counts on the "propName<separator>propValue" format.
int extractAttrString(clang::Attr *attribute, std::string &attrString)
Extract attr string.
RooCmdArg Layout(Double_t xmin, Double_t xmax=0.99, Double_t ymin=0.95)
const clang::Decl * GetDecl() const override
virtual const char * Name()
static const std::string separator("@@@")
int MaxIndex(int dim) const
std::vector< clang::DeclContext::decl_iterator > fIterStack
Emulation of the CINT TypeInfo class.
const char * Float
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, etc.) and adding default template argument for all types except the STL collections where we remove the default template argument if any.
static double C[]
llvm::SmallVector< clang::DeclContext *, 2 > fContexts
const T * GetAnnotatedRedeclarable(const T *Redecl)
Definition: TClingUtils.h:634
cling::Interpreter * fInterp
virtual const clang::Decl * GetDecl() const
static constexpr double L
long Property() const
Emulation of the CINT ClassInfo class.
TClingClassInfo * fClassInfo
const clang::Decl * fDecl
typedef void((*Func_t)())
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...
std::string fNameCache
const char * cnt
Definition: TXMLSetup.cxx:74
const clang::Type * GetType() const