30 #include "TClingUtils.h"
34 #include "cling/Interpreter/Interpreter.h"
35 #include "cling/Interpreter/LookupHelper.h"
36 #include "cling/Utils/AST.h"
38 #include "clang/AST/ASTContext.h"
39 #include "clang/AST/Decl.h"
40 #include "clang/AST/DeclCXX.h"
41 #include "clang/AST/DeclTemplate.h"
42 #include "clang/AST/ExprCXX.h"
43 #include "clang/AST/GlobalDecl.h"
44 #include "clang/AST/Mangle.h"
45 #include "clang/AST/PrettyPrinter.h"
46 #include "clang/AST/Type.h"
47 #include "clang/Basic/IdentifierTable.h"
48 #include "clang/Sema/Lookup.h"
49 #include "clang/Sema/Sema.h"
50 #include "clang/Sema/Template.h"
51 #include "clang/Sema/TemplateDeduction.h"
53 #include "llvm/Support/Casting.h"
54 #include "llvm/Support/raw_ostream.h"
58 using namespace clang;
60 TClingMethodInfo::TClingMethodInfo(
const TClingMethodInfo &rhs) :
63 fContexts(rhs.fContexts),
64 fFirstTime(rhs.fFirstTime),
65 fContextIdx(rhs.fContextIdx),
68 fTemplateSpec(rhs.fTemplateSpec)
73 TClingMethodInfo& TClingMethodInfo::operator=(
const TClingMethodInfo &rhs) {
77 this->TClingDeclInfo::operator=(rhs);
78 fInterp = rhs.fInterp;
79 fContexts = rhs.fContexts;
80 fFirstTime = rhs.fFirstTime;
81 fContextIdx = rhs.fContextIdx;
84 fTemplateSpec = rhs.fTemplateSpec;
90 TClingMethodInfo::TClingMethodInfo(cling::Interpreter *interp,
92 : TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fContextIdx(0U), fTitle(
""),
95 R__LOCKGUARD(gInterpreterMutex);
97 if (!ci || !ci->IsValid()) {
100 clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(
const_cast<clang::Decl*
>(ci->GetDecl()));
105 cling::Interpreter::PushTransactionRAII RAII(interp);
107 fInterp->getSema().ForceDeclarationOfImplicitMembers(cxxdecl);
109 clang::DeclContext *dc =
110 llvm::cast<clang::DeclContext>(
const_cast<clang::Decl*
>(ci->GetDecl()));
111 dc->collectAllContexts(fContexts);
113 cling::Interpreter::PushTransactionRAII RAII(interp);
114 fIter = dc->decls_begin();
119 TClingMethodInfo::TClingMethodInfo(cling::Interpreter *interp,
120 const clang::FunctionDecl *FD)
121 : TClingDeclInfo(FD), fInterp(interp), fFirstTime(true), fContextIdx(0U), fTitle(
""),
127 TClingMethodInfo::~TClingMethodInfo()
129 delete fTemplateSpec;
132 TDictionary::DeclId_t TClingMethodInfo::GetDeclId()
const
135 return TDictionary::DeclId_t();
137 return (
const clang::Decl*)(GetMethodDecl()->getCanonicalDecl());
140 const clang::FunctionDecl *TClingMethodInfo::GetMethodDecl()
const
142 return cast_or_null<FunctionDecl>(GetDecl());
145 void TClingMethodInfo::CreateSignature(TString &signature)
const
153 R__LOCKGUARD(gInterpreterMutex);
154 TClingMethodArgInfo arg(fInterp,
this);
161 signature += arg.Type()->Name();
162 if (arg.Name() && strlen(arg.Name())) {
164 signature += arg.Name();
166 if (arg.DefaultValue()) {
168 signature += arg.DefaultValue();
172 auto decl = GetMethodDecl();
173 if (decl && decl->isVariadic())
179 void TClingMethodInfo::Init(
const clang::FunctionDecl *decl)
184 fIter = clang::DeclContext::decl_iterator();
189 void *TClingMethodInfo::InterfaceMethod(
const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
const
194 R__LOCKGUARD(gInterpreterMutex);
195 TClingCallFunc cf(fInterp,normCtxt);
197 return cf.InterfaceMethod();
200 const clang::Decl* TClingMethodInfo::GetDeclSlow()
const
203 return fTemplateSpec;
208 int TClingMethodInfo::NArg()
const
213 const clang::FunctionDecl *fd = GetMethodDecl();
214 unsigned num_params = fd->getNumParams();
216 return static_cast<int>(num_params);
219 int TClingMethodInfo::NDefaultArg()
const
224 const clang::FunctionDecl *fd = GetMethodDecl();
225 unsigned num_params = fd->getNumParams();
226 unsigned min_args = fd->getMinRequiredArguments();
227 unsigned defaulted_params = num_params - min_args;
229 return static_cast<int>(defaulted_params);
245 static const clang::FunctionDecl *
246 GetOrInstantiateFuncTemplateWithDefaults(clang::FunctionTemplateDecl* FTDecl,
248 const cling::LookupHelper& LH) {
250 using namespace clang;
252 auto templateParms = FTDecl->getTemplateParameters();
253 if (templateParms->containsUnexpandedParameterPack())
256 if (templateParms->getMinRequiredArguments() > 0)
259 if (templateParms->size() > 0) {
260 NamedDecl *arg0 = *templateParms->begin();
261 if (arg0->isTemplateParameterPack())
263 if (
auto TTP = dyn_cast<TemplateTypeParmDecl>(*templateParms->begin())) {
264 if (!TTP->hasDefaultArgument())
266 }
else if (
auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(
267 *templateParms->begin())) {
268 if (!NTTP->hasDefaultArgument())
276 FunctionDecl *templatedDecl = FTDecl->getTemplatedDecl();
277 Decl *declCtxDecl = dyn_cast<Decl>(FTDecl->getDeclContext());
287 llvm::SmallVector<TemplateArgument, 8> defaultTemplateArgs(templateParms->size());
288 for (
int iParam = 0, nParams = templateParms->size(); iParam < nParams; ++iParam) {
289 const NamedDecl* templateParm = templateParms->getParam(iParam);
290 if (templateParm->isTemplateParameterPack()) {
292 assert(0 &&
"unexpected template parameter pack");
294 }
if (
auto TTP = dyn_cast<TemplateTypeParmDecl>(templateParm)) {
295 if (!TTP->hasDefaultArgument())
297 defaultTemplateArgs[iParam] = TemplateArgument(TTP->getDefaultArgument());
298 }
else if (
auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(templateParm)) {
299 if (!NTTP->hasDefaultArgument())
301 defaultTemplateArgs[iParam] = TemplateArgument(NTTP->getDefaultArgument());
302 }
else if (
auto TTP = dyn_cast<TemplateTemplateParmDecl>(templateParm)) {
303 if (!TTP->hasDefaultArgument())
305 defaultTemplateArgs[iParam] = TemplateArgument(TTP->getDefaultArgument().getArgument());
308 assert(0 &&
"unexpected template parameter kind");
314 llvm::SmallVector<QualType, 8> paramTypes;
317 SmallVector<DeducedTemplateArgument, 4> DeducedArgs;
318 sema::TemplateDeductionInfo Info{SourceLocation()};
320 Sema::InstantiatingTemplate Inst(S, Info.getLocation(), FTDecl,
322 Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
327 TemplateArgumentList templArgList(TemplateArgumentList::OnStack, defaultTemplateArgs);
328 MultiLevelTemplateArgumentList MLTAL{templArgList};
329 for (
const clang::ParmVarDecl *param: templatedDecl->parameters()) {
330 QualType paramType = param->getOriginalType();
334 if (paramType->isDependentType()) {
341 paramType = S.SubstType(paramType, MLTAL, SourceLocation(),
342 templatedDecl->getDeclName());
344 if (paramType.isNull() || paramType->isDependentType()) {
350 paramTypes.push_back(paramType);
353 return LH.findFunctionProto(declCtxDecl, FTDecl->getNameAsString(),
354 paramTypes, LH.NoDiagnostics,
355 templatedDecl->getType().isConstQualified());
358 int TClingMethodInfo::InternalNext()
361 assert(!fDecl &&
"This is not an iterator!");
365 if (!fFirstTime && !*fIter) {
372 fTemplateSpec =
nullptr;
385 if (fContextIdx >= fContexts.size()) {
389 clang::DeclContext *dc = fContexts[fContextIdx];
392 cling::Interpreter::PushTransactionRAII RAII(fInterp);
393 fIter = dc->decls_begin();
400 if (
const auto templateDecl = llvm::dyn_cast<clang::FunctionTemplateDecl>(*fIter)) {
402 cling::Interpreter::PushTransactionRAII RAII(fInterp);
407 fTemplateSpec = GetOrInstantiateFuncTemplateWithDefaults(templateDecl, fInterp->getSema(),
408 fInterp->getLookupHelper());
414 if (llvm::isa<clang::FunctionDecl>(*fIter)) {
420 if (
auto NS = dyn_cast<NamespaceDecl>(*fIter)) {
421 if (NS->getDeclContext()->isTranslationUnit() && NS->isInlineNamespace())
422 fContexts.push_back(NS);
433 int TClingMethodInfo::Next()
435 return InternalNext();
438 long TClingMethodInfo::Property()
const
444 property |= kIsCompiled;
445 const clang::FunctionDecl *fd = GetMethodDecl();
446 if (fd->isConstexpr())
447 property |= kIsConstexpr;
448 switch (fd->getAccess()) {
449 case clang::AS_public:
450 property |= kIsPublic;
452 case clang::AS_protected:
453 property |= kIsProtected;
455 case clang::AS_private:
456 property |= kIsPrivate;
459 if (fd->getDeclContext()->isNamespace())
460 property |= kIsPublic;
466 if (fd->getStorageClass() == clang::SC_Static) {
467 property |= kIsStatic;
469 clang::QualType qt = fd->getReturnType().getCanonicalType();
470 if (qt.isConstQualified()) {
471 property |= kIsConstant;
474 if (qt->isArrayType()) {
475 qt = llvm::cast<clang::ArrayType>(qt)->getElementType();
478 else if (qt->isReferenceType()) {
479 property |= kIsReference;
480 qt = llvm::cast<clang::ReferenceType>(qt)->getPointeeType();
483 else if (qt->isPointerType()) {
484 property |= kIsPointer;
485 if (qt.isConstQualified()) {
486 property |= kIsConstPointer;
488 qt = llvm::cast<clang::PointerType>(qt)->getPointeeType();
491 else if (qt->isMemberPointerType()) {
492 qt = llvm::cast<clang::MemberPointerType>(qt)->getPointeeType();
497 if (qt.isConstQualified()) {
498 property |= kIsConstant;
500 if (
const clang::CXXMethodDecl *md =
501 llvm::dyn_cast<clang::CXXMethodDecl>(fd)) {
502 if (md->getTypeQualifiers() & clang::Qualifiers::Const) {
503 property |= kIsConstant | kIsConstMethod;
505 if (md->isVirtual()) {
506 property |= kIsVirtual;
509 property |= kIsPureVirtual;
511 if (
const clang::CXXConstructorDecl *cd =
512 llvm::dyn_cast<clang::CXXConstructorDecl>(md)) {
513 if (cd->isExplicit()) {
514 property |= kIsExplicit;
517 else if (
const clang::CXXConversionDecl *cd =
518 llvm::dyn_cast<clang::CXXConversionDecl>(md)) {
519 if (cd->isExplicit()) {
520 property |= kIsExplicit;
527 long TClingMethodInfo::ExtraProperty()
const
535 const clang::FunctionDecl *fd = GetMethodDecl();
536 if (fd->isOverloadedOperator())
537 property |= kIsOperator;
538 if (llvm::isa<clang::CXXConversionDecl>(fd))
539 property |= kIsConversion;
540 if (llvm::isa<clang::CXXConstructorDecl>(fd))
541 property |= kIsConstructor;
542 if (llvm::isa<clang::CXXDestructorDecl>(fd))
543 property |= kIsDestructor;
545 property |= kIsInlined;
549 TClingTypeInfo *TClingMethodInfo::Type()
const
551 TTHREAD_TLS_DECL_ARG( TClingTypeInfo, ti, fInterp );
553 ti.Init(clang::QualType());
556 if (llvm::isa<clang::CXXConstructorDecl>(GetMethodDecl())) {
558 const clang::TypeDecl* ctorClass = llvm::dyn_cast_or_null<clang::TypeDecl>
559 (GetMethodDecl()->getDeclContext());
561 Error(
"TClingMethodInfo::Type",
"Cannot find DeclContext for constructor!");
563 clang::QualType qt(ctorClass->getTypeForDecl(), 0);
567 clang::QualType qt = GetMethodDecl()->getReturnType();
573 std::string TClingMethodInfo::GetMangledName()
const
578 std::string mangled_name;
579 mangled_name.clear();
580 const FunctionDecl* D = GetMethodDecl();
582 R__LOCKGUARD(gInterpreterMutex);
583 cling::Interpreter::PushTransactionRAII RAII(fInterp);
585 if (
const CXXConstructorDecl* Ctor = dyn_cast<CXXConstructorDecl>(D))
586 GD = GlobalDecl(Ctor, Ctor_Complete);
587 else if (
const CXXDestructorDecl* Dtor = dyn_cast<CXXDestructorDecl>(D))
588 GD = GlobalDecl(Dtor, Dtor_Deleting);
592 cling::utils::Analyze::maybeMangleDeclName(GD, mangled_name);
596 const char *TClingMethodInfo::GetPrototype()
601 TTHREAD_TLS_DECL( std::string, buf );
603 buf += Type()->Name();
605 if (
const clang::TypeDecl *td = llvm::dyn_cast<clang::TypeDecl>(GetMethodDecl()->getDeclContext())) {
607 clang::QualType qualType(td->getTypeForDecl(),0);
608 ROOT::TMetaUtils::GetFullyQualifiedTypeName(name,qualType,*fInterp);
611 }
else if (
const clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(GetMethodDecl()->getDeclContext())) {
613 clang::PrintingPolicy policy(GetMethodDecl()->getASTContext().getPrintingPolicy());
614 llvm::raw_string_ostream stream(name);
615 nd->getNameForDiagnostic(stream, policy,
true);
623 CreateSignature(signature);
626 if (
const clang::CXXMethodDecl *md =
627 llvm::dyn_cast<clang::CXXMethodDecl>( GetMethodDecl())) {
628 if (md->getTypeQualifiers() & clang::Qualifiers::Const) {
635 const char *TClingMethodInfo::Name()
640 if (!fNameCache.empty())
641 return fNameCache.c_str();
643 ((TCling*)gCling)->GetFunctionName(GetMethodDecl(), fNameCache);
644 return fNameCache.c_str();
647 const char *TClingMethodInfo::TypeName()
const
653 return Type()->Name();
656 const char *TClingMethodInfo::Title()
670 const FunctionDecl *FD = GetMethodDecl();
672 R__LOCKGUARD(gInterpreterMutex);
675 cling::Interpreter::PushTransactionRAII RAII(fInterp);
676 if (
const FunctionDecl *AnnotFD
677 = ROOT::TMetaUtils::GetAnnotatedRedeclarable(FD)) {
678 if (AnnotateAttr *A = AnnotFD->getAttr<AnnotateAttr>()) {
679 fTitle = A->getAnnotation().str();
680 return fTitle.c_str();
683 if (!FD->isFromASTFile()) {
687 fTitle = ROOT::TMetaUtils::GetComment(*FD).str();
690 return fTitle.c_str();