Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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->getMethodQualifiers().hasConst()) {
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 if (fd->getTemplatedKind() != clang::FunctionDecl::TK_NonTemplate)
556 property |= kIsTemplateSpec;
557 return property;
558}
559
561{
562 TTHREAD_TLS_DECL_ARG( TClingTypeInfo, ti, fInterp );
563 if (!IsValid()) {
564 ti.Init(clang::QualType());
565 return &ti;
566 }
567 if (llvm::isa<clang::CXXConstructorDecl>(GetTargetFunctionDecl())) {
568 // CINT claims that constructors return the class object.
569 // For using-ctors of a base, claim that it "returns" the derived class.
570 const clang::TypeDecl* ctorClass = llvm::dyn_cast_or_null<clang::TypeDecl>
571 (GetDecl()->getDeclContext());
572 if (!ctorClass) {
573 Error("TClingMethodInfo::Type", "Cannot find DeclContext for constructor!");
574 } else {
575 clang::QualType qt(ctorClass->getTypeForDecl(), 0);
576 ti.Init(qt);
577 }
578 } else {
579 clang::QualType qt = GetTargetFunctionDecl()->getReturnType();
580 ti.Init(qt);
581 }
582 return &ti;
583}
584
586{
587 if (!IsValid()) {
588 return "";
589 }
590 std::string mangled_name;
591 mangled_name.clear();
592 const FunctionDecl* D = GetTargetFunctionDecl();
593
595 cling::Interpreter::PushTransactionRAII RAII(fInterp);
596 GlobalDecl GD;
597 if (const CXXConstructorDecl* Ctor = dyn_cast<CXXConstructorDecl>(D))
598 GD = GlobalDecl(Ctor, Ctor_Complete);
599 else if (const CXXDestructorDecl* Dtor = dyn_cast<CXXDestructorDecl>(D))
600 GD = GlobalDecl(Dtor, Dtor_Deleting);
601 else
602 GD = GlobalDecl(D);
603
604 cling::utils::Analyze::maybeMangleDeclName(GD, mangled_name);
605 return mangled_name;
606}
607
609{
610 if (!IsValid()) {
611 return 0;
612 }
613 TTHREAD_TLS_DECL( std::string, buf );
614 buf.clear();
615 buf += Type()->Name();
616 buf += ' ';
617 const FunctionDecl *FD = GetTargetFunctionDecl();
618 // Use the DeclContext of the decl, not of the target decl:
619 // Used base functions should show as if they are part of the derived class,
620 // e.g. `Derived Derived::Derived(int)`, not `Derived Base::Derived(int)`.
621 if (const clang::TypeDecl *td = llvm::dyn_cast<clang::TypeDecl>(GetDecl()->getDeclContext())) {
622 std::string name;
623 clang::QualType qualType(td->getTypeForDecl(),0);
625 buf += name;
626 buf += "::";
627 } else if (const clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(FD->getDeclContext())) {
628 std::string name;
629 clang::PrintingPolicy policy(FD->getASTContext().getPrintingPolicy());
630 llvm::raw_string_ostream stream(name);
631 nd->getNameForDiagnostic(stream, policy, /*Qualified=*/true);
632 stream.flush();
633 buf += name;
634 buf += "::";
635 }
636 buf += Name();
637
638 TString signature;
639 CreateSignature(signature);
640 buf += signature;
641
642 if (const clang::CXXMethodDecl *md =
643 llvm::dyn_cast<clang::CXXMethodDecl>(FD)) {
644 if (md->getMethodQualifiers().hasConst()) {
645 buf += " const";
646 }
647 }
648 return buf.c_str();
649}
650
651const char *TClingMethodInfo::Name() const
652{
653 if (!IsValid()) {
654 return 0;
655 }
656 if (!fNameCache.empty())
657 return fNameCache.c_str();
658
659 ((TCling*)gCling)->GetFunctionName(GetDecl(), fNameCache);
660 return fNameCache.c_str();
661}
662
663const char *TClingMethodInfo::TypeName() const
664{
665 if (!IsValid()) {
666 // FIXME: Cint does not check!
667 return 0;
668 }
669 return Type()->Name();
670}
671
673{
674 if (!IsValid()) {
675 return 0;
676 }
677
678 //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
679 //if (fTitle.size())
680 // return fTitle.c_str();
681
682 // Try to get the comment either from the annotation or the header file if present
683
684 // Iterate over the redeclarations, we can have multiple definitions in the
685 // redecl chain (came from merging of pcms).
686 const FunctionDecl *FD = GetTargetFunctionDecl();
687
689
690 // Could trigger deserialization of decls.
691 cling::Interpreter::PushTransactionRAII RAII(fInterp);
692 if (const FunctionDecl *AnnotFD
694 if (AnnotateAttr *A = AnnotFD->getAttr<AnnotateAttr>()) {
695 fTitle = A->getAnnotation().str();
696 return fTitle.c_str();
697 }
698 }
699 if (!FD->isFromASTFile()) {
700 // Try to get the comment from the header file if present
701 // but not for decls from AST file, where rootcling would have
702 // created an annotation
704 }
705
706 return fTitle.c_str();
707}
708
@ kIsDestructor
@ kIsConversion
@ kIsTemplateSpec
@ kIsInlined
@ kIsConstructor
@ kIsOperator
@ 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,...)
Use this function for informational messages.
Definition TError.cxx:220
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:187
char name[80]
Definition TGX11.cxx:110
R__EXTERN TVirtualMutex * gInterpreterMutex
R__EXTERN TInterpreter * gCling
#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)
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
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:102
const void * DeclId_t
Basic string class.
Definition TString.h:136
const T * GetAnnotatedRedeclarable(const T *Redecl)
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.