Logo ROOT   6.08/07
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
13 Emulation of the CINT MethodInfo class.
14 
15 The CINT C++ interpreter provides an interface to metadata about
16 the arguments to a function through the MethodArgInfo class. This
17 class provides the same functionality, using an interface as close
18 as possible to MethodArgInfo but the typedef metadata comes from
19 the 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 
44 {
45  if (!fMethodInfo || !fMethodInfo->IsValid()) {
46  return false;
47  }
48  int numParams = static_cast<int>(fMethodInfo->GetMethodDecl()->getNumParams());
49  return (fIdx > -1) && (fIdx < numParams);
50 }
51 
53 {
54  ++fIdx;
55  return IsValid();
56 }
57 
59 {
60  if (!IsValid()) {
61  return 0L;
62  }
63  long property = 0L;
64  const clang::FunctionDecl *fd = fMethodInfo->GetMethodDecl();
65  const clang::ParmVarDecl *pvd = fd->getParamDecl(fIdx);
66  if (pvd->hasDefaultArg() || pvd->hasInheritedDefaultArg()) {
67  property |= kIsDefault;
68  }
69  clang::QualType qt = pvd->getOriginalType().getCanonicalType();
70  if (qt.isConstQualified()) {
71  property |= kIsConstant;
72  }
73  while (1) {
74  if (qt->isArrayType()) {
75  qt = llvm::cast<clang::ArrayType>(qt)->getElementType();
76  continue;
77  }
78  else if (qt->isReferenceType()) {
79  property |= kIsReference;
80  qt = llvm::cast<clang::ReferenceType>(qt)->getPointeeType();
81  continue;
82  }
83  else if (qt->isPointerType()) {
84  property |= kIsPointer;
85  if (qt.isConstQualified()) {
86  property |= kIsConstPointer;
87  }
88  qt = llvm::cast<clang::PointerType>(qt)->getPointeeType();
89  continue;
90  }
91  else if (qt->isMemberPointerType()) {
92  qt = llvm::cast<clang::MemberPointerType>(qt)->getPointeeType();
93  continue;
94  }
95  break;
96  }
97  if (qt.isConstQualified()) {
98  property |= kIsConstant;
99  }
100  return property;
101 }
102 
104 {
105  if (!IsValid()) {
106  return 0;
107  }
108  const clang::FunctionDecl *fd = fMethodInfo->GetMethodDecl();
109  const clang::ParmVarDecl *pvd = fd->getParamDecl(fIdx);
110  // Instantiate default arg if needed
111  if (pvd->hasUninstantiatedDefaultArg()) {
112  // Could deserialize / create instantiated decls.
113  cling::Interpreter::PushTransactionRAII RAII(fInterp);
114 
115  fInterp->getSema().BuildCXXDefaultArgExpr(clang::SourceLocation(),
116  const_cast<clang::FunctionDecl*>(fd),
117  const_cast<clang::ParmVarDecl*>(pvd));
118  }
119  const clang::Expr *expr = 0;
120  if (pvd->hasUninstantiatedDefaultArg()) {
121  // We tried to instantiate it above; if we fail, use the uninstantiated one.
122  expr = pvd->getUninstantiatedDefaultArg();
123  } else {
124  expr = pvd->getDefaultArg();
125  }
126  clang::ASTContext &context = pvd->getASTContext();
127  clang::PrintingPolicy policy(context.getPrintingPolicy());
128  TTHREAD_TLS_DECL( std::string, buf );
129  buf.clear();
130  llvm::raw_string_ostream out(buf);
131  if (!expr) {
132  // CINT returned NULL for non-defaulted args.
133  return 0;
134  }
135  bool implicitInit = false;
136  if (const clang::CXXConstructExpr *construct =
137  llvm::dyn_cast<clang::CXXConstructExpr>(expr)) {
138  implicitInit = (pvd->getInitStyle() == clang::VarDecl::CallInit) &&
139  (construct->getNumArgs() == 0) &&
140  !construct->isListInitialization();
141  }
142  if (!implicitInit) {
143  if (pvd->getInitStyle() == clang::VarDecl::CallInit) {
144  //out << "(";
145  }
146  else if (pvd->getInitStyle() == clang::VarDecl::CInit) {
147  //out << " = ";
148  }
149  expr->printPretty(out, 0, policy, /*Indentation=*/0);
150  if (pvd->getInitStyle() == clang::VarDecl::CallInit) {
151  //out << ")";
152  }
153  out.flush();
154  }
155  return buf.c_str();
156 }
157 
158 const char *TClingMethodArgInfo::Name() const
159 {
160  if (!IsValid()) {
161  return 0;
162  }
163  const clang::FunctionDecl *fd = fMethodInfo->GetMethodDecl();
164  const clang::ParmVarDecl *pvd = fd->getParamDecl(fIdx);
165  TTHREAD_TLS_DECL( std::string, buf);
166  buf.clear();
167  clang::PrintingPolicy policy(pvd->getASTContext().getPrintingPolicy());
168  llvm::raw_string_ostream stream(buf);
169  pvd->getNameForDiagnostic(stream, policy, /*Qualified=*/true);
170  stream.flush();
171  return buf.c_str();
172 }
173 
175 {
176  TTHREAD_TLS_DECL_ARG( TClingTypeInfo, ti, fInterp);
177  if (!IsValid()) {
178  return &ti;
179  }
180  const clang::FunctionDecl *fd = fMethodInfo->GetMethodDecl();
181  const clang::ParmVarDecl *pvd = fd->getParamDecl(fIdx);
182  clang::QualType qt = pvd->getOriginalType();
183  ti.Init(qt);
184  return &ti;
185 }
186 
187 const char *TClingMethodArgInfo::TypeName() const
188 {
189  if (!IsValid()) {
190  return 0;
191  }
192  return Type()->Name();
193 }
194 
const TClingTypeInfo * Type() const
RooArgList L(const RooAbsArg &v1)
const char * Name() const
const char * DefaultValue() const
const TClingMethodInfo * fMethodInfo
Emulation of the CINT TypeInfo class.
const clang::FunctionDecl * GetMethodDecl() const
const char * TypeName() const
cling::Interpreter * fInterp
const char * Name() const