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 | kIsNotReacheable;
485 break;
486 case clang::AS_private:
487 property |= kIsPrivate | kIsNotReacheable;
488 break;
489 case clang::AS_none:
490 if (declAccess->getDeclContext()->isNamespace())
491 property |= kIsPublic;
492 break;
493 default:
494 // IMPOSSIBLE
495 assert(false && "Unexpected value for the access property value in Clang");
496 break;
497 }
498
499 if (!(property & kIsNotReacheable)) {
501 property |= kIsNotReacheable;
502 }
503
504 if (fd->isConstexpr())
505 property |= kIsConstexpr;
506 if (fd->getStorageClass() == clang::SC_Static) {
507 property |= kIsStatic;
508 }
509 clang::QualType qt = fd->getReturnType().getCanonicalType();
510
511 property = TClingDeclInfo::Property(property, qt);
512
513 if (const clang::CXXMethodDecl *md =
514 llvm::dyn_cast<clang::CXXMethodDecl>(fd)) {
515 if (md->getMethodQualifiers().hasConst()) {
516 property |= kIsConstant | kIsConstMethod;
517 }
518 if (md->isVirtual()) {
519 property |= kIsVirtual;
520 }
521 if (md->isPure()) {
522 property |= kIsPureVirtual;
523 }
524 if (const clang::CXXConstructorDecl *cd =
525 llvm::dyn_cast<clang::CXXConstructorDecl>(md)) {
526 if (cd->isExplicit()) {
527 property |= kIsExplicit;
528 }
529 }
530 else if (const clang::CXXConversionDecl *cd =
531 llvm::dyn_cast<clang::CXXConversionDecl>(md)) {
532 if (cd->isExplicit()) {
533 property |= kIsExplicit;
534 }
535 }
536 }
537 return property;
538}
539
541{
542 // Return the property not already defined in Property
543 // See TDictionary's EFunctionProperty
544 if (!IsValid()) {
545 return 0L;
546 }
547 long property = 0;
548 // The next call locks the interpreter mutex.
549 const clang::FunctionDecl *fd = GetTargetFunctionDecl();
550 if (fd->isOverloadedOperator())
551 property |= kIsOperator;
552 if (llvm::isa<clang::CXXConversionDecl>(fd))
553 property |= kIsConversion;
554 if (llvm::isa<clang::CXXConstructorDecl>(fd))
555 property |= kIsConstructor;
556 if (llvm::isa<clang::CXXDestructorDecl>(fd))
557 property |= kIsDestructor;
558 if (fd->isInlined())
559 property |= kIsInlined;
560 if (fd->getTemplatedKind() != clang::FunctionDecl::TK_NonTemplate)
561 property |= kIsTemplateSpec;
562 return property;
563}
564
566{
567 TTHREAD_TLS_DECL_ARG( TClingTypeInfo, ti, fInterp );
568 if (!IsValid()) {
569 ti.Init(clang::QualType());
570 return &ti;
571 }
572
573 // The next part interacts with clang, thus needs locking.
575 if (llvm::isa<clang::CXXConstructorDecl>(GetTargetFunctionDecl())) {
576 // CINT claims that constructors return the class object.
577 // For using-ctors of a base, claim that it "returns" the derived class.
578 const clang::TypeDecl* ctorClass = llvm::dyn_cast_or_null<clang::TypeDecl>
579 (GetDecl()->getDeclContext());
580 if (!ctorClass) {
581 Error("TClingMethodInfo::Type", "Cannot find DeclContext for constructor!");
582 } else {
583 clang::QualType qt(ctorClass->getTypeForDecl(), 0);
584 ti.Init(qt);
585 }
586 } else {
587 clang::QualType qt = GetTargetFunctionDecl()->getReturnType();
588 ti.Init(qt);
589 }
590 return &ti;
591}
592
594{
595 if (!IsValid()) {
596 return "";
597 }
598 std::string mangled_name;
599 mangled_name.clear();
600 const FunctionDecl* D = GetTargetFunctionDecl();
601
602 // Creating an interpreter transaction, needs locking.
604 cling::Interpreter::PushTransactionRAII RAII(fInterp);
605 GlobalDecl GD;
606 if (const CXXConstructorDecl* Ctor = dyn_cast<CXXConstructorDecl>(D))
607 GD = GlobalDecl(Ctor, Ctor_Complete);
608 else if (const CXXDestructorDecl* Dtor = dyn_cast<CXXDestructorDecl>(D))
609 GD = GlobalDecl(Dtor, Dtor_Deleting);
610 else
611 GD = GlobalDecl(D);
612
613 cling::utils::Analyze::maybeMangleDeclName(GD, mangled_name);
614 return mangled_name;
615}
616
618{
619 if (!IsValid()) {
620 return nullptr;
621 }
622 TTHREAD_TLS_DECL( std::string, buf );
623 buf.clear();
624 buf += Type()->Name();
625 buf += ' ';
626 // The next call locks the interpreter mutex.
627 const FunctionDecl *FD = GetTargetFunctionDecl();
628 // Use the DeclContext of the decl, not of the target decl:
629 // Used base functions should show as if they are part of the derived class,
630 // e.g. `Derived Derived::Derived(int)`, not `Derived Base::Derived(int)`.
631 // Interacting with clang in the next part, needs locking
633 if (const clang::TypeDecl *td = llvm::dyn_cast<clang::TypeDecl>(GetDecl()->getDeclContext())) {
634 std::string name;
635 clang::QualType qualType(td->getTypeForDecl(),0);
637 buf += name;
638 buf += "::";
639 } else if (const clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(FD->getDeclContext())) {
640 std::string name;
641 clang::PrintingPolicy policy(FD->getASTContext().getPrintingPolicy());
642 llvm::raw_string_ostream stream(name);
643 nd->getNameForDiagnostic(stream, policy, /*Qualified=*/true);
644 stream.flush();
645 buf += name;
646 buf += "::";
647 }
648 buf += Name();
649
650 TString signature;
651 CreateSignature(signature);
652 buf += signature;
653
654 if (const clang::CXXMethodDecl *md =
655 llvm::dyn_cast<clang::CXXMethodDecl>(FD)) {
656 if (md->getMethodQualifiers().hasConst()) {
657 buf += " const";
658 }
659 }
660 return buf.c_str(); // NOLINT
661}
662
663const char *TClingMethodInfo::Name() const
664{
665 if (!IsValid()) {
666 return nullptr;
667 }
668 if (!fNameCache.empty())
669 return fNameCache.c_str();
670
671 {
672 // The data member needs to be filled. This calls into the interpreter,
673 // needs locking.
674 // TODO: Check if the lock can be moved further deep.
676 ((TCling *)gCling)->GetFunctionName(GetDecl(), fNameCache);
677 }
678 return fNameCache.c_str();
679}
680
681const char *TClingMethodInfo::TypeName() const
682{
683 if (!IsValid()) {
684 // FIXME: Cint does not check!
685 return nullptr;
686 }
687 // The next *two* calls lock the interpreter mutex. Lock here first instead
688 // of locking/unlocking twice.
690 return Type()->Name();
691}
692
694{
695 if (!IsValid()) {
696 return nullptr;
697 }
698
699 //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
700 //if (fTitle.size())
701 // return fTitle.c_str();
702
703 // Try to get the comment either from the annotation or the header file if present
704
705 // Iterate over the redeclarations, we can have multiple definitions in the
706 // redecl chain (came from merging of pcms).
707 const FunctionDecl *FD = GetTargetFunctionDecl();
708
709 // Creating an interpreter transaction, needs locking.
711
712 // Could trigger deserialization of decls.
713 cling::Interpreter::PushTransactionRAII RAII(fInterp);
714 if (const FunctionDecl *AnnotFD
716 if (AnnotateAttr *A = AnnotFD->getAttr<AnnotateAttr>()) {
717 fTitle = A->getAnnotation().str();
718 return fTitle.c_str();
719 }
720 }
721 if (!FD->isFromASTFile()) {
722 // Try to get the comment from the header file if present
723 // but not for decls from AST file, where rootcling would have
724 // created an annotation
726 }
727
728 return fTitle.c_str();
729}
730
@ 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: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)
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.