Logo ROOT   6.08/07
Reference Guide
TClingClassInfo.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 TClingClassInfo
13 
14 Emulation of the CINT ClassInfo class.
15 
16 The CINT C++ interpreter provides an interface to metadata about
17 a class through the ClassInfo class. This class provides the same
18 functionality, using an interface as close as possible to ClassInfo
19 but the class metadata comes from the Clang C++ compiler, not CINT.
20 */
21 
22 #include "TClingClassInfo.h"
23 
24 #include "TClassEdit.h"
25 #include "TClingBaseClassInfo.h"
26 #include "TClingCallFunc.h"
27 #include "TClingMethodInfo.h"
28 #include "TDictionary.h"
29 #include "TClingTypeInfo.h"
30 #include "TError.h"
31 #include "TMetaUtils.h"
32 #include "ThreadLocalStorage.h"
33 
34 #include "cling/Interpreter/Interpreter.h"
35 #include "cling/Interpreter/LookupHelper.h"
36 #include "cling/Utils/AST.h"
37 
38 #include "clang/AST/ASTContext.h"
39 #include "clang/AST/Decl.h"
40 #include "clang/AST/DeclCXX.h"
41 #include "clang/AST/DeclTemplate.h"
42 #include "clang/AST/GlobalDecl.h"
43 #include "clang/AST/PrettyPrinter.h"
44 #include "clang/AST/RecordLayout.h"
45 #include "clang/AST/Type.h"
46 #include "clang/Basic/Specifiers.h"
47 #include "clang/Frontend/CompilerInstance.h"
48 #include "clang/Sema/Sema.h"
49 
50 #include "llvm/ExecutionEngine/GenericValue.h"
51 #include "llvm/Support/Casting.h"
52 #include "llvm/Support/raw_ostream.h"
53 
54 #include <sstream>
55 #include <string>
56 
57 using namespace clang;
58 using namespace ROOT;
59 
60 static std::string FullyQualifiedName(const Decl *decl) {
61  // Return the fully qualified name without worrying about normalizing it.
62  std::string buf;
63  if (const NamedDecl* ND = llvm::dyn_cast<NamedDecl>(decl)) {
64  PrintingPolicy Policy(decl->getASTContext().getPrintingPolicy());
65  llvm::raw_string_ostream stream(buf);
66  ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true);
67  }
68  return buf;
69 }
70 
71 TClingClassInfo::TClingClassInfo(cling::Interpreter *interp, Bool_t all)
72  : fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(all),
73  fDecl(0), fType(0), fOffsetCache(0)
74 {
75  TranslationUnitDecl *TU =
76  interp->getCI()->getASTContext().getTranslationUnitDecl();
77  // Could trigger deserialization of decls.
78  cling::Interpreter::PushTransactionRAII RAII(interp);
79  if (fIterAll)
80  fIter = TU->decls_begin();
81  else
82  fIter = TU->noload_decls_begin();
83 
84  InternalNext();
85  fFirstTime = true;
86  // CINT had this odd behavior where a ClassInfo created without any
87  // argument/input was set as an iterator that was ready to be iterated
88  // on but was set an not IsValid *BUT* a few routine where using this
89  // state as representing the global namespace (These routines include the
90  // GetMethod routines and CallFunc::SetFunc, but do not include many others
91  // (such as Property etc). To be somewhat backward compatible, let's make
92  // this state actually valid (i.e., representing both the ready-for-first-
93  // iteration iterator *and* the global namespace) so that code that was
94  // working with CINT (grabbing the default initialized ClassInfo
95  // to look at the global namespace) is working again (and, yes, things that
96  // used to not work like 'asking' the filename on this will go 'further'
97  // but oh well).
98  fDecl = TU;
99  fType = 0;
100 }
101 
102 TClingClassInfo::TClingClassInfo(cling::Interpreter *interp, const char *name)
103  : fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(kTRUE), fDecl(0),
104  fType(0), fTitle(""), fOffsetCache(0)
105 {
106  const cling::LookupHelper& lh = fInterp->getLookupHelper();
107  const Type *type = 0;
108  const Decl *decl = lh.findScope(name,
109  gDebug > 5 ? cling::LookupHelper::WithDiagnostics
110  : cling::LookupHelper::NoDiagnostics,
111  &type, /* intantiateTemplate= */ true );
112  if (!decl) {
113  std::string buf = TClassEdit::InsertStd(name);
114  if (buf != name) {
115  decl = lh.findScope(buf,
116  gDebug > 5 ? cling::LookupHelper::WithDiagnostics
117  : cling::LookupHelper::NoDiagnostics,
118  &type, /* intantiateTemplate= */ true );
119  }
120  }
121  if (!decl && type) {
122  const TagType *tagtype =type->getAs<TagType>();
123  if (tagtype) {
124  decl = tagtype->getDecl();
125  }
126  }
127  fDecl = decl;
128  fType = type;
129  if (decl && decl->isInvalidDecl()) {
130  Error("TClingClassInfo", "Found an invalid decl for %s.",name);
131  fDecl = nullptr;
132  fType = nullptr;
133  }
134 }
135 
136 TClingClassInfo::TClingClassInfo(cling::Interpreter *interp,
137  const Type &tag)
138  : fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(kTRUE),
139  fDecl(0), fType(0), fTitle(""), fOffsetCache(0)
140 {
141  Init(tag);
142 }
143 
144 void TClingClassInfo::AddBaseOffsetValue(const clang::Decl* decl, ptrdiff_t offset)
145 {
146  // Add the offset value from this class to the non-virtual base class
147  // determined by the parameter decl.
148 
149  OffsetPtrFunc_t executableFunc = 0;
150  fOffsetCache[decl] = std::make_pair(offset, executableFunc);
151 }
152 
154 {
155  if (!IsValid()) {
156  return 0L;
157  }
158  long property = 0L;
159  const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(fDecl);
160  if (!RD) {
161  // We are an enum or namespace.
162  // The cint interface always returns 0L for these guys.
163  return property;
164  }
165  if (RD->isUnion()) {
166  // The cint interface always returns 0L for these guys.
167  return property;
168  }
169  // We now have a class or a struct.
170  const CXXRecordDecl *CRD =
171  llvm::dyn_cast<CXXRecordDecl>(fDecl);
172  property |= kClassIsValid;
173  if (CRD->isAbstract()) {
174  property |= kClassIsAbstract;
175  }
176  if (CRD->hasUserDeclaredConstructor()) {
177  property |= kClassHasExplicitCtor;
178  }
179  if (
180  !CRD->hasUserDeclaredConstructor() &&
181  !CRD->hasTrivialDefaultConstructor()
182  ) {
183  property |= kClassHasImplicitCtor;
184  }
185  if (
186  CRD->hasUserProvidedDefaultConstructor() ||
187  !CRD->hasTrivialDefaultConstructor()
188  ) {
189  property |= kClassHasDefaultCtor;
190  }
191  if (CRD->hasUserDeclaredDestructor()) {
192  property |= kClassHasExplicitDtor;
193  }
194  else if (!CRD->hasTrivialDestructor()) {
195  property |= kClassHasImplicitDtor;
196  }
197  if (CRD->hasUserDeclaredCopyAssignment()) {
198  property |= kClassHasAssignOpr;
199  }
200  if (CRD->isPolymorphic()) {
201  property |= kClassHasVirtual;
202  }
203  return property;
204 }
205 
206 void TClingClassInfo::Delete(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
207 {
208  // Invoke operator delete on a pointer to an object
209  // of this class type.
210  if (!IsValid()) {
211  Error("TClingClassInfo::Delete()", "Called while invalid!");
212  return;
213  }
214  if (!IsLoaded()) {
215  Error("TClingClassInfo::Delete()", "Class is not loaded: %s",
216  FullyQualifiedName(fDecl).c_str());
217  return;
218  }
219  TClingCallFunc cf(fInterp,normCtxt);
220  cf.ExecDestructor(this, arena, /*nary=*/0, /*withFree=*/true);
221 }
222 
223 void TClingClassInfo::DeleteArray(void *arena, bool dtorOnly, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
224 {
225  // Invoke operator delete[] on a pointer to an array object
226  // of this class type.
227  if (!IsLoaded()) {
228  return;
229  }
230  if (dtorOnly) {
231  // There is no syntax in C++ for invoking the placement delete array
232  // operator, so we have to placement destroy each element by hand.
233  // Unfortunately we do not know how many elements to delete.
234  //TClingCallFunc cf(fInterp);
235  //cf.ExecDestructor(this, arena, nary, /*withFree=*/false);
236  Error("DeleteArray", "Placement delete of an array is unsupported!\n");
237  return;
238  }
239  TClingCallFunc cf(fInterp,normCtxt);
240  cf.ExecDestructor(this, arena, /*nary=*/1, /*withFree=*/true);
241 }
242 
243 void TClingClassInfo::Destruct(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
244 {
245  // Invoke placement operator delete on a pointer to an array object
246  // of this class type.
247  if (!IsLoaded()) {
248  return;
249  }
250  TClingCallFunc cf(fInterp,normCtxt);
251  cf.ExecDestructor(this, arena, /*nary=*/0, /*withFree=*/false);
252 }
253 
254 const FunctionTemplateDecl *TClingClassInfo::GetFunctionTemplate(const char *fname) const
255 {
256  // Return any method or function in this scope with the name 'fname'.
257 
258  if (!IsLoaded()) {
259  return 0;
260  }
261 
262  if (fType) {
263  const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
264  if (TT) {
265  llvm::StringRef tname(TT->getDecl()->getName());
266  if (tname.equals(fname)) {
267  const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(fDecl);
268  if (ndecl && !ndecl->getName().equals(fname)) {
269  // Constructor name matching the typedef type, use the decl name instead.
270  return GetFunctionTemplate(ndecl->getName().str().c_str());
271  }
272  }
273  }
274  }
275  const cling::LookupHelper &lh = fInterp->getLookupHelper();
276  const FunctionTemplateDecl *fd
277  = lh.findFunctionTemplate(fDecl, fname,
278  gDebug > 5 ? cling::LookupHelper::WithDiagnostics
279  : cling::LookupHelper::NoDiagnostics, false);
280  if (fd) return fd->getCanonicalDecl();
281  return 0;
282 }
283 
284 const clang::ValueDecl *TClingClassInfo::GetDataMember(const char *name) const
285 {
286  // Return the value decl (if any) corresponding to a data member which
287  // the given name declared in this scope.
288 
289  const cling::LookupHelper &lh = fInterp->getLookupHelper();
290  const ValueDecl *vd
291  = lh.findDataMember(fDecl, name,
292  gDebug > 5 ? cling::LookupHelper::WithDiagnostics
293  : cling::LookupHelper::NoDiagnostics);
294  if (vd) return llvm::dyn_cast<ValueDecl>(vd->getCanonicalDecl());
295  else return 0;
296 }
297 
299 {
300  // Return any method or function in this scope with the name 'fname'.
301 
302  if (!IsLoaded()) {
304  return tmi;
305  }
306 
308 
309  if (fType) {
310  const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
311  if (TT) {
312  llvm::StringRef tname(TT->getDecl()->getName());
313  if (tname.equals(fname)) {
314  const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(fDecl);
315  if (ndecl && !ndecl->getName().equals(fname)) {
316  // Constructor name matching the typedef type, use the decl name instead.
317  return GetMethod(ndecl->getName().str().c_str());
318  }
319  }
320  }
321  }
322  const cling::LookupHelper &lh = fInterp->getLookupHelper();
323  const FunctionDecl *fd
324  = lh.findAnyFunction(fDecl, fname,
325  gDebug > 5 ? cling::LookupHelper::WithDiagnostics
326  : cling::LookupHelper::NoDiagnostics,
327  false);
328  if (!fd) {
329  // Function not found.
331  return tmi;
332  }
334  tmi.Init(fd);
335  return tmi;
336 }
337 
339  const char *proto, long *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
340  EInheritanceMode imode /*= kWithInheritance*/) const
341 {
342  return GetMethod(fname,proto,false,poffset,mode,imode);
343 }
344 
346  const char *proto, bool objectIsConst,
347  long *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
348  EInheritanceMode imode /*= kWithInheritance*/) const
349 {
350  if (poffset) {
351  *poffset = 0L;
352  }
353  if (!IsLoaded()) {
355  return tmi;
356  }
357 
359 
360  if (fType) {
361  const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
362  if (TT) {
363  llvm::StringRef tname(TT->getDecl()->getName());
364  if (tname.equals(fname)) {
365  const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(fDecl);
366  if (ndecl && !ndecl->getName().equals(fname)) {
367  // Constructor name matching the typedef type, use the decl name instead.
368  return GetMethod(ndecl->getName().str().c_str(),proto,
369  objectIsConst,poffset,
370  mode,imode);
371  }
372  }
373  }
374 
375  }
376  const cling::LookupHelper& lh = fInterp->getLookupHelper();
377  const FunctionDecl *fd;
378  if (mode == kConversionMatch) {
379  fd = lh.findFunctionProto(fDecl, fname, proto,
380  gDebug > 5 ? cling::LookupHelper::WithDiagnostics
381  : cling::LookupHelper::NoDiagnostics,
382  objectIsConst);
383  } else if (mode == kExactMatch) {
384  fd = lh.matchFunctionProto(fDecl, fname, proto,
385  gDebug > 5 ? cling::LookupHelper::WithDiagnostics
386  : cling::LookupHelper::NoDiagnostics,
387  objectIsConst);
388  } else {
389  Error("TClingClassInfo::GetMethod",
390  "The MatchMode %d is not supported.", mode);
392  return tmi;
393  }
394  if (!fd) {
395  // Function not found.
397  return tmi;
398  }
399  if (imode == TClingClassInfo::kInThisScope) {
400  // If requested, check whether fd is a member function of this class.
401  // Even though this seems to be the wrong order (we should not allow the
402  // lookup to even collect candidates from the base) it does the right
403  // thing: if any function overload exists in the derived class, all
404  // (but explicitly used) will be hidden. Thus we will only find the
405  // derived class's function overloads (or used, which is fine). Only
406  // if there is none will we find those from the base, in which case
407  // we will reject them here:
408  const clang::DeclContext* ourDC = llvm::dyn_cast<clang::DeclContext>(fDecl);
409  if (!fd->getDeclContext()->Equals(ourDC)
410  && !(fd->getDeclContext()->isTransparentContext()
411  && fd->getDeclContext()->getParent()->Equals(ourDC)))
412  return TClingMethodInfo(fInterp);
413 
414  // The offset must be 0 - the function must be ours.
415  if (poffset) *poffset = 0;
416  } else {
417  if (poffset) {
418  // We have been asked to return a this pointer adjustment.
419  if (const CXXMethodDecl *md =
420  llvm::dyn_cast<CXXMethodDecl>(fd)) {
421  // This is a class member function.
422  *poffset = GetOffset(md);
423  }
424  }
425  }
427  tmi.Init(fd);
428  return tmi;
429 }
430 
432  const llvm::SmallVectorImpl<clang::QualType> &proto,
433  long *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
434  EInheritanceMode imode /*= kWithInheritance*/) const
435 {
436  return GetMethod(fname,proto,false,poffset,mode,imode);
437 }
438 
440  const llvm::SmallVectorImpl<clang::QualType> &proto, bool objectIsConst,
441  long *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
442  EInheritanceMode imode /*= kWithInheritance*/) const
443 {
444  if (poffset) {
445  *poffset = 0L;
446  }
447  if (!IsLoaded()) {
449  return tmi;
450  }
451 
453 
454  if (fType) {
455  const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
456  if (TT) {
457  llvm::StringRef tname(TT->getDecl()->getName());
458  if (tname.equals(fname)) {
459  const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(fDecl);
460  if (ndecl && !ndecl->getName().equals(fname)) {
461  // Constructor name matching the typedef type, use the decl name instead.
462  return GetMethod(ndecl->getName().str().c_str(),proto,objectIsConst,poffset,
463  mode,imode);
464  }
465  }
466  }
467 
468  }
469  const cling::LookupHelper& lh = fInterp->getLookupHelper();
470  const FunctionDecl *fd;
471  if (mode == kConversionMatch) {
472  fd = lh.findFunctionProto(fDecl, fname, proto,
473  gDebug > 5 ? cling::LookupHelper::WithDiagnostics
474  : cling::LookupHelper::NoDiagnostics,
475  objectIsConst);
476  } else if (mode == kExactMatch) {
477  fd = lh.matchFunctionProto(fDecl, fname, proto,
478  gDebug > 5 ? cling::LookupHelper::WithDiagnostics
479  : cling::LookupHelper::NoDiagnostics,
480  objectIsConst);
481  } else {
482  Error("TClingClassInfo::GetMethod",
483  "The MatchMode %d is not supported.", mode);
485  return tmi;
486  }
487  if (!fd) {
488  // Function not found.
490  return tmi;
491  }
492  if (poffset) {
493  // We have been asked to return a this pointer adjustment.
494  if (const CXXMethodDecl *md =
495  llvm::dyn_cast<CXXMethodDecl>(fd)) {
496  // This is a class member function.
497  *poffset = GetOffset(md);
498  }
499  }
501  tmi.Init(fd);
502  return tmi;
503 }
504 
506  const char *arglist, long *poffset, EFunctionMatchMode mode /* = kConversionMatch*/,
507  EInheritanceMode imode /* = kWithInheritance*/) const
508 {
509  return GetMethodWithArgs(fname,arglist,false,poffset,mode,imode);
510 }
511 
513  const char *arglist, bool objectIsConst,
514  long *poffset, EFunctionMatchMode /*mode = kConversionMatch*/,
515  EInheritanceMode /* imode = kWithInheritance*/) const
516 {
517 
519 
520  if (fType) {
521  const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
522  if (TT) {
523  llvm::StringRef tname(TT->getDecl()->getName());
524  if (tname.equals(fname)) {
525  const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(fDecl);
526  if (ndecl && !ndecl->getName().equals(fname)) {
527  // Constructor name matching the typedef type, use the decl name instead.
528  return GetMethod(ndecl->getName().str().c_str(),arglist,
529  objectIsConst,poffset
530  /* ,mode,imode */);
531  }
532  }
533  }
534 
535  }
536  if (poffset) {
537  *poffset = 0L;
538  }
539  if (!IsLoaded()) {
541  return tmi;
542  }
543  if (!strcmp(arglist, ")")) {
544  // CINT accepted a single right paren as meaning no arguments.
545  arglist = "";
546  }
547  const cling::LookupHelper &lh = fInterp->getLookupHelper();
548  const FunctionDecl *fd
549  = lh.findFunctionArgs(fDecl, fname, arglist,
550  gDebug > 5 ? cling::LookupHelper::WithDiagnostics
551  : cling::LookupHelper::NoDiagnostics,
552  objectIsConst);
553  if (!fd) {
554  // Function not found.
556  return tmi;
557  }
558  if (poffset) {
559  // We have been asked to return a this pointer adjustment.
560  if (const CXXMethodDecl *md =
561  llvm::dyn_cast<CXXMethodDecl>(fd)) {
562  // This is a class member function.
563  *poffset = GetOffset(md);
564  }
565  }
567  tmi.Init(fd);
568  return tmi;
569 }
570 
571 int TClingClassInfo::GetMethodNArg(const char *method, const char *proto,
572  Bool_t objectIsConst,
573  EFunctionMatchMode mode /*= kConversionMatch*/) const
574 {
575  // Note: Used only by TQObject.cxx:170 and only for interpreted classes.
576  if (!IsLoaded()) {
577  return -1;
578  }
579 
581 
582  TClingMethodInfo mi = GetMethod(method, proto, objectIsConst, 0, mode);
583  int clang_val = -1;
584  if (mi.IsValid()) {
585  unsigned num_params = mi.GetMethodDecl()->getNumParams();
586  clang_val = static_cast<int>(num_params);
587  }
588  return clang_val;
589 }
590 
591 long TClingClassInfo::GetOffset(const CXXMethodDecl* md) const
592 {
593 
595 
596  long offset = 0L;
597  const CXXRecordDecl* definer = md->getParent();
598  const CXXRecordDecl* accessor =
599  llvm::cast<CXXRecordDecl>(fDecl);
600  if (definer != accessor) {
601  // This function may not be accessible using a pointer
602  // to the declaring class, get the adjustment necessary
603  // to convert that to a pointer to the defining class.
604  TClingBaseClassInfo bi(fInterp, const_cast<TClingClassInfo*>(this));
605  while (bi.Next(0)) {
606  TClingClassInfo* bci = bi.GetBase();
607  if (bci->GetDecl() == definer) {
608  // We have found the right base class, now get the
609  // necessary adjustment.
610  offset = bi.Offset();
611  break;
612  }
613  }
614  }
615  return offset;
616 }
617 
618 ptrdiff_t TClingClassInfo::GetBaseOffset(TClingClassInfo* base, void* address, bool isDerivedObject)
619 {
620 
622 
623  // Check for the offset in the cache.
624  auto iter = fOffsetCache.find(base->GetDecl());
625  if (iter != fOffsetCache.end()) {
626  std::pair<ptrdiff_t, OffsetPtrFunc_t> offsetCache = (*iter).second;
627  if (OffsetPtrFunc_t executableFunc = offsetCache.second) {
628  if (address) {
629  return (*executableFunc)(address, isDerivedObject);
630  }
631  else {
632  Error("TClingBaseClassInfo::Offset", "The address of the object for virtual base offset calculation is not valid.");
633  return -1;
634  }
635  }
636  else {
637  return offsetCache.first;
638  }
639  }
640 
641  // Compute the offset.
642  TClingBaseClassInfo binfo(fInterp, this, base);
643  return binfo.Offset(address, isDerivedObject);
644 }
645 
647 {
648  // Return true if there a constructor taking no arguments (including
649  // a constructor that has defaults for all of its arguments) which
650  // is callable. Either it has a body, or it is trivial and the
651  // compiler elides it.
652  //
653  // Note: This is could enhanced to also know about the ROOT ioctor
654  // but this was not the case in CINT.
655  //
656  if (!IsLoaded()) {
657  return false;
658  }
659  const CXXRecordDecl* CRD = llvm::dyn_cast<CXXRecordDecl>(fDecl);
660  if (!CRD) {
661  // Namespaces do not have constructors.
662  return false;
663  }
664  using namespace TMetaUtils;
665  const RConstructorType ioctortype("",*fInterp);
666  return EIOCtorCategory::kAbsent != CheckConstructor(CRD,ioctortype,*fInterp);
667 }
668 
669 bool TClingClassInfo::HasMethod(const char *name) const
670 {
672  if (IsLoaded() && !llvm::isa<EnumDecl>(fDecl)) {
673  return fInterp->getLookupHelper()
674  .hasFunction(fDecl, name,
675  gDebug > 5 ? cling::LookupHelper::WithDiagnostics
676  : cling::LookupHelper::NoDiagnostics);
677  }
678  return false;
679 }
680 
681 void TClingClassInfo::Init(const char *name)
682 {
683  fFirstTime = true;
684  fDescend = false;
685  fIter = DeclContext::decl_iterator();
686  fDecl = 0;
687  fType = 0;
688  fIterStack.clear();
689  const cling::LookupHelper& lh = fInterp->getLookupHelper();
690  fDecl = lh.findScope(name, gDebug > 5 ? cling::LookupHelper::WithDiagnostics
691  : cling::LookupHelper::NoDiagnostics,
692  &fType, /* intantiateTemplate= */ true );
693  if (!fDecl) {
694  std::string buf = TClassEdit::InsertStd(name);
695  if (buf != name) {
696  fDecl = lh.findScope(buf, gDebug > 5 ? cling::LookupHelper::WithDiagnostics
697  : cling::LookupHelper::NoDiagnostics,
698  &fType, /* intantiateTemplate= */ true );
699  }
700  }
701  if (!fDecl && fType) {
702  const TagType *tagtype =fType->getAs<TagType>();
703  if (tagtype) {
704  fDecl = tagtype->getDecl();
705  }
706  }
707 }
708 
709 void TClingClassInfo::Init(const Decl* decl)
710 {
711  fFirstTime = true;
712  fDescend = false;
713  fIter = DeclContext::decl_iterator();
714  fDecl = decl;
715  fType = 0;
716  fIterStack.clear();
717 }
718 
719 void TClingClassInfo::Init(int tagnum)
720 {
721  Fatal("TClingClassInfo::Init(tagnum)", "Should no longer be called");
722  return;
723 }
724 
725 void TClingClassInfo::Init(const Type &tag)
726 {
727  fType = &tag;
728 
730 
731  const TagType *tagtype = fType->getAs<TagType>();
732  if (tagtype) {
733  fDecl = tagtype->getDecl();
734  }
735  else {
736  fDecl = 0;
737  }
738  if (!fDecl) {
739  QualType qType(fType,0);
740  static PrintingPolicy printPol(fInterp->getCI()->getLangOpts());
741  printPol.SuppressScope = false;
742  Error("TClingClassInfo::Init(const Type&)",
743  "The given type %s does not point to a Decl",
744  qType.getAsString(printPol).c_str());
745  }
746 }
747 
748 bool TClingClassInfo::IsBase(const char *name) const
749 {
750  if (!IsLoaded()) {
751  return false;
752  }
753  TClingClassInfo base(fInterp, name);
754  if (!base.IsValid()) {
755  return false;
756  }
757 
759 
760  const CXXRecordDecl *CRD =
761  llvm::dyn_cast<CXXRecordDecl>(fDecl);
762  if (!CRD) {
763  // We are an enum, namespace, or translation unit,
764  // we cannot be the base of anything.
765  return false;
766  }
767  const CXXRecordDecl *baseCRD =
768  llvm::dyn_cast<CXXRecordDecl>(base.GetDecl());
769  return CRD->isDerivedFrom(baseCRD);
770 }
771 
772 bool TClingClassInfo::IsEnum(cling::Interpreter *interp, const char *name)
773 {
774  // Note: This is a static member function.
775  TClingClassInfo info(interp, name);
776  if (info.IsValid() && (info.Property() & kIsEnum)) {
777  return true;
778  }
779  return false;
780 }
781 
783 {
784  // IsLoaded in CINT was meaning is known to the interpreter
785  // and has a complete definition.
786  // IsValid in Cling (as in CING) means 'just' is known to the
787  // interpreter.
788  if (!IsValid()) {
789  return false;
790  }
791  if (fDecl == 0) {
792  return false;
793  }
794 
796 
797  const CXXRecordDecl *CRD = llvm::dyn_cast<CXXRecordDecl>(fDecl);
798  if ( CRD ) {
799  if (!CRD->hasDefinition()) {
800  return false;
801  }
802  } else {
803  const TagDecl *TD = llvm::dyn_cast<TagDecl>(fDecl);
804  if (TD && TD->getDefinition() == 0) {
805  return false;
806  }
807  }
808  // All clang classes are considered loaded.
809  return true;
810 }
811 
813 {
814  return fDecl;
815 }
816 
817 bool TClingClassInfo::IsValidMethod(const char *method, const char *proto,
818  Bool_t objectIsConst,
819  long *offset,
820  EFunctionMatchMode mode /*= kConversionMatch*/) const
821 {
822  // Check if the method with the given prototype exist.
823  if (!IsLoaded()) {
824  return false;
825  }
826  if (offset) {
827  *offset = 0L;
828  }
829  TClingMethodInfo mi = GetMethod(method, proto, offset, mode);
830  return mi.IsValid();
831 }
832 
834 {
835 
837 
838  if (!*fIter) {
839  // Iterator is already invalid.
840  if (fFirstTime && fDecl) {
841  std::string buf;
842  if (const NamedDecl* ND =
843  llvm::dyn_cast<NamedDecl>(fDecl)) {
844  PrintingPolicy Policy(fDecl->getASTContext().
845  getPrintingPolicy());
846  llvm::raw_string_ostream stream(buf);
847  ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/false);
848  }
849  Error("TClingClassInfo::InternalNext",
850  "Next called but iteration not prepared for %s!", buf.c_str());
851  }
852  return 0;
853  }
854  cling::Interpreter::PushTransactionRAII pushedT(fInterp);
855  while (true) {
856  // Advance to next usable decl, or return if there is no next usable decl.
857  if (fFirstTime) {
858  // The cint semantics are strange.
859  fFirstTime = false;
860  }
861  else {
862  // Advance the iterator one decl, descending into the current decl
863  // context if necessary.
864  if (!fDescend) {
865  // Do not need to scan the decl context of the current decl,
866  // move on to the next decl.
867  ++fIter;
868  }
869  else {
870  // Descend into the decl context of the current decl.
871  fDescend = false;
872  //fprintf(stderr,
873  // "TClingClassInfo::InternalNext: "
874  // "pushing ...\n");
875  fIterStack.push_back(fIter);
876  DeclContext *DC = llvm::cast<DeclContext>(*fIter);
877  if (fIterAll)
878  fIter = DC->decls_begin();
879  else
880  fIter = DC->noload_decls_begin();
881  }
882  // Fix it if we went past the end.
883  while (!*fIter && fIterStack.size()) {
884  //fprintf(stderr,
885  // "TClingClassInfo::InternalNext: "
886  // "popping ...\n");
887  fIter = fIterStack.back();
888  fIterStack.pop_back();
889  ++fIter;
890  }
891  // Check for final termination.
892  if (!*fIter) {
893  // We have reached the end of the translation unit, all done.
894  fDecl = 0;
895  fType = 0;
896  return 0;
897  }
898  }
899  // Return if this decl is a class, struct, union, enum, or namespace.
900  Decl::Kind DK = fIter->getKind();
901  if ((DK == Decl::Namespace) || (DK == Decl::Enum) ||
902  (DK == Decl::CXXRecord) ||
903  (DK == Decl::ClassTemplateSpecialization)) {
904  const TagDecl *TD = llvm::dyn_cast<TagDecl>(*fIter);
905  if (TD && !TD->isCompleteDefinition()) {
906  // For classes and enums, stop only on definitions.
907  continue;
908  }
909  if (DK == Decl::Namespace) {
910  // For namespaces, stop only on the first definition.
911  if (!fIter->isCanonicalDecl()) {
912  // Not the first definition.
913  fDescend = true;
914  continue;
915  }
916  }
917  if (DK != Decl::Enum) {
918  // We do not descend into enums.
919  DeclContext *DC = llvm::cast<DeclContext>(*fIter);
920  if ((fIterAll && *DC->decls_begin())
921  || (!fIterAll && *DC->noload_decls_begin())) {
922  // Next iteration will begin scanning the decl context
923  // contained by this decl.
924  fDescend = true;
925  }
926  }
927  // Iterator is now valid.
928  fDecl = *fIter;
929  fType = 0;
930  if (fDecl) {
931  if (fDecl->isInvalidDecl()) {
932  Warning("TClingClassInfo::Next()","Reached an invalid decl.");
933  }
934  if (const RecordDecl *RD =
935  llvm::dyn_cast<RecordDecl>(fDecl)) {
936  fType = RD->getASTContext().getRecordType(RD).getTypePtr();
937  }
938  }
939  return 1;
940  }
941  }
942 }
943 
945 {
946  return InternalNext();
947 }
948 
950 {
951  // Invoke a new expression to use the class constructor
952  // that takes no arguments to create an object of this class type.
953  if (!IsValid()) {
954  Error("TClingClassInfo::New()", "Called while invalid!");
955  return 0;
956  }
957  if (!IsLoaded()) {
958  Error("TClingClassInfo::New()", "Class is not loaded: %s",
959  FullyQualifiedName(fDecl).c_str());
960  return 0;
961  }
962  {
964  const CXXRecordDecl* RD = dyn_cast<CXXRecordDecl>(fDecl);
965  if (!RD) {
966  Error("TClingClassInfo::New()", "This is a namespace!: %s",
967  FullyQualifiedName(fDecl).c_str());
968  return 0;
969  }
970  if (!HasDefaultConstructor()) {
971  // FIXME: We fail roottest root/io/newdelete if we issue this message!
972  //Error("TClingClassInfo::New()", "Class has no default constructor: %s",
973  // FullyQualifiedName(fDecl).c_str());
974  return 0;
975  }
976  } // End of Lock section.
977  void* obj = 0;
978  TClingCallFunc cf(fInterp,normCtxt);
979  obj = cf.ExecDefaultConstructor(this, /*address=*/0, /*nary=*/0);
980  if (!obj) {
981  Error("TClingClassInfo::New()", "Call of default constructor "
982  "failed to return an object for class: %s",
983  FullyQualifiedName(fDecl).c_str());
984  return 0;
985  }
986  return obj;
987 }
988 
990 {
991  // Invoke a new expression to use the class constructor
992  // that takes no arguments to create an array object
993  // of this class type.
994  if (!IsValid()) {
995  Error("TClingClassInfo::New(n)", "Called while invalid!");
996  return 0;
997  }
998  if (!IsLoaded()) {
999  Error("TClingClassInfo::New(n)", "Class is not loaded: %s",
1000  FullyQualifiedName(fDecl).c_str());
1001  return 0;
1002  }
1003 
1004  {
1006 
1007  const CXXRecordDecl* RD = dyn_cast<CXXRecordDecl>(fDecl);
1008  if (!RD) {
1009  Error("TClingClassInfo::New(n)", "This is a namespace!: %s",
1010  FullyQualifiedName(fDecl).c_str());
1011  return 0;
1012  }
1013  if (!HasDefaultConstructor()) {
1014  // FIXME: We fail roottest root/io/newdelete if we issue this message!
1015  //Error("TClingClassInfo::New(n)",
1016  // "Class has no default constructor: %s",
1017  // FullyQualifiedName(fDecl).c_str());
1018  return 0;
1019  }
1020  } // End of Lock section.
1021  void* obj = 0;
1022  TClingCallFunc cf(fInterp,normCtxt);
1023  obj = cf.ExecDefaultConstructor(this, /*address=*/0,
1024  /*nary=*/(unsigned long)n);
1025  if (!obj) {
1026  Error("TClingClassInfo::New(n)", "Call of default constructor "
1027  "failed to return an array of class: %s",
1028  FullyQualifiedName(fDecl).c_str());
1029  return 0;
1030  }
1031  return obj;
1032 }
1033 
1034 void *TClingClassInfo::New(int n, void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
1035 {
1036  // Invoke a placement new expression to use the class
1037  // constructor that takes no arguments to create an
1038  // array of objects of this class type in the given
1039  // memory arena.
1040  if (!IsValid()) {
1041  Error("TClingClassInfo::New(n, arena)", "Called while invalid!");
1042  return 0;
1043  }
1044  if (!IsLoaded()) {
1045  Error("TClingClassInfo::New(n, arena)", "Class is not loaded: %s",
1046  FullyQualifiedName(fDecl).c_str());
1047  return 0;
1048  }
1049  {
1051 
1052  const CXXRecordDecl* RD = dyn_cast<CXXRecordDecl>(fDecl);
1053  if (!RD) {
1054  Error("TClingClassInfo::New(n, arena)", "This is a namespace!: %s",
1055  FullyQualifiedName(fDecl).c_str());
1056  return 0;
1057  }
1058  if (!HasDefaultConstructor()) {
1059  // FIXME: We fail roottest root/io/newdelete if we issue this message!
1060  //Error("TClingClassInfo::New(n, arena)",
1061  // "Class has no default constructor: %s",
1062  // FullyQualifiedName(fDecl).c_str());
1063  return 0;
1064  }
1065  } // End of Lock section
1066  void* obj = 0;
1067  TClingCallFunc cf(fInterp,normCtxt);
1068  // Note: This will always return arena.
1069  obj = cf.ExecDefaultConstructor(this, /*address=*/arena,
1070  /*nary=*/(unsigned long)n);
1071  return obj;
1072 }
1073 
1074 void *TClingClassInfo::New(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
1075 {
1076  // Invoke a placement new expression to use the class
1077  // constructor that takes no arguments to create an
1078  // object of this class type in the given memory arena.
1079  if (!IsValid()) {
1080  Error("TClingClassInfo::New(arena)", "Called while invalid!");
1081  return 0;
1082  }
1083  if (!IsLoaded()) {
1084  Error("TClingClassInfo::New(arena)", "Class is not loaded: %s",
1085  FullyQualifiedName(fDecl).c_str());
1086  return 0;
1087  }
1088  {
1090 
1091  const CXXRecordDecl* RD = dyn_cast<CXXRecordDecl>(fDecl);
1092  if (!RD) {
1093  Error("TClingClassInfo::New(arena)", "This is a namespace!: %s",
1094  FullyQualifiedName(fDecl).c_str());
1095  return 0;
1096  }
1097  if (!HasDefaultConstructor()) {
1098  // FIXME: We fail roottest root/io/newdelete if we issue this message!
1099  //Error("TClingClassInfo::New(arena)",
1100  // "Class has no default constructor: %s",
1101  // FullyQualifiedName(fDecl).c_str());
1102  return 0;
1103  }
1104  } // End of Locked section.
1105  void* obj = 0;
1106  TClingCallFunc cf(fInterp,normCtxt);
1107  // Note: This will always return arena.
1108  obj = cf.ExecDefaultConstructor(this, /*address=*/arena, /*nary=*/0);
1109  return obj;
1110 }
1111 
1113 {
1114  if (!IsValid()) {
1115  return 0L;
1116  }
1117 
1119 
1120  long property = 0L;
1121  property |= kIsCPPCompiled;
1122  const clang::DeclContext *ctxt = fDecl->getDeclContext();
1123  clang::NamespaceDecl *std_ns =fInterp->getSema().getStdNamespace();
1124  while (! ctxt->isTranslationUnit()) {
1125  if (ctxt->Equals(std_ns)) {
1126  property |= kIsDefinedInStd;
1127  break;
1128  }
1129  ctxt = ctxt->getParent();
1130  }
1131  Decl::Kind DK = fDecl->getKind();
1132  if ((DK == Decl::Namespace) || (DK == Decl::TranslationUnit)) {
1133  property |= kIsNamespace;
1134  return property;
1135  }
1136  // Note: Now we have class, enum, struct, union only.
1137  const TagDecl *TD = llvm::dyn_cast<TagDecl>(fDecl);
1138  if (!TD) {
1139  return 0L;
1140  }
1141  if (TD->isEnum()) {
1142  property |= kIsEnum;
1143  return property;
1144  }
1145  // Note: Now we have class, struct, union only.
1146  const CXXRecordDecl *CRD =
1147  llvm::dyn_cast<CXXRecordDecl>(fDecl);
1148  if (CRD->isClass()) {
1149  property |= kIsClass;
1150  }
1151  else if (CRD->isStruct()) {
1152  property |= kIsStruct;
1153  }
1154  else if (CRD->isUnion()) {
1155  property |= kIsUnion;
1156  }
1157  if (CRD->hasDefinition() && CRD->isAbstract()) {
1158  property |= kIsAbstract;
1159  }
1160  return property;
1161 }
1162 
1164 {
1165  if (!IsValid()) {
1166  return 0;
1167  }
1168  // FIXME: Implement this when rootcling provides the value.
1169  return 0;
1170 }
1171 
1173 {
1174  if (!IsValid()) {
1175  return -1;
1176  }
1177  if (!fDecl) {
1178  // A forward declared class.
1179  return 0;
1180  }
1181 
1183 
1184  Decl::Kind DK = fDecl->getKind();
1185  if (DK == Decl::Namespace) {
1186  // Namespaces are special for cint.
1187  return 1;
1188  }
1189  else if (DK == Decl::Enum) {
1190  // Enums are special for cint.
1191  return 0;
1192  }
1193  const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(fDecl);
1194  if (!RD) {
1195  // Should not happen.
1196  return -1;
1197  }
1198  if (!RD->getDefinition()) {
1199  // Forward-declared class.
1200  return 0;
1201  }
1202  ASTContext &Context = fDecl->getASTContext();
1203  cling::Interpreter::PushTransactionRAII RAII(fInterp);
1204  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1205  int64_t size = Layout.getSize().getQuantity();
1206  int clang_size = static_cast<int>(size);
1207  return clang_size;
1208 }
1209 
1211 {
1212  if (!IsValid()) {
1213  return -1L;
1214  }
1215  return reinterpret_cast<long>(fDecl);
1216 }
1217 
1219 {
1220  if (!IsValid()) {
1221  return 0;
1222  }
1224  return fDeclFileName.c_str();
1225 }
1226 
1227 void TClingClassInfo::FullName(std::string &output, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
1228 {
1229  // Return QualifiedName.
1230  output.clear();
1231  if (!IsValid()) {
1232  return;
1233  }
1234  if (fType) {
1235  QualType type(fType, 0);
1236  ROOT::TMetaUtils::GetNormalizedName(output, type, *fInterp, normCtxt);
1237  }
1238  else {
1239  if (const NamedDecl* ND =
1240  llvm::dyn_cast<NamedDecl>(fDecl)) {
1241  PrintingPolicy Policy(fDecl->getASTContext().
1242  getPrintingPolicy());
1243  llvm::raw_string_ostream stream(output);
1244  ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true);
1245  }
1246  }
1247 }
1248 
1249 const char *TClingClassInfo::Name() const
1250 {
1251  // Return unqualified name.
1252  if (!IsValid()) {
1253  return 0;
1254  }
1255  // Note: This *must* be static/thread_local because we are returning a pointer inside it!
1256  TTHREAD_TLS_DECL( std::string, buf);
1257 
1258  buf.clear();
1259  if (const NamedDecl* ND = llvm::dyn_cast<NamedDecl>(fDecl)) {
1260  PrintingPolicy Policy(fDecl->getASTContext().getPrintingPolicy());
1261  llvm::raw_string_ostream stream(buf);
1262  ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/false);
1263  }
1264  return buf.c_str();
1265 }
1266 
1268 {
1269  if (!IsValid()) {
1270  return 0;
1271  }
1272  // NOTE: We cannot cache the result, since we are really an iterator.
1273  // Try to get the comment either from the annotation or the header
1274  // file, if present.
1275  // Iterate over the redeclarations, we can have multiple definitions in the
1276  // redecl chain (came from merging of pcms).
1277 
1279 
1280  if (const TagDecl *TD = llvm::dyn_cast<TagDecl>(GetDecl())) {
1281  if ( (TD = ROOT::TMetaUtils::GetAnnotatedRedeclarable(TD)) ) {
1282  if (AnnotateAttr *A = TD->getAttr<AnnotateAttr>()) {
1283  std::string attr = A->getAnnotation().str();
1284  if (attr.find(TMetaUtils::propNames::separator) != std::string::npos) {
1286  fTitle = attr;
1287  return fTitle.c_str();
1288  }
1289  } else {
1290  fTitle = attr;
1291  return fTitle.c_str();
1292  }
1293  }
1294  }
1295  }
1296  // Try to get the comment from the header file, if present.
1297  // but not for decls from AST file, where rootcling would have
1298  // created an annotation
1299  const CXXRecordDecl *CRD =
1300  llvm::dyn_cast<CXXRecordDecl>(GetDecl());
1301  if (CRD && !CRD->isFromASTFile()) {
1303  }
1304  return fTitle.c_str();
1305 }
1306 
1307 const char *TClingClassInfo::TmpltName() const
1308 {
1309  if (!IsValid()) {
1310  return 0;
1311  }
1312 
1314 
1315  // Note: This *must* be static/thread_local because we are returning a pointer inside it!
1316  TTHREAD_TLS_DECL( std::string, buf);
1317  buf.clear();
1318  if (const NamedDecl* ND = llvm::dyn_cast<NamedDecl>(fDecl)) {
1319  // Note: This does *not* include the template arguments!
1320  buf = ND->getNameAsString();
1321  }
1322  return buf.c_str();
1323 }
1324 
const clang::FunctionTemplateDecl * GetFunctionTemplate(const char *fname) const
bool IsValid() const
void AddBaseOffsetValue(const clang::Decl *decl, ptrdiff_t offset)
llvm::DenseMap< const clang::Decl *, std::pair< ptrdiff_t, OffsetPtrFunc_t > > fOffsetCache
llvm::StringRef GetFileName(const clang::Decl &decl, const cling::Interpreter &interp)
Return the header file to be included to declare the Decl.
This namespace contains pre-defined functions to be used in conjuction with TExecutor::Map and TExecu...
Definition: StringConv.hxx:21
void Fatal(const char *location, const char *msgfmt,...)
RooArgList L(const RooAbsArg &v1)
static const std::string comment("comment")
const clang::Decl * GetDecl() const
const clang::Type * fType
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:46
TClingMethodInfo GetMethod(const char *fname) const
Small helper to keep current directory context.
Emulation of the CINT MethodInfo class.
std::string fTitle
ptrdiff_t GetBaseOffset(TClingClassInfo *toBase, void *address, bool isDerivedObject)
long ClassProperty() const
bool HasDefaultConstructor() const
std::string InsertStd(const char *tname)
bool Bool_t
Definition: RtypesCore.h:59
long Property() const
const char * FileName()
void Delete(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
static double A[]
Emulation of the CINT CallFunc class.
bool ExtractAttrPropertyFromName(const clang::Decl &decl, const std::string &propName, std::string &propValue)
This routine counts on the "propName<separator>propValue" format.
ptrdiff_t(* OffsetPtrFunc_t)(void *, bool)
bool IsBase(const char *name) const
const clang::Decl * fDecl
static const std::string separator("@@@")
const char * Title()
EFunctionMatchMode
Definition: TDictionary.h:155
static bool IsEnum(cling::Interpreter *interp, const char *name)
long GetOffset(const clang::CXXMethodDecl *md) const
bool HasMethod(const char *name) const
void Error(const char *location, const char *msgfmt,...)
const clang::FunctionDecl * GetMethodDecl() const
const clang::ValueDecl * GetDataMember(const char *name) const
std::string fDeclFileName
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.
const char * TmpltName() const
void Init(const char *name)
void Init(const clang::FunctionDecl *)
void DeleteArray(void *arena, bool dtorOnly, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
Emulation of the CINT BaseClassInfo class.
int GetMethodNArg(const char *method, const char *proto, Bool_t objectIsConst, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch) const
const T * GetAnnotatedRedeclarable(const T *Redecl)
Definition: TMetaUtils.h:628
void Warning(const char *location, const char *msgfmt,...)
Type
enumeration specifying the integration types.
PyObject * fType
void * New(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
bool IsValidMethod(const char *method, const char *proto, Bool_t objectIsConst, long *offset, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch) const
TClingClassInfo * GetBase() const
Definition: TCling.h:48
EIOCtorCategory CheckConstructor(const clang::CXXRecordDecl *, const RConstructorType &, const cling::Interpreter &interp)
Definition: TMetaUtils.cxx:963
int type
Definition: TGX11.cxx:120
Emulation of the CINT ClassInfo class.
#define R__LOCKGUARD(mutex)
llvm::StringRef GetClassComment(const clang::CXXRecordDecl &decl, clang::SourceLocation *loc, const cling::Interpreter &interpreter)
Return the class comment after the ClassDef: class MyClass { ...
ptrdiff_t Offset(void *address=0, bool isDerivedObject=true) const
void * ExecDefaultConstructor(const TClingClassInfo *info, void *address=0, unsigned long nary=0UL)
RooCmdArg Layout(Double_t xmin, Double_t xmax=0.99, Double_t ymin=0.95)
clang::DeclContext::decl_iterator fIter
void ExecDestructor(const TClingClassInfo *info, void *address=0, unsigned long nary=0UL, bool withFree=true)
const char * Name() const
void Destruct(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
const char * proto
Definition: civetweb.c:11652
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
static std::string FullyQualifiedName(const Decl *decl)
std::vector< clang::DeclContext::decl_iterator > fIterStack
void FullName(std::string &output, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
bool IsLoaded() const
cling::Interpreter * fInterp
const Bool_t kTRUE
Definition: Rtypes.h:91
const Int_t n
Definition: legend1.C:16
char name[80]
Definition: TGX11.cxx:109
TClingMethodInfo GetMethodWithArgs(const char *fname, const char *arglist, long *poffset, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch, EInheritanceMode imode=kWithInheritance) const