Logo ROOT   6.08/07
Reference Guide
TClingTypeInfo.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 TClingTypeInfo
13 Emulation of the CINT TypeInfo class.
14 
15 The CINT C++ interpreter provides an interface to metadata about
16 a type through the TypeInfo class. This class provides the same
17 functionality, using an interface as close as possible to TypeInfo
18 but the type metadata comes from the Clang C++ compiler, not CINT.
19 */
20 
21 #include "TClingTypeInfo.h"
22 
23 #include "TDictionary.h"
24 #include "Rtypes.h" // for gDebug
25 #include "TClassEdit.h"
26 #include "TMetaUtils.h"
27 #include "TInterpreter.h"
28 #include "ThreadLocalStorage.h"
29 
30 #include "cling/Interpreter/Interpreter.h"
31 #include "cling/Interpreter/LookupHelper.h"
32 #include "cling/Utils/AST.h"
33 
34 #include "clang/AST/ASTContext.h"
35 #include "clang/AST/DeclCXX.h"
36 #include "clang/AST/Type.h"
37 #include "clang/AST/PrettyPrinter.h"
38 #include "clang/Frontend/CompilerInstance.h"
39 
40 #include <cstdio>
41 #include <string>
42 
43 using namespace std;
44 
45 ////////////////////////////////////////////////////////////////////////////////
46 
47 TClingTypeInfo::TClingTypeInfo(cling::Interpreter *interp, const char *name)
48  : fInterp(interp)
49 {
50  Init(name);
51 }
52 
53 ////////////////////////////////////////////////////////////////////////////////
54 
55 void TClingTypeInfo::Init(const char *name)
56 {
57  fQualType = clang::QualType();
58  if (gDebug > 0) {
59  fprintf(stderr,
60  "TClingTypeInfo::Init(name): looking up clang type: %s", name);
61  }
62  const cling::LookupHelper& lh = fInterp->getLookupHelper();
63  clang::QualType QT = lh.findType(name,
64  gDebug > 5 ? cling::LookupHelper::WithDiagnostics
65  : cling::LookupHelper::NoDiagnostics);
66  if (QT.isNull()) {
67  if (gDebug > 0) {
68  fprintf(stderr,
69  "TClingTypeInfo::Init(name): clang type not found: %s", name);
70  }
71  std::string buf = TClassEdit::InsertStd(name);
72  QT = lh.findType(buf,
73  gDebug > 5 ? cling::LookupHelper::WithDiagnostics
74  : cling::LookupHelper::NoDiagnostics);
75  if (QT.isNull()) {
76  if (gDebug > 0) {
77  fprintf(stderr,
78  "TClingTypeInfo::Init(name): "
79  "clang type not found name: %s\n", buf.c_str());
80  }
81  }
82  else {
83  fQualType = QT;
84  if (gDebug > 0) {
85  fprintf(stderr,
86  "TClingTypeInfo::Init(name): found clang type name: %s\n",
87  buf.c_str());
88  }
89  }
90  }
91  else {
92  fQualType = QT;
93  if (gDebug > 0) {
94  fprintf(stderr,
95  "TClingTypeInfo::Init(name): clang type found: %s\n", name);
96  }
97  }
98 }
99 
100 ////////////////////////////////////////////////////////////////////////////////
101 
102 const char *TClingTypeInfo::Name() const
103 {
104  if (!IsValid()) {
105  return "";
106  }
107  // Note: This *must* be static because we are returning a pointer inside it!
108  TTHREAD_TLS_DECL( std::string, buf);
109  buf.clear();
110 
113  return buf.c_str();
114 }
115 
116 ////////////////////////////////////////////////////////////////////////////////
117 
119 {
120  if (!IsValid()) {
121  return 0L;
122  }
123  long property = 0L;
124  if (llvm::isa<clang::TypedefType>(*fQualType)) {
125  property |= kIsTypedef;
126  }
127  clang::QualType QT = fQualType.getCanonicalType();
128  if (QT.isConstQualified()) {
129  property |= kIsConstant;
130  }
131  while (1) {
132  if (QT->isArrayType()) {
133  QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
134  continue;
135  }
136  else if (QT->isReferenceType()) {
137  property |= kIsReference;
138  QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
139  continue;
140  }
141  else if (QT->isPointerType()) {
142  property |= kIsPointer;
143  if (QT.isConstQualified()) {
144  property |= kIsConstPointer;
145  }
146  QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
147  continue;
148  }
149  else if (QT->isMemberPointerType()) {
150  QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
151  continue;
152  }
153  break;
154  }
155  if (QT->isBuiltinType()) {
156  property |= kIsFundamental;
157  }
158  if (QT.isConstQualified()) {
159  property |= kIsConstant;
160  }
161  const clang::TagType *tagQT = llvm::dyn_cast<clang::TagType>(QT.getTypePtr());
162  if (tagQT) {
163  // Note: Now we have class, enum, struct, union only.
164  const clang::TagDecl *TD = llvm::dyn_cast<clang::TagDecl>(tagQT->getDecl());
165  if (TD->isEnum()) {
166  property |= kIsEnum;
167  } else {
168  // Note: Now we have class, struct, union only.
169  const clang::CXXRecordDecl *CRD =
170  llvm::dyn_cast<clang::CXXRecordDecl>(TD);
171  if (CRD->isClass()) {
172  property |= kIsClass;
173  }
174  else if (CRD->isStruct()) {
175  property |= kIsStruct;
176  }
177  else if (CRD->isUnion()) {
178  property |= kIsUnion;
179  }
180  if (CRD->isThisDeclarationADefinition() && CRD->isAbstract()) {
181  property |= kIsAbstract;
182  }
183  }
184  }
185  return property;
186 }
187 
188 ////////////////////////////////////////////////////////////////////////////////
189 
191 {
192  if (!IsValid()) {
193  return 0;
194  }
195  int cnt = 0;
196  bool is_ref = false;
197  clang::QualType QT = fQualType.getCanonicalType();
198  while (1) {
199  if (QT->isArrayType()) {
200  QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
201  continue;
202  }
203  else if (QT->isReferenceType()) {
204  is_ref = true;
205  QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
206  continue;
207  }
208  else if (QT->isPointerType()) {
209  ++cnt;
210  QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
211  continue;
212  }
213  else if (QT->isMemberPointerType()) {
214  QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
215  continue;
216  }
217  break;
218  }
219  int val = 0;
220  if (cnt > 1) {
221  val = cnt;
222  }
223  if (is_ref) {
224  if (cnt < 2) {
225  val = kParaReference;
226  }
227  else {
228  val |= kParaRef;
229  }
230  }
231  return val;
232 }
233 
234 ////////////////////////////////////////////////////////////////////////////////
235 
237 {
238  if (!IsValid()) {
239  return 1;
240  }
241  if (fQualType->isDependentType()) {
242  // Dependent on a template parameter, we do not know what it is yet.
243  return 0;
244  }
245  if (const clang::RecordType *RT = fQualType->getAs<clang::RecordType>()) {
246  if (!RT->getDecl()->getDefinition()) {
247  // This is a forward-declared class.
248  return 0;
249  }
250  }
251  clang::ASTContext &Context = fInterp->getCI()->getASTContext();
252  // Note: This is an int64_t.
253  clang::CharUnits::QuantityType Quantity =
254  Context.getTypeSizeInChars(fQualType).getQuantity();
255  return static_cast<int>(Quantity);
256 }
257 
258 ////////////////////////////////////////////////////////////////////////////////
259 
260 const char *TClingTypeInfo::StemName() const
261 {
262  if (!IsValid()) {
263  return 0;
264  }
265  clang::QualType QT = fQualType.getCanonicalType();
266  while (1) {
267  if (QT->isArrayType()) {
268  QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
269  continue;
270  }
271  else if (QT->isReferenceType()) {
272  QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
273  continue;
274  }
275  else if (QT->isPointerType()) {
276  QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
277  continue;
278  }
279  else if (QT->isMemberPointerType()) {
280  QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
281  continue;
282  }
283  break;
284  }
285  // Note: This *must* be static because we are returning a pointer inside it.
286  TTHREAD_TLS_DECL( std::string, buf);
287  buf.clear();
288  clang::PrintingPolicy Policy(fInterp->getCI()->getASTContext().
289  getPrintingPolicy());
290  QT.getAsStringInternal(buf, Policy);
291  return buf.c_str();
292 }
293 
294 ////////////////////////////////////////////////////////////////////////////////
295 /// Return the normalized name of the type (i.e. fully qualified and without
296 /// the non-opaque typedefs.
297 
299 {
300  if (!IsValid()) {
301  return 0;
302  }
303  // Note: This *must* be static because we are returning a pointer inside it.
304  TTHREAD_TLS_DECL( std::string, buf);
305  buf.clear();
306 
308 
309  return buf.c_str();
310 }
311 
312 ////////////////////////////////////////////////////////////////////////////////
313 /// Return the normalized name of the type (i.e. fully qualified and without
314 /// the non-opaque typedefs.
315 
317 {
318  if (!IsValid()) {
319  return "";
320  }
321  std::string buf;
323 
324  // in C++11 this will be efficient thanks to the move constructor.
325  return buf;
326 }
327 
const char * TrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
Return the normalized name of the type (i.e.
RooArgList L(const RooAbsArg &v1)
void Init(const char *name)
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:46
const char * Name() const
Small helper to keep current directory context.
cling::Interpreter * fInterp
TClingTypeInfo(cling::Interpreter *interp)
std::string InsertStd(const char *tname)
STL namespace.
void GetFullyQualifiedTypeName(std::string &name, const clang::QualType &type, const cling::Interpreter &interpreter)
bool IsValid() const
void GetNormalizedName(std::string &norm_name, const clang::QualType &type, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt)
Return the type name normalized for ROOT, keeping only the ROOT opaque typedef (Double32_t, etc.) and adding default template argument for all types except the STL collections where we remove the default template argument if any.
const char * StemName() const
std::string NormalizedName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
Return the normalized name of the type (i.e.
long Property() const
clang::QualType fQualType
#define R__LOCKGUARD(mutex)
int Size() const
int RefType() const
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
char name[80]
Definition: TGX11.cxx:109
const char * cnt
Definition: TXMLSetup.cxx:75