Logo ROOT  
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 "TClingMemberIter.h"
27#include "TClingMethodArgInfo.h"
28#include "TDictionary.h"
29#include "TClingTypeInfo.h"
30#include "TError.h"
31#include "TClingUtils.h"
32#include "TCling.h"
33#include "ThreadLocalStorage.h"
34
35#include "cling/Interpreter/Interpreter.h"
36#include "cling/Interpreter/LookupHelper.h"
37#include "cling/Utils/AST.h"
38
39#include "clang/AST/ASTContext.h"
40#include "clang/AST/CXXInheritance.h"
41#include "clang/AST/Decl.h"
42#include "clang/AST/DeclBase.h"
43#include "clang/AST/DeclCXX.h"
44#include "clang/AST/DeclTemplate.h"
45#include "clang/AST/ExprCXX.h"
46#include "clang/AST/GlobalDecl.h"
47#include "clang/AST/Mangle.h"
48#include "clang/AST/PrettyPrinter.h"
49#include "clang/AST/Type.h"
50#include "clang/Basic/IdentifierTable.h"
51#include "clang/Sema/Lookup.h"
52#include "clang/Sema/Sema.h"
53#include "clang/Sema/Template.h"
54#include "clang/Sema/TemplateDeduction.h"
55
56#include "llvm/Support/Casting.h"
57#include "llvm/Support/raw_ostream.h"
58
59#include <algorithm>
60#include <string>
61
62using namespace clang;
63
64TClingCXXRecMethIter::SpecFuncIter::SpecFuncIter(cling::Interpreter *interp, clang::DeclContext *DC,
65 llvm::SmallVectorImpl<clang::CXXMethodDecl *> &&specFuncs)
66{
67 auto *CXXRD = llvm::dyn_cast<CXXRecordDecl>(DC);
68 if (!CXXRD)
69 return;
70
71 // Could trigger deserialization of decls.
72 cling::Interpreter::PushTransactionRAII RAII(interp);
73
74 auto emplaceSpecFunIfNeeded = [&](clang::CXXMethodDecl *D) {
75 if (!D)
76 return; // Handle "structor not found" case.
77
78 if (std::find(CXXRD->decls_begin(), CXXRD->decls_end(), D) == CXXRD->decls_end()) {
79 fDefDataSpecFuns.emplace_back(D);
80 }
81 };
82
83 for (auto SpecFunc : specFuncs)
84 emplaceSpecFunIfNeeded(SpecFunc);
85}
86
87bool TClingCXXRecMethIter::ShouldSkip(const clang::Decl *D) const
88{
89 if (const auto *FD = llvm::dyn_cast<clang::FunctionDecl>(D)) {
90 if (FD->isDeleted())
91 return true;
92 if (const auto *RD = llvm::dyn_cast<clang::RecordDecl>(FD->getDeclContext())) {
93 if (const auto *CXXMD = llvm::dyn_cast<clang::CXXMethodDecl>(FD)) {
94 if (RD->isAnonymousStructOrUnion() &&
95 GetInterpreter()->getSema().getSpecialMember(CXXMD) != clang::Sema::CXXInvalid) {
96 // Do not enumerate special members of anonymous structs.
97 return true;
98 }
99 }
100 }
101 return false;
102 }
103 return true;
104}
105
106bool TClingCXXRecMethIter::ShouldSkip(const clang::UsingShadowDecl *USD) const
107{
108 if (auto *FD = llvm::dyn_cast<clang::FunctionDecl>(USD->getTargetDecl())) {
109 if (const auto *CXXMD = llvm::dyn_cast<clang::CXXMethodDecl>(FD)) {
110 auto SpecMemKind = GetInterpreter()->getSema().getSpecialMember(CXXMD);
111 if ((SpecMemKind == clang::Sema::CXXDefaultConstructor && CXXMD->getNumParams() == 0) ||
112 ((SpecMemKind == clang::Sema::CXXCopyConstructor || SpecMemKind == clang::Sema::CXXMoveConstructor) &&
113 CXXMD->getNumParams() == 1)) {
114 // This is a special member pulled in through a using decl. Special
115 // members of derived classes cannot be replaced; ignore this using decl,
116 // and keep only the (still possibly compiler-generated) special member of the
117 // derived class.
118 // NOTE that e.g. `Klass(int = 0)` has SpecMemKind == clang::Sema::CXXDefaultConstructor,
119 // yet this signature must be exposed, so check the argument count.
120 return true;
121 }
122 }
123 return ShouldSkip(FD);
124 }
125 // TODO: handle multi-level UsingShadowDecls.
126 return true;
127}
128
129const clang::Decl *
130TClingCXXRecMethIter::InstantiateTemplateWithDefaults(const clang::RedeclarableTemplateDecl *TD) const
131{
132 // Force instantiation if it doesn't exist yet, by looking it up.
133
134 using namespace clang;
135
136 cling::Interpreter *interp = GetInterpreter();
137 Sema &S = interp->getSema();
138 const cling::LookupHelper &LH = interp->getLookupHelper();
139
140 if (!isa<FunctionTemplateDecl>(TD))
141 return nullptr;
142
143 auto templateParms = TD->getTemplateParameters();
144 if (templateParms->containsUnexpandedParameterPack())
145 return nullptr;
146
147 if (templateParms->getMinRequiredArguments() > 0)
148 return nullptr;
149
150 if (templateParms->size() > 0) {
151 NamedDecl *arg0 = *templateParms->begin();
152 if (arg0->isTemplateParameterPack())
153 return nullptr;
154 if (auto TTP = dyn_cast<TemplateTypeParmDecl>(*templateParms->begin())) {
155 if (!TTP->hasDefaultArgument())
156 return nullptr;
157 } else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(*templateParms->begin())) {
158 if (!NTTP->hasDefaultArgument())
159 return nullptr;
160 } else {
161 // TemplateTemplateParmDecl, pack
162 return nullptr;
163 }
164 }
165
166 const FunctionDecl *templatedDecl = llvm::dyn_cast<FunctionDecl>(TD->getTemplatedDecl());
167 const Decl *declCtxDecl = dyn_cast<Decl>(TD->getDeclContext());
168
169 // We have a function template
170 // template <class X = int, int i = 7> void func(int a0, X a1[i], X::type a2[i])
171 // which has defaults for all its template parameters `X` and `i`. To
172 // instantiate it we have to do a lookup, which in turn needs the function
173 // argument types, e.g. `int[12]`.
174 // If the function argument type is dependent (a1 and a2) we need to
175 // substitute the types first, using the template arguments derived from the
176 // template parameters' defaults.
177 llvm::SmallVector<TemplateArgument, 8> defaultTemplateArgs(templateParms->size());
178 for (int iParam = 0, nParams = templateParms->size(); iParam < nParams; ++iParam) {
179 const NamedDecl *templateParm = templateParms->getParam(iParam);
180 if (templateParm->isTemplateParameterPack()) {
181 // shouldn't end up here
182 assert(0 && "unexpected template parameter pack");
183 return nullptr;
184 }
185 if (auto TTP = dyn_cast<TemplateTypeParmDecl>(templateParm)) {
186 if (!TTP->hasDefaultArgument())
187 return nullptr;
188 defaultTemplateArgs[iParam] = TemplateArgument(TTP->getDefaultArgument());
189 } else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(templateParm)) {
190 if (!NTTP->hasDefaultArgument())
191 return nullptr;
192 defaultTemplateArgs[iParam] = TemplateArgument(NTTP->getDefaultArgument());
193 } else if (auto TTP = dyn_cast<TemplateTemplateParmDecl>(templateParm)) {
194 if (!TTP->hasDefaultArgument())
195 return nullptr;
196 defaultTemplateArgs[iParam] = TemplateArgument(TTP->getDefaultArgument().getArgument());
197 } else {
198 // shouldn't end up here
199 assert(0 && "unexpected template parameter kind");
200 return nullptr;
201 }
202 }
203
204 cling::Interpreter::PushTransactionRAII RAII(interp);
205
206 // Now substitute the dependent function parameter types given defaultTemplateArgs.
207 llvm::SmallVector<QualType, 8> paramTypes;
208 // Provide an instantiation context that suppresses errors:
209 // DeducedTemplateArgumentSubstitution! (ROOT-8422)
210 SmallVector<DeducedTemplateArgument, 4> DeducedArgs;
211 sema::TemplateDeductionInfo Info{SourceLocation()};
212
213 Sema::InstantiatingTemplate Inst(
214 S, Info.getLocation(), const_cast<clang::FunctionTemplateDecl *>(llvm::dyn_cast<clang::FunctionTemplateDecl>(TD)),
215 defaultTemplateArgs, Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
216
217 // Collect the function arguments of the templated function, substituting
218 // dependent types as possible.
219 TemplateArgumentList templArgList(TemplateArgumentList::OnStack, defaultTemplateArgs);
220 MultiLevelTemplateArgumentList MLTAL{templArgList};
221 for (const clang::ParmVarDecl *param : templatedDecl->parameters()) {
222 QualType paramType = param->getOriginalType();
223
224 // If the function type is dependent, try to resolve it through the class's
225 // template arguments. If that fails, skip this function.
226 if (paramType->isDependentType()) {
227 /*if (HasUnexpandedParameterPack(paramType, S)) {
228 // We are not going to expand the pack here...
229 Skip = true;
230 break;
231 }*/
232
233 paramType = S.SubstType(paramType, MLTAL, SourceLocation(), templatedDecl->getDeclName());
234
235 if (paramType.isNull() || paramType->isDependentType()) {
236 // Even after resolving the types through the surrounding template
237 // this argument type is still dependent: do not look it up.
238 return nullptr;
239 }
240 }
241 paramTypes.push_back(paramType);
242 }
243
244 return LH.findFunctionProto(declCtxDecl, TD->getNameAsString(), paramTypes, LH.NoDiagnostics,
245 templatedDecl->getType().isConstQualified());
246}
247
248TClingMethodInfo::TClingMethodInfo(cling::Interpreter *interp,
249 TClingClassInfo *ci)
250 : TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fTitle("")
251{
253
254 if (!ci || !ci->IsValid()) {
255 return;
256 }
257 clang::Decl *D = const_cast<clang::Decl *>(ci->GetDecl());
258 auto *DC = llvm::dyn_cast<clang::DeclContext>(D);
259
260 llvm::SmallVector<clang::CXXMethodDecl*, 8> SpecFuncs;
261
262 if (auto *CXXRD = llvm::dyn_cast<CXXRecordDecl>(DC)) {
263 // Initialize the CXXRecordDecl's special functions; could change the
264 // DeclContext content!
265
266 // Could trigger deserialization of decls.
267 cling::Interpreter::PushTransactionRAII RAII(interp);
268
269 auto &SemaRef = interp->getSema();
270 SemaRef.ForceDeclarationOfImplicitMembers(CXXRD);
271
272 // Assemble special functions (or FunctionTemplate-s) that are synthesized from DefinitionData but
273 // won't be enumerated as part of decls_begin()/decls_end().
274 for (clang::NamedDecl *ctor : SemaRef.LookupConstructors(CXXRD)) {
275 // Filter out constructor templates, they are not functions we can iterate over:
276 if (auto *CXXCD = llvm::dyn_cast<clang::CXXConstructorDecl>(ctor))
277 SpecFuncs.emplace_back(CXXCD);
278 }
279 SpecFuncs.emplace_back(SemaRef.LookupCopyingAssignment(CXXRD, /*Quals*/ 0, /*RValueThis*/ false, 0 /*ThisQuals*/));
280 SpecFuncs.emplace_back(SemaRef.LookupMovingAssignment(CXXRD, /*Quals*/ 0, /*RValueThis*/ false, 0 /*ThisQuals*/));
281 SpecFuncs.emplace_back(SemaRef.LookupDestructor(CXXRD));
282 }
283
284 fIter = TClingCXXRecMethIter(interp, DC, std::move(SpecFuncs));
285 fIter.Init();
286}
287
288TClingMethodInfo::TClingMethodInfo(cling::Interpreter *interp,
289 const clang::Decl *D)
290 : TClingDeclInfo(D), fInterp(interp), fFirstTime(true), fTitle("")
291{
292 if (!D)
293 Error("TClingMethodInfo", "nullptr FunctionDecl passed!");
294}
295
297{
298 if (!IsValid()) {
299 return TDictionary::DeclId_t();
300 }
301 if (auto *FD = GetAsFunctionDecl())
302 return (const clang::Decl*)(FD->getCanonicalDecl());
303 return (const clang::Decl*)(GetAsUsingShadowDecl()->getCanonicalDecl());
304}
305
306const clang::FunctionDecl *TClingMethodInfo::GetAsFunctionDecl() const
307{
308 return dyn_cast<FunctionDecl>(GetDecl());
309}
310
311const clang::UsingShadowDecl *TClingMethodInfo::GetAsUsingShadowDecl() const
312{
313 return dyn_cast<UsingShadowDecl>(GetDecl());
314}
315
316const clang::FunctionDecl *TClingMethodInfo::GetTargetFunctionDecl() const
317{
318 const Decl *D = GetDecl();
319 do {
320 if (auto FD = dyn_cast<FunctionDecl>(D))
321 return FD;
322 } while ((D = dyn_cast<UsingShadowDecl>(D)->getTargetDecl()));
323 return nullptr;
324}
325
327{
328 signature = "(";
329 if (!IsValid()) {
330 signature += ")";
331 return;
332 }
333
335 TClingMethodArgInfo arg(fInterp, this);
336
337 int idx = 0;
338 while (arg.Next()) {
339 if (idx) {
340 signature += ", ";
341 }
342 signature += arg.Type()->Name();
343 if (arg.Name() && strlen(arg.Name())) {
344 signature += " ";
345 signature += arg.Name();
346 }
347 if (arg.DefaultValue()) {
348 signature += " = ";
349 signature += arg.DefaultValue();
350 }
351 ++idx;
352 }
353 auto decl = GetTargetFunctionDecl();
354 if (decl && decl->isVariadic())
355 signature += ",...";
356
357 signature += ")";
358}
359
360void TClingMethodInfo::Init(const clang::FunctionDecl *decl)
361{
362 fFirstTime = true;
363 fIter = {};
364 fDecl = decl;
365}
366
368{
369 if (!IsValid()) {
370 return 0;
371 }
373 TClingCallFunc cf(fInterp,normCtxt);
374 cf.SetFunc(this);
375 return cf.InterfaceMethod();
376}
377
378const clang::Decl* TClingMethodInfo::GetDeclSlow() const
379{
380 return *fIter;
381}
382
384{
385 if (!IsValid()) {
386 return -1;
387 }
388 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
389 unsigned num_params = fd->getNumParams();
390 // Truncate cast to fit cint interface.
391 return static_cast<int>(num_params);
392}
393
395{
396 if (!IsValid()) {
397 return -1;
398 }
399 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
400 unsigned num_params = fd->getNumParams();
401 unsigned min_args = fd->getMinRequiredArguments();
402 unsigned defaulted_params = num_params - min_args;
403 // Truncate cast to fit cint interface.
404 return static_cast<int>(defaulted_params);
405}
406
407/*
408static bool HasUnexpandedParameterPack(clang::QualType QT, clang::Sema& S) {
409 if (llvm::isa<PackExpansionType>(*QT)) {
410 // We are not going to expand the pack here...
411 return true;
412 }
413 SmallVector<UnexpandedParameterPack, 4> Unexpanded;
414 S.collectUnexpandedParameterPacks (QT, Unexpanded);
415
416 return !Unexpanded.empty();
417}
418 */
419
421{
422
423 assert(!fDecl && "This is not an iterator!");
424
425 fNameCache.clear(); // invalidate the cache.
426
427 if (!fFirstTime && !fIter.IsValid()) {
428 // Iterator is already invalid.
429 return 0;
430 }
431 // Advance to the next decl.
432 if (fFirstTime) {
433 // The cint semantics are weird.
434 fFirstTime = false;
435 } else {
436 fIter.Next();
437 }
438 return fIter.IsValid();
439}
440
442{
443 if (!IsValid()) {
444 return 0L;
445 }
446 long property = 0L;
447 property |= kIsCompiled;
448
449 // NOTE: this uses `GetDecl()`, to capture the access of the UsingShadowDecl,
450 // which is defined in the derived class and might differ from the access of fd
451 // in the base class.
452 const Decl *declAccess = GetDecl();
453 if (llvm::isa<UsingShadowDecl>(declAccess))
454 property |= kIsUsing;
455
456 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
457 clang::AccessSpecifier Access = clang::AS_public;
458 if (!declAccess->getDeclContext()->isNamespace())
459 Access = declAccess->getAccess();
460
461 if ((property & kIsUsing) && llvm::isa<CXXConstructorDecl>(fd)) {
462 Access = clang::AS_public;
463 clang::CXXRecordDecl *typeCXXRD = llvm::cast<RecordType>(Type()->GetQualType())->getAsCXXRecordDecl();
464 clang::CXXBasePaths basePaths;
465 if (typeCXXRD->isDerivedFrom(llvm::dyn_cast<CXXRecordDecl>(fd->getDeclContext()), basePaths)) {
466 // Access of the ctor is access of the base inheritance, and
467 // cannot be overruled by the access of the using decl.
468
469 for (auto el: basePaths) {
470 if (el.Access > Access)
471 Access = el.Access;
472 }
473 } else {
474 Error("Property()", "UsingDecl of ctor not shadowing a base ctor!");
475 }
476
477 // But a private ctor stays private:
478 if (fd->getAccess() > Access)
479 Access = fd->getAccess();
480 }
481 switch (Access) {
482 case clang::AS_public:
483 property |= kIsPublic;
484 break;
485 case clang::AS_protected:
486 property |= kIsProtected;
487 break;
488 case clang::AS_private:
489 property |= kIsPrivate;
490 break;
491 case clang::AS_none:
492 if (declAccess->getDeclContext()->isNamespace())
493 property |= kIsPublic;
494 break;
495 default:
496 // IMPOSSIBLE
497 break;
498 }
499
500 if (fd->isConstexpr())
501 property |= kIsConstexpr;
502 if (fd->getStorageClass() == clang::SC_Static) {
503 property |= kIsStatic;
504 }
505 clang::QualType qt = fd->getReturnType().getCanonicalType();
506
507 property = TClingDeclInfo::Property(property, qt);
508
509 if (const clang::CXXMethodDecl *md =
510 llvm::dyn_cast<clang::CXXMethodDecl>(fd)) {
511 if (md->getTypeQualifiers() & clang::Qualifiers::Const) {
512 property |= kIsConstant | kIsConstMethod;
513 }
514 if (md->isVirtual()) {
515 property |= kIsVirtual;
516 }
517 if (md->isPure()) {
518 property |= kIsPureVirtual;
519 }
520 if (const clang::CXXConstructorDecl *cd =
521 llvm::dyn_cast<clang::CXXConstructorDecl>(md)) {
522 if (cd->isExplicit()) {
523 property |= kIsExplicit;
524 }
525 }
526 else if (const clang::CXXConversionDecl *cd =
527 llvm::dyn_cast<clang::CXXConversionDecl>(md)) {
528 if (cd->isExplicit()) {
529 property |= kIsExplicit;
530 }
531 }
532 }
533 return property;
534}
535
537{
538 // Return the property not already defined in Property
539 // See TDictionary's EFunctionProperty
540 if (!IsValid()) {
541 return 0L;
542 }
543 long property = 0;
544 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
545 if (fd->isOverloadedOperator())
546 property |= kIsOperator;
547 if (llvm::isa<clang::CXXConversionDecl>(fd))
548 property |= kIsConversion;
549 if (llvm::isa<clang::CXXConstructorDecl>(fd))
550 property |= kIsConstructor;
551 if (llvm::isa<clang::CXXDestructorDecl>(fd))
552 property |= kIsDestructor;
553 if (fd->isInlined())
554 property |= kIsInlined;
555 return property;
556}
557
559{
560 TTHREAD_TLS_DECL_ARG( TClingTypeInfo, ti, fInterp );
561 if (!IsValid()) {
562 ti.Init(clang::QualType());
563 return &ti;
564 }
565 if (llvm::isa<clang::CXXConstructorDecl>(GetTargetFunctionDecl())) {
566 // CINT claims that constructors return the class object.
567 // For using-ctors of a base, claim that it "returns" the derived class.
568 const clang::TypeDecl* ctorClass = llvm::dyn_cast_or_null<clang::TypeDecl>
569 (GetDecl()->getDeclContext());
570 if (!ctorClass) {
571 Error("TClingMethodInfo::Type", "Cannot find DeclContext for constructor!");
572 } else {
573 clang::QualType qt(ctorClass->getTypeForDecl(), 0);
574 ti.Init(qt);
575 }
576 } else {
577 clang::QualType qt = GetTargetFunctionDecl()->getReturnType();
578 ti.Init(qt);
579 }
580 return &ti;
581}
582
584{
585 if (!IsValid()) {
586 return "";
587 }
588 std::string mangled_name;
589 mangled_name.clear();
590 const FunctionDecl* D = GetTargetFunctionDecl();
591
593 cling::Interpreter::PushTransactionRAII RAII(fInterp);
594 GlobalDecl GD;
595 if (const CXXConstructorDecl* Ctor = dyn_cast<CXXConstructorDecl>(D))
596 GD = GlobalDecl(Ctor, Ctor_Complete);
597 else if (const CXXDestructorDecl* Dtor = dyn_cast<CXXDestructorDecl>(D))
598 GD = GlobalDecl(Dtor, Dtor_Deleting);
599 else
600 GD = GlobalDecl(D);
601
602 cling::utils::Analyze::maybeMangleDeclName(GD, mangled_name);
603 return mangled_name;
604}
605
607{
608 if (!IsValid()) {
609 return 0;
610 }
611 TTHREAD_TLS_DECL( std::string, buf );
612 buf.clear();
613 buf += Type()->Name();
614 buf += ' ';
615 const FunctionDecl *FD = GetTargetFunctionDecl();
616 // Use the DeclContext of the decl, not of the target decl:
617 // Used base functions should show as if they are part of the derived class,
618 // e.g. `Derived Derived::Derived(int)`, not `Derived Base::Derived(int)`.
619 if (const clang::TypeDecl *td = llvm::dyn_cast<clang::TypeDecl>(GetDecl()->getDeclContext())) {
620 std::string name;
621 clang::QualType qualType(td->getTypeForDecl(),0);
623 buf += name;
624 buf += "::";
625 } else if (const clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(FD->getDeclContext())) {
626 std::string name;
627 clang::PrintingPolicy policy(FD->getASTContext().getPrintingPolicy());
628 llvm::raw_string_ostream stream(name);
629 nd->getNameForDiagnostic(stream, policy, /*Qualified=*/true);
630 stream.flush();
631 buf += name;
632 buf += "::";
633 }
634 buf += Name();
635
636 TString signature;
637 CreateSignature(signature);
638 buf += signature;
639
640 if (const clang::CXXMethodDecl *md =
641 llvm::dyn_cast<clang::CXXMethodDecl>(FD)) {
642 if (md->getTypeQualifiers() & clang::Qualifiers::Const) {
643 buf += " const";
644 }
645 }
646 return buf.c_str();
647}
648
649const char *TClingMethodInfo::Name() const
650{
651 if (!IsValid()) {
652 return 0;
653 }
654 if (!fNameCache.empty())
655 return fNameCache.c_str();
656
657 ((TCling*)gCling)->GetFunctionName(GetDecl(), fNameCache);
658 return fNameCache.c_str();
659}
660
661const char *TClingMethodInfo::TypeName() const
662{
663 if (!IsValid()) {
664 // FIXME: Cint does not check!
665 return 0;
666 }
667 return Type()->Name();
668}
669
671{
672 if (!IsValid()) {
673 return 0;
674 }
675
676 //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
677 //if (fTitle.size())
678 // return fTitle.c_str();
679
680 // Try to get the comment either from the annotation or the header file if present
681
682 // Iterate over the redeclarations, we can have multiple definitions in the
683 // redecl chain (came from merging of pcms).
684 const FunctionDecl *FD = GetTargetFunctionDecl();
685
687
688 // Could trigger deserialization of decls.
689 cling::Interpreter::PushTransactionRAII RAII(fInterp);
690 if (const FunctionDecl *AnnotFD
692 if (AnnotateAttr *A = AnnotFD->getAttr<AnnotateAttr>()) {
693 fTitle = A->getAnnotation().str();
694 return fTitle.c_str();
695 }
696 }
697 if (!FD->isFromASTFile()) {
698 // Try to get the comment from the header file if present
699 // but not for decls from AST file, where rootcling would have
700 // created an annotation
702 }
703
704 return fTitle.c_str();
705}
706
@ kIsDestructor
Definition: TDictionary.h:129
@ kIsConversion
Definition: TDictionary.h:128
@ kIsInlined
Definition: TDictionary.h:131
@ kIsConstructor
Definition: TDictionary.h:127
@ kIsOperator
Definition: TDictionary.h:130
@ kIsPublic
Definition: TDictionary.h:75
@ kIsConstexpr
Definition: TDictionary.h:93
@ kIsConstant
Definition: TDictionary.h:88
@ kIsConstMethod
Definition: TDictionary.h:96
@ kIsPrivate
Definition: TDictionary.h:77
@ kIsCompiled
Definition: TDictionary.h:86
@ kIsUsing
Definition: TDictionary.h:97
@ kIsStatic
Definition: TDictionary.h:80
@ kIsExplicit
Definition: TDictionary.h:94
@ kIsProtected
Definition: TDictionary.h:76
@ 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:41
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:557
#define R__LOCKGUARD(mutex)
const_iterator begin() const
Iterate over FunctionDecl and UsingShadowDecls of FunctionDecl, within a scope, recursing through "tr...
bool IsValid() const final
const clang::Decl * InstantiateTemplateWithDefaults(const clang::RedeclarableTemplateDecl *TD) const final
bool ShouldSkip(const clang::Decl *FD) const final
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() const
virtual bool IsValid() const
long Property(long property, clang::QualType &qt) const
std::string fNameCache
virtual const clang::Decl * GetDecl() const
bool Next()
Advance to next non-skipped; return false if no next decl exists.
cling::Interpreter * fInterp
cling::Interpreter * GetInterpreter() const
Emulation of the CINT MethodInfo class.
const char * DefaultValue() const
const TClingTypeInfo * Type() const
std::string GetMangledName() const
const char * TypeName() const
const clang::FunctionDecl * GetAsFunctionDecl() const
const char * Name() const override
const clang::UsingShadowDecl * GetAsUsingShadowDecl() const
void * InterfaceMethod(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
const clang::FunctionDecl * GetTargetFunctionDecl() const
Get the FunctionDecl, or if this represents a UsingShadowDecl, the underlying target FunctionDecl.
const clang::Decl * GetDecl() const override
TClingCXXRecMethIter fIter
const char * GetPrototype()
void Init(const clang::FunctionDecl *)
long ExtraProperty() const
const clang::Decl * GetDeclSlow() const
TClingMethodInfo(cling::Interpreter *interp)
void CreateSignature(TString &signature) const
const char * Title()
TDictionary::DeclId_t GetDeclId() const
cling::Interpreter * fInterp
TClingTypeInfo * Type() const
Emulation of the CINT TypeInfo class.
const char * Name() const override
This class defines an interface to the cling C++ interpreter.
Definition: TCling.h:99
const void * DeclId_t
Definition: TDictionary.h:222
Basic string class.
Definition: TString.h:131
static double A[]
const T * GetAnnotatedRedeclarable(const T *Redecl)
Definition: TClingUtils.h:638
void GetFullyQualifiedTypeName(std::string &name, const clang::QualType &type, const cling::Interpreter &interpreter)
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.
RooArgSet S(const RooAbsArg &v1)
static constexpr double L