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 : 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();
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
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:117
@ 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
Definition: TDictionary.h:153
@ kParaReference
Definition: TDictionary.h:150
char name[80]
Definition: TGX11.cxx:109
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:41
#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 Size() const
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)
static constexpr double L
const char * cnt
Definition: TXMLSetup.cxx:74