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
111 // TODO: This needs to be locked, but the lock cannot be placed in TClingUtils.cxx as it cannot depend from
112 // TInterpreter.h for the declaration of gInterpreterMutex. Or can it?
115 return buf.c_str(); // NOLINT
116}
117
118////////////////////////////////////////////////////////////////////////////////
119
121{
122 if (!IsValid()) {
123 return 0L;
124 }
125 long property = 0L;
126 if (llvm::isa<clang::TypedefType>(*fQualType)) {
127 property |= kIsTypedef;
128 }
129 clang::QualType QT = fQualType.getCanonicalType();
130 property = TClingDeclInfo::Property(property, QT);
131 const clang::TagType *tagQT = llvm::dyn_cast<clang::TagType>(QT.getTypePtr());
132 if (tagQT) {
133 // Note: Now we have class, enum, struct, union only.
134 const clang::TagDecl *TD = llvm::dyn_cast<clang::TagDecl>(tagQT->getDecl());
135 if (!TD)
136 return property;
137 switch (TD->getAccess()) {
138 case clang::AS_public:
139 property |= kIsPublic;
140 break;
141 case clang::AS_protected:
142 property |= kIsProtected | kIsNotReacheable;
143 break;
144 case clang::AS_private:
145 property |= kIsPrivate | kIsNotReacheable;
146 break;
147 case clang::AS_none:
148 if (TD->getDeclContext()->isNamespace())
149 property |= kIsPublic;
150 break;
151 default:
152 // IMPOSSIBLE
153 assert(false && "Unexpected value for the access property value in Clang");
154 break;
155 }
156 if (!(property & kIsNotReacheable)) {
158 property |= kIsNotReacheable;
159 }
160 if (TD->isEnum()) {
161 property |= kIsEnum;
162 } else {
163 // Note: Now we have class, struct, union only.
164 const clang::CXXRecordDecl *CRD =
165 llvm::dyn_cast<clang::CXXRecordDecl>(TD);
166 if (!CRD)
167 return property;
168 if (CRD->isClass()) {
169 property |= kIsClass;
170 }
171 else if (CRD->isStruct()) {
172 property |= kIsStruct;
173 }
174 else if (CRD->isUnion()) {
175 property |= kIsUnion;
176 }
177 // isAbstract can trigger deserialization
178 cling::Interpreter::PushTransactionRAII RAII(fInterp);
179 if (CRD->isThisDeclarationADefinition() && CRD->isAbstract()) {
180 property |= kIsAbstract;
181 }
182 }
183 }
184 return property;
185}
186
187////////////////////////////////////////////////////////////////////////////////
188
190{
191 if (!IsValid()) {
192 return 0;
193 }
194 int cnt = 0;
195 bool is_ref = false;
196 clang::QualType QT = fQualType.getCanonicalType();
197 while (1) {
198 if (QT->isArrayType()) {
199 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
200 continue;
201 }
202 else if (QT->isReferenceType()) {
203 is_ref = true;
204 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
205 continue;
206 }
207 else if (QT->isPointerType()) {
208 ++cnt;
209 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
210 continue;
211 }
212 else if (QT->isMemberPointerType()) {
213 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
214 continue;
215 }
216 break;
217 }
218 int val = 0;
219 if (cnt > 1) {
220 val = cnt;
221 }
222 if (is_ref) {
223 if (cnt < 2) {
224 val = kParaReference;
225 }
226 else {
227 val |= kParaRef;
228 }
229 }
230 return val;
231}
232
233////////////////////////////////////////////////////////////////////////////////
234
236{
237 if (!IsValid()) {
238 return 1;
239 }
240 if (fQualType->isDependentType()) {
241 // Dependent on a template parameter, we do not know what it is yet.
242 return 0;
243 }
244 if (const clang::RecordType *RT = fQualType->getAs<clang::RecordType>()) {
245 if (!RT->getDecl()->getDefinition()) {
246 // This is a forward-declared class.
247 return 0;
248 }
249 }
250 clang::ASTContext &Context = fInterp->getCI()->getASTContext();
251 // Note: This is an int64_t.
252 clang::CharUnits::QuantityType Quantity =
253 Context.getTypeSizeInChars(fQualType).getQuantity();
254 return static_cast<int>(Quantity);
255}
256
257////////////////////////////////////////////////////////////////////////////////
258/// Return the normalized name of the type (i.e. fully qualified and without
259/// the non-opaque typedefs.
260
262{
263 if (!IsValid()) {
264 return nullptr;
265 }
266 // Note: This *must* be static because we are returning a pointer inside it.
267 TTHREAD_TLS_DECL( std::string, buf);
268 buf.clear();
269
270 // TODO: This needs to be locked, but the lock cannot be placed in TClingUtils.cxx as it cannot depend from
271 // TInterpreter.h for the declaration of gInterpreterMutex. Or can it?
274
275 return buf.c_str(); // NOLINT
276}
277
278////////////////////////////////////////////////////////////////////////////////
279/// Return the normalized name of the type (i.e. fully qualified and without
280/// the non-opaque typedefs.
281
283{
284 if (!IsValid()) {
285 return "";
286 }
287 std::string buf;
288
289 // TODO: This needs to be locked, but the lock cannot be placed in TClingUtils.cxx as it cannot depend from
290 // TInterpreter.h for the declaration of gInterpreterMutex. Or can it?
293
294 // in C++11 this will be efficient thanks to the move constructor.
295 return buf;
296}
297
298////////////////////////////////////////////////////////////////////////////////
299/// Return the QualType as a void pointer
300
302{
303 return fQualType.getAsOpaquePtr();
304}
305
306
@ kIsPublic
Definition TDictionary.h:75
@ kIsClass
Definition TDictionary.h:65
@ kIsEnum
Definition TDictionary.h:68
@ kIsPrivate
Definition TDictionary.h:77
@ kIsAbstract
Definition TDictionary.h:71
@ kIsStruct
Definition TDictionary.h:66
@ kIsProtected
Definition TDictionary.h:76
@ kIsUnion
Definition TDictionary.h:67
@ kIsNotReacheable
Definition TDictionary.h:87
@ kIsTypedef
Definition TDictionary.h:69
@ kParaRef
@ kParaReference
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t property
char name[80]
Definition TGX11.cxx:110
R__EXTERN TVirtualMutex * gInterpreterMutex
Int_t gDebug
Definition TROOT.cxx:597
#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
void * QualTypePtr() const
Return the QualType as a void pointer.
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.
bool IsDeclReacheable(const clang::Decl &decl)
Return true if the decl is representing an entity reacheable from the global namespace.
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)