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