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 const FunctionDecl *templatedDecl = llvm::dyn_cast<FunctionDecl>(TD->getTemplatedDecl());
151 const Decl *declCtxDecl = dyn_cast<Decl>(TD->getDeclContext());
152
153 // We have a function template
154 // template <class X = int, int i = 7> void func(int a0, X a1[i], X::type a2[i])
155 // which has defaults for all its template parameters `X` and `i`. To
156 // instantiate it we have to do a lookup, which in turn needs the function
157 // argument types, e.g. `int[12]`.
158 // If the function argument type is dependent (a1 and a2) we need to
159 // substitute the types first, using the template arguments derived from the
160 // template parameters' defaults.
161 llvm::SmallVector<TemplateArgument, 8> defaultTemplateArgs;
162 for (const NamedDecl *templateParm: *templateParms) {
163 if (templateParm->isTemplateParameterPack()) {
164 // This would inject an emprt parameter pack, which is a good default.
165 // But for cases where instantiation fails, this hits bug in unloading
166 // of the failed instantiation, causing a missing symbol in subsequent
167 // transactions where a Decl instantiated by the failed instatiation
168 // is not re-emitted. So for now just give up default-instantiating
169 // templates with parameter packs, even if this is simply a work-around.
170 //defaultTemplateArgs.emplace_back(ArrayRef<TemplateArgument>{}); // empty pack.
171 return nullptr;
172 } else if (auto TTP = dyn_cast<TemplateTypeParmDecl>(templateParm)) {
173 if (!TTP->hasDefaultArgument())
174 return nullptr;
175 defaultTemplateArgs.emplace_back(TTP->getDefaultArgument());
176 } else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(templateParm)) {
177 if (!NTTP->hasDefaultArgument())
178 return nullptr;
179 defaultTemplateArgs.emplace_back(NTTP->getDefaultArgument());
180 } else if (auto TTP = dyn_cast<TemplateTemplateParmDecl>(templateParm)) {
181 if (!TTP->hasDefaultArgument())
182 return nullptr;
183 defaultTemplateArgs.emplace_back(TTP->getDefaultArgument().getArgument());
184 } else {
185 // shouldn't end up here
186 assert(0 && "unexpected template parameter kind");
187 return nullptr;
188 }
189 }
190
191 cling::Interpreter::PushTransactionRAII RAII(interp);
192
193 // Now substitute the dependent function parameter types given defaultTemplateArgs.
194 llvm::SmallVector<QualType, 8> paramTypes;
195 // Provide an instantiation context that suppresses errors:
196 // DeducedTemplateArgumentSubstitution! (ROOT-8422)
197 SmallVector<DeducedTemplateArgument, 4> DeducedArgs;
198 sema::TemplateDeductionInfo Info{SourceLocation()};
199
200 Sema::InstantiatingTemplate Inst(
201 S, Info.getLocation(), const_cast<clang::FunctionTemplateDecl *>(llvm::dyn_cast<clang::FunctionTemplateDecl>(TD)),
202 defaultTemplateArgs, Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
203
204 // Collect the function arguments of the templated function, substituting
205 // dependent types as possible.
206 TemplateArgumentList templArgList(TemplateArgumentList::OnStack, defaultTemplateArgs);
207 MultiLevelTemplateArgumentList MLTAL{templArgList};
208 for (const clang::ParmVarDecl *param : templatedDecl->parameters()) {
209 QualType paramType = param->getOriginalType();
210
211 // If the function type is dependent, try to resolve it through the class's
212 // template arguments. If that fails, skip this function.
213 if (paramType->isDependentType()) {
214 /*if (HasUnexpandedParameterPack(paramType, S)) {
215 // We are not going to expand the pack here...
216 Skip = true;
217 break;
218 }*/
219
220 paramType = S.SubstType(paramType, MLTAL, SourceLocation(), templatedDecl->getDeclName());
221
222 if (paramType.isNull() || paramType->isDependentType()) {
223 // Even after resolving the types through the surrounding template
224 // this argument type is still dependent: do not look it up.
225 return nullptr;
226 }
227 }
228 paramTypes.push_back(paramType);
229 }
230
231 return LH.findFunctionProto(declCtxDecl, TD->getNameAsString(), paramTypes, LH.NoDiagnostics,
232 templatedDecl->getType().isConstQualified());
233}
234
235TClingMethodInfo::TClingMethodInfo(cling::Interpreter *interp,
236 TClingClassInfo *ci)
237 : TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fTitle("")
238{
240
241 if (!ci || !ci->IsValid()) {
242 return;
243 }
244 clang::Decl *D = const_cast<clang::Decl *>(ci->GetDecl());
245 auto *DC = llvm::dyn_cast<clang::DeclContext>(D);
246
247 llvm::SmallVector<clang::CXXMethodDecl*, 8> SpecFuncs;
248
249 if (auto *CXXRD = llvm::dyn_cast<CXXRecordDecl>(DC)) {
250 // Initialize the CXXRecordDecl's special functions; could change the
251 // DeclContext content!
252
253 // Could trigger deserialization of decls.
254 cling::Interpreter::PushTransactionRAII RAII(interp);
255
256 auto &SemaRef = interp->getSema();
257 SemaRef.ForceDeclarationOfImplicitMembers(CXXRD);
258
259 // Assemble special functions (or FunctionTemplate-s) that are synthesized from DefinitionData but
260 // won't be enumerated as part of decls_begin()/decls_end().
261 for (clang::NamedDecl *ctor : SemaRef.LookupConstructors(CXXRD)) {
262 // Filter out constructor templates, they are not functions we can iterate over:
263 if (auto *CXXCD = llvm::dyn_cast<clang::CXXConstructorDecl>(ctor))
264 SpecFuncs.emplace_back(CXXCD);
265 }
266 SpecFuncs.emplace_back(SemaRef.LookupCopyingAssignment(CXXRD, /*Quals*/ 0, /*RValueThis*/ false, 0 /*ThisQuals*/));
267 SpecFuncs.emplace_back(SemaRef.LookupMovingAssignment(CXXRD, /*Quals*/ 0, /*RValueThis*/ false, 0 /*ThisQuals*/));
268 SpecFuncs.emplace_back(SemaRef.LookupDestructor(CXXRD));
269 }
270
271 fIter = TClingCXXRecMethIter(interp, DC, std::move(SpecFuncs));
272 fIter.Init();
273}
274
275TClingMethodInfo::TClingMethodInfo(cling::Interpreter *interp,
276 const clang::Decl *D)
277 : TClingDeclInfo(D), fInterp(interp), fFirstTime(true), fTitle("")
278{
279 if (!D)
280 Error("TClingMethodInfo", "nullptr FunctionDecl passed!");
281}
282
284{
285 if (!IsValid()) {
286 return TDictionary::DeclId_t();
287 }
288 if (auto *FD = GetAsFunctionDecl())
289 return (const clang::Decl*)(FD->getCanonicalDecl());
290 return (const clang::Decl*)(GetAsUsingShadowDecl()->getCanonicalDecl());
291}
292
293const clang::FunctionDecl *TClingMethodInfo::GetAsFunctionDecl() const
294{
295 return dyn_cast<FunctionDecl>(GetDecl());
296}
297
298const clang::UsingShadowDecl *TClingMethodInfo::GetAsUsingShadowDecl() const
299{
300 return dyn_cast<UsingShadowDecl>(GetDecl());
301}
302
303const clang::FunctionDecl *TClingMethodInfo::GetTargetFunctionDecl() const
304{
305 const Decl *D = GetDecl();
306 do {
307 if (auto FD = dyn_cast<FunctionDecl>(D))
308 return FD;
309 } while ((D = dyn_cast<UsingShadowDecl>(D)->getTargetDecl()));
310 return nullptr;
311}
312
314{
315 signature = "(";
316 if (!IsValid()) {
317 signature += ")";
318 return;
319 }
320
322 TClingMethodArgInfo arg(fInterp, this);
323
324 int idx = 0;
325 while (arg.Next()) {
326 if (idx) {
327 signature += ", ";
328 }
329 signature += arg.Type()->Name();
330 if (arg.Name() && strlen(arg.Name())) {
331 signature += " ";
332 signature += arg.Name();
333 }
334 if (arg.DefaultValue()) {
335 signature += " = ";
336 signature += arg.DefaultValue();
337 }
338 ++idx;
339 }
340 auto decl = GetTargetFunctionDecl();
341 if (decl && decl->isVariadic())
342 signature += ",...";
343
344 signature += ")";
345}
346
347void TClingMethodInfo::Init(const clang::FunctionDecl *decl)
348{
349 fFirstTime = true;
350 fIter = {};
351 fDecl = decl;
352}
353
355{
356 if (!IsValid()) {
357 return 0;
358 }
361 cf.SetFunc(this);
362 return cf.InterfaceMethod();
363}
364
365const clang::Decl* TClingMethodInfo::GetDeclSlow() const
366{
367 return *fIter;
368}
369
371{
372 if (!IsValid()) {
373 return -1;
374 }
375 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
376 unsigned num_params = fd->getNumParams();
377 // Truncate cast to fit cint interface.
378 return static_cast<int>(num_params);
379}
380
382{
383 if (!IsValid()) {
384 return -1;
385 }
386 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
387 unsigned num_params = fd->getNumParams();
388 unsigned min_args = fd->getMinRequiredArguments();
389 unsigned defaulted_params = num_params - min_args;
390 // Truncate cast to fit cint interface.
391 return static_cast<int>(defaulted_params);
392}
393
394/*
395static bool HasUnexpandedParameterPack(clang::QualType QT, clang::Sema& S) {
396 if (llvm::isa<PackExpansionType>(*QT)) {
397 // We are not going to expand the pack here...
398 return true;
399 }
400 SmallVector<UnexpandedParameterPack, 4> Unexpanded;
401 S.collectUnexpandedParameterPacks (QT, Unexpanded);
402
403 return !Unexpanded.empty();
404}
405 */
406
408{
409
410 assert(!fDecl && "This is not an iterator!");
411
412 fNameCache.clear(); // invalidate the cache.
413
414 if (!fFirstTime && !fIter.IsValid()) {
415 // Iterator is already invalid.
416 return 0;
417 }
418 // Advance to the next decl.
419 if (fFirstTime) {
420 // The cint semantics are weird.
421 fFirstTime = false;
422 } else {
423 fIter.Next();
424 }
425 return fIter.IsValid();
426}
427
429{
430 if (!IsValid()) {
431 return 0L;
432 }
433 long property = 0L;
434 property |= kIsCompiled;
435
436 // NOTE: this uses `GetDecl()`, to capture the access of the UsingShadowDecl,
437 // which is defined in the derived class and might differ from the access of fd
438 // in the base class.
439 const Decl *declAccess = GetDecl();
440 if (llvm::isa<UsingShadowDecl>(declAccess))
441 property |= kIsUsing;
442
443 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
444 clang::AccessSpecifier Access = clang::AS_public;
445 if (!declAccess->getDeclContext()->isNamespace())
446 Access = declAccess->getAccess();
447
448 if ((property & kIsUsing) && llvm::isa<CXXConstructorDecl>(fd)) {
449 Access = clang::AS_public;
450 clang::CXXRecordDecl *typeCXXRD = llvm::cast<RecordType>(Type()->GetQualType())->getAsCXXRecordDecl();
451 clang::CXXBasePaths basePaths;
452 if (typeCXXRD->isDerivedFrom(llvm::dyn_cast<CXXRecordDecl>(fd->getDeclContext()), basePaths)) {
453 // Access of the ctor is access of the base inheritance, and
454 // cannot be overruled by the access of the using decl.
455
456 for (auto el: basePaths) {
457 if (el.Access > Access)
458 Access = el.Access;
459 }
460 } else {
461 Error("Property()", "UsingDecl of ctor not shadowing a base ctor!");
462 }
463
464 // But a private ctor stays private:
465 if (fd->getAccess() > Access)
466 Access = fd->getAccess();
467 }
468 switch (Access) {
469 case clang::AS_public:
470 property |= kIsPublic;
471 break;
472 case clang::AS_protected:
473 property |= kIsProtected;
474 break;
475 case clang::AS_private:
476 property |= kIsPrivate;
477 break;
478 case clang::AS_none:
479 if (declAccess->getDeclContext()->isNamespace())
480 property |= kIsPublic;
481 break;
482 default:
483 // IMPOSSIBLE
484 break;
485 }
486
487 if (fd->isConstexpr())
488 property |= kIsConstexpr;
489 if (fd->getStorageClass() == clang::SC_Static) {
490 property |= kIsStatic;
491 }
492 clang::QualType qt = fd->getReturnType().getCanonicalType();
493
494 property = TClingDeclInfo::Property(property, qt);
495
496 if (const clang::CXXMethodDecl *md =
497 llvm::dyn_cast<clang::CXXMethodDecl>(fd)) {
498 if (md->getMethodQualifiers().hasConst()) {
499 property |= kIsConstant | kIsConstMethod;
500 }
501 if (md->isVirtual()) {
502 property |= kIsVirtual;
503 }
504 if (md->isPure()) {
505 property |= kIsPureVirtual;
506 }
507 if (const clang::CXXConstructorDecl *cd =
508 llvm::dyn_cast<clang::CXXConstructorDecl>(md)) {
509 if (cd->isExplicit()) {
510 property |= kIsExplicit;
511 }
512 }
513 else if (const clang::CXXConversionDecl *cd =
514 llvm::dyn_cast<clang::CXXConversionDecl>(md)) {
515 if (cd->isExplicit()) {
516 property |= kIsExplicit;
517 }
518 }
519 }
520 return property;
521}
522
524{
525 // Return the property not already defined in Property
526 // See TDictionary's EFunctionProperty
527 if (!IsValid()) {
528 return 0L;
529 }
530 long property = 0;
531 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
532 if (fd->isOverloadedOperator())
533 property |= kIsOperator;
534 if (llvm::isa<clang::CXXConversionDecl>(fd))
535 property |= kIsConversion;
536 if (llvm::isa<clang::CXXConstructorDecl>(fd))
537 property |= kIsConstructor;
538 if (llvm::isa<clang::CXXDestructorDecl>(fd))
539 property |= kIsDestructor;
540 if (fd->isInlined())
541 property |= kIsInlined;
542 if (fd->getTemplatedKind() != clang::FunctionDecl::TK_NonTemplate)
543 property |= kIsTemplateSpec;
544 return property;
545}
546
548{
549 TTHREAD_TLS_DECL_ARG( TClingTypeInfo, ti, fInterp );
550 if (!IsValid()) {
551 ti.Init(clang::QualType());
552 return &ti;
553 }
554 if (llvm::isa<clang::CXXConstructorDecl>(GetTargetFunctionDecl())) {
555 // CINT claims that constructors return the class object.
556 // For using-ctors of a base, claim that it "returns" the derived class.
557 const clang::TypeDecl* ctorClass = llvm::dyn_cast_or_null<clang::TypeDecl>
558 (GetDecl()->getDeclContext());
559 if (!ctorClass) {
560 Error("TClingMethodInfo::Type", "Cannot find DeclContext for constructor!");
561 } else {
562 clang::QualType qt(ctorClass->getTypeForDecl(), 0);
563 ti.Init(qt);
564 }
565 } else {
566 clang::QualType qt = GetTargetFunctionDecl()->getReturnType();
567 ti.Init(qt);
568 }
569 return &ti;
570}
571
573{
574 if (!IsValid()) {
575 return "";
576 }
577 std::string mangled_name;
578 mangled_name.clear();
579 const FunctionDecl* D = GetTargetFunctionDecl();
580
582 cling::Interpreter::PushTransactionRAII RAII(fInterp);
583 GlobalDecl GD;
584 if (const CXXConstructorDecl* Ctor = dyn_cast<CXXConstructorDecl>(D))
585 GD = GlobalDecl(Ctor, Ctor_Complete);
586 else if (const CXXDestructorDecl* Dtor = dyn_cast<CXXDestructorDecl>(D))
587 GD = GlobalDecl(Dtor, Dtor_Deleting);
588 else
589 GD = GlobalDecl(D);
590
591 cling::utils::Analyze::maybeMangleDeclName(GD, mangled_name);
592 return mangled_name;
593}
594
596{
597 if (!IsValid()) {
598 return 0;
599 }
600 TTHREAD_TLS_DECL( std::string, buf );
601 buf.clear();
602 buf += Type()->Name();
603 buf += ' ';
604 const FunctionDecl *FD = GetTargetFunctionDecl();
605 // Use the DeclContext of the decl, not of the target decl:
606 // Used base functions should show as if they are part of the derived class,
607 // e.g. `Derived Derived::Derived(int)`, not `Derived Base::Derived(int)`.
608 if (const clang::TypeDecl *td = llvm::dyn_cast<clang::TypeDecl>(GetDecl()->getDeclContext())) {
609 std::string name;
610 clang::QualType qualType(td->getTypeForDecl(),0);
612 buf += name;
613 buf += "::";
614 } else if (const clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(FD->getDeclContext())) {
615 std::string name;
616 clang::PrintingPolicy policy(FD->getASTContext().getPrintingPolicy());
617 llvm::raw_string_ostream stream(name);
618 nd->getNameForDiagnostic(stream, policy, /*Qualified=*/true);
619 stream.flush();
620 buf += name;
621 buf += "::";
622 }
623 buf += Name();
624
625 TString signature;
626 CreateSignature(signature);
627 buf += signature;
628
629 if (const clang::CXXMethodDecl *md =
630 llvm::dyn_cast<clang::CXXMethodDecl>(FD)) {
631 if (md->getMethodQualifiers().hasConst()) {
632 buf += " const";
633 }
634 }
635 return buf.c_str(); // NOLINT
636}
637
638const char *TClingMethodInfo::Name() const
639{
640 if (!IsValid()) {
641 return 0;
642 }
643 if (!fNameCache.empty())
644 return fNameCache.c_str();
645
646 ((TCling*)gCling)->GetFunctionName(GetDecl(), fNameCache);
647 return fNameCache.c_str();
648}
649
650const char *TClingMethodInfo::TypeName() const
651{
652 if (!IsValid()) {
653 // FIXME: Cint does not check!
654 return 0;
655 }
656 return Type()->Name();
657}
658
660{
661 if (!IsValid()) {
662 return 0;
663 }
664
665 //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
666 //if (fTitle.size())
667 // return fTitle.c_str();
668
669 // Try to get the comment either from the annotation or the header file if present
670
671 // Iterate over the redeclarations, we can have multiple definitions in the
672 // redecl chain (came from merging of pcms).
673 const FunctionDecl *FD = GetTargetFunctionDecl();
674
676
677 // Could trigger deserialization of decls.
678 cling::Interpreter::PushTransactionRAII RAII(fInterp);
679 if (const FunctionDecl *AnnotFD
681 if (AnnotateAttr *A = AnnotFD->getAttr<AnnotateAttr>()) {
682 fTitle = A->getAnnotation().str();
683 return fTitle.c_str();
684 }
685 }
686 if (!FD->isFromASTFile()) {
687 // Try to get the comment from the header file if present
688 // but not for decls from AST file, where rootcling would have
689 // created an annotation
691 }
692
693 return fTitle.c_str();
694}
695
@ 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:230
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:197
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t property
char name[80]
Definition TGX11.cxx:110
R__EXTERN TVirtualMutex * gInterpreterMutex
R__EXTERN TInterpreter * gCling
#define R__LOCKGUARD(mutex)
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, Longptr_t *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
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
void * InterfaceMethod() 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:139
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.