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