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::CXXSpecialMemberKind::Invalid) {
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::CXXSpecialMemberKind::DefaultConstructor && CXXMD->getNumParams() == 0) ||
112 ((SpecMemKind == clang::CXXSpecialMemberKind::CopyConstructor || SpecMemKind == clang::CXXSpecialMemberKind::MoveConstructor) &&
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::CXXSpecialMemberKind::DefaultConstructor,
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
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;
173 if (!TTP->hasDefaultArgument())
174 return nullptr;
175 defaultTemplateArgs.emplace_back(TTP->getDefaultArgument().getArgument());
177 if (!NTTP->hasDefaultArgument())
178 return nullptr;
179 defaultTemplateArgs.emplace_back(NTTP->getDefaultArgument().getArgument());
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)
198 sema::TemplateDeductionInfo Info{SourceLocation()};
199
200 auto *FTD = const_cast<clang::FunctionTemplateDecl *>(llvm::dyn_cast<clang::FunctionTemplateDecl>(TD));
201 Sema::InstantiatingTemplate Inst(
202 S, Info.getLocation(), FTD,
203 defaultTemplateArgs, Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, SourceRange());
204
205 // Collect the function arguments of the templated function, substituting
206 // dependent types as possible.
208 // LLVM22 (CWG2369): alias templates are now eagerly expanded during substitution, which can emit hard diagnostics
209 // for non-SFINAE-safe alias templates. Suppress them explicitly.
210 Sema::SFINAETrap Trap(S, /*WithAccessChecking=*/true);
211 for (const clang::ParmVarDecl *param : templatedDecl->parameters()) {
212 QualType paramType = param->getOriginalType();
213
214 // If the function type is dependent, try to resolve it through the class's
215 // template arguments. If that fails, skip this function.
216 if (paramType->isDependentType()) {
217 /*if (HasUnexpandedParameterPack(paramType, S)) {
218 // We are not going to expand the pack here...
219 Skip = true;
220 break;
221 }*/
222
223 paramType = S.SubstType(paramType, MLTAL, SourceLocation(), templatedDecl->getDeclName());
224
225 if (paramType.isNull() || paramType->isDependentType()) {
226 // Even after resolving the types through the surrounding template
227 // this argument type is still dependent: do not look it up.
228 return nullptr;
229 }
230 }
231 paramTypes.push_back(paramType);
232 }
233
234 return LH.findFunctionProto(declCtxDecl, TD->getNameAsString(), paramTypes, LH.NoDiagnostics,
235 templatedDecl->getType().isConstQualified());
236}
237
240 : TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fTitle("")
241{
242 // Creating an interpreter transaction, needs locking.
244
245 if (!ci || !ci->IsValid()) {
246 return;
247 }
248 clang::Decl *D = const_cast<clang::Decl *>(ci->GetDecl());
249 auto *DC = llvm::dyn_cast<clang::DeclContext>(D);
250
251 llvm::SmallVector<clang::CXXMethodDecl*, 8> SpecFuncs;
252
253 if (auto *CXXRD = llvm::dyn_cast<CXXRecordDecl>(DC)) {
254 // Initialize the CXXRecordDecl's special functions; could change the
255 // DeclContext content!
256
257 // Could trigger deserialization of decls.
258 cling::Interpreter::PushTransactionRAII RAII(interp);
259
260 auto &SemaRef = interp->getSema();
261 SemaRef.ForceDeclarationOfImplicitMembers(CXXRD);
262
263 // Assemble special functions (or FunctionTemplate-s) that are synthesized from DefinitionData but
264 // won't be enumerated as part of decls_begin()/decls_end().
265 for (clang::NamedDecl *ctor : SemaRef.LookupConstructors(CXXRD)) {
266 // Filter out constructor templates, they are not functions we can iterate over:
267 if (auto *CXXCD = llvm::dyn_cast<clang::CXXConstructorDecl>(ctor))
268 SpecFuncs.emplace_back(CXXCD);
269 }
270 SpecFuncs.emplace_back(SemaRef.LookupCopyingAssignment(CXXRD, /*Quals*/ 0, /*RValueThis*/ false, 0 /*ThisQuals*/));
271 SpecFuncs.emplace_back(SemaRef.LookupMovingAssignment(CXXRD, /*Quals*/ 0, /*RValueThis*/ false, 0 /*ThisQuals*/));
272 SpecFuncs.emplace_back(SemaRef.LookupDestructor(CXXRD));
273 }
274
276 fIter.Init();
277}
278
280 const clang::Decl *D)
281 : TClingDeclInfo(D), fInterp(interp), fFirstTime(true), fTitle("")
282{
283 if (!D)
284 Error("TClingMethodInfo", "nullptr FunctionDecl passed!");
285}
286
288{
289 if (!IsValid()) {
290 return TDictionary::DeclId_t();
291 }
292 // Next part interacts with clang, needs locking
294 if (auto *FD = GetAsFunctionDecl())
295 return (const clang::Decl*)(FD->getCanonicalDecl());
296 return (const clang::Decl*)(GetAsUsingShadowDecl()->getCanonicalDecl());
297}
298
299const clang::FunctionDecl *TClingMethodInfo::GetAsFunctionDecl() const
300{
302}
303
304const clang::UsingShadowDecl *TClingMethodInfo::GetAsUsingShadowDecl() const
305{
307}
308
309const clang::FunctionDecl *TClingMethodInfo::GetTargetFunctionDecl() const
310{
311 // May need to resolve the declaration interacting with clang, needs locking.
313 const Decl *D = GetDecl();
314 do {
315 if (auto FD = dyn_cast<FunctionDecl>(D))
316 return FD;
317 } while ((D = dyn_cast<UsingShadowDecl>(D)->getTargetDecl()));
318 return nullptr;
319}
320
322{
323 signature = "(";
324 if (!IsValid()) {
325 signature += ")";
326 return;
327 }
328
330 TClingMethodArgInfo arg(fInterp, this);
331
332 int idx = 0;
333 while (arg.Next()) {
334 if (idx) {
335 signature += ", ";
336 }
337 signature += arg.Type()->Name();
338 if (arg.Name() && strlen(arg.Name())) {
339 signature += " ";
340 signature += arg.Name();
341 }
342 if (arg.DefaultValue()) {
343 signature += " = ";
344 signature += arg.DefaultValue();
345 }
346 ++idx;
347 }
349 if (decl && decl->isVariadic())
350 signature += ",...";
351
352 signature += ")";
353}
354
355void TClingMethodInfo::Init(const clang::FunctionDecl *decl)
356{
357 fFirstTime = true;
358 fIter = {};
359 fDecl = decl;
360}
361
363{
364 if (!IsValid()) {
365 return nullptr;
366 }
367 // TODO: can this lock be moved further deep?
370 cf.SetFunc(this);
371 return cf.InterfaceMethod();
372}
373
374const clang::Decl* TClingMethodInfo::GetDeclSlow() const
375{
376 return *fIter;
377}
378
380{
381 if (!IsValid()) {
382 return -1;
383 }
384 // The next call locks the interpreter mutex.
385 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
386 unsigned num_params = fd->getNumParams();
387 // Truncate cast to fit cint interface.
388 return static_cast<int>(num_params);
389}
390
392{
393 if (!IsValid()) {
394 return -1;
395 }
396 // The next call locks the interpreter mutex.
397 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
398 unsigned num_params = fd->getNumParams();
399 unsigned min_args = fd->getMinRequiredArguments();
401 // Truncate cast to fit cint interface.
402 return static_cast<int>(defaulted_params);
403}
404
405/*
406static bool HasUnexpandedParameterPack(clang::QualType QT, clang::Sema& S) {
407 if (llvm::isa<PackExpansionType>(*QT)) {
408 // We are not going to expand the pack here...
409 return true;
410 }
411 SmallVector<UnexpandedParameterPack, 4> Unexpanded;
412 S.collectUnexpandedParameterPacks (QT, Unexpanded);
413
414 return !Unexpanded.empty();
415}
416 */
417
419{
420
421 assert(!fDecl && "This is not an iterator!");
422
423 fNameCache.clear(); // invalidate the cache.
424
425 if (!fFirstTime && !fIter.IsValid()) {
426 // Iterator is already invalid.
427 return 0;
428 }
429 // Advance to the next decl.
430 if (fFirstTime) {
431 // The cint semantics are weird.
432 fFirstTime = false;
433 } else {
434 fIter.Next();
435 }
436 return fIter.IsValid();
437}
438
440{
441 if (!IsValid()) {
442 return 0L;
443 }
444 long property = 0L;
445 property |= kIsCompiled;
446
447 // NOTE: this uses `GetDecl()`, to capture the access of the UsingShadowDecl,
448 // which is defined in the derived class and might differ from the access of fd
449 // in the base class.
450 const Decl *declAccess = GetDecl();
451 if (llvm::isa<UsingShadowDecl>(declAccess))
452 property |= kIsUsing;
453
454 // The next call locks the interpreter mutex.
455 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
456 clang::AccessSpecifier Access = clang::AS_public;
457 if (!declAccess->getDeclContext()->isNamespace())
458 Access = declAccess->getAccess();
459
460 // From here on the method interacts with clang directly, needs locking.
462 if ((property & kIsUsing) && llvm::isa<CXXConstructorDecl>(fd)) {
463 Access = clang::AS_public;
464 clang::CXXRecordDecl *typeCXXRD = llvm::cast<RecordType>(Type()->GetQualType())->getAsCXXRecordDecl();
465 clang::CXXBasePaths basePaths;
466 if (typeCXXRD->isDerivedFrom(llvm::dyn_cast<CXXRecordDecl>(fd->getDeclContext()), basePaths)) {
467 // Access of the ctor is access of the base inheritance, and
468 // cannot be overruled by the access of the using decl.
469
470 for (auto el: basePaths) {
471 if (el.Access > Access)
472 Access = el.Access;
473 }
474 } else {
475 Error("Property()", "UsingDecl of ctor not shadowing a base ctor!");
476 }
477
478 // But a private ctor stays private:
479 if (fd->getAccess() > Access)
480 Access = fd->getAccess();
481 }
482 switch (Access) {
483 case clang::AS_public:
484 property |= kIsPublic;
485 break;
486 case clang::AS_protected:
487 property |= kIsProtected | kIsNotReacheable;
488 break;
489 case clang::AS_private:
490 property |= kIsPrivate | kIsNotReacheable;
491 break;
492 case clang::AS_none:
493 if (declAccess->getDeclContext()->isNamespace())
494 property |= kIsPublic;
495 break;
496 default:
497 // IMPOSSIBLE
498 assert(false && "Unexpected value for the access property value in Clang");
499 break;
500 }
501
502 if (!(property & kIsNotReacheable)) {
504 property |= kIsNotReacheable;
505 }
506
507 if (fd->isConstexpr())
508 property |= kIsConstexpr;
509 if (fd->getStorageClass() == clang::SC_Static) {
510 property |= kIsStatic;
511 }
512 clang::QualType qt = fd->getReturnType().getCanonicalType();
513
515
516 if (const clang::CXXMethodDecl *md =
517 llvm::dyn_cast<clang::CXXMethodDecl>(fd)) {
518 if (md->getMethodQualifiers().hasConst()) {
519 property |= kIsConstant | kIsConstMethod;
520 }
521 if (md->isVirtual()) {
522 property |= kIsVirtual;
523 }
524 if (md->isPureVirtual()) {
525 property |= kIsPureVirtual;
526 }
527 if (const clang::CXXConstructorDecl *cd =
528 llvm::dyn_cast<clang::CXXConstructorDecl>(md)) {
529 if (cd->isExplicit()) {
530 property |= kIsExplicit;
531 }
532 }
533 else if (const clang::CXXConversionDecl *cd =
534 llvm::dyn_cast<clang::CXXConversionDecl>(md)) {
535 if (cd->isExplicit()) {
536 property |= kIsExplicit;
537 }
538 }
539 }
540 return property;
541}
542
544{
545 // Return the property not already defined in Property
546 // See TDictionary's EFunctionProperty
547 if (!IsValid()) {
548 return 0L;
549 }
550 long property = 0;
551 // The next call locks the interpreter mutex.
552 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
553 if (fd->isOverloadedOperator())
554 property |= kIsOperator;
555 if (llvm::isa<clang::CXXConversionDecl>(fd))
556 property |= kIsConversion;
557 if (llvm::isa<clang::CXXConstructorDecl>(fd))
558 property |= kIsConstructor;
559 if (llvm::isa<clang::CXXDestructorDecl>(fd))
560 property |= kIsDestructor;
561 if (fd->isInlined())
562 property |= kIsInlined;
563 if (fd->getTemplatedKind() != clang::FunctionDecl::TK_NonTemplate)
564 property |= kIsTemplateSpec;
565 return property;
566}
567
569{
571 if (!IsValid()) {
572 ti.Init(clang::QualType());
573 return &ti;
574 }
575
576 // The next part interacts with clang, thus needs locking.
578 if (llvm::isa<clang::CXXConstructorDecl>(GetTargetFunctionDecl())) {
579 // CINT claims that constructors return the class object.
580 // For using-ctors of a base, claim that it "returns" the derived class.
581 const clang::TypeDecl* ctorClass = llvm::dyn_cast_or_null<clang::TypeDecl>
582 (GetDecl()->getDeclContext());
583 if (!ctorClass) {
584 Error("TClingMethodInfo::Type", "Cannot find DeclContext for constructor!");
585 } else {
586 clang::QualType qt = ctorClass->getASTContext().getTypeDeclType(ctorClass);
587 ti.Init(qt);
588 }
589 } else {
590 clang::QualType qt = GetTargetFunctionDecl()->getReturnType();
591 ti.Init(qt);
592 }
593 return &ti;
594}
595
597{
598 if (!IsValid()) {
599 return "";
600 }
601 std::string mangled_name;
602 mangled_name.clear();
604
605 // Creating an interpreter transaction, needs locking.
607 cling::Interpreter::PushTransactionRAII RAII(fInterp);
613 else
614 GD = GlobalDecl(D);
615
616 cling::utils::Analyze::maybeMangleDeclName(GD, mangled_name);
617 return mangled_name;
618}
619
621{
622 if (!IsValid()) {
623 return nullptr;
624 }
625 TTHREAD_TLS_DECL( std::string, buf );
626 buf.clear();
627 buf += Type()->Name();
628 buf += ' ';
629 // The next call locks the interpreter mutex.
631 // Use the DeclContext of the decl, not of the target decl:
632 // Used base functions should show as if they are part of the derived class,
633 // e.g. `Derived Derived::Derived(int)`, not `Derived Base::Derived(int)`.
634 // Interacting with clang in the next part, needs locking
636 if (const clang::TypeDecl *td = llvm::dyn_cast<clang::TypeDecl>(GetDecl()->getDeclContext())) {
637 std::string name;
638 clang::QualType qualType = td->getASTContext().getTypeDeclType(td);
640 buf += name;
641 buf += "::";
642 } else if (const clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(FD->getDeclContext())) {
643 std::string name;
644 clang::PrintingPolicy policy(FD->getASTContext().getPrintingPolicy());
645 llvm::raw_string_ostream stream(name);
646 nd->getNameForDiagnostic(stream, policy, /*Qualified=*/true);
647 stream.flush();
648 buf += name;
649 buf += "::";
650 }
651 buf += Name();
652
655 buf += signature;
656
657 if (const clang::CXXMethodDecl *md =
658 llvm::dyn_cast<clang::CXXMethodDecl>(FD)) {
659 if (md->getMethodQualifiers().hasConst()) {
660 buf += " const";
661 }
662 }
663 return buf.c_str(); // NOLINT
664}
665
666const char *TClingMethodInfo::Name() const
667{
668 if (!IsValid()) {
669 return nullptr;
670 }
671 if (!fNameCache.empty())
672 return fNameCache.c_str();
673
674 {
675 // The data member needs to be filled. This calls into the interpreter,
676 // needs locking.
677 // TODO: Check if the lock can be moved further deep.
679 ((TCling *)gCling)->GetFunctionName(GetDecl(), fNameCache);
680 }
681 return fNameCache.c_str();
682}
683
684const char *TClingMethodInfo::TypeName() const
685{
686 if (!IsValid()) {
687 // FIXME: Cint does not check!
688 return nullptr;
689 }
690 // The next *two* calls lock the interpreter mutex. Lock here first instead
691 // of locking/unlocking twice.
693 return Type()->Name();
694}
695
697{
698 if (!IsValid()) {
699 return nullptr;
700 }
701
702 //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
703 //if (fTitle.size())
704 // return fTitle.c_str();
705
706 // Try to get the comment either from the annotation or the header file if present
707
708 // Iterate over the redeclarations, we can have multiple definitions in the
709 // redecl chain (came from merging of pcms).
711
712 // Creating an interpreter transaction, needs locking.
714
715 // Could trigger deserialization of decls.
716 cling::Interpreter::PushTransactionRAII RAII(fInterp);
717 if (const FunctionDecl *AnnotFD
719 if (AnnotateAttr *A = AnnotFD->getAttr<AnnotateAttr>()) {
720 fTitle = A->getAnnotation().str();
721 return fTitle.c_str();
722 }
723 }
724 if (!FD->isFromASTFile()) {
725 // Try to get the comment from the header file if present
726 // but not for decls from AST file, where rootcling would have
727 // created an annotation
729 }
730
731 return fTitle.c_str();
732}
733
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
@ 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
@ kIsNotReacheable
Definition TDictionary.h:87
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:241
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
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:148
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.
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
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:138
const T * GetAnnotatedRedeclarable(const T *Redecl)
bool IsDeclReacheable(const clang::Decl &decl)
Return true if the decl is representing an entity reacheable from the global namespace.
void GetFullyQualifiedTypeName(std::string &name, const clang::QualType &type, const cling::Interpreter &interpreter)
llvm::StringRef GetComment(const clang::Decl &decl, clang::SourceLocation *loc=nullptr)
Returns the comment (// striped away), annotating declaration in a meaningful for ROOT IO way.