Logo ROOT  
Reference Guide
TClingMethodArgInfo.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 TClingMethodArgInfo
13Emulation of the CINT MethodInfo class.
14
15The CINT C++ interpreter provides an interface to metadata about
16the arguments to a function through the MethodArgInfo class. This
17class provides the same functionality, using an interface as close
18as possible to MethodArgInfo but the typedef metadata comes from
19the Clang C++ compiler, not CINT.
20*/
21
22#include "TClingMethodArgInfo.h"
23
24#include "TDictionary.h"
25#include "TClingMethodInfo.h"
26#include "TClingTypeInfo.h"
27#include "ThreadLocalStorage.h"
28
29#include "cling/Interpreter/Interpreter.h"
30#include "clang/AST/ASTContext.h"
31#include "clang/AST/Decl.h"
32#include "clang/AST/Expr.h"
33#include "clang/AST/ExprCXX.h"
34#include "clang/AST/PrettyPrinter.h"
35#include "clang/AST/Type.h"
36#include "clang/Sema/Sema.h"
37
38#include "llvm/Support/Casting.h"
39#include "llvm/Support/raw_ostream.h"
40
41#include <string>
42
43TClingMethodArgInfo::TClingMethodArgInfo(cling::Interpreter *interp, const TClingMethodInfo* mi) : TClingDeclInfo(mi->GetTargetFunctionDecl()), fInterp(interp), fIdx(-1) {}
44
46{
47 // Calling the base class implementation is unsafe because we override the
48 // GetDecl which it forwads to. That implementation depends on fIdx which is
49 // used to determine validity.
50 if (!fDecl)
51 return false;
52
53 auto FD = llvm::cast_or_null<clang::FunctionDecl>(TClingDeclInfo::GetDecl());
54 int numParams = static_cast<int>(FD->getNumParams());
55 return (fIdx > -1) && (fIdx < numParams);
56}
57
59{
60 ++fIdx;
61 fNameCache.clear(); // invalidate the cache.
62 return IsValid();
63}
64
66{
67 if (!IsValid()) {
68 return 0L;
69 }
70 long property = 0L;
71 const clang::ParmVarDecl *pvd = GetDecl();
72 if (pvd->hasDefaultArg() || pvd->hasInheritedDefaultArg()) {
73 property |= kIsDefault;
74 }
75 clang::QualType qt = pvd->getOriginalType().getCanonicalType();
76
77 return TClingDeclInfo::Property(property, qt);
78}
79
81{
82 if (!IsValid()) {
83 return 0;
84 }
85 const clang::ParmVarDecl *pvd = GetDecl();
86 // Instantiate default arg if needed
87 if (pvd->hasUninstantiatedDefaultArg()) {
88 // Could deserialize / create instantiated decls.
89 cling::Interpreter::PushTransactionRAII RAII(fInterp);
90 auto fd = llvm::cast_or_null<clang::FunctionDecl>(TClingDeclInfo::GetDecl());
91 fInterp->getSema().BuildCXXDefaultArgExpr(clang::SourceLocation(),
92 const_cast<clang::FunctionDecl*>(fd),
93 const_cast<clang::ParmVarDecl*>(pvd));
94 }
95 const clang::Expr *expr = 0;
96 if (pvd->hasUninstantiatedDefaultArg()) {
97 // We tried to instantiate it above; if we fail, use the uninstantiated one.
98 expr = pvd->getUninstantiatedDefaultArg();
99 } else {
100 expr = pvd->getDefaultArg();
101 }
102 clang::ASTContext &context = pvd->getASTContext();
103 clang::PrintingPolicy policy(context.getPrintingPolicy());
104 TTHREAD_TLS_DECL( std::string, buf );
105 buf.clear();
106 llvm::raw_string_ostream out(buf);
107 if (!expr) {
108 // CINT returned NULL for non-defaulted args.
109 return 0;
110 }
111 bool implicitInit = false;
112 if (const clang::CXXConstructExpr *construct =
113 llvm::dyn_cast<clang::CXXConstructExpr>(expr)) {
114 implicitInit = (pvd->getInitStyle() == clang::VarDecl::CallInit) &&
115 (construct->getNumArgs() == 0) &&
116 !construct->isListInitialization();
117 }
118 if (!implicitInit) {
119 if (pvd->getInitStyle() == clang::VarDecl::CallInit) {
120 //out << "(";
121 }
122 else if (pvd->getInitStyle() == clang::VarDecl::CInit) {
123 //out << " = ";
124 }
125 expr->printPretty(out, 0, policy, /*Indentation=*/0);
126 if (pvd->getInitStyle() == clang::VarDecl::CallInit) {
127 //out << ")";
128 }
129 out.flush();
130 }
131 return buf.c_str();
132}
133
135{
136 TTHREAD_TLS_DECL_ARG( TClingTypeInfo, ti, fInterp);
137 if (!IsValid()) {
138 return &ti;
139 }
140 const clang::ParmVarDecl *pvd = GetDecl();
141 clang::QualType qt = pvd->getOriginalType();
142 ti.Init(qt);
143 return &ti;
144}
145
147{
148 if (!IsValid()) {
149 return 0;
150 }
151 return Type()->Name();
152}
153
@ kIsDefault
Definition: TDictionary.h:81
const clang::Decl * fDecl
long Property(long property, clang::QualType &qt) const
std::string fNameCache
virtual const clang::Decl * GetDecl() const
bool IsValid() const override
TClingMethodArgInfo(cling::Interpreter *interp)
cling::Interpreter * fInterp
const clang::ParmVarDecl * GetDecl() const override
const char * DefaultValue() const
const TClingTypeInfo * Type() const
const char * TypeName() const
Emulation of the CINT MethodInfo class.
Emulation of the CINT TypeInfo class.
const char * Name() const override
static constexpr double L