Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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
13Emulation of the CINT TypeInfo class.
14
15The CINT C++ interpreter provides an interface to metadata about
16a type through the TypeInfo class. This class provides the same
17functionality, using an interface as close as possible to TypeInfo
18but 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
43using namespace std;
44
45////////////////////////////////////////////////////////////////////////////////
46
47TClingTypeInfo::TClingTypeInfo(cling::Interpreter *interp, const char *name)
48 : TClingDeclInfo(nullptr), fInterp(interp)
49{
50 Init(name);
51}
52
53////////////////////////////////////////////////////////////////////////////////
54
55void 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
102const 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(); // NOLINT
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)
134 return property;
135 if (TD->isEnum()) {
136 property |= kIsEnum;
137 } else {
138 // Note: Now we have class, struct, union only.
139 const clang::CXXRecordDecl *CRD =
140 llvm::dyn_cast<clang::CXXRecordDecl>(TD);
141 if (!CRD)
142 return property;
143 if (CRD->isClass()) {
144 property |= kIsClass;
145 }
146 else if (CRD->isStruct()) {
147 property |= kIsStruct;
148 }
149 else if (CRD->isUnion()) {
150 property |= kIsUnion;
151 }
152 // isAbstract can trigger deserialization
153 cling::Interpreter::PushTransactionRAII RAII(fInterp);
154 if (CRD->isThisDeclarationADefinition() && CRD->isAbstract()) {
155 property |= kIsAbstract;
156 }
157 }
158 }
159 return property;
160}
161
162////////////////////////////////////////////////////////////////////////////////
163
165{
166 if (!IsValid()) {
167 return 0;
168 }
169 int cnt = 0;
170 bool is_ref = false;
171 clang::QualType QT = fQualType.getCanonicalType();
172 while (1) {
173 if (QT->isArrayType()) {
174 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
175 continue;
176 }
177 else if (QT->isReferenceType()) {
178 is_ref = true;
179 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
180 continue;
181 }
182 else if (QT->isPointerType()) {
183 ++cnt;
184 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
185 continue;
186 }
187 else if (QT->isMemberPointerType()) {
188 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
189 continue;
190 }
191 break;
192 }
193 int val = 0;
194 if (cnt > 1) {
195 val = cnt;
196 }
197 if (is_ref) {
198 if (cnt < 2) {
199 val = kParaReference;
200 }
201 else {
202 val |= kParaRef;
203 }
204 }
205 return val;
206}
207
208////////////////////////////////////////////////////////////////////////////////
209
211{
212 if (!IsValid()) {
213 return 1;
214 }
215 if (fQualType->isDependentType()) {
216 // Dependent on a template parameter, we do not know what it is yet.
217 return 0;
218 }
219 if (const clang::RecordType *RT = fQualType->getAs<clang::RecordType>()) {
220 if (!RT->getDecl()->getDefinition()) {
221 // This is a forward-declared class.
222 return 0;
223 }
224 }
225 clang::ASTContext &Context = fInterp->getCI()->getASTContext();
226 // Note: This is an int64_t.
227 clang::CharUnits::QuantityType Quantity =
228 Context.getTypeSizeInChars(fQualType).getQuantity();
229 return static_cast<int>(Quantity);
230}
231
232////////////////////////////////////////////////////////////////////////////////
233/// Return the normalized name of the type (i.e. fully qualified and without
234/// the non-opaque typedefs.
235
237{
238 if (!IsValid()) {
239 return 0;
240 }
241 // Note: This *must* be static because we are returning a pointer inside it.
242 TTHREAD_TLS_DECL( std::string, buf);
243 buf.clear();
244
246
247 return buf.c_str(); // NOLINT
248}
249
250////////////////////////////////////////////////////////////////////////////////
251/// Return the normalized name of the type (i.e. fully qualified and without
252/// the non-opaque typedefs.
253
255{
256 if (!IsValid()) {
257 return "";
258 }
259 std::string buf;
261
262 // in C++11 this will be efficient thanks to the move constructor.
263 return buf;
264}
265
@ kIsClass
Definition TDictionary.h:65
@ kIsEnum
Definition TDictionary.h:68
@ kIsAbstract
Definition TDictionary.h:71
@ kIsStruct
Definition TDictionary.h:66
@ kIsUnion
Definition TDictionary.h:67
@ kIsTypedef
Definition TDictionary.h:69
@ kParaRef
@ kParaReference
char name[80]
Definition TGX11.cxx:110
R__EXTERN TVirtualMutex * gInterpreterMutex
Int_t gDebug
Definition TROOT.cxx:592
#define R__LOCKGUARD(mutex)
long Property(long property, clang::QualType &qt) const
long Property() const
clang::QualType fQualType
std::string NormalizedName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
Return the normalized name of the type (i.e.
const char * Name() const override
TClingTypeInfo(cling::Interpreter *interp)
int RefType() const
cling::Interpreter * fInterp
bool IsValid() const override
void Init(const char *name)
const char * TrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
Return the normalized name of the type (i.e.
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,...
void GetFullyQualifiedTypeName(std::string &name, const clang::QualType &type, const cling::Interpreter &interpreter)
std::string InsertStd(const char *tname)