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 if (TD->isEnum()) {
138 property |= kIsEnum;
139 } else {
140 // Note: Now we have class, struct, union only.
141 const clang::CXXRecordDecl *CRD =
142 llvm::dyn_cast<clang::CXXRecordDecl>(TD);
143 if (!CRD)
144 return property;
145 if (CRD->isClass()) {
146 property |= kIsClass;
147 }
148 else if (CRD->isStruct()) {
149 property |= kIsStruct;
150 }
151 else if (CRD->isUnion()) {
152 property |= kIsUnion;
153 }
154 // isAbstract can trigger deserialization
155 cling::Interpreter::PushTransactionRAII RAII(fInterp);
156 if (CRD->isThisDeclarationADefinition() && CRD->isAbstract()) {
157 property |= kIsAbstract;
158 }
159 }
160 }
161 return property;
162}
163
164////////////////////////////////////////////////////////////////////////////////
165
167{
168 if (!IsValid()) {
169 return 0;
170 }
171 int cnt = 0;
172 bool is_ref = false;
173 clang::QualType QT = fQualType.getCanonicalType();
174 while (1) {
175 if (QT->isArrayType()) {
176 QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
177 continue;
178 }
179 else if (QT->isReferenceType()) {
180 is_ref = true;
181 QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
182 continue;
183 }
184 else if (QT->isPointerType()) {
185 ++cnt;
186 QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
187 continue;
188 }
189 else if (QT->isMemberPointerType()) {
190 QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
191 continue;
192 }
193 break;
194 }
195 int val = 0;
196 if (cnt > 1) {
197 val = cnt;
198 }
199 if (is_ref) {
200 if (cnt < 2) {
201 val = kParaReference;
202 }
203 else {
204 val |= kParaRef;
205 }
206 }
207 return val;
208}
209
210////////////////////////////////////////////////////////////////////////////////
211
213{
214 if (!IsValid()) {
215 return 1;
216 }
217 if (fQualType->isDependentType()) {
218 // Dependent on a template parameter, we do not know what it is yet.
219 return 0;
220 }
221 if (const clang::RecordType *RT = fQualType->getAs<clang::RecordType>()) {
222 if (!RT->getDecl()->getDefinition()) {
223 // This is a forward-declared class.
224 return 0;
225 }
226 }
227 clang::ASTContext &Context = fInterp->getCI()->getASTContext();
228 // Note: This is an int64_t.
229 clang::CharUnits::QuantityType Quantity =
230 Context.getTypeSizeInChars(fQualType).getQuantity();
231 return static_cast<int>(Quantity);
232}
233
234////////////////////////////////////////////////////////////////////////////////
235/// Return the normalized name of the type (i.e. fully qualified and without
236/// the non-opaque typedefs.
237
239{
240 if (!IsValid()) {
241 return nullptr;
242 }
243 // Note: This *must* be static because we are returning a pointer inside it.
244 TTHREAD_TLS_DECL( std::string, buf);
245 buf.clear();
246
247 // TODO: This needs to be locked, but the lock cannot be placed in TClingUtils.cxx as it cannot depend from
248 // TInterpreter.h for the declaration of gInterpreterMutex. Or can it?
251
252 return buf.c_str(); // NOLINT
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 "";
263 }
264 std::string buf;
265
266 // TODO: This needs to be locked, but the lock cannot be placed in TClingUtils.cxx as it cannot depend from
267 // TInterpreter.h for the declaration of gInterpreterMutex. Or can it?
270
271 // in C++11 this will be efficient thanks to the move constructor.
272 return buf;
273}
274
275////////////////////////////////////////////////////////////////////////////////
276/// Return the QualType as a void pointer
277
279{
280 return fQualType.getAsOpaquePtr();
281}
282
283
@ 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
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:595
#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.
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)