Logo ROOT   6.08/07
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 "TMetaUtils.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 : fInterp(interp), fClassInfo(0), fFirstTime(true), fTitle(""), fSingleDecl(0), 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 : fInterp(interp), fClassInfo(ci ? new TClingClassInfo(*ci) : new TClingClassInfo(interp)), fFirstTime(true),
82  fTitle(""), fSingleDecl(ValD), fContextIdx(0U), fIoType(""), fIoName(""){
83 
84  using namespace llvm;
85  assert((ci || isa<TranslationUnitDecl>(ValD->getDeclContext()) ||
86  (ValD->getDeclContext()->isTransparentContext() && isa<TranslationUnitDecl>(ValD->getDeclContext()->getParent()) ) ||
87  isa<EnumConstantDecl>(ValD)) && "Not TU?");
88  assert((isa<VarDecl>(ValD) ||
89  isa<FieldDecl>(ValD) ||
90  isa<EnumConstantDecl>(ValD) ||
91  isa<IndirectFieldDecl>(ValD)) &&
92  "The decl should be either VarDecl or FieldDecl or EnumConstDecl");
93 
94 }
95 
97 {
98  // Three cases:
99  // 1) 00: none to be checked
100  // 2) 01: type to be checked
101  // 3) 10: none to be checked
102  // 4) 11: both to be checked
103  unsigned int code = fIoType.empty() + (int(fIoName.empty()) << 1);
104 
105  if (code == 0) return;
106 
107  const Decl* decl = GetDecl();
108 
109  if (code == 3 || code == 2) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,"ioname",fIoName);
110  if (code == 3 || code == 1) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,"iotype",fIoType);
111 
112 }
113 
115 {
116  if (!IsValid()) {
117  return TDictionary::DeclId_t();
118  }
119  return (const clang::Decl*)(GetDecl()->getCanonicalDecl());
120 }
121 
123 {
124  if (!IsValid()) {
125  return -1;
126  }
127  // Sanity check the current data member.
128  clang::Decl::Kind DK = GetDecl()->getKind();
129  if (
130  (DK != clang::Decl::Field) &&
131  (DK != clang::Decl::Var) &&
132  (DK != clang::Decl::EnumConstant)
133  ) {
134  // Error, was not a data member, variable, or enumerator.
135  return -1;
136  }
137  if (DK == clang::Decl::EnumConstant) {
138  // We know that an enumerator value does not have array type.
139  return 0;
140  }
141  // To get this information we must count the number
142  // of array type nodes in the canonical type chain.
143  const clang::ValueDecl *VD = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
144  clang::QualType QT = VD->getType().getCanonicalType();
145  int cnt = 0;
146  while (1) {
147  if (QT->isArrayType()) {
148  ++cnt;
149  QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
150  continue;
151  }
152  else if (QT->isReferenceType()) {
153  QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
154  continue;
155  }
156  else if (QT->isPointerType()) {
157  QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
158  continue;
159  }
160  else if (QT->isMemberPointerType()) {
161  QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
162  continue;
163  }
164  break;
165  }
166  return cnt;
167 }
168 
170 {
171  if (!IsValid()) {
172  return -1;
173  }
174  // Sanity check the current data member.
175  clang::Decl::Kind DK = GetDecl()->getKind();
176  if (
177  (DK != clang::Decl::Field) &&
178  (DK != clang::Decl::Var) &&
179  (DK != clang::Decl::EnumConstant)
180  ) {
181  // Error, was not a data member, variable, or enumerator.
182  return -1;
183  }
184  if (DK == clang::Decl::EnumConstant) {
185  // We know that an enumerator value does not have array type.
186  return 0;
187  }
188  // To get this information we must count the number
189  // of array type nodes in the canonical type chain.
190  const clang::ValueDecl *VD = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
191  clang::QualType QT = VD->getType().getCanonicalType();
192  int paran = ArrayDim();
193  if ((dim < 0) || (dim >= paran)) {
194  // Passed dimension is out of bounds.
195  return -1;
196  }
197  int cnt = dim;
198  int max = 0;
199  while (1) {
200  if (QT->isArrayType()) {
201  if (cnt == 0) {
202  if (const clang::ConstantArrayType *CAT =
203  llvm::dyn_cast<clang::ConstantArrayType>(QT)
204  ) {
205  max = static_cast<int>(CAT->getSize().getZExtValue());
206  }
207  else if (llvm::dyn_cast<clang::IncompleteArrayType>(QT)) {
208  max = INT_MAX;
209  }
210  else {
211  max = -1;
212  }
213  break;
214  }
215  --cnt;
216  QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
217  continue;
218  }
219  else if (QT->isReferenceType()) {
220  QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
221  continue;
222  }
223  else if (QT->isPointerType()) {
224  QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
225  continue;
226  }
227  else if (QT->isMemberPointerType()) {
228  QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
229  continue;
230  }
231  break;
232  }
233  return max;
234 }
235 
237 {
238  assert(!fSingleDecl && "This is not an iterator!");
239 
240  bool increment = true;
241  // Move to next acceptable data member.
242  while (fFirstTime || *fIter) {
243  // Move to next decl in context.
244  if (fFirstTime) {
245  fFirstTime = false;
246  }
247  else if (increment) {
248  ++fIter;
249  } else {
250  increment = true;
251  }
252 
253  // Handle reaching end of current decl context.
254  if (!*fIter) {
255  if (fIterStack.size()) {
256  // End of current decl context, and we have more to go.
257  fIter = fIterStack.back();
258  fIterStack.pop_back();
259  continue;
260  }
261  while (!*fIter) {
262  // Check the next decl context (of namespace)
263  ++fContextIdx;
264  if (fContextIdx >= fContexts.size()) {
265  // Iterator is now invalid.
266  return 0;
267  }
268  clang::DeclContext *dc = fContexts[fContextIdx];
269  // Could trigger deserialization of decls.
270  cling::Interpreter::PushTransactionRAII RAII(fInterp);
271  fIter = dc->decls_begin();
272  if (*fIter) {
273  // Good, a non-empty context.
274  break;
275  }
276  }
277  }
278 
279  // Valid decl, recurse into it, accept it, or reject it.
280  clang::Decl::Kind DK = fIter->getKind();
281  if (DK == clang::Decl::Enum) {
282  // We have an enum, recurse into these.
283  // Note: For C++11 we will have to check for a transparent context.
284  fIterStack.push_back(fIter);
285  cling::Interpreter::PushTransactionRAII RAII(fInterp);
286  fIter = llvm::dyn_cast<clang::DeclContext>(*fIter)->decls_begin();
287  increment = false; // avoid the next incrementation
288  continue;
289  }
290  if ((DK == clang::Decl::Field) || (DK == clang::Decl::EnumConstant) ||
291  (DK == clang::Decl::Var)) {
292  // Stop on class data members, enumerator values,
293  // and namespace variable members.
294  return 1;
295  }
296  }
297  return 0;
298 }
299 
301 {
302  using namespace clang;
303 
304  if (!IsValid()) {
305  return -1L;
306  }
307 
308  const Decl *D = GetDecl();
309  ASTContext& C = D->getASTContext();
310  if (const FieldDecl *FldD = dyn_cast<FieldDecl>(D)) {
311  // The current member is a non-static data member.
312  const clang::RecordDecl *RD = FldD->getParent();
313  const clang::ASTRecordLayout &Layout = C.getASTRecordLayout(RD);
314  uint64_t bits = Layout.getFieldOffset(FldD->getFieldIndex());
315  int64_t offset = C.toCharUnitsFromBits(bits).getQuantity();
316  return static_cast<long>(offset);
317  }
318  else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
319  // Could trigger deserialization of decls, in particular in case
320  // of constexpr, like:
321  // static constexpr Long64_t something = std::numeric_limits<Long64_t>::max();
322  cling::Interpreter::PushTransactionRAII RAII(fInterp);
323 
324  if (long addr = reinterpret_cast<long>(fInterp->getAddressOfGlobal(GlobalDecl(VD))))
325  return addr;
326  auto evalStmt = VD->ensureEvaluatedStmt();
327  if (evalStmt && evalStmt->Value) {
328  if (const APValue* val = VD->evaluateValue()) {
329  if (VD->getType()->isIntegralType(C)) {
330  return reinterpret_cast<long>(val->getInt().getRawData());
331  } else {
332  // The VD stores the init value; its lifetime should the lifetime of
333  // this offset.
334  switch (val->getKind()) {
335  case APValue::Int: {
336  if (val->getInt().isSigned())
337  fConstInitVal.fLong = (long)val->getInt().getSExtValue();
338  else
339  fConstInitVal.fLong = (long)val->getInt().getZExtValue();
340  return (long) &fConstInitVal.fLong;
341  }
342  case APValue::Float:
343  if (&val->getFloat().getSemantics()
344  == &llvm::APFloat::IEEEsingle) {
345  fConstInitVal.fFloat = val->getFloat().convertToFloat();
346  return (long)&fConstInitVal.fFloat;
347  } else if (&val->getFloat().getSemantics()
348  == &llvm::APFloat::IEEEdouble) {
349  fConstInitVal.fDouble = val->getFloat().convertToDouble();
350  return (long)&fConstInitVal.fDouble;
351  }
352  // else fall-through
353  default:
354  ;// fall-through
355  };
356  // fall-through
357  } // not integral type
358  } // have an APValue
359  } // have an initializing value
360  }
361  // FIXME: We have to explicitly check for not enum constant because the
362  // implementation of getAddressOfGlobal relies on mangling the name and in
363  // clang there is misbehaviour in MangleContext::shouldMangleDeclName.
364  // enum constants are essentially numbers and don't get addresses. However
365  // ROOT expects the address to the enum constant initializer to be returned.
366  else if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
367  // The raw data is stored as a long long, so we need to find the 'long'
368  // part.
369 #ifdef R__BYTESWAP
370  // In this case at the beginning.
371  return reinterpret_cast<long>(ECD->getInitVal().getRawData());
372 #else
373  // In this case in the second part.
374  return reinterpret_cast<long>(((char*)ECD->getInitVal().getRawData())+sizeof(long) );
375 #endif
376  return -1L;
377 }
378 
380 {
381  if (!IsValid()) {
382  return 0L;
383  }
384  long property = 0L;
385  const clang::Decl *declaccess = GetDecl();
386  if (declaccess->getDeclContext()->isTransparentContext()) {
387  declaccess = llvm::dyn_cast<clang::Decl>(declaccess->getDeclContext());
388  if (!declaccess) declaccess = GetDecl();
389  }
390  switch (declaccess->getAccess()) {
391  case clang::AS_public:
392  property |= kIsPublic;
393  break;
394  case clang::AS_protected:
395  property |= kIsProtected;
396  break;
397  case clang::AS_private:
398  property |= kIsPrivate;
399  break;
400  case clang::AS_none:
401  if (declaccess->getDeclContext()->isNamespace()) {
402  property |= kIsPublic;
403  } else {
404  // IMPOSSIBLE
405  }
406  break;
407  default:
408  // IMPOSSIBLE
409  break;
410  }
411  if (const clang::VarDecl *vard = llvm::dyn_cast<clang::VarDecl>(GetDecl())) {
412  if (vard->getStorageClass() == clang::SC_Static) {
413  property |= kIsStatic;
414  } else if (declaccess->getDeclContext()->isNamespace()) {
415  // Data members of a namespace are global variable which were
416  // considered to be 'static' in the CINT (and thus ROOT) scheme.
417  property |= kIsStatic;
418  }
419  }
420  if (llvm::isa<clang::EnumConstantDecl>(GetDecl())) {
421  // Enumeration constant are considered to be 'static' data member in
422  // the CINT (and thus ROOT) scheme.
423  property |= kIsStatic;
424  }
425  const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
426  clang::QualType qt = vd->getType();
427  if (llvm::isa<clang::TypedefType>(qt)) {
428  property |= kIsTypedef;
429  }
430  qt = qt.getCanonicalType();
431  if (qt.isConstQualified()) {
432  property |= kIsConstant;
433  }
434  while (1) {
435  if (qt->isArrayType()) {
436  property |= kIsArray;
437  qt = llvm::cast<clang::ArrayType>(qt)->getElementType();
438  continue;
439  }
440  else if (qt->isReferenceType()) {
441  property |= kIsReference;
442  qt = llvm::cast<clang::ReferenceType>(qt)->getPointeeType();
443  continue;
444  }
445  else if (qt->isPointerType()) {
446  property |= kIsPointer;
447  if (qt.isConstQualified()) {
448  property |= kIsConstPointer;
449  }
450  qt = llvm::cast<clang::PointerType>(qt)->getPointeeType();
451  continue;
452  }
453  else if (qt->isMemberPointerType()) {
454  qt = llvm::cast<clang::MemberPointerType>(qt)->getPointeeType();
455  continue;
456  }
457  break;
458  }
459  if (qt->isBuiltinType()) {
460  property |= kIsFundamental;
461  }
462  if (qt.isConstQualified()) {
463  property |= kIsConstant;
464  }
465  const clang::TagType *tt = qt->getAs<clang::TagType>();
466  if (tt) {
467  const clang::TagDecl *td = tt->getDecl();
468  if (td->isClass()) {
469  property |= kIsClass;
470  }
471  else if (td->isStruct()) {
472  property |= kIsStruct;
473  }
474  else if (td->isUnion()) {
475  property |= kIsUnion;
476  }
477  else if (td->isEnum()) {
478  property |= kIsEnum;
479  }
480  }
481  // We can't be a namespace, can we?
482  // if (dc->isNamespace() && !dc->isTranslationUnit()) {
483  // property |= kIsNamespace;
484  // }
485  return property;
486 }
487 
489 {
490  if (!IsValid()) {
491  return 0L;
492  }
493  const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
494  clang::QualType qt = vd->getType();
495  return TClingTypeInfo(fInterp, qt).Property();
496 }
497 
499 {
500  if (!IsValid()) {
501  return -1;
502  }
503 
504  // Sanity check the current data member.
505  clang::Decl::Kind dk = GetDecl()->getKind();
506  if ((dk != clang::Decl::Field) && (dk != clang::Decl::Var) &&
507  (dk != clang::Decl::EnumConstant)) {
508  // Error, was not a data member, variable, or enumerator.
509  return -1;
510  }
511  const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
512  clang::QualType qt = vd->getType();
513  if (qt->isIncompleteType()) {
514  // We cannot determine the size of forward-declared types.
515  return -1;
516  }
517  clang::ASTContext &context = GetDecl()->getASTContext();
518  // Truncate cast to fit to cint interface.
519  return static_cast<int>(context.getTypeSizeInChars(qt).getQuantity());
520 }
521 
523 {
524  if (!IsValid()) {
525  return 0;
526  }
527 
529  if (!fIoType.empty()) return fIoType.c_str();
530 
531  // Note: This must be static because we return a pointer inside it!
532  static std::string buf;
533  buf.clear();
534  if (const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl())) {
535  clang::QualType vdType = vd->getType();
536  // In CINT's version, the type name returns did *not* include any array
537  // information, ROOT's existing code depends on it.
538  while (vdType->isArrayType()) {
539  vdType = GetDecl()->getASTContext().getQualifiedType(vdType->getBaseElementTypeUnsafe(),vdType.getQualifiers());
540  }
541 
542  // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
544 
546 
547  return buf.c_str();
548  }
549  return 0;
550 }
551 
553 {
554  if (!IsValid()) {
555  return 0;
556  }
557 
559  if (!fIoType.empty()) return fIoType.c_str();
560 
561  // Note: This must be static because we return a pointer inside it!
562  static std::string buf;
563  buf.clear();
564  if (const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl())) {
565  // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
566  clang::QualType vdType = ROOT::TMetaUtils::ReSubstTemplateArg(vd->getType(), fClassInfo->GetType());
567 
568  ROOT::TMetaUtils::GetNormalizedName(buf, vdType, *fInterp, normCtxt);
569 
570  // In CINT's version, the type name returns did *not* include any array
571  // information, ROOT's existing code depends on it.
572  // This might become part of the implementation of GetNormalizedName.
573  while (buf.length() && buf[buf.length()-1] == ']') {
574  size_t last = buf.rfind('['); // if this is not the bracket we are looking, the type is malformed.
575  if (last != std::string::npos) {
576  buf.erase(last);
577  }
578  }
579  return buf.c_str();
580  }
581  return 0;
582 }
583 
584 const char *TClingDataMemberInfo::Name() const
585 {
586  if (!IsValid()) {
587  return 0;
588  }
589 
591  if (!fIoName.empty()) return fIoName.c_str();
592 
593  // Note: This must be static because we return a pointer inside it!
594  static std::string buf;
595  buf.clear();
596 
597  if (const clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(GetDecl())) {
598  clang::PrintingPolicy policy(GetDecl()->getASTContext().getPrintingPolicy());
599  llvm::raw_string_ostream stream(buf);
600  nd->getNameForDiagnostic(stream, policy, /*Qualified=*/false);
601  stream.flush();
602  return buf.c_str();
603  }
604  return 0;
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 
bool IsValid() const
Definition: TString.h:780
const char * Int
RooArgList L(const RooAbsArg &v1)
const clang::Decl * GetDecl() const
const char * TypeName() const
llvm::StringRef ValidArrayIndex() const
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...
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 ...
void GetFullyQualifiedTypeName(std::string &name, const clang::QualType &type, const cling::Interpreter &interpreter)
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.
static const std::string separator("@@@")
TText * tt
Definition: textangle.C:16
int MaxIndex(int dim) const
std::vector< clang::DeclContext::decl_iterator > fIterStack
Emulation of the CINT TypeInfo class.
union TClingDataMemberInfo::@42 fConstInitVal
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: TMetaUtils.h:628
cling::Interpreter * fInterp
long Property() const
Definition: TCling.h:48
const clang::ValueDecl * fSingleDecl
Emulation of the CINT ClassInfo class.
TClingClassInfo * fClassInfo
const clang::Decl * GetDecl() const
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...
const int increment
RooCmdArg Layout(Double_t xmin, Double_t xmax=0.99, Double_t ymin=0.95)
const char * Name() const
const char * cnt
Definition: TXMLSetup.cxx:75
const clang::Type * GetType() const