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->GetMethodDecl()), 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 if (qt.isConstQualified()) {
77 property |= kIsConstant;
78 }
79 while (1) {
80 if (qt->isArrayType()) {
81 qt = llvm::cast<clang::ArrayType>(qt)->getElementType();
82 continue;
83 }
84 else if (qt->isReferenceType()) {
85 property |= kIsReference;
86 qt = llvm::cast<clang::ReferenceType>(qt)->getPointeeType();
87 continue;
88 }
89 else if (qt->isPointerType()) {
90 property |= kIsPointer;
91 if (qt.isConstQualified()) {
92 property |= kIsConstPointer;
93 }
94 qt = llvm::cast<clang::PointerType>(qt)->getPointeeType();
95 continue;
96 }
97 else if (qt->isMemberPointerType()) {
98 qt = llvm::cast<clang::MemberPointerType>(qt)->getPointeeType();
99 continue;
100 }
101 break;
102 }
103 if (qt.isConstQualified()) {
104 property |= kIsConstant;
105 }
106 return property;
107}
108
110{
111 if (!IsValid()) {
112 return 0;
113 }
114 const clang::ParmVarDecl *pvd = GetDecl();
115 // Instantiate default arg if needed
116 if (pvd->hasUninstantiatedDefaultArg()) {
117 // Could deserialize / create instantiated decls.
118 cling::Interpreter::PushTransactionRAII RAII(fInterp);
119 auto fd = llvm::cast_or_null<clang::FunctionDecl>(TClingDeclInfo::GetDecl());
120 fInterp->getSema().BuildCXXDefaultArgExpr(clang::SourceLocation(),
121 const_cast<clang::FunctionDecl*>(fd),
122 const_cast<clang::ParmVarDecl*>(pvd));
123 }
124 const clang::Expr *expr = 0;
125 if (pvd->hasUninstantiatedDefaultArg()) {
126 // We tried to instantiate it above; if we fail, use the uninstantiated one.
127 expr = pvd->getUninstantiatedDefaultArg();
128 } else {
129 expr = pvd->getDefaultArg();
130 }
131 clang::ASTContext &context = pvd->getASTContext();
132 clang::PrintingPolicy policy(context.getPrintingPolicy());
133 TTHREAD_TLS_DECL( std::string, buf );
134 buf.clear();
135 llvm::raw_string_ostream out(buf);
136 if (!expr) {
137 // CINT returned NULL for non-defaulted args.
138 return 0;
139 }
140 bool implicitInit = false;
141 if (const clang::CXXConstructExpr *construct =
142 llvm::dyn_cast<clang::CXXConstructExpr>(expr)) {
143 implicitInit = (pvd->getInitStyle() == clang::VarDecl::CallInit) &&
144 (construct->getNumArgs() == 0) &&
145 !construct->isListInitialization();
146 }
147 if (!implicitInit) {
148 if (pvd->getInitStyle() == clang::VarDecl::CallInit) {
149 //out << "(";
150 }
151 else if (pvd->getInitStyle() == clang::VarDecl::CInit) {
152 //out << " = ";
153 }
154 expr->printPretty(out, 0, policy, /*Indentation=*/0);
155 if (pvd->getInitStyle() == clang::VarDecl::CallInit) {
156 //out << ")";
157 }
158 out.flush();
159 }
160 return buf.c_str();
161}
162
164{
165 TTHREAD_TLS_DECL_ARG( TClingTypeInfo, ti, fInterp);
166 if (!IsValid()) {
167 return &ti;
168 }
169 const clang::ParmVarDecl *pvd = GetDecl();
170 clang::QualType qt = pvd->getOriginalType();
171 ti.Init(qt);
172 return &ti;
173}
174
176{
177 if (!IsValid()) {
178 return 0;
179 }
180 return Type()->Name();
181}
182
@ kIsDefault
Definition: TDictionary.h:80
@ kIsPointer
Definition: TDictionary.h:77
@ kIsConstant
Definition: TDictionary.h:86
@ kIsReference
Definition: TDictionary.h:81
@ kIsConstPointer
Definition: TDictionary.h:88
const clang::Decl * fDecl
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
static constexpr double L