Logo ROOT   master
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 "TClingUtils.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  : TClingDeclInfo(nullptr), 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  property = TClingDeclInfo::Property(property, QT);
129  const clang::TagType *tagQT = llvm::dyn_cast<clang::TagType>(QT.getTypePtr());
130  if (tagQT) {
131  // Note: Now we have class, enum, struct, union only.
132  const clang::TagDecl *TD = llvm::dyn_cast<clang::TagDecl>(tagQT->getDecl());
133  if (TD->isEnum()) {
134  property |= kIsEnum;
135  } else {
136  // Note: Now we have class, struct, union only.
137  const clang::CXXRecordDecl *CRD =
138  llvm::dyn_cast<clang::CXXRecordDecl>(TD);
139  if (CRD->isClass()) {
140  property |= kIsClass;
141  }
142  else if (CRD->isStruct()) {
143  property |= kIsStruct;
144  }
145  else if (CRD->isUnion()) {
146  property |= kIsUnion;
147  }
148  // isAbstract can trigger deserialization
149  cling::Interpreter::PushTransactionRAII RAII(fInterp);
150  if (CRD->isThisDeclarationADefinition() && CRD->isAbstract()) {
151  property |= kIsAbstract;
152  }
153  }
154  }
155  return property;
156 }
157 
158 ////////////////////////////////////////////////////////////////////////////////
159 
161 {
162  if (!IsValid()) {
163  return 0;
164  }
165  int cnt = 0;
166  bool is_ref = false;
167  clang::QualType QT = fQualType.getCanonicalType();
168  while (1) {
169  if (QT->isArrayType()) {
170  QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
171  continue;
172  }
173  else if (QT->isReferenceType()) {
174  is_ref = true;
175  QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
176  continue;
177  }
178  else if (QT->isPointerType()) {
179  ++cnt;
180  QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
181  continue;
182  }
183  else if (QT->isMemberPointerType()) {
184  QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
185  continue;
186  }
187  break;
188  }
189  int val = 0;
190  if (cnt > 1) {
191  val = cnt;
192  }
193  if (is_ref) {
194  if (cnt < 2) {
195  val = kParaReference;
196  }
197  else {
198  val |= kParaRef;
199  }
200  }
201  return val;
202 }
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 
207 {
208  if (!IsValid()) {
209  return 1;
210  }
211  if (fQualType->isDependentType()) {
212  // Dependent on a template parameter, we do not know what it is yet.
213  return 0;
214  }
215  if (const clang::RecordType *RT = fQualType->getAs<clang::RecordType>()) {
216  if (!RT->getDecl()->getDefinition()) {
217  // This is a forward-declared class.
218  return 0;
219  }
220  }
221  clang::ASTContext &Context = fInterp->getCI()->getASTContext();
222  // Note: This is an int64_t.
223  clang::CharUnits::QuantityType Quantity =
224  Context.getTypeSizeInChars(fQualType).getQuantity();
225  return static_cast<int>(Quantity);
226 }
227 
228 ////////////////////////////////////////////////////////////////////////////////
229 /// Return the normalized name of the type (i.e. fully qualified and without
230 /// the non-opaque typedefs.
231 
233 {
234  if (!IsValid()) {
235  return 0;
236  }
237  // Note: This *must* be static because we are returning a pointer inside it.
238  TTHREAD_TLS_DECL( std::string, buf);
239  buf.clear();
240 
242 
243  return buf.c_str();
244 }
245 
246 ////////////////////////////////////////////////////////////////////////////////
247 /// Return the normalized name of the type (i.e. fully qualified and without
248 /// the non-opaque typedefs.
249 
251 {
252  if (!IsValid()) {
253  return "";
254  }
255  std::string buf;
257 
258  // in C++11 this will be efficient thanks to the move constructor.
259  return buf;
260 }
261 
const char * TrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
Return the normalized name of the type (i.e.
void Init(const char *name)
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:41
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)
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:117
bool IsValid() const override
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.
std::string NormalizedName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
Return the normalized name of the type (i.e.
const char * Name() const override
static constexpr double L
long Property() const
clang::QualType fQualType
#define R__LOCKGUARD(mutex)
int Size() const
int RefType() const
long Property(long property, clang::QualType &qt) const
char name[80]
Definition: TGX11.cxx:109
const char * cnt
Definition: TXMLSetup.cxx:75