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