Logo ROOT  
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
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 : 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
112 ROOT::TMetaUtils::GetFullyQualifiedTypeName(buf,fQualType,*fInterp);
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
260const 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
298const char *TClingTypeInfo::TrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
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
316std::string TClingTypeInfo::NormalizedName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
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
R__EXTERN Int_t gDebug
Definition: Rtypes.h:91
@ kIsPointer
Definition: TDictionary.h:77
@ kIsConstant
Definition: TDictionary.h:86
@ kIsClass
Definition: TDictionary.h:65
@ kIsReference
Definition: TDictionary.h:81
@ kIsEnum
Definition: TDictionary.h:68
@ kIsConstPointer
Definition: TDictionary.h:88
@ kIsFundamental
Definition: TDictionary.h:70
@ kIsAbstract
Definition: TDictionary.h:71
@ kIsStruct
Definition: TDictionary.h:66
@ kIsUnion
Definition: TDictionary.h:67
@ kIsTypedef
Definition: TDictionary.h:69
@ kParaRef
Definition: TDictionary.h:149
@ kParaReference
Definition: TDictionary.h:146
char name[80]
Definition: TGX11.cxx:109
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:40
#define R__LOCKGUARD(mutex)
long Property() const
clang::QualType fQualType
bool IsValid() const
std::string NormalizedName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
Return the normalized name of the type (i.e.
TClingTypeInfo(cling::Interpreter *interp)
int Size() const
int RefType() const
const char * StemName() const
cling::Interpreter * fInterp
const char * Name() const
void Init(const char *name)
const char * TrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
Return the normalized name of the type (i.e.
std::string InsertStd(const char *tname)
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
Definition: TClassEdit.cxx:832
static constexpr double L
const char * cnt
Definition: TXMLSetup.cxx:74