Logo ROOT   6.08/07
Reference Guide
TClingMethodInfo.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 TClingMethodInfo
13 Emulation of the CINT MethodInfo class.
14 
15 The CINT C++ interpreter provides an interface to metadata about
16 a function through the MethodInfo class. This class provides the
17 same functionality, using an interface as close as possible to
18 MethodInfo but the typedef metadata comes from the Clang C++
19 compiler, not CINT.
20 */
21 
22 #include "TClingMethodInfo.h"
23 
24 #include "TClingCallFunc.h"
25 #include "TClingClassInfo.h"
26 #include "TClingMethodArgInfo.h"
27 #include "TDictionary.h"
28 #include "TClingTypeInfo.h"
29 #include "TError.h"
30 #include "TMetaUtils.h"
31 #include "TCling.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/ExprCXX.h"
43 #include "clang/AST/GlobalDecl.h"
44 #include "clang/AST/Mangle.h"
45 #include "clang/AST/PrettyPrinter.h"
46 #include "clang/AST/Type.h"
47 #include "clang/Basic/IdentifierTable.h"
48 #include "clang/Sema/Lookup.h"
49 #include "clang/Sema/Sema.h"
50 #include "clang/Sema/Template.h"
51 #include "clang/Sema/TemplateDeduction.h"
52 
53 #include "llvm/Support/Casting.h"
54 #include "llvm/Support/raw_ostream.h"
55 
56 #include <string>
57 
58 using namespace clang;
59 
60 class TClingMethodInfo::SpecIterator
61 {
62 public:
63  typedef clang::FunctionTemplateDecl::spec_iterator Iterator;
64 
65  SpecIterator(Iterator begin, Iterator end) : fIter(begin), fEnd(end) {}
66  explicit SpecIterator(clang::FunctionTemplateDecl *decl) : fIter(decl->spec_begin()), fEnd(decl->spec_end()) {}
67 
68  FunctionDecl *operator* () const { return *fIter; }
69  FunctionDecl *operator-> () const { return *fIter; }
70  SpecIterator & operator++ () { ++fIter; return *this; }
71  SpecIterator operator++ (int) {
72  SpecIterator tmp(fIter,fEnd);
73  ++(*this);
74  return tmp;
75  }
76  bool operator!() { return fIter == fEnd; }
77  operator bool() { return fIter != fEnd; }
78 
79 private:
80 
81  Iterator fIter;
82  Iterator fEnd;
83 };
84 
86  fInterp(rhs.fInterp),
87  fContexts(rhs.fContexts),
88  fFirstTime(rhs.fFirstTime),
89  fContextIdx(rhs.fContextIdx),
90  fIter(rhs.fIter),
91  fTitle(rhs.fTitle),
92  fTemplateSpecIter(nullptr),
93  fSingleDecl(rhs.fSingleDecl)
94 {
95  if (rhs.fTemplateSpecIter) {
96  // The SpecIterator query the decl.
98  fTemplateSpecIter = new SpecIterator(*rhs.fTemplateSpecIter);
99  }
100 }
101 
102 
103 TClingMethodInfo::TClingMethodInfo(cling::Interpreter *interp,
104  TClingClassInfo *ci)
105  : fInterp(interp), fFirstTime(true), fContextIdx(0U), fTitle(""),
107 {
109 
110  if (!ci || !ci->IsValid()) {
111  return;
112  }
113  clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(const_cast<clang::Decl*>(ci->GetDecl()));
114  if (cxxdecl) {
115  // Make sure we have an entry for all the implicit function.
116 
117  // Could trigger deserialization of decls.
118  cling::Interpreter::PushTransactionRAII RAII(interp);
119 
120  fInterp->getSema().ForceDeclarationOfImplicitMembers(cxxdecl);
121  }
122  clang::DeclContext *dc =
123  llvm::cast<clang::DeclContext>(const_cast<clang::Decl*>(ci->GetDecl()));
124  dc->collectAllContexts(fContexts);
125  // Could trigger deserialization of decls.
126  cling::Interpreter::PushTransactionRAII RAII(interp);
127  fIter = dc->decls_begin();
128  InternalNext();
129  fFirstTime = true;
130 }
131 
132 TClingMethodInfo::TClingMethodInfo(cling::Interpreter *interp,
133  const clang::FunctionDecl *FD)
134  : fInterp(interp), fFirstTime(true), fContextIdx(0U), fTitle(""),
136 {
137 
138 }
139 
141 {
142  delete fTemplateSpecIter;
143 }
144 
146 {
147  if (!IsValid()) {
148  return TDictionary::DeclId_t();
149  }
150  return (const clang::Decl*)(GetMethodDecl()->getCanonicalDecl());
151 }
152 
153 const clang::FunctionDecl *TClingMethodInfo::GetMethodDecl() const
154 {
155  if (!IsValid()) {
156  return 0;
157  }
158 
159  if (fSingleDecl)
160  return fSingleDecl;
161 
162  if (fTemplateSpecIter)
163  return *(*fTemplateSpecIter);
164 
165  return llvm::dyn_cast<clang::FunctionDecl>(*fIter);
166 }
167 
168 void TClingMethodInfo::CreateSignature(TString &signature) const
169 {
170  signature = "(";
171  if (!IsValid()) {
172  signature += ")";
173  return;
174  }
175 
177  TClingMethodArgInfo arg(fInterp, this);
178 
179  int idx = 0;
180  while (arg.Next()) {
181  if (idx) {
182  signature += ", ";
183  }
184  signature += arg.Type()->Name();
185  if (arg.Name() && strlen(arg.Name())) {
186  signature += " ";
187  signature += arg.Name();
188  }
189  if (arg.DefaultValue()) {
190  signature += " = ";
191  signature += arg.DefaultValue();
192  }
193  ++idx;
194  }
195  signature += ")";
196 }
197 
198 void TClingMethodInfo::Init(const clang::FunctionDecl *decl)
199 {
200  fContexts.clear();
201  fFirstTime = true;
202  fContextIdx = 0U;
203  fIter = clang::DeclContext::decl_iterator();
204  delete fTemplateSpecIter;
205  fTemplateSpecIter = 0;
206  fSingleDecl = decl;
207 }
208 
210 {
211  if (!IsValid()) {
212  return 0;
213  }
215  TClingCallFunc cf(fInterp,normCtxt);
216  cf.SetFunc(this);
217  return cf.InterfaceMethod();
218 }
219 
221 {
222  if (fSingleDecl) return fSingleDecl;
223  else if (fTemplateSpecIter) {
224  // Could trigger deserialization of decls.
226  cling::Interpreter::PushTransactionRAII RAII(fInterp);
227  return *(*fTemplateSpecIter);
228  }
229  return *fIter;
230 }
231 
233 {
234  if (!IsValid()) {
235  return -1;
236  }
237  const clang::FunctionDecl *fd = GetMethodDecl();
238  unsigned num_params = fd->getNumParams();
239  // Truncate cast to fit cint interface.
240  return static_cast<int>(num_params);
241 }
242 
244 {
245  if (!IsValid()) {
246  return -1;
247  }
248  const clang::FunctionDecl *fd = GetMethodDecl();
249  unsigned num_params = fd->getNumParams();
250  unsigned min_args = fd->getMinRequiredArguments();
251  unsigned defaulted_params = num_params - min_args;
252  // Truncate cast to fit cint interface.
253  return static_cast<int>(defaulted_params);
254 }
255 
256 /*
257 static bool HasUnexpandedParameterPack(clang::QualType QT, clang::Sema& S) {
258  if (llvm::isa<PackExpansionType>(*QT)) {
259  // We are not going to expand the pack here...
260  return true;
261  }
262  SmallVector<UnexpandedParameterPack, 4> Unexpanded;
263  S.collectUnexpandedParameterPacks (QT, Unexpanded);
264 
265  return !Unexpanded.empty();
266 }
267  */
268 
269 static void InstantiateFuncTemplateWithDefaults(clang::FunctionTemplateDecl* FTDecl,
270  clang::Sema& S,
271  const cling::LookupHelper& LH) {
272  // Force instantiation if it doesn't exist yet, by looking it up.
273  using namespace clang;
274 
275  auto templateParms = FTDecl->getTemplateParameters();
276  if (templateParms->containsUnexpandedParameterPack())
277  return;
278 
279  if (templateParms->getMinRequiredArguments() > 0)
280  return;
281 
282  if (templateParms->size() > 0) {
283  NamedDecl *arg0 = *templateParms->begin();
284  if (arg0->isTemplateParameterPack())
285  return;
286  if (auto TTP = dyn_cast<TemplateTypeParmDecl>(*templateParms->begin())) {
287  if (!TTP->hasDefaultArgument())
288  return;
289  } else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(
290  *templateParms->begin())) {
291  if (!NTTP->hasDefaultArgument())
292  return;
293  } else {
294  // TemplateTemplateParmDecl, pack
295  return;
296  }
297  }
298 
299  FunctionDecl *templatedDecl = FTDecl->getTemplatedDecl();
300  Decl *declCtxDecl = dyn_cast<Decl>(FTDecl->getDeclContext());
301 
302  llvm::SmallVector<QualType, 8> paramTypes;
303  bool skip = false; // whether we should not look this up.
304  const ClassTemplateSpecializationDecl *ctxInstance
305  = dyn_cast<ClassTemplateSpecializationDecl>(declCtxDecl);
306 
307  // Provide an instantiation context that suppresses errors:
308  // DeducedTemplateArgumentSubstitution! (ROOT-8422)
309  SmallVector<DeducedTemplateArgument, 4> DeducedArgs;
310  ArrayRef< TemplateArgument > TemplateArgs;
311  sema::TemplateDeductionInfo Info{SourceLocation()};
312 
313  Sema::InstantiatingTemplate Inst(S, Info.getLocation(), FTDecl,
314  TemplateArgs,
315  Sema::ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
316  Info);
317 
318  // Collect the function arguments of the templated function, substituting
319  // dependent types as possible.
320  for (const clang::ParmVarDecl *param: templatedDecl->parameters()) {
321  QualType paramType = param->getOriginalType();
322 
323  // If the function type is dependent, try to resolve it through the class's
324  // template arguments. If that fails, skip this function.
325  if (ctxInstance && paramType->isDependentType()) {
326  /*if (HasUnexpandedParameterPack(paramType, S)) {
327  // We are not going to expand the pack here...
328  skip = true;
329  break;
330  }*/
331 
332  MultiLevelTemplateArgumentList MLTAL(
333  ctxInstance->getTemplateInstantiationArgs());
334  paramType = S.SubstType(paramType, MLTAL, SourceLocation(),
335  templatedDecl->getDeclName());
336 
337  if (paramType.isNull() || paramType->isDependentType()) {
338  // Even after resolving the types through the surrounding template
339  // this argument type is still dependent: do not look it up.
340  skip = true;
341  break;
342  }
343  }
344  paramTypes.push_back(paramType);
345  }
346 
347  if (!skip) {
348  LH.findFunctionProto(declCtxDecl, FTDecl->getNameAsString(),
349  paramTypes, LH.NoDiagnostics,
350  templatedDecl->getType().isConstQualified());
351  }
352 }
353 
355 {
356 
357  assert(!fSingleDecl && "This is not an iterator!");
358 
359  if (!fFirstTime && !*fIter) {
360  // Iterator is already invalid.
361  return 0;
362  }
363  while (true) {
364  // Advance to the next decl.
365  if (fFirstTime) {
366  // The cint semantics are weird.
367  fFirstTime = false;
368  }
369  else {
370  if (fTemplateSpecIter) {
371  ++(*fTemplateSpecIter);
372  if ( !(*fTemplateSpecIter) ) {
373  // We reached the end of the template specialization.
374  delete fTemplateSpecIter;
375  fTemplateSpecIter = 0;
376  ++fIter;
377  } else {
378  return 1;
379  }
380  } else {
381  ++fIter;
382  }
383  }
384  // Fix it if we have gone past the end of the current decl context.
385  while (!*fIter) {
386  ++fContextIdx;
387  if (fContextIdx >= fContexts.size()) {
388  // Iterator is now invalid.
389  return 0;
390  }
391  clang::DeclContext *dc = fContexts[fContextIdx];
392  // Could trigger deserialization of decls.
393 
394  cling::Interpreter::PushTransactionRAII RAII(fInterp);
395  fIter = dc->decls_begin();
396  if (*fIter) {
397  // Good, a non-empty context.
398  break;
399  }
400  }
401 
402  clang::FunctionTemplateDecl *templateDecl =
403  llvm::dyn_cast<clang::FunctionTemplateDecl>(*fIter);
404 
405  if ( templateDecl ) {
406  // SpecIterator calls clang::FunctionTemplateDecl::spec_begin
407  // which calls clang::FunctionTemplateDecl::LoadLazySpecializations.
408  // Instantiation below can also trigger deserialization.
409  cling::Interpreter::PushTransactionRAII RAII(fInterp);
410 
411  // If this function template can be instantiated without template
412  // arguments then it's worth having it. This commonly happens for
413  // enable_if'ed functions.
414  // Whatever this finds / instantiates will be picked up by the
415  // SpecIterator below.
416  InstantiateFuncTemplateWithDefaults(templateDecl, fInterp->getSema(),
417  fInterp->getLookupHelper());
418 
419  SpecIterator subiter(templateDecl);
420  if (subiter) {
421  delete fTemplateSpecIter;
422  fTemplateSpecIter = new SpecIterator(templateDecl);
423  return 1;
424  }
425  }
426 
427  // Return if this decl is a function or method.
428  if (llvm::isa<clang::FunctionDecl>(*fIter)) {
429  // Iterator is now valid.
430  return 1;
431  }
432 // if (clang::FunctionDecl *fdecl = llvm::dyn_cast<clang::FunctionDecl>(*fIter)) {
433 // if (fdecl->getAccess() == clang::AS_public || fdecl->getAccess() == clang::AS_none) {
434 // // Iterator is now valid.
435 // return 1;
436 // }
437 // }
438  }
439 }
440 
442 {
443  return InternalNext();
444 }
445 
447 {
448  if (!IsValid()) {
449  return 0L;
450  }
451  long property = 0L;
452  property |= kIsCompiled;
453  const clang::FunctionDecl *fd = GetMethodDecl();
454  switch (fd->getAccess()) {
455  case clang::AS_public:
456  property |= kIsPublic;
457  break;
458  case clang::AS_protected:
459  property |= kIsProtected;
460  break;
461  case clang::AS_private:
462  property |= kIsPrivate;
463  break;
464  case clang::AS_none:
465  if (fd->getDeclContext()->isNamespace())
466  property |= kIsPublic;
467  break;
468  default:
469  // IMPOSSIBLE
470  break;
471  }
472  if (fd->getStorageClass() == clang::SC_Static) {
473  property |= kIsStatic;
474  }
475  clang::QualType qt = fd->getReturnType().getCanonicalType();
476  if (qt.isConstQualified()) {
477  property |= kIsConstant;
478  }
479  while (1) {
480  if (qt->isArrayType()) {
481  qt = llvm::cast<clang::ArrayType>(qt)->getElementType();
482  continue;
483  }
484  else if (qt->isReferenceType()) {
485  property |= kIsReference;
486  qt = llvm::cast<clang::ReferenceType>(qt)->getPointeeType();
487  continue;
488  }
489  else if (qt->isPointerType()) {
490  property |= kIsPointer;
491  if (qt.isConstQualified()) {
492  property |= kIsConstPointer;
493  }
494  qt = llvm::cast<clang::PointerType>(qt)->getPointeeType();
495  continue;
496  }
497  else if (qt->isMemberPointerType()) {
498  qt = llvm::cast<clang::MemberPointerType>(qt)->getPointeeType();
499  continue;
500  }
501  break;
502  }
503  if (qt.isConstQualified()) {
504  property |= kIsConstant;
505  }
506  if (const clang::CXXMethodDecl *md =
507  llvm::dyn_cast<clang::CXXMethodDecl>(fd)) {
508  if (md->getTypeQualifiers() & clang::Qualifiers::Const) {
509  property |= kIsConstant | kIsConstMethod;
510  }
511  if (md->isVirtual()) {
512  property |= kIsVirtual;
513  }
514  if (md->isPure()) {
515  property |= kIsPureVirtual;
516  }
517  if (const clang::CXXConstructorDecl *cd =
518  llvm::dyn_cast<clang::CXXConstructorDecl>(md)) {
519  if (cd->isExplicit()) {
520  property |= kIsExplicit;
521  }
522  }
523  else if (const clang::CXXConversionDecl *cd =
524  llvm::dyn_cast<clang::CXXConversionDecl>(md)) {
525  if (cd->isExplicit()) {
526  property |= kIsExplicit;
527  }
528  }
529  }
530  return property;
531 }
532 
534 {
535  // Return the property not already defined in Property
536  // See TDictionary's EFunctionProperty
537  if (!IsValid()) {
538  return 0L;
539  }
540  long property = 0;
541  const clang::FunctionDecl *fd = GetMethodDecl();
542  if (fd->isOverloadedOperator()) {
543  property |= kIsOperator;
544  }
545  else if (llvm::isa<clang::CXXConversionDecl>(fd)) {
546  property |= kIsConversion;
547  } else if (llvm::isa<clang::CXXConstructorDecl>(fd)) {
548  property |= kIsConstructor;
549  } else if (llvm::isa<clang::CXXDestructorDecl>(fd)) {
550  property |= kIsDestructor;
551  }
552  return property;
553 }
554 
556 {
557  TTHREAD_TLS_DECL_ARG( TClingTypeInfo, ti, fInterp );
558  if (!IsValid()) {
559  ti.Init(clang::QualType());
560  return &ti;
561  }
562  if (llvm::isa<clang::CXXConstructorDecl>(GetMethodDecl())) {
563  // CINT claims that constructors return the class object.
564  const clang::TypeDecl* ctorClass = llvm::dyn_cast_or_null<clang::TypeDecl>
565  (GetMethodDecl()->getDeclContext());
566  if (!ctorClass) {
567  Error("TClingMethodInfo::Type", "Cannot find DeclContext for constructor!");
568  } else {
569  clang::QualType qt(ctorClass->getTypeForDecl(), 0);
570  ti.Init(qt);
571  }
572  } else {
573  clang::QualType qt = GetMethodDecl()->getReturnType();
574  ti.Init(qt);
575  }
576  return &ti;
577 }
578 
580 {
581  if (!IsValid()) {
582  return "";
583  }
584  std::string mangled_name;
585  mangled_name.clear();
586  const FunctionDecl* D = GetMethodDecl();
587 
589  GlobalDecl GD;
590  if (const CXXConstructorDecl* Ctor = dyn_cast<CXXConstructorDecl>(D))
591  GD = GlobalDecl(Ctor, Ctor_Complete);
592  else if (const CXXDestructorDecl* Dtor = dyn_cast<CXXDestructorDecl>(D))
593  GD = GlobalDecl(Dtor, Dtor_Deleting);
594  else
595  GD = GlobalDecl(D);
596 
597  cling::utils::Analyze::maybeMangleDeclName(GD, mangled_name);
598  return mangled_name;
599 }
600 
602 {
603  if (!IsValid()) {
604  return 0;
605  }
606  TTHREAD_TLS_DECL( std::string, buf );
607  buf.clear();
608  buf += Type()->Name();
609  buf += ' ';
610  if (const clang::TypeDecl *td = llvm::dyn_cast<clang::TypeDecl>(GetMethodDecl()->getDeclContext())) {
611  std::string name;
612  clang::QualType qualType(td->getTypeForDecl(),0);
614  buf += name;
615  buf += "::";
616  } else if (const clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(GetMethodDecl()->getDeclContext())) {
617  std::string name;
618  clang::PrintingPolicy policy(GetMethodDecl()->getASTContext().getPrintingPolicy());
619  llvm::raw_string_ostream stream(name);
620  nd->getNameForDiagnostic(stream, policy, /*Qualified=*/true);
621  stream.flush();
622  buf += name;
623  buf += "::";
624  }
625  buf += Name(normCtxt);
626  buf += '(';
627  TClingMethodArgInfo arg(fInterp, this);
628  int idx = 0;
629  while (arg.Next()) {
630  if (idx) {
631  buf += ", ";
632  }
633  buf += arg.Type()->Name();
634  if (arg.Name() && strlen(arg.Name())) {
635  buf += ' ';
636  buf += arg.Name();
637  }
638  if (arg.DefaultValue()) {
639  buf += " = ";
640  buf += arg.DefaultValue();
641  }
642  ++idx;
643  }
644  buf += ')';
645  if (const clang::CXXMethodDecl *md =
646  llvm::dyn_cast<clang::CXXMethodDecl>( GetMethodDecl())) {
647  if (md->getTypeQualifiers() & clang::Qualifiers::Const) {
648  buf += " const";
649  }
650  }
651  return buf.c_str();
652 }
653 
655 {
656  if (!IsValid()) {
657  return 0;
658  }
659  TTHREAD_TLS_DECL( std::string, buf );
660  ((TCling*)gCling)->GetFunctionName(GetMethodDecl(),buf);
661  return buf.c_str();
662 }
663 
664 const char *TClingMethodInfo::TypeName() const
665 {
666  if (!IsValid()) {
667  // FIXME: Cint does not check!
668  return 0;
669  }
670  return Type()->Name();
671 }
672 
674 {
675  if (!IsValid()) {
676  return 0;
677  }
678 
679  //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
680  //if (fTitle.size())
681  // return fTitle.c_str();
682 
683  // Try to get the comment either from the annotation or the header file if present
684 
685  // Iterate over the redeclarations, we can have multiple definitions in the
686  // redecl chain (came from merging of pcms).
687  const FunctionDecl *FD = GetMethodDecl();
688 
690 
691  // Could trigger deserialization of decls.
692  cling::Interpreter::PushTransactionRAII RAII(fInterp);
693  if (const FunctionDecl *AnnotFD
695  if (AnnotateAttr *A = AnnotFD->getAttr<AnnotateAttr>()) {
696  fTitle = A->getAnnotation().str();
697  return fTitle.c_str();
698  }
699  }
700  if (!FD->isFromASTFile()) {
701  // Try to get the comment from the header file if present
702  // but not for decls from AST file, where rootcling would have
703  // created an annotation
705  }
706 
707  return fTitle.c_str();
708 }
709 
const TClingTypeInfo * Type() const
bool IsValid() const
RooArgList L(const RooAbsArg &v1)
const clang::Decl * GetDecl() const
static void InstantiateFuncTemplateWithDefaults(clang::FunctionTemplateDecl *FTDecl, clang::Sema &S, const cling::LookupHelper &LH)
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:46
const char * Name() const
void SetFunc(const TClingClassInfo *info, const char *method, const char *arglist, long *poffset)
llvm::SmallVector< clang::DeclContext *, 2 > fContexts
Emulation of the CINT MethodInfo class.
const char * DefaultValue() const
clang::DeclContext::decl_iterator fIter
void * InterfaceMethod(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
void GetFullyQualifiedTypeName(std::string &name, const clang::QualType &type, const cling::Interpreter &interpreter)
std::string GetMangledName() const
const char * Title()
static double A[]
Emulation of the CINT CallFunc class.
const void * DeclId_t
Definition: TDictionary.h:209
void CreateSignature(TString &signature) const
const char * TypeName() const
void Info(const char *location, const char *msgfmt,...)
Emulation of the CINT TypeInfo class.
This class defines an interface to the cling C++ interpreter.
Definition: TCling.h:92
void Error(const char *location, const char *msgfmt,...)
long ExtraProperty() const
const clang::FunctionDecl * GetMethodDecl() const
const char * GetPrototype(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
void * InterfaceMethod()
SpecIterator * fTemplateSpecIter
RooArgSet S(const RooAbsArg &v1)
TCut operator!(const TCut &rhs)
Logical negation.
Definition: TCut.cxx:292
void Init(const clang::FunctionDecl *)
unsigned int fContextIdx
TTime operator*(const TTime &t1, const TTime &t2)
Definition: TTime.h:87
const T * GetAnnotatedRedeclarable(const T *Redecl)
Definition: TMetaUtils.h:628
TDictionary::DeclId_t GetDeclId() const
std::string fTitle
const clang::FunctionDecl * fSingleDecl
Emulation of the CINT MethodInfo class.
Definition: TCling.h:48
Emulation of the CINT ClassInfo class.
#define R__LOCKGUARD(mutex)
TClingMethodInfo(cling::Interpreter *interp)
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...
#define nullptr
Definition: Rtypes.h:87
TClingTypeInfo * Type() const
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:519
const char * Name() const
cling::Interpreter * fInterp
static char * skip(char **buf, const char *delimiters)
Definition: civetweb.c:2039
const char * Name(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
char name[80]
Definition: TGX11.cxx:109