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