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