Logo ROOT   6.07/09
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  if (const APValue* val = VD->evaluateValue()) {
327  if (VD->getType()->isIntegralType(C)) {
328  return reinterpret_cast<long>(val->getInt().getRawData());
329  } else {
330  // The VD stores the init value; its lifetime should the lifetime of
331  // this offset.
332  switch (val->getKind()) {
333  case APValue::Int: {
334  if (val->getInt().isSigned())
335  fConstInitVal.fLong = (long)val->getInt().getSExtValue();
336  else
337  fConstInitVal.fLong = (long)val->getInt().getZExtValue();
338  return (long) &fConstInitVal.fLong;
339  }
340  case APValue::Float:
341  if (&val->getFloat().getSemantics()
342  == &llvm::APFloat::IEEEsingle) {
343  fConstInitVal.fFloat = val->getFloat().convertToFloat();
344  return (long)&fConstInitVal.fFloat;
345  } else if (&val->getFloat().getSemantics()
346  == &llvm::APFloat::IEEEdouble) {
347  fConstInitVal.fDouble = val->getFloat().convertToDouble();
348  return (long)&fConstInitVal.fDouble;
349  }
350  // else fall-through
351  default:
352  ;// fall-through
353  };
354  // fall-through
355  }
356  }
357  }
358  // FIXME: We have to explicitly check for not enum constant because the
359  // implementation of getAddressOfGlobal relies on mangling the name and in
360  // clang there is misbehaviour in MangleContext::shouldMangleDeclName.
361  // enum constants are essentially numbers and don't get addresses. However
362  // ROOT expects the address to the enum constant initializer to be returned.
363  else if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
364  // The raw data is stored as a long long, so we need to find the 'long'
365  // part.
366 #ifdef R__BYTESWAP
367  // In this case at the beginning.
368  return reinterpret_cast<long>(ECD->getInitVal().getRawData());
369 #else
370  // In this case in the second part.
371  return reinterpret_cast<long>(((char*)ECD->getInitVal().getRawData())+sizeof(long) );
372 #endif
373  return -1L;
374 }
375 
377 {
378  if (!IsValid()) {
379  return 0L;
380  }
381  long property = 0L;
382  const clang::Decl *declaccess = GetDecl();
383  if (declaccess->getDeclContext()->isTransparentContext()) {
384  declaccess = llvm::dyn_cast<clang::Decl>(declaccess->getDeclContext());
385  if (!declaccess) declaccess = GetDecl();
386  }
387  switch (declaccess->getAccess()) {
388  case clang::AS_public:
389  property |= kIsPublic;
390  break;
391  case clang::AS_protected:
392  property |= kIsProtected;
393  break;
394  case clang::AS_private:
395  property |= kIsPrivate;
396  break;
397  case clang::AS_none:
398  if (declaccess->getDeclContext()->isNamespace()) {
399  property |= kIsPublic;
400  } else {
401  // IMPOSSIBLE
402  }
403  break;
404  default:
405  // IMPOSSIBLE
406  break;
407  }
408  if (const clang::VarDecl *vard = llvm::dyn_cast<clang::VarDecl>(GetDecl())) {
409  if (vard->getStorageClass() == clang::SC_Static) {
410  property |= kIsStatic;
411  } else if (declaccess->getDeclContext()->isNamespace()) {
412  // Data members of a namespace are global variable which were
413  // considered to be 'static' in the CINT (and thus ROOT) scheme.
414  property |= kIsStatic;
415  }
416  }
417  if (llvm::isa<clang::EnumConstantDecl>(GetDecl())) {
418  // Enumeration constant are considered to be 'static' data member in
419  // the CINT (and thus ROOT) scheme.
420  property |= kIsStatic;
421  }
422  const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
423  clang::QualType qt = vd->getType();
424  if (llvm::isa<clang::TypedefType>(qt)) {
425  property |= kIsTypedef;
426  }
427  qt = qt.getCanonicalType();
428  if (qt.isConstQualified()) {
429  property |= kIsConstant;
430  }
431  while (1) {
432  if (qt->isArrayType()) {
433  property |= kIsArray;
434  qt = llvm::cast<clang::ArrayType>(qt)->getElementType();
435  continue;
436  }
437  else if (qt->isReferenceType()) {
438  property |= kIsReference;
439  qt = llvm::cast<clang::ReferenceType>(qt)->getPointeeType();
440  continue;
441  }
442  else if (qt->isPointerType()) {
443  property |= kIsPointer;
444  if (qt.isConstQualified()) {
445  property |= kIsConstPointer;
446  }
447  qt = llvm::cast<clang::PointerType>(qt)->getPointeeType();
448  continue;
449  }
450  else if (qt->isMemberPointerType()) {
451  qt = llvm::cast<clang::MemberPointerType>(qt)->getPointeeType();
452  continue;
453  }
454  break;
455  }
456  if (qt->isBuiltinType()) {
457  property |= kIsFundamental;
458  }
459  if (qt.isConstQualified()) {
460  property |= kIsConstant;
461  }
462  const clang::TagType *tt = qt->getAs<clang::TagType>();
463  if (tt) {
464  const clang::TagDecl *td = tt->getDecl();
465  if (td->isClass()) {
466  property |= kIsClass;
467  }
468  else if (td->isStruct()) {
469  property |= kIsStruct;
470  }
471  else if (td->isUnion()) {
472  property |= kIsUnion;
473  }
474  else if (td->isEnum()) {
475  property |= kIsEnum;
476  }
477  }
478  // We can't be a namespace, can we?
479  // if (dc->isNamespace() && !dc->isTranslationUnit()) {
480  // property |= kIsNamespace;
481  // }
482  return property;
483 }
484 
486 {
487  if (!IsValid()) {
488  return 0L;
489  }
490  const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
491  clang::QualType qt = vd->getType();
492  return TClingTypeInfo(fInterp, qt).Property();
493 }
494 
496 {
497  if (!IsValid()) {
498  return -1;
499  }
500 
501  // Sanity check the current data member.
502  clang::Decl::Kind dk = GetDecl()->getKind();
503  if ((dk != clang::Decl::Field) && (dk != clang::Decl::Var) &&
504  (dk != clang::Decl::EnumConstant)) {
505  // Error, was not a data member, variable, or enumerator.
506  return -1;
507  }
508  const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
509  clang::QualType qt = vd->getType();
510  if (qt->isIncompleteType()) {
511  // We cannot determine the size of forward-declared types.
512  return -1;
513  }
514  clang::ASTContext &context = GetDecl()->getASTContext();
515  // Truncate cast to fit to cint interface.
516  return static_cast<int>(context.getTypeSizeInChars(qt).getQuantity());
517 }
518 
520 {
521  if (!IsValid()) {
522  return 0;
523  }
524 
526  if (!fIoType.empty()) return fIoType.c_str();
527 
528  // Note: This must be static because we return a pointer inside it!
529  static std::string buf;
530  buf.clear();
531  if (const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl())) {
532  clang::QualType vdType = vd->getType();
533  // In CINT's version, the type name returns did *not* include any array
534  // information, ROOT's existing code depends on it.
535  while (vdType->isArrayType()) {
536  vdType = GetDecl()->getASTContext().getQualifiedType(vdType->getBaseElementTypeUnsafe(),vdType.getQualifiers());
537  }
538 
539  // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
541 
543 
544  return buf.c_str();
545  }
546  return 0;
547 }
548 
550 {
551  if (!IsValid()) {
552  return 0;
553  }
554 
556  if (!fIoType.empty()) return fIoType.c_str();
557 
558  // Note: This must be static because we return a pointer inside it!
559  static std::string buf;
560  buf.clear();
561  if (const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl())) {
562  // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
563  clang::QualType vdType = ROOT::TMetaUtils::ReSubstTemplateArg(vd->getType(), fClassInfo->GetType());
564 
565  ROOT::TMetaUtils::GetNormalizedName(buf, vdType, *fInterp, normCtxt);
566 
567  // In CINT's version, the type name returns did *not* include any array
568  // information, ROOT's existing code depends on it.
569  // This might become part of the implementation of GetNormalizedName.
570  while (buf.length() && buf[buf.length()-1] == ']') {
571  size_t last = buf.rfind('['); // if this is not the bracket we are looking, the type is malformed.
572  if (last != std::string::npos) {
573  buf.erase(last);
574  }
575  }
576  return buf.c_str();
577  }
578  return 0;
579 }
580 
581 const char *TClingDataMemberInfo::Name() const
582 {
583  if (!IsValid()) {
584  return 0;
585  }
586 
588  if (!fIoName.empty()) return fIoName.c_str();
589 
590  // Note: This must be static because we return a pointer inside it!
591  static std::string buf;
592  buf.clear();
593 
594  if (const clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(GetDecl())) {
595  clang::PrintingPolicy policy(GetDecl()->getASTContext().getPrintingPolicy());
596  llvm::raw_string_ostream stream(buf);
597  nd->getNameForDiagnostic(stream, policy, /*Qualified=*/false);
598  stream.flush();
599  return buf.c_str();
600  }
601  return 0;
602 }
603 
605 {
606  if (!IsValid()) {
607  return 0;
608  }
609 
610  //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
611  //if (fTitle.size())
612  // return fTitle.c_str();
613 
614  bool titleFound=false;
615  // Try to get the comment either from the annotation or the header file if present
616  std::string attribute_s;
617  const Decl* decl = GetDecl();
618  for (Decl::attr_iterator attrIt = decl->attr_begin();
619  attrIt!=decl->attr_end() && !titleFound ;++attrIt){
620  if (0 == ROOT::TMetaUtils::extractAttrString(*attrIt, attribute_s) &&
621  attribute_s.find(ROOT::TMetaUtils::propNames::separator) == std::string::npos){
622  fTitle = attribute_s;
623  titleFound=true;
624  }
625  }
626 
627  if (!titleFound && !GetDecl()->isFromASTFile()) {
628  // Try to get the comment from the header file if present
629  // but not for decls from AST file, where rootcling would have
630  // created an annotation
632  }
633 
634  return fTitle.c_str();
635 }
636 
637 // ValidArrayIndex return a static string (so use it or copy it immediately, do not
638 // call GrabIndex twice in the same expression) containing the size of the
639 // array data member.
641 {
642  if (!IsValid()) {
643  return llvm::StringRef();
644  }
645  const clang::DeclaratorDecl *FD = llvm::dyn_cast<clang::DeclaratorDecl>(GetDecl());
647  else return llvm::StringRef();
648 }
649 
const char * Name() const
Definition: TString.h:780
bool IsValid() const
const char * Int
RooArgList L(const RooAbsArg &v1)
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 ...
llvm::StringRef ValidArrayIndex() const
void GetFullyQualifiedTypeName(std::string &name, const clang::QualType &type, const cling::Interpreter &interpreter)
const clang::Type * GetType() const
clang::DeclContext::decl_iterator fIter
const void * DeclId_t
Definition: TDictionary.h:209
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
std::vector< clang::DeclContext::decl_iterator > fIterStack
Emulation of the CINT TypeInfo class.
const char * TypeTrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
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.
int MaxIndex(int dim) const
static double C[]
llvm::SmallVector< clang::DeclContext *, 2 > fContexts
void CheckForIoTypeAndName() const
const T * GetAnnotatedRedeclarable(const T *Redecl)
Definition: TMetaUtils.h:628
const clang::Decl * GetDecl() const
cling::Interpreter * fInterp
const clang::Decl * GetDecl() const
const char * TypeName() const
Definition: TCling.h:48
const clang::ValueDecl * fSingleDecl
Emulation of the CINT ClassInfo class.
TClingClassInfo * fClassInfo
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)
long Property() const
union TClingDataMemberInfo::@40 fConstInitVal
const char * cnt
Definition: TXMLSetup.cxx:75