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
43////////////////////////////////////////////////////////////////////////////////
44
45TClingTypeInfo::TClingTypeInfo(cling::Interpreter *interp, const char *name)
46 : TClingDeclInfo(nullptr), fInterp(interp)
47{
48 Init(name);
49}
50
51////////////////////////////////////////////////////////////////////////////////
52
53void TClingTypeInfo::Init(const char *name)
54{
55 fQualType = clang::QualType();
56 if (gDebug > 0) {
57 fprintf(stderr,
58 "TClingTypeInfo::Init(name): looking up clang type: %s", name);
59 }
60 const cling::LookupHelper& lh = fInterp->getLookupHelper();
61 clang::QualType QT = lh.findType(name,
62 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
63 : cling::LookupHelper::NoDiagnostics);
64 if (QT.isNull()) {
65 if (gDebug > 0) {
66 fprintf(stderr,
67 "TClingTypeInfo::Init(name): clang type not found: %s", name);
68 }
69 std::string buf = TClassEdit::InsertStd(name);
70 QT = lh.findType(buf,
71 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
72 : cling::LookupHelper::NoDiagnostics);
73 if (QT.isNull()) {
74 if (gDebug > 0) {
75 fprintf(stderr,
76 "TClingTypeInfo::Init(name): "
77 "clang type not found name: %s\n", buf.c_str());
78 }
79 }
80 else {
81 fQualType = QT;
82 if (gDebug > 0) {
83 fprintf(stderr,
84 "TClingTypeInfo::Init(name): found clang type name: %s\n",
85 buf.c_str());
86 }
87 }
88 }
89 else {
90 fQualType = QT;
91 if (gDebug > 0) {
92 fprintf(stderr,
93 "TClingTypeInfo::Init(name): clang type found: %s\n", name);
94 }
95 }
96}
97
98////////////////////////////////////////////////////////////////////////////////
99
100const char *TClingTypeInfo::Name() const
101{
102 if (!IsValid()) {
103 return "";
104 }
105 // Note: This *must* be static because we are returning a pointer inside it!
106 TTHREAD_TLS_DECL( std::string, buf);
107 buf.clear();
108
109 // TODO: This needs to be locked, but the lock cannot be placed in TClingUtils.cxx as it cannot depend from
110 // TInterpreter.h for the declaration of gInterpreterMutex. Or can it?
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 switch (TD->getAccess()) {
136 case clang::AS_public:
137 property |= kIsPublic;
138 break;
139 case clang::AS_protected:
140 property |= kIsProtected | kIsNotReacheable;
141 break;
142 case clang::AS_private:
143 property |= kIsPrivate | kIsNotReacheable;
144 break;
145 case clang::AS_none:
146 if (TD->getDeclContext()->isNamespace())
147 property |= kIsPublic;
148 break;
149 default:
150 // IMPOSSIBLE
151 assert(false && "Unexpected value for the access property value in Clang");
152 break;
153 }
154 if (!(property & kIsNotReacheable)) {
156 property |= kIsNotReacheable;
157 }
158 if (TD->isEnum()) {
159 property |= kIsEnum;
160 } else {
161 // Note: Now we have class, struct, union only.
162 const clang::CXXRecordDecl *CRD =
163 llvm::dyn_cast<clang::CXXRecordDecl>(TD);
164 if (!CRD)
165 return property;
166 if (CRD->isClass()) {
167 property |= kIsClass;
168 }
169 else if (CRD->isStruct()) {
170 property |= kIsStruct;
171 }
172 else if (CRD->isUnion()) {
173 property |= kIsUnion;
174 }
175 // isAbstract can trigger deserialization
176 cling::Interpreter::PushTransactionRAII RAII(fInterp);
177 if (CRD->isThisDeclarationADefinition() && CRD->isAbstract()) {
178 property |= kIsAbstract;
179 }
180 }
181 }
182 return property;
183}
184
185////////////////////////////////////////////////////////////////////////////////
186
188{
189 if (!IsValid()) {
190 return 0;
191 }
192 int cnt = 0;
193 bool is_ref = false;
194 clang::QualType QT = fQualType.getCanonicalType();
195 while (1) {
196 if (QT->isArrayType()) {
197 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
198 continue;
199 }
200 else if (QT->isReferenceType()) {
201 is_ref = true;
202 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
203 continue;
204 }
205 else if (QT->isPointerType()) {
206 ++cnt;
207 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
208 continue;
209 }
210 else if (QT->isMemberPointerType()) {
211 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
212 continue;
213 }
214 break;
215 }
216 int val = 0;
217 if (cnt > 1) {
218 val = cnt;
219 }
220 if (is_ref) {
221 if (cnt < 2) {
222 val = kParaReference;
223 }
224 else {
225 val |= kParaRef;
226 }
227 }
228 return val;
229}
230
231////////////////////////////////////////////////////////////////////////////////
232
234{
235 if (!IsValid()) {
236 return 1;
237 }
238 if (fQualType->isDependentType()) {
239 // Dependent on a template parameter, we do not know what it is yet.
240 return 0;
241 }
242 if (const clang::RecordType *RT = fQualType->getAs<clang::RecordType>()) {
243 if (!RT->getDecl()->getDefinition()) {
244 // This is a forward-declared class.
245 return 0;
246 }
247 }
248 clang::ASTContext &Context = fInterp->getCI()->getASTContext();
249 // Note: This is an int64_t.
250 clang::CharUnits::QuantityType Quantity =
251 Context.getTypeSizeInChars(fQualType).getQuantity();
252 return static_cast<int>(Quantity);
253}
254
255////////////////////////////////////////////////////////////////////////////////
256/// Return the normalized name of the type (i.e. fully qualified and without
257/// the non-opaque typedefs.
258
260{
261 if (!IsValid()) {
262 return nullptr;
263 }
264 // Note: This *must* be static because we are returning a pointer inside it.
265 TTHREAD_TLS_DECL( std::string, buf);
266 buf.clear();
267
268 // TODO: This needs to be locked, but the lock cannot be placed in TClingUtils.cxx as it cannot depend from
269 // TInterpreter.h for the declaration of gInterpreterMutex. Or can it?
272
273 return buf.c_str(); // NOLINT
274}
275
276////////////////////////////////////////////////////////////////////////////////
277/// Return the normalized name of the type (i.e. fully qualified and without
278/// the non-opaque typedefs.
279
281{
282 if (!IsValid()) {
283 return "";
284 }
285 std::string buf;
286
287 // TODO: This needs to be locked, but the lock cannot be placed in TClingUtils.cxx as it cannot depend from
288 // TInterpreter.h for the declaration of gInterpreterMutex. Or can it?
291
292 // in C++11 this will be efficient thanks to the move constructor.
293 return buf;
294}
295
296////////////////////////////////////////////////////////////////////////////////
297/// Return the QualType as a void pointer
298
300{
301 return fQualType.getAsOpaquePtr();
302}
303
304
@ 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)