ROOT  6.06/09
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 
646 static bool HasBody(const clang::FunctionDecl &decl, const cling::Interpreter &interp)
647 {
648  if (decl.hasBody()) return true;
649 
650  GlobalDecl GD;
651  if (const CXXConstructorDecl* Ctor = dyn_cast<CXXConstructorDecl>(&decl))
652  GD = GlobalDecl(Ctor, Ctor_Complete);
653  else if (const CXXDestructorDecl* Dtor = dyn_cast<CXXDestructorDecl>(&decl))
654  GD = GlobalDecl(Dtor, Dtor_Deleting);
655  else
656  GD = GlobalDecl(&decl);
657  std::string mangledName;
658  cling::utils::Analyze::maybeMangleDeclName(GD, mangledName);
659 
660  void *GV = interp.getAddressOfGlobal(mangledName.c_str());
661  if (GV) return true;
662 
663  return false;
664 }
665 
667 {
668  // Return true if there a constructor taking no arguments (including
669  // a constructor that has defaults for all of its arguments) which
670  // is callable. Either it has a body, or it is trivial and the
671  // compiler elides it.
672  //
673  // Note: This is could enhanced to also know about the ROOT ioctor
674  // but this was not the case in CINT.
675  //
676  if (!IsLoaded()) {
677  return false;
678  }
679  const CXXRecordDecl* CRD = llvm::dyn_cast<CXXRecordDecl>(fDecl);
680  if (!CRD) {
681  // Namespaces do not have constructors.
682  return false;
683  }
684  if (CRD->hasTrivialDefaultConstructor()) {
685  // This class has a default constructor that can be called,
686  // but has no body.
687  return true;
688  }
689  // Note: This iteration may force template instantiations!
690  cling::Interpreter::PushTransactionRAII pushedT(fInterp);
691  for (CXXRecordDecl::ctor_iterator I = CRD->ctor_begin(),
692  E = CRD->ctor_end(); I != E; ++I) {
693  if (I->getMinRequiredArguments() == 0) {
694  if ((I->getAccess() == AS_public) && HasBody(**I,*fInterp)) {
695  return true;
696  }
697  if (I->isTemplateInstantiation()) {
698  const clang::FunctionDecl* FD =
699  I->getInstantiatedFromMemberFunction();
700  if ((FD->getAccess() == AS_public) && HasBody(*FD,*fInterp)) {
701  return true;
702  }
703  }
704  }
705  }
706  return false;
707 }
708 
709 bool TClingClassInfo::HasMethod(const char *name) const
710 {
712  if (IsLoaded() && !llvm::isa<EnumDecl>(fDecl)) {
713  return fInterp->getLookupHelper()
714  .hasFunction(fDecl, name,
715  gDebug > 5 ? cling::LookupHelper::WithDiagnostics
716  : cling::LookupHelper::NoDiagnostics);
717  }
718  return false;
719 }
720 
721 void TClingClassInfo::Init(const char *name)
722 {
723  fFirstTime = true;
724  fDescend = false;
725  fIter = DeclContext::decl_iterator();
726  fDecl = 0;
727  fType = 0;
728  fIterStack.clear();
729  const cling::LookupHelper& lh = fInterp->getLookupHelper();
730  fDecl = lh.findScope(name, gDebug > 5 ? cling::LookupHelper::WithDiagnostics
731  : cling::LookupHelper::NoDiagnostics,
732  &fType, /* intantiateTemplate= */ true );
733  if (!fDecl) {
734  std::string buf = TClassEdit::InsertStd(name);
735  if (buf != name) {
736  fDecl = lh.findScope(buf, gDebug > 5 ? cling::LookupHelper::WithDiagnostics
737  : cling::LookupHelper::NoDiagnostics,
738  &fType, /* intantiateTemplate= */ true );
739  }
740  }
741  if (!fDecl && fType) {
742  const TagType *tagtype =fType->getAs<TagType>();
743  if (tagtype) {
744  fDecl = tagtype->getDecl();
745  }
746  }
747 }
748 
749 void TClingClassInfo::Init(const Decl* decl)
750 {
751  fFirstTime = true;
752  fDescend = false;
753  fIter = DeclContext::decl_iterator();
754  fDecl = decl;
755  fType = 0;
756  fIterStack.clear();
757 }
758 
759 void TClingClassInfo::Init(int tagnum)
760 {
761  Fatal("TClingClassInfo::Init(tagnum)", "Should no longer be called");
762  return;
763 }
764 
765 void TClingClassInfo::Init(const Type &tag)
766 {
767  fType = &tag;
768 
770 
771  const TagType *tagtype = fType->getAs<TagType>();
772  if (tagtype) {
773  fDecl = tagtype->getDecl();
774  }
775  else {
776  fDecl = 0;
777  }
778  if (!fDecl) {
779  QualType qType(fType,0);
780  static PrintingPolicy printPol(fInterp->getCI()->getLangOpts());
781  printPol.SuppressScope = false;
782  Error("TClingClassInfo::Init(const Type&)",
783  "The given type %s does not point to a Decl",
784  qType.getAsString(printPol).c_str());
785  }
786 }
787 
788 bool TClingClassInfo::IsBase(const char *name) const
789 {
790  if (!IsLoaded()) {
791  return false;
792  }
793  TClingClassInfo base(fInterp, name);
794  if (!base.IsValid()) {
795  return false;
796  }
797 
799 
800  const CXXRecordDecl *CRD =
801  llvm::dyn_cast<CXXRecordDecl>(fDecl);
802  if (!CRD) {
803  // We are an enum, namespace, or translation unit,
804  // we cannot be the base of anything.
805  return false;
806  }
807  const CXXRecordDecl *baseCRD =
808  llvm::dyn_cast<CXXRecordDecl>(base.GetDecl());
809  return CRD->isDerivedFrom(baseCRD);
810 }
811 
812 bool TClingClassInfo::IsEnum(cling::Interpreter *interp, const char *name)
813 {
814  // Note: This is a static member function.
815  TClingClassInfo info(interp, name);
816  if (info.IsValid() && (info.Property() & kIsEnum)) {
817  return true;
818  }
819  return false;
820 }
821 
823 {
824  // IsLoaded in CINT was meaning is known to the interpreter
825  // and has a complete definition.
826  // IsValid in Cling (as in CING) means 'just' is known to the
827  // interpreter.
828  if (!IsValid()) {
829  return false;
830  }
831  if (fDecl == 0) {
832  return false;
833  }
834 
836 
837  const CXXRecordDecl *CRD = llvm::dyn_cast<CXXRecordDecl>(fDecl);
838  if ( CRD ) {
839  if (!CRD->hasDefinition()) {
840  return false;
841  }
842  } else {
843  const TagDecl *TD = llvm::dyn_cast<TagDecl>(fDecl);
844  if (TD && TD->getDefinition() == 0) {
845  return false;
846  }
847  }
848  // All clang classes are considered loaded.
849  return true;
850 }
851 
853 {
854  return fDecl;
855 }
856 
857 bool TClingClassInfo::IsValidMethod(const char *method, const char *proto,
858  Bool_t objectIsConst,
859  long *offset,
860  EFunctionMatchMode mode /*= kConversionMatch*/) const
861 {
862  // Check if the method with the given prototype exist.
863  if (!IsLoaded()) {
864  return false;
865  }
866  if (offset) {
867  *offset = 0L;
868  }
869  TClingMethodInfo mi = GetMethod(method, proto, offset, mode);
870  return mi.IsValid();
871 }
872 
874 {
875 
877 
878  if (!*fIter) {
879  // Iterator is already invalid.
880  if (fFirstTime && fDecl) {
881  std::string buf;
882  if (const NamedDecl* ND =
883  llvm::dyn_cast<NamedDecl>(fDecl)) {
884  PrintingPolicy Policy(fDecl->getASTContext().
885  getPrintingPolicy());
886  llvm::raw_string_ostream stream(buf);
887  ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/false);
888  }
889  Error("TClingClassInfo::InternalNext",
890  "Next called but iteration not prepared for %s!", buf.c_str());
891  }
892  return 0;
893  }
894  cling::Interpreter::PushTransactionRAII pushedT(fInterp);
895  while (true) {
896  // Advance to next usable decl, or return if there is no next usable decl.
897  if (fFirstTime) {
898  // The cint semantics are strange.
899  fFirstTime = false;
900  }
901  else {
902  // Advance the iterator one decl, descending into the current decl
903  // context if necessary.
904  if (!fDescend) {
905  // Do not need to scan the decl context of the current decl,
906  // move on to the next decl.
907  ++fIter;
908  }
909  else {
910  // Descend into the decl context of the current decl.
911  fDescend = false;
912  //fprintf(stderr,
913  // "TClingClassInfo::InternalNext: "
914  // "pushing ...\n");
915  fIterStack.push_back(fIter);
916  DeclContext *DC = llvm::cast<DeclContext>(*fIter);
917  if (fIterAll)
918  fIter = DC->decls_begin();
919  else
920  fIter = DC->noload_decls_begin();
921  }
922  // Fix it if we went past the end.
923  while (!*fIter && fIterStack.size()) {
924  //fprintf(stderr,
925  // "TClingClassInfo::InternalNext: "
926  // "popping ...\n");
927  fIter = fIterStack.back();
928  fIterStack.pop_back();
929  ++fIter;
930  }
931  // Check for final termination.
932  if (!*fIter) {
933  // We have reached the end of the translation unit, all done.
934  fDecl = 0;
935  fType = 0;
936  return 0;
937  }
938  }
939  // Return if this decl is a class, struct, union, enum, or namespace.
940  Decl::Kind DK = fIter->getKind();
941  if ((DK == Decl::Namespace) || (DK == Decl::Enum) ||
942  (DK == Decl::CXXRecord) ||
943  (DK == Decl::ClassTemplateSpecialization)) {
944  const TagDecl *TD = llvm::dyn_cast<TagDecl>(*fIter);
945  if (TD && !TD->isCompleteDefinition()) {
946  // For classes and enums, stop only on definitions.
947  continue;
948  }
949  if (DK == Decl::Namespace) {
950  // For namespaces, stop only on the first definition.
951  if (!fIter->isCanonicalDecl()) {
952  // Not the first definition.
953  fDescend = true;
954  continue;
955  }
956  }
957  if (DK != Decl::Enum) {
958  // We do not descend into enums.
959  DeclContext *DC = llvm::cast<DeclContext>(*fIter);
960  if ((fIterAll && *DC->decls_begin())
961  || (!fIterAll && *DC->noload_decls_begin())) {
962  // Next iteration will begin scanning the decl context
963  // contained by this decl.
964  fDescend = true;
965  }
966  }
967  // Iterator is now valid.
968  fDecl = *fIter;
969  fType = 0;
970  if (fDecl) {
971  if (fDecl->isInvalidDecl()) {
972  Warning("TClingClassInfo::Next()","Reached an invalid decl.");
973  }
974  if (const RecordDecl *RD =
975  llvm::dyn_cast<RecordDecl>(fDecl)) {
976  fType = RD->getASTContext().getRecordType(RD).getTypePtr();
977  }
978  }
979  return 1;
980  }
981  }
982 }
983 
985 {
986  return InternalNext();
987 }
988 
990 {
991  // Invoke a new expression to use the class constructor
992  // that takes no arguments to create an object of this class type.
993  if (!IsValid()) {
994  Error("TClingClassInfo::New()", "Called while invalid!");
995  return 0;
996  }
997  if (!IsLoaded()) {
998  Error("TClingClassInfo::New()", "Class is not loaded: %s",
999  FullyQualifiedName(fDecl).c_str());
1000  return 0;
1001  }
1002  {
1004  const CXXRecordDecl* RD = dyn_cast<CXXRecordDecl>(fDecl);
1005  if (!RD) {
1006  Error("TClingClassInfo::New()", "This is a namespace!: %s",
1007  FullyQualifiedName(fDecl).c_str());
1008  return 0;
1009  }
1010  if (!HasDefaultConstructor()) {
1011  // FIXME: We fail roottest root/io/newdelete if we issue this message!
1012  //Error("TClingClassInfo::New()", "Class has no default constructor: %s",
1013  // FullyQualifiedName(fDecl).c_str());
1014  return 0;
1015  }
1016  } // End of Lock section.
1017  void* obj = 0;
1018  TClingCallFunc cf(fInterp,normCtxt);
1019  obj = cf.ExecDefaultConstructor(this, /*address=*/0, /*nary=*/0);
1020  if (!obj) {
1021  Error("TClingClassInfo::New()", "Call of default constructor "
1022  "failed to return an object for class: %s",
1023  FullyQualifiedName(fDecl).c_str());
1024  return 0;
1025  }
1026  return obj;
1027 }
1028 
1030 {
1031  // Invoke a new expression to use the class constructor
1032  // that takes no arguments to create an array object
1033  // of this class type.
1034  if (!IsValid()) {
1035  Error("TClingClassInfo::New(n)", "Called while invalid!");
1036  return 0;
1037  }
1038  if (!IsLoaded()) {
1039  Error("TClingClassInfo::New(n)", "Class is not loaded: %s",
1040  FullyQualifiedName(fDecl).c_str());
1041  return 0;
1042  }
1043 
1044  {
1046 
1047  const CXXRecordDecl* RD = dyn_cast<CXXRecordDecl>(fDecl);
1048  if (!RD) {
1049  Error("TClingClassInfo::New(n)", "This is a namespace!: %s",
1050  FullyQualifiedName(fDecl).c_str());
1051  return 0;
1052  }
1053  if (!HasDefaultConstructor()) {
1054  // FIXME: We fail roottest root/io/newdelete if we issue this message!
1055  //Error("TClingClassInfo::New(n)",
1056  // "Class has no default constructor: %s",
1057  // FullyQualifiedName(fDecl).c_str());
1058  return 0;
1059  }
1060  } // End of Lock section.
1061  void* obj = 0;
1062  TClingCallFunc cf(fInterp,normCtxt);
1063  obj = cf.ExecDefaultConstructor(this, /*address=*/0,
1064  /*nary=*/(unsigned long)n);
1065  if (!obj) {
1066  Error("TClingClassInfo::New(n)", "Call of default constructor "
1067  "failed to return an array of class: %s",
1068  FullyQualifiedName(fDecl).c_str());
1069  return 0;
1070  }
1071  return obj;
1072 }
1073 
1074 void *TClingClassInfo::New(int n, 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  // array of objects of this class type in the given
1079  // memory arena.
1080  if (!IsValid()) {
1081  Error("TClingClassInfo::New(n, arena)", "Called while invalid!");
1082  return 0;
1083  }
1084  if (!IsLoaded()) {
1085  Error("TClingClassInfo::New(n, arena)", "Class is not loaded: %s",
1086  FullyQualifiedName(fDecl).c_str());
1087  return 0;
1088  }
1089  {
1091 
1092  const CXXRecordDecl* RD = dyn_cast<CXXRecordDecl>(fDecl);
1093  if (!RD) {
1094  Error("TClingClassInfo::New(n, arena)", "This is a namespace!: %s",
1095  FullyQualifiedName(fDecl).c_str());
1096  return 0;
1097  }
1098  if (!HasDefaultConstructor()) {
1099  // FIXME: We fail roottest root/io/newdelete if we issue this message!
1100  //Error("TClingClassInfo::New(n, arena)",
1101  // "Class has no default constructor: %s",
1102  // FullyQualifiedName(fDecl).c_str());
1103  return 0;
1104  }
1105  } // End of Lock section
1106  void* obj = 0;
1107  TClingCallFunc cf(fInterp,normCtxt);
1108  // Note: This will always return arena.
1109  obj = cf.ExecDefaultConstructor(this, /*address=*/arena,
1110  /*nary=*/(unsigned long)n);
1111  return obj;
1112 }
1113 
1114 void *TClingClassInfo::New(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
1115 {
1116  // Invoke a placement new expression to use the class
1117  // constructor that takes no arguments to create an
1118  // object of this class type in the given memory arena.
1119  if (!IsValid()) {
1120  Error("TClingClassInfo::New(arena)", "Called while invalid!");
1121  return 0;
1122  }
1123  if (!IsLoaded()) {
1124  Error("TClingClassInfo::New(arena)", "Class is not loaded: %s",
1125  FullyQualifiedName(fDecl).c_str());
1126  return 0;
1127  }
1128  {
1130 
1131  const CXXRecordDecl* RD = dyn_cast<CXXRecordDecl>(fDecl);
1132  if (!RD) {
1133  Error("TClingClassInfo::New(arena)", "This is a namespace!: %s",
1134  FullyQualifiedName(fDecl).c_str());
1135  return 0;
1136  }
1137  if (!HasDefaultConstructor()) {
1138  // FIXME: We fail roottest root/io/newdelete if we issue this message!
1139  //Error("TClingClassInfo::New(arena)",
1140  // "Class has no default constructor: %s",
1141  // FullyQualifiedName(fDecl).c_str());
1142  return 0;
1143  }
1144  } // End of Locked section.
1145  void* obj = 0;
1146  TClingCallFunc cf(fInterp,normCtxt);
1147  // Note: This will always return arena.
1148  obj = cf.ExecDefaultConstructor(this, /*address=*/arena, /*nary=*/0);
1149  return obj;
1150 }
1151 
1153 {
1154  if (!IsValid()) {
1155  return 0L;
1156  }
1157 
1159 
1160  long property = 0L;
1161  property |= kIsCPPCompiled;
1162  const clang::DeclContext *ctxt = fDecl->getDeclContext();
1163  clang::NamespaceDecl *std_ns =fInterp->getSema().getStdNamespace();
1164  while (! ctxt->isTranslationUnit()) {
1165  if (ctxt->Equals(std_ns)) {
1166  property |= kIsDefinedInStd;
1167  break;
1168  }
1169  ctxt = ctxt->getParent();
1170  }
1171  Decl::Kind DK = fDecl->getKind();
1172  if ((DK == Decl::Namespace) || (DK == Decl::TranslationUnit)) {
1173  property |= kIsNamespace;
1174  return property;
1175  }
1176  // Note: Now we have class, enum, struct, union only.
1177  const TagDecl *TD = llvm::dyn_cast<TagDecl>(fDecl);
1178  if (!TD) {
1179  return 0L;
1180  }
1181  if (TD->isEnum()) {
1182  property |= kIsEnum;
1183  return property;
1184  }
1185  // Note: Now we have class, struct, union only.
1186  const CXXRecordDecl *CRD =
1187  llvm::dyn_cast<CXXRecordDecl>(fDecl);
1188  if (CRD->isClass()) {
1189  property |= kIsClass;
1190  }
1191  else if (CRD->isStruct()) {
1192  property |= kIsStruct;
1193  }
1194  else if (CRD->isUnion()) {
1195  property |= kIsUnion;
1196  }
1197  if (CRD->hasDefinition() && CRD->isAbstract()) {
1198  property |= kIsAbstract;
1199  }
1200  return property;
1201 }
1202 
1204 {
1205  if (!IsValid()) {
1206  return 0;
1207  }
1208  // FIXME: Implement this when rootcling provides the value.
1209  return 0;
1210 }
1211 
1213 {
1214  if (!IsValid()) {
1215  return -1;
1216  }
1217  if (!fDecl) {
1218  // A forward declared class.
1219  return 0;
1220  }
1221 
1223 
1224  Decl::Kind DK = fDecl->getKind();
1225  if (DK == Decl::Namespace) {
1226  // Namespaces are special for cint.
1227  return 1;
1228  }
1229  else if (DK == Decl::Enum) {
1230  // Enums are special for cint.
1231  return 0;
1232  }
1233  const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(fDecl);
1234  if (!RD) {
1235  // Should not happen.
1236  return -1;
1237  }
1238  if (!RD->getDefinition()) {
1239  // Forward-declared class.
1240  return 0;
1241  }
1242  ASTContext &Context = fDecl->getASTContext();
1243  cling::Interpreter::PushTransactionRAII RAII(fInterp);
1244  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1245  int64_t size = Layout.getSize().getQuantity();
1246  int clang_size = static_cast<int>(size);
1247  return clang_size;
1248 }
1249 
1251 {
1252  if (!IsValid()) {
1253  return -1L;
1254  }
1255  return reinterpret_cast<long>(fDecl);
1256 }
1257 
1259 {
1260  if (!IsValid()) {
1261  return 0;
1262  }
1264  return fDeclFileName.c_str();
1265 }
1266 
1267 void TClingClassInfo::FullName(std::string &output, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
1268 {
1269  // Return QualifiedName.
1270  output.clear();
1271  if (!IsValid()) {
1272  return;
1273  }
1274  if (fType) {
1275  QualType type(fType, 0);
1276  ROOT::TMetaUtils::GetNormalizedName(output, type, *fInterp, normCtxt);
1277  }
1278  else {
1279  if (const NamedDecl* ND =
1280  llvm::dyn_cast<NamedDecl>(fDecl)) {
1281  PrintingPolicy Policy(fDecl->getASTContext().
1282  getPrintingPolicy());
1283  llvm::raw_string_ostream stream(output);
1284  ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true);
1285  }
1286  }
1287 }
1288 
1289 const char *TClingClassInfo::Name() const
1290 {
1291  // Return unqualified name.
1292  if (!IsValid()) {
1293  return 0;
1294  }
1295  // Note: This *must* be static/thread_local because we are returning a pointer inside it!
1296  TTHREAD_TLS_DECL( std::string, buf);
1297 
1298  buf.clear();
1299  if (const NamedDecl* ND = llvm::dyn_cast<NamedDecl>(fDecl)) {
1300  PrintingPolicy Policy(fDecl->getASTContext().getPrintingPolicy());
1301  llvm::raw_string_ostream stream(buf);
1302  ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/false);
1303  }
1304  return buf.c_str();
1305 }
1306 
1308 {
1309  if (!IsValid()) {
1310  return 0;
1311  }
1312  // NOTE: We cannot cache the result, since we are really an iterator.
1313  // Try to get the comment either from the annotation or the header
1314  // file, if present.
1315  // Iterate over the redeclarations, we can have multiple definitions in the
1316  // redecl chain (came from merging of pcms).
1317 
1319 
1320  if (const TagDecl *TD = llvm::dyn_cast<TagDecl>(GetDecl())) {
1321  if ( (TD = ROOT::TMetaUtils::GetAnnotatedRedeclarable(TD)) ) {
1322  if (AnnotateAttr *A = TD->getAttr<AnnotateAttr>()) {
1323  std::string attr = A->getAnnotation().str();
1324  if (attr.find(TMetaUtils::propNames::separator) != std::string::npos) {
1326  fTitle = attr;
1327  return fTitle.c_str();
1328  }
1329  } else {
1330  fTitle = attr;
1331  return fTitle.c_str();
1332  }
1333  }
1334  }
1335  }
1336  // Try to get the comment from the header file, if present.
1337  // but not for decls from AST file, where rootcling would have
1338  // created an annotation
1339  const CXXRecordDecl *CRD =
1340  llvm::dyn_cast<CXXRecordDecl>(GetDecl());
1341  if (CRD && !CRD->isFromASTFile()) {
1343  }
1344  return fTitle.c_str();
1345 }
1346 
1347 const char *TClingClassInfo::TmpltName() const
1348 {
1349  if (!IsValid()) {
1350  return 0;
1351  }
1352 
1354 
1355  // Note: This *must* be static/thread_local because we are returning a pointer inside it!
1356  TTHREAD_TLS_DECL( std::string, buf);
1357  buf.clear();
1358  if (const NamedDecl* ND = llvm::dyn_cast<NamedDecl>(fDecl)) {
1359  // Note: This does *not* include the template arguments!
1360  buf = ND->getNameAsString();
1361  }
1362  return buf.c_str();
1363 }
1364 
const clang::FunctionTemplateDecl * GetFunctionTemplate(const char *fname) const
void AddBaseOffsetValue(const clang::Decl *decl, ptrdiff_t offset)
llvm::DenseMap< const clang::Decl *, std::pair< ptrdiff_t, OffsetPtrFunc_t > > fOffsetCache
bool IsLoaded() const
llvm::StringRef GetFileName(const clang::Decl &decl, const cling::Interpreter &interp)
Return the header file to be included to declare the Decl.
Namespace for new ROOT classes and functions.
Definition: ROOT.py:1
void Fatal(const char *location, const char *msgfmt,...)
bool IsValid() const
const char * Name() const
RooArgList L(const RooAbsArg &v1)
static const std::string comment("comment")
const clang::Type * fType
int GetMethodNArg(const char *method, const char *proto, Bool_t objectIsConst, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch) const
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:46
bool HasMethod(const char *name) const
void Destruct(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) 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)
std::string InsertStd(const char *tname)
bool HasDefaultConstructor() const
TClingMethodInfo GetMethod(const char *fname) const
bool Bool_t
Definition: RtypesCore.h:59
long Tagnum() const
const char * FileName()
ClassImp(TIterator) Bool_t TIterator return false
Compare two iterator objects.
Definition: TIterator.cxx:20
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 "propNamepropValue" format.
ptrdiff_t(* OffsetPtrFunc_t)(void *, bool)
const clang::Decl * fDecl
static const std::string separator("@@@")
const char * Title()
long ClassProperty() const
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
EFunctionMatchMode
Definition: TDictionary.h:155
static bool IsEnum(cling::Interpreter *interp, const char *name)
bool IsValid() const
def Namespace(name)
Definition: cppyy.py:193
void Error(const char *location, const char *msgfmt,...)
long GetOffset(const clang::CXXMethodDecl *md) 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)
TClingClassInfo * GetBase() const
void Init(const clang::FunctionDecl *)
Emulation of the CINT BaseClassInfo class.
ptrdiff_t Offset(void *address=0, bool isDerivedObject=true) const
const clang::FunctionDecl * GetMethodDecl() const
const T * GetAnnotatedRedeclarable(const T *Redecl)
Definition: TMetaUtils.h:617
Double_t E()
Definition: TMath.h:54
void Warning(const char *location, const char *msgfmt,...)
Type
enumeration specifying the integration types.
PyObject * fType
const clang::Decl * GetDecl() const
Definition: TCling.h:48
void DeleteArray(void *arena, bool dtorOnly, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
int type
Definition: TGX11.cxx:120
void FullName(std::string &output, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
Emulation of the CINT ClassInfo class.
#define R__LOCKGUARD(mutex)
Enum
Definition: load.cpp:93
llvm::StringRef GetClassComment(const clang::CXXRecordDecl &decl, clang::SourceLocation *loc, const cling::Interpreter &interpreter)
Return the class comment after the ClassDef: class MyClass { ...
long Property() const
const clang::ValueDecl * GetDataMember(const char *name) const
void Delete(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
void * New(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
#define name(a, b)
Definition: linkTestLib0.cpp:5
void * ExecDefaultConstructor(const TClingClassInfo *info, void *address=0, unsigned long nary=0UL)
static bool HasBody(const clang::FunctionDecl &decl, const cling::Interpreter &interp)
RooCmdArg Layout(Double_t xmin, Double_t xmax=0.99, Double_t ymin=0.95)
clang::DeclContext::decl_iterator fIter
TClingMethodInfo GetMethodWithArgs(const char *fname, const char *arglist, long *poffset, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch, EInheritanceMode imode=kWithInheritance) const
void ExecDestructor(const TClingClassInfo *info, void *address=0, unsigned long nary=0UL, bool withFree=true)
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
static std::string FullyQualifiedName(const Decl *decl)
std::vector< clang::DeclContext::decl_iterator > fIterStack
bool IsBase(const char *name) const
#define I(x, y, z)
bool IsValidMethod(const char *method, const char *proto, Bool_t objectIsConst, long *offset, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch) const
cling::Interpreter * fInterp
static void output(int code)
Definition: gifencode.c:226
const Bool_t kTRUE
Definition: Rtypes.h:91
TObject * obj
const Int_t n
Definition: legend1.C:16
int RootFlag() const