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 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 llvm::SmallVector<NamedDecl*, 16> Ctors;
262 SemaRef.LookupConstructors(CXXRD, Ctors);
263 for (clang::NamedDecl *ctor : Ctors) {
264 // Filter out constructor templates, they are not functions we can iterate over:
265 if (auto *CXXCD = llvm::dyn_cast<clang::CXXConstructorDecl>(ctor))
266 SpecFuncs.emplace_back(CXXCD);
267 }
268 SpecFuncs.emplace_back(SemaRef.LookupCopyingAssignment(CXXRD, /*Quals*/ 0, /*RValueThis*/ false, 0 /*ThisQuals*/));
269 SpecFuncs.emplace_back(SemaRef.LookupMovingAssignment(CXXRD, /*Quals*/ 0, /*RValueThis*/ false, 0 /*ThisQuals*/));
270 SpecFuncs.emplace_back(SemaRef.LookupDestructor(CXXRD));
271 }
272
273 fIter = TClingCXXRecMethIter(interp, DC, std::move(SpecFuncs));
274 fIter.Init();
275}
276
277TClingMethodInfo::TClingMethodInfo(cling::Interpreter *interp,
278 const clang::Decl *D)
279 : TClingDeclInfo(D), fInterp(interp), fFirstTime(true), fTitle("")
280{
281 if (!D)
282 Error("TClingMethodInfo", "nullptr FunctionDecl passed!");
283}
284
286{
287 if (!IsValid()) {
288 return TDictionary::DeclId_t();
289 }
290 if (auto *FD = GetAsFunctionDecl())
291 return (const clang::Decl*)(FD->getCanonicalDecl());
292 return (const clang::Decl*)(GetAsUsingShadowDecl()->getCanonicalDecl());
293}
294
295const clang::FunctionDecl *TClingMethodInfo::GetAsFunctionDecl() const
296{
297 return dyn_cast<FunctionDecl>(GetDecl());
298}
299
300const clang::UsingShadowDecl *TClingMethodInfo::GetAsUsingShadowDecl() const
301{
302 return dyn_cast<UsingShadowDecl>(GetDecl());
303}
304
305const clang::FunctionDecl *TClingMethodInfo::GetTargetFunctionDecl() const
306{
307 const Decl *D = GetDecl();
308 do {
309 if (auto FD = dyn_cast<FunctionDecl>(D))
310 return FD;
311 } while ((D = dyn_cast<UsingShadowDecl>(D)->getTargetDecl()));
312 return nullptr;
313}
314
316{
317 signature = "(";
318 if (!IsValid()) {
319 signature += ")";
320 return;
321 }
322
324 TClingMethodArgInfo arg(fInterp, this);
325
326 int idx = 0;
327 while (arg.Next()) {
328 if (idx) {
329 signature += ", ";
330 }
331 signature += arg.Type()->Name();
332 if (arg.Name() && strlen(arg.Name())) {
333 signature += " ";
334 signature += arg.Name();
335 }
336 if (arg.DefaultValue()) {
337 signature += " = ";
338 signature += arg.DefaultValue();
339 }
340 ++idx;
341 }
342 auto decl = GetTargetFunctionDecl();
343 if (decl && decl->isVariadic())
344 signature += ",...";
345
346 signature += ")";
347}
348
349void TClingMethodInfo::Init(const clang::FunctionDecl *decl)
350{
351 fFirstTime = true;
352 fIter = {};
353 fDecl = decl;
354}
355
357{
358 if (!IsValid()) {
359 return 0;
360 }
362 TClingCallFunc cf(fInterp,normCtxt);
363 cf.SetFunc(this);
364 return cf.InterfaceMethod();
365}
366
367const clang::Decl* TClingMethodInfo::GetDeclSlow() const
368{
369 return *fIter;
370}
371
373{
374 if (!IsValid()) {
375 return -1;
376 }
377 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
378 unsigned num_params = fd->getNumParams();
379 // Truncate cast to fit cint interface.
380 return static_cast<int>(num_params);
381}
382
384{
385 if (!IsValid()) {
386 return -1;
387 }
388 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
389 unsigned num_params = fd->getNumParams();
390 unsigned min_args = fd->getMinRequiredArguments();
391 unsigned defaulted_params = num_params - min_args;
392 // Truncate cast to fit cint interface.
393 return static_cast<int>(defaulted_params);
394}
395
396/*
397static bool HasUnexpandedParameterPack(clang::QualType QT, clang::Sema& S) {
398 if (llvm::isa<PackExpansionType>(*QT)) {
399 // We are not going to expand the pack here...
400 return true;
401 }
402 SmallVector<UnexpandedParameterPack, 4> Unexpanded;
403 S.collectUnexpandedParameterPacks (QT, Unexpanded);
404
405 return !Unexpanded.empty();
406}
407 */
408
410{
411
412 assert(!fDecl && "This is not an iterator!");
413
414 fNameCache.clear(); // invalidate the cache.
415
416 if (!fFirstTime && !fIter.IsValid()) {
417 // Iterator is already invalid.
418 return 0;
419 }
420 // Advance to the next decl.
421 if (fFirstTime) {
422 // The cint semantics are weird.
423 fFirstTime = false;
424 } else {
425 fIter.Next();
426 }
427 return fIter.IsValid();
428}
429
431{
432 if (!IsValid()) {
433 return 0L;
434 }
435 long property = 0L;
436 property |= kIsCompiled;
437
438 // NOTE: this uses `GetDecl()`, to capture the access of the UsingShadowDecl,
439 // which is defined in the derived class and might differ from the access of fd
440 // in the base class.
441 const Decl *declAccess = GetDecl();
442 if (llvm::isa<UsingShadowDecl>(declAccess))
443 property |= kIsUsing;
444
445 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
446 clang::AccessSpecifier Access = clang::AS_public;
447 if (!declAccess->getDeclContext()->isNamespace())
448 Access = declAccess->getAccess();
449
450 if ((property & kIsUsing) && llvm::isa<CXXConstructorDecl>(fd)) {
451 Access = clang::AS_public;
452 clang::CXXRecordDecl *typeCXXRD = llvm::cast<RecordType>(Type()->GetQualType())->getAsCXXRecordDecl();
453 clang::CXXBasePaths basePaths;
454 if (typeCXXRD->isDerivedFrom(llvm::dyn_cast<CXXRecordDecl>(fd->getDeclContext()), basePaths)) {
455 // Access of the ctor is access of the base inheritance, and
456 // cannot be overruled by the access of the using decl.
457
458 for (auto el: basePaths) {
459 if (el.Access > Access)
460 Access = el.Access;
461 }
462 } else {
463 Error("Property()", "UsingDecl of ctor not shadowing a base ctor!");
464 }
465
466 // But a private ctor stays private:
467 if (fd->getAccess() > Access)
468 Access = fd->getAccess();
469 }
470 switch (Access) {
471 case clang::AS_public:
472 property |= kIsPublic;
473 break;
474 case clang::AS_protected:
475 property |= kIsProtected;
476 break;
477 case clang::AS_private:
478 property |= kIsPrivate;
479 break;
480 case clang::AS_none:
481 if (declAccess->getDeclContext()->isNamespace())
482 property |= kIsPublic;
483 break;
484 default:
485 // IMPOSSIBLE
486 break;
487 }
488
489 if (fd->isConstexpr())
490 property |= kIsConstexpr;
491 if (fd->getStorageClass() == clang::SC_Static) {
492 property |= kIsStatic;
493 }
494 clang::QualType qt = fd->getReturnType().getCanonicalType();
495
496 property = TClingDeclInfo::Property(property, qt);
497
498 if (const clang::CXXMethodDecl *md =
499 llvm::dyn_cast<clang::CXXMethodDecl>(fd)) {
500 if (md->getMethodQualifiers().hasConst()) {
501 property |= kIsConstant | kIsConstMethod;
502 }
503 if (md->isVirtual()) {
504 property |= kIsVirtual;
505 }
506 if (md->isPure()) {
507 property |= kIsPureVirtual;
508 }
509 if (const clang::CXXConstructorDecl *cd =
510 llvm::dyn_cast<clang::CXXConstructorDecl>(md)) {
511 if (cd->isExplicit()) {
512 property |= kIsExplicit;
513 }
514 }
515 else if (const clang::CXXConversionDecl *cd =
516 llvm::dyn_cast<clang::CXXConversionDecl>(md)) {
517 if (cd->isExplicit()) {
518 property |= kIsExplicit;
519 }
520 }
521 }
522 return property;
523}
524
526{
527 // Return the property not already defined in Property
528 // See TDictionary's EFunctionProperty
529 if (!IsValid()) {
530 return 0L;
531 }
532 long property = 0;
533 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
534 if (fd->isOverloadedOperator())
535 property |= kIsOperator;
536 if (llvm::isa<clang::CXXConversionDecl>(fd))
537 property |= kIsConversion;
538 if (llvm::isa<clang::CXXConstructorDecl>(fd))
539 property |= kIsConstructor;
540 if (llvm::isa<clang::CXXDestructorDecl>(fd))
541 property |= kIsDestructor;
542 if (fd->isInlined())
543 property |= kIsInlined;
544 if (fd->getTemplatedKind() != clang::FunctionDecl::TK_NonTemplate)
545 property |= kIsTemplateSpec;
546 return property;
547}
548
550{
551 TTHREAD_TLS_DECL_ARG( TClingTypeInfo, ti, fInterp );
552 if (!IsValid()) {
553 ti.Init(clang::QualType());
554 return &ti;
555 }
556 if (llvm::isa<clang::CXXConstructorDecl>(GetTargetFunctionDecl())) {
557 // CINT claims that constructors return the class object.
558 // For using-ctors of a base, claim that it "returns" the derived class.
559 const clang::TypeDecl* ctorClass = llvm::dyn_cast_or_null<clang::TypeDecl>
560 (GetDecl()->getDeclContext());
561 if (!ctorClass) {
562 Error("TClingMethodInfo::Type", "Cannot find DeclContext for constructor!");
563 } else {
564 clang::QualType qt(ctorClass->getTypeForDecl(), 0);
565 ti.Init(qt);
566 }
567 } else {
568 clang::QualType qt = GetTargetFunctionDecl()->getReturnType();
569 ti.Init(qt);
570 }
571 return &ti;
572}
573
575{
576 if (!IsValid()) {
577 return "";
578 }
579 std::string mangled_name;
580 mangled_name.clear();
581 const FunctionDecl* D = GetTargetFunctionDecl();
582
584 cling::Interpreter::PushTransactionRAII RAII(fInterp);
585 GlobalDecl GD;
586 if (const CXXConstructorDecl* Ctor = dyn_cast<CXXConstructorDecl>(D))
587 GD = GlobalDecl(Ctor, Ctor_Complete);
588 else if (const CXXDestructorDecl* Dtor = dyn_cast<CXXDestructorDecl>(D))
589 GD = GlobalDecl(Dtor, Dtor_Deleting);
590 else
591 GD = GlobalDecl(D);
592
593 cling::utils::Analyze::maybeMangleDeclName(GD, mangled_name);
594 return mangled_name;
595}
596
598{
599 if (!IsValid()) {
600 return 0;
601 }
602 TTHREAD_TLS_DECL( std::string, buf );
603 buf.clear();
604 buf += Type()->Name();
605 buf += ' ';
606 const FunctionDecl *FD = GetTargetFunctionDecl();
607 // Use the DeclContext of the decl, not of the target decl:
608 // Used base functions should show as if they are part of the derived class,
609 // e.g. `Derived Derived::Derived(int)`, not `Derived Base::Derived(int)`.
610 if (const clang::TypeDecl *td = llvm::dyn_cast<clang::TypeDecl>(GetDecl()->getDeclContext())) {
611 std::string name;
612 clang::QualType qualType(td->getTypeForDecl(),0);
614 buf += name;
615 buf += "::";
616 } else if (const clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(FD->getDeclContext())) {
617 std::string name;
618 clang::PrintingPolicy policy(FD->getASTContext().getPrintingPolicy());
619 llvm::raw_string_ostream stream(name);
620 nd->getNameForDiagnostic(stream, policy, /*Qualified=*/true);
621 stream.flush();
622 buf += name;
623 buf += "::";
624 }
625 buf += Name();
626
627 TString signature;
628 CreateSignature(signature);
629 buf += signature;
630
631 if (const clang::CXXMethodDecl *md =
632 llvm::dyn_cast<clang::CXXMethodDecl>(FD)) {
633 if (md->getMethodQualifiers().hasConst()) {
634 buf += " const";
635 }
636 }
637 return buf.c_str(); // NOLINT
638}
639
640const char *TClingMethodInfo::Name() const
641{
642 if (!IsValid()) {
643 return 0;
644 }
645 if (!fNameCache.empty())
646 return fNameCache.c_str();
647
648 ((TCling*)gCling)->GetFunctionName(GetDecl(), fNameCache);
649 return fNameCache.c_str();
650}
651
652const char *TClingMethodInfo::TypeName() const
653{
654 if (!IsValid()) {
655 // FIXME: Cint does not check!
656 return 0;
657 }
658 return Type()->Name();
659}
660
662{
663 if (!IsValid()) {
664 return 0;
665 }
666
667 //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
668 //if (fTitle.size())
669 // return fTitle.c_str();
670
671 // Try to get the comment either from the annotation or the header file if present
672
673 // Iterate over the redeclarations, we can have multiple definitions in the
674 // redecl chain (came from merging of pcms).
675 const FunctionDecl *FD = GetTargetFunctionDecl();
676
678
679 // Could trigger deserialization of decls.
680 cling::Interpreter::PushTransactionRAII RAII(fInterp);
681 if (const FunctionDecl *AnnotFD
683 if (AnnotateAttr *A = AnnotFD->getAttr<AnnotateAttr>()) {
684 fTitle = A->getAnnotation().str();
685 return fTitle.c_str();
686 }
687 }
688 if (!FD->isFromASTFile()) {
689 // Try to get the comment from the header file if present
690 // but not for decls from AST file, where rootcling would have
691 // created an annotation
693 }
694
695 return fTitle.c_str();
696}
697
@ kIsDestructor
Definition: TDictionary.h:129
@ kIsConversion
Definition: TDictionary.h:128
@ kIsTemplateSpec
Definition: TDictionary.h:132
@ 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,...)
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
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
Definition: TInterpreter.h:46
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:565
#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)
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:102
const void * DeclId_t
Definition: TDictionary.h:223
Basic string class.
Definition: TString.h:136
static double A[]
const T * GetAnnotatedRedeclarable(const T *Redecl)
Definition: TClingUtils.h:644
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(Args_t &&... args)
Definition: RooArgSet.h:240
static constexpr double L