Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TClingClassInfo.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 TClingClassInfo
13
14Emulation of the CINT ClassInfo class.
15
16The CINT C++ interpreter provides an interface to metadata about
17a class through the ClassInfo class. This class provides the same
18functionality, using an interface as close as possible to ClassInfo
19but the class metadata comes from the Clang C++ compiler, not CINT.
20*/
21
22#include "TClingClassInfo.h"
23
24#include "TClassEdit.h"
25#include "TClingBaseClassInfo.h"
26#include "TClingCallFunc.h"
27#include "TClingMethodInfo.h"
28#include "TDictionary.h"
29#include "TClingTypeInfo.h"
30#include "TError.h"
31#include "TClingUtils.h"
32#include "ThreadLocalStorage.h"
33
34#include "cling/Interpreter/Interpreter.h"
35#include "cling/Interpreter/LookupHelper.h"
36#include "cling/Utils/AST.h"
37
38#include "clang/AST/ASTContext.h"
39#include "clang/AST/Decl.h"
40#include "clang/AST/DeclCXX.h"
41#include "clang/AST/DeclTemplate.h"
42#include "clang/AST/GlobalDecl.h"
43#include "clang/AST/PrettyPrinter.h"
44#include "clang/AST/RecordLayout.h"
45#include "clang/AST/Type.h"
46#include "clang/Basic/Specifiers.h"
47#include "clang/Frontend/CompilerInstance.h"
48#include "clang/Sema/Sema.h"
49
50#include "llvm/ExecutionEngine/GenericValue.h"
51#include "llvm/Support/Casting.h"
52#include "llvm/Support/raw_ostream.h"
53
54#include <sstream>
55#include <string>
56
57using namespace clang;
58using namespace ROOT;
59
60static std::string FullyQualifiedName(const Decl *decl) {
61 // Return the fully qualified name without worrying about normalizing it.
62 std::string buf;
63 if (const NamedDecl* ND = llvm::dyn_cast<NamedDecl>(decl)) {
64 PrintingPolicy Policy(decl->getASTContext().getPrintingPolicy());
65 llvm::raw_string_ostream stream(buf);
66 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true);
67 }
68 return buf;
69}
70
71TClingClassInfo::TClingClassInfo(cling::Interpreter *interp, Bool_t all)
72 : TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(all),
73 fIsIter(true), fType(0), fOffsetCache(0)
74{
75 TranslationUnitDecl *TU =
76 interp->getCI()->getASTContext().getTranslationUnitDecl();
77 fFirstTime = true;
78 SetDecl(TU);
79 fType = 0;
80}
81
82TClingClassInfo::TClingClassInfo(cling::Interpreter *interp, const char *name, bool intantiateTemplate /* = true */)
83 : TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(kTRUE), fIsIter(false),
84 fType(0), fTitle(""), fOffsetCache(0)
85{
86 const cling::LookupHelper& lh = fInterp->getLookupHelper();
87 const Type *type = 0;
88 const Decl *decl = lh.findScope(name,
89 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
90 : cling::LookupHelper::NoDiagnostics,
91 &type, intantiateTemplate);
92 if (!decl) {
93 std::string buf = TClassEdit::InsertStd(name);
94 if (buf != name) {
95 decl = lh.findScope(buf,
96 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
97 : cling::LookupHelper::NoDiagnostics,
98 &type, intantiateTemplate);
99 }
100 }
101 if (!decl && type) {
102 const TagType *tagtype =type->getAs<TagType>();
103 if (tagtype) {
104 decl = tagtype->getDecl();
105 }
106 }
107 SetDecl(decl);
108 fType = type;
109 if (decl && decl->isInvalidDecl()) {
110 Error("TClingClassInfo", "Found an invalid decl for %s.",name);
111 SetDecl(nullptr);
112 fType = nullptr;
113 }
114}
115
116TClingClassInfo::TClingClassInfo(cling::Interpreter *interp,
117 const Type &tag)
118 : TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(kTRUE),
119 fIsIter(false), fType(0), fTitle(""), fOffsetCache(0)
120{
121 Init(tag);
122}
123
124TClingClassInfo::TClingClassInfo(cling::Interpreter *interp,
125 const Decl *D)
126 : TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(kTRUE),
127 fIsIter(false), fType(0), fTitle(""), fOffsetCache(0)
128{
129 Init(D);
130}
131
132void TClingClassInfo::AddBaseOffsetValue(const clang::Decl* decl, ptrdiff_t offset)
133{
134 // Add the offset value from this class to the non-virtual base class
135 // determined by the parameter decl.
136
137 OffsetPtrFunc_t executableFunc = 0;
138 std::unique_lock<std::mutex> lock(fOffsetCacheMutex);
139 fOffsetCache[decl] = std::make_pair(offset, executableFunc);
140}
141
143{
144 if (!IsValid()) {
145 return 0L;
146 }
147 long property = 0L;
148 const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(GetDecl());
149
150 // isAbstract and other calls can trigger deserialization
151 cling::Interpreter::PushTransactionRAII RAII(fInterp);
152
153 if (!RD) {
154 // We are an enum or namespace.
155 // The cint interface always returns 0L for these guys.
156 return property;
157 }
158 if (RD->isUnion()) {
159 // The cint interface always returns 0L for these guys.
160 return property;
161 }
162 // We now have a class or a struct.
163 const CXXRecordDecl *CRD =
164 llvm::dyn_cast<CXXRecordDecl>(GetDecl());
165 property |= kClassIsValid;
166 if (CRD->isAbstract()) {
167 property |= kClassIsAbstract;
168 }
169 if (CRD->hasUserDeclaredConstructor()) {
170 property |= kClassHasExplicitCtor;
171 }
172 if (
173 !CRD->hasUserDeclaredConstructor() &&
174 !CRD->hasTrivialDefaultConstructor()
175 ) {
176 property |= kClassHasImplicitCtor;
177 }
178 if (
179 CRD->hasUserProvidedDefaultConstructor() ||
180 !CRD->hasTrivialDefaultConstructor()
181 ) {
182 property |= kClassHasDefaultCtor;
183 }
184 if (CRD->hasUserDeclaredDestructor()) {
185 property |= kClassHasExplicitDtor;
186 }
187 else if (!CRD->hasTrivialDestructor()) {
188 property |= kClassHasImplicitDtor;
189 }
190 if (CRD->hasUserDeclaredCopyAssignment()) {
191 property |= kClassHasAssignOpr;
192 }
193 if (CRD->isPolymorphic()) {
194 property |= kClassHasVirtual;
195 }
196 return property;
197}
198
199void TClingClassInfo::Delete(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
200{
201 // Invoke operator delete on a pointer to an object
202 // of this class type.
203 if (!IsValid()) {
204 Error("TClingClassInfo::Delete()", "Called while invalid!");
205 return;
206 }
207 if (!IsLoaded()) {
208 Error("TClingClassInfo::Delete()", "Class is not loaded: %s",
209 FullyQualifiedName(GetDecl()).c_str());
210 return;
211 }
212 TClingCallFunc cf(fInterp,normCtxt);
213 cf.ExecDestructor(this, arena, /*nary=*/0, /*withFree=*/true);
214}
215
216void TClingClassInfo::DeleteArray(void *arena, bool dtorOnly, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
217{
218 // Invoke operator delete[] on a pointer to an array object
219 // of this class type.
220 if (!IsLoaded()) {
221 return;
222 }
223 if (dtorOnly) {
224 // There is no syntax in C++ for invoking the placement delete array
225 // operator, so we have to placement destroy each element by hand.
226 // Unfortunately we do not know how many elements to delete.
227 //TClingCallFunc cf(fInterp);
228 //cf.ExecDestructor(this, arena, nary, /*withFree=*/false);
229 Error("DeleteArray", "Placement delete of an array is unsupported!\n");
230 return;
231 }
232 TClingCallFunc cf(fInterp,normCtxt);
233 cf.ExecDestructor(this, arena, /*nary=*/1, /*withFree=*/true);
234}
235
236void TClingClassInfo::Destruct(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
237{
238 // Invoke placement operator delete on a pointer to an array object
239 // of this class type.
240 if (!IsLoaded()) {
241 return;
242 }
243 TClingCallFunc cf(fInterp,normCtxt);
244 cf.ExecDestructor(this, arena, /*nary=*/0, /*withFree=*/false);
245}
246
247const FunctionTemplateDecl *TClingClassInfo::GetFunctionTemplate(const char *fname) const
248{
249 // Return any method or function in this scope with the name 'fname'.
250
251 if (!IsLoaded()) {
252 return 0;
253 }
254
255 if (fType) {
256 const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
257 if (TT) {
258 llvm::StringRef tname(TT->getDecl()->getName());
259 if (tname.equals(fname)) {
260 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(GetDecl());
261 if (ndecl && !ndecl->getName().equals(fname)) {
262 // Constructor name matching the typedef type, use the decl name instead.
263 return GetFunctionTemplate(ndecl->getName().str().c_str());
264 }
265 }
266 }
267 }
268 const cling::LookupHelper &lh = fInterp->getLookupHelper();
269 const FunctionTemplateDecl *fd
270 = lh.findFunctionTemplate(GetDecl(), fname,
271 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
272 : cling::LookupHelper::NoDiagnostics, false);
273 if (fd) return fd->getCanonicalDecl();
274 return 0;
275}
276
277const clang::ValueDecl *TClingClassInfo::GetDataMember(const char *name) const
278{
279 // Return the value decl (if any) corresponding to a data member which
280 // the given name declared in this scope.
281
282 const cling::LookupHelper &lh = fInterp->getLookupHelper();
283 const ValueDecl *vd
284 = lh.findDataMember(GetDecl(), name,
285 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
286 : cling::LookupHelper::NoDiagnostics);
287 if (vd) return llvm::dyn_cast<ValueDecl>(vd->getCanonicalDecl());
288 else return 0;
289}
290
292{
293 // Return any method or function in this scope with the name 'fname'.
294
295 if (!IsLoaded()) {
297 return tmi;
298 }
299
301
302 if (fType) {
303 const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
304 if (TT) {
305 llvm::StringRef tname(TT->getDecl()->getName());
306 if (tname.equals(fname)) {
307 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(GetDecl());
308 if (ndecl && !ndecl->getName().equals(fname)) {
309 // Constructor name matching the typedef type, use the decl name instead.
310 return GetMethod(ndecl->getName().str().c_str());
311 }
312 }
313 }
314 }
315 const cling::LookupHelper &lh = fInterp->getLookupHelper();
316 const FunctionDecl *fd
317 = lh.findAnyFunction(GetDecl(), fname,
318 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
319 : cling::LookupHelper::NoDiagnostics,
320 false);
321 if (!fd) {
322 // Function not found.
324 return tmi;
325 }
327 tmi.Init(fd);
328 return tmi;
329}
330
332 const char *proto, long *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
333 EInheritanceMode imode /*= kWithInheritance*/) const
334{
335 return GetMethod(fname,proto,false,poffset,mode,imode);
336}
337
339 const char *proto, bool objectIsConst,
340 long *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
341 EInheritanceMode imode /*= kWithInheritance*/) const
342{
343 if (poffset) {
344 *poffset = 0L;
345 }
346 if (!IsLoaded()) {
348 return tmi;
349 }
350
352
353 if (fType) {
354 const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
355 if (TT) {
356 llvm::StringRef tname(TT->getDecl()->getName());
357 if (tname.equals(fname)) {
358 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(GetDecl());
359 if (ndecl && !ndecl->getName().equals(fname)) {
360 // Constructor name matching the typedef type, use the decl name instead.
361 return GetMethod(ndecl->getName().str().c_str(),proto,
362 objectIsConst,poffset,
363 mode,imode);
364 }
365 }
366 }
367
368 }
369 const cling::LookupHelper& lh = fInterp->getLookupHelper();
370 const FunctionDecl *fd;
371 if (mode == kConversionMatch) {
372 fd = lh.findFunctionProto(GetDecl(), fname, proto,
373 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
374 : cling::LookupHelper::NoDiagnostics,
375 objectIsConst);
376 } else if (mode == kExactMatch) {
377 fd = lh.matchFunctionProto(GetDecl(), fname, proto,
378 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
379 : cling::LookupHelper::NoDiagnostics,
380 objectIsConst);
381 } else {
382 Error("TClingClassInfo::GetMethod",
383 "The MatchMode %d is not supported.", mode);
385 return tmi;
386 }
387 if (!fd) {
388 // Function not found.
390 return tmi;
391 }
392 if (imode == TClingClassInfo::kInThisScope) {
393 // If requested, check whether fd is a member function of this class.
394 // Even though this seems to be the wrong order (we should not allow the
395 // lookup to even collect candidates from the base) it does the right
396 // thing: if any function overload exists in the derived class, all
397 // (but explicitly used) will be hidden. Thus we will only find the
398 // derived class's function overloads (or used, which is fine). Only
399 // if there is none will we find those from the base, in which case
400 // we will reject them here:
401 const clang::DeclContext* ourDC = llvm::dyn_cast<clang::DeclContext>(GetDecl());
402 if (!fd->getDeclContext()->Equals(ourDC)
403 && !(fd->getDeclContext()->isTransparentContext()
404 && fd->getDeclContext()->getParent()->Equals(ourDC)))
406
407 // The offset must be 0 - the function must be ours.
408 if (poffset) *poffset = 0;
409 } else {
410 if (poffset) {
411 // We have been asked to return a this pointer adjustment.
412 if (const CXXMethodDecl *md =
413 llvm::dyn_cast<CXXMethodDecl>(fd)) {
414 // This is a class member function.
415 *poffset = GetOffset(md);
416 }
417 }
418 }
420 tmi.Init(fd);
421 return tmi;
422}
423
425 const llvm::SmallVectorImpl<clang::QualType> &proto,
426 long *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
427 EInheritanceMode imode /*= kWithInheritance*/) const
428{
429 return GetMethod(fname,proto,false,poffset,mode,imode);
430}
431
433 const llvm::SmallVectorImpl<clang::QualType> &proto, bool objectIsConst,
434 long *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
435 EInheritanceMode imode /*= kWithInheritance*/) const
436{
437 if (poffset) {
438 *poffset = 0L;
439 }
440 if (!IsLoaded()) {
442 return tmi;
443 }
444
446
447 if (fType) {
448 const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
449 if (TT) {
450 llvm::StringRef tname(TT->getDecl()->getName());
451 if (tname.equals(fname)) {
452 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(GetDecl());
453 if (ndecl && !ndecl->getName().equals(fname)) {
454 // Constructor name matching the typedef type, use the decl name instead.
455 return GetMethod(ndecl->getName().str().c_str(),proto,objectIsConst,poffset,
456 mode,imode);
457 }
458 }
459 }
460
461 }
462 const cling::LookupHelper& lh = fInterp->getLookupHelper();
463 const FunctionDecl *fd;
464 if (mode == kConversionMatch) {
465 fd = lh.findFunctionProto(GetDecl(), fname, proto,
466 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
467 : cling::LookupHelper::NoDiagnostics,
468 objectIsConst);
469 } else if (mode == kExactMatch) {
470 fd = lh.matchFunctionProto(GetDecl(), fname, proto,
471 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
472 : cling::LookupHelper::NoDiagnostics,
473 objectIsConst);
474 } else {
475 Error("TClingClassInfo::GetMethod",
476 "The MatchMode %d is not supported.", mode);
478 return tmi;
479 }
480 if (!fd) {
481 // Function not found.
483 return tmi;
484 }
485 if (poffset) {
486 // We have been asked to return a this pointer adjustment.
487 if (const CXXMethodDecl *md =
488 llvm::dyn_cast<CXXMethodDecl>(fd)) {
489 // This is a class member function.
490 *poffset = GetOffset(md);
491 }
492 }
494 tmi.Init(fd);
495 return tmi;
496}
497
499 const char *arglist, long *poffset, EFunctionMatchMode mode /* = kConversionMatch*/,
500 EInheritanceMode imode /* = kWithInheritance*/) const
501{
502 return GetMethodWithArgs(fname,arglist,false,poffset,mode,imode);
503}
504
506 const char *arglist, bool objectIsConst,
507 long *poffset, EFunctionMatchMode /*mode = kConversionMatch*/,
508 EInheritanceMode /* imode = kWithInheritance*/) const
509{
510
512
513 if (fType) {
514 const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
515 if (TT) {
516 llvm::StringRef tname(TT->getDecl()->getName());
517 if (tname.equals(fname)) {
518 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(GetDecl());
519 if (ndecl && !ndecl->getName().equals(fname)) {
520 // Constructor name matching the typedef type, use the decl name instead.
521 return GetMethod(ndecl->getName().str().c_str(),arglist,
522 objectIsConst,poffset
523 /* ,mode,imode */);
524 }
525 }
526 }
527
528 }
529 if (poffset) {
530 *poffset = 0L;
531 }
532 if (!IsLoaded()) {
534 return tmi;
535 }
536 if (!strcmp(arglist, ")")) {
537 // CINT accepted a single right paren as meaning no arguments.
538 arglist = "";
539 }
540 const cling::LookupHelper &lh = fInterp->getLookupHelper();
541 const FunctionDecl *fd
542 = lh.findFunctionArgs(GetDecl(), fname, arglist,
543 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
544 : cling::LookupHelper::NoDiagnostics,
545 objectIsConst);
546 if (!fd) {
547 // Function not found.
549 return tmi;
550 }
551 if (poffset) {
552 // We have been asked to return a this pointer adjustment.
553 if (const CXXMethodDecl *md =
554 llvm::dyn_cast<CXXMethodDecl>(fd)) {
555 // This is a class member function.
556 *poffset = GetOffset(md);
557 }
558 }
560 tmi.Init(fd);
561 return tmi;
562}
563
564int TClingClassInfo::GetMethodNArg(const char *method, const char *proto,
565 Bool_t objectIsConst,
566 EFunctionMatchMode mode /*= kConversionMatch*/) const
567{
568 // Note: Used only by TQObject.cxx:170 and only for interpreted classes.
569 if (!IsLoaded()) {
570 return -1;
571 }
572
574
575 TClingMethodInfo mi = GetMethod(method, proto, objectIsConst, 0, mode);
576 int clang_val = -1;
577 if (mi.IsValid()) {
578 unsigned num_params = mi.GetTargetFunctionDecl()->getNumParams();
579 clang_val = static_cast<int>(num_params);
580 }
581 return clang_val;
582}
583
584long TClingClassInfo::GetOffset(const CXXMethodDecl* md) const
585{
586
588
589 long offset = 0L;
590 const CXXRecordDecl* definer = md->getParent();
591 const CXXRecordDecl* accessor =
592 llvm::cast<CXXRecordDecl>(GetDecl());
593 if (definer != accessor) {
594 // This function may not be accessible using a pointer
595 // to the declaring class, get the adjustment necessary
596 // to convert that to a pointer to the defining class.
597 TClingBaseClassInfo bi(fInterp, const_cast<TClingClassInfo*>(this));
598 while (bi.Next(0)) {
599 TClingClassInfo* bci = bi.GetBase();
600 if (bci->GetDecl() == definer) {
601 // We have found the right base class, now get the
602 // necessary adjustment.
603 offset = bi.Offset();
604 break;
605 }
606 }
607 }
608 return offset;
609}
610
611ptrdiff_t TClingClassInfo::GetBaseOffset(TClingClassInfo* base, void* address, bool isDerivedObject)
612{
613
614 {
615 std::unique_lock<std::mutex> lock(fOffsetCacheMutex);
616
617 // Check for the offset in the cache.
618 auto iter = fOffsetCache.find(base->GetDecl());
619 if (iter != fOffsetCache.end()) {
620 std::pair<ptrdiff_t, OffsetPtrFunc_t> offsetCache = (*iter).second;
621 if (OffsetPtrFunc_t executableFunc = offsetCache.second) {
622 if (address) {
623 return (*executableFunc)(address, isDerivedObject);
624 }
625 else {
626 Error("TClingBaseClassInfo::Offset", "The address of the object for virtual base offset calculation is not valid.");
627 return -1;
628 }
629 }
630 else {
631 return offsetCache.first;
632 }
633 }
634 }
635
636 // Compute the offset.
638 TClingBaseClassInfo binfo(fInterp, this, base);
639 return binfo.Offset(address, isDerivedObject);
640}
641
642std::vector<std::string> TClingClassInfo::GetUsingNamespaces()
643{
644 // Find and return all 'using' declarations of namespaces.
645 std::vector<std::string> res;
646
648
649 cling::Interpreter::PushTransactionRAII RAII(fInterp);
650 const auto DC = dyn_cast<DeclContext>(fDecl);
651 if (!DC)
652 return res;
653
654 clang::PrintingPolicy policy(fDecl->getASTContext().getPrintingPolicy());
655 for (auto UD : DC->using_directives()) {
656 NamespaceDecl *NS = UD->getNominatedNamespace();
657 if (NS) {
658 std::string nsName;
659 llvm::raw_string_ostream stream(nsName);
660
661 NS->getNameForDiagnostic(stream, policy, /*Qualified=*/true);
662
663 stream.flush();
664 res.push_back(nsName);
665 }
666 }
667
668 return res;
669}
670
672{
673 // Return true if there a constructor taking no arguments (including
674 // a constructor that has defaults for all of its arguments) which
675 // is callable. Either it has a body, or it is trivial and the
676 // compiler elides it.
677 //
678 // Note: This is could enhanced to also know about the ROOT ioctor
679 // but this was not the case in CINT.
680 //
681
682 using namespace ROOT::TMetaUtils;
683
684 if (!IsLoaded())
685 return EIOCtorCategory::kAbsent;
686
687 auto CRD = llvm::dyn_cast<CXXRecordDecl>(GetDecl());
688 // Namespaces do not have constructors.
689 if (!CRD)
690 return EIOCtorCategory::kAbsent;
691
692 if (checkio) {
693 auto kind = CheckIOConstructor(CRD, "TRootIOCtor", nullptr, *fInterp);
694 if ((kind == EIOCtorCategory::kIORefType) || (kind == EIOCtorCategory::kIOPtrType)) {
695 if (type_name) *type_name = "TRootIOCtor";
696 return kind;
697 }
698
699 kind = CheckIOConstructor(CRD, "__void__", nullptr, *fInterp);
700 if (kind == EIOCtorCategory::kIORefType) {
701 if (type_name) *type_name = "__void__";
702 return kind;
703 }
704 }
705
706 return CheckDefaultConstructor(CRD, *fInterp) ? EIOCtorCategory::kDefault : EIOCtorCategory::kAbsent;
707}
708
709bool TClingClassInfo::HasMethod(const char *name) const
710{
712 if (IsLoaded() && !llvm::isa<EnumDecl>(GetDecl())) {
713 return fInterp->getLookupHelper()
714 .hasFunction(GetDecl(), name,
715 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
716 : cling::LookupHelper::NoDiagnostics);
717 }
718 return false;
719}
720
722{
723 fFirstTime = true;
724 fDescend = false;
725 fIsIter = false;
726 fIter = DeclContext::decl_iterator();
727 SetDecl(nullptr);
728 fType = 0;
729 fIterStack.clear();
730 const cling::LookupHelper& lh = fInterp->getLookupHelper();
731 SetDecl(lh.findScope(name, gDebug > 5 ? cling::LookupHelper::WithDiagnostics
732 : cling::LookupHelper::NoDiagnostics,
733 &fType, /* intantiateTemplate= */ true ));
734 if (!GetDecl()) {
735 std::string buf = TClassEdit::InsertStd(name);
736 if (buf != name) {
737 SetDecl(lh.findScope(buf, gDebug > 5 ? cling::LookupHelper::WithDiagnostics
738 : cling::LookupHelper::NoDiagnostics,
739 &fType, /* intantiateTemplate= */ true ));
740 }
741 }
742 if (!GetDecl() && fType) {
743 const TagType *tagtype =fType->getAs<TagType>();
744 if (tagtype) {
745 SetDecl(tagtype->getDecl());
746 }
747 }
748}
749
750void TClingClassInfo::Init(const Decl* decl)
751{
752 fFirstTime = true;
753 fDescend = false;
754 fIsIter = false;
755 fIter = DeclContext::decl_iterator();
756 SetDecl(decl);
757 fType = 0;
758 fIterStack.clear();
759}
760
761void TClingClassInfo::Init(int tagnum)
762{
763 Fatal("TClingClassInfo::Init(tagnum)", "Should no longer be called");
764 return;
765}
766
767void TClingClassInfo::Init(const Type &tag)
768{
769 fType = &tag;
770
772
773 const TagType *tagtype = fType->getAs<TagType>();
774 if (tagtype) {
775 SetDecl(tagtype->getDecl());
776 }
777 else {
778 SetDecl(nullptr);
779 }
780 if (!GetDecl()) {
781 QualType qType(fType,0);
782 static PrintingPolicy printPol(fInterp->getCI()->getLangOpts());
783 printPol.SuppressScope = false;
784 Error("TClingClassInfo::Init(const Type&)",
785 "The given type %s does not point to a Decl",
786 qType.getAsString(printPol).c_str());
787 }
788}
789
790bool TClingClassInfo::IsBase(const char *name) const
791{
792 if (!IsLoaded()) {
793 return false;
794 }
796 if (!base.IsValid()) {
797 return false;
798 }
799
801
802 const CXXRecordDecl *CRD =
803 llvm::dyn_cast<CXXRecordDecl>(GetDecl());
804 if (!CRD) {
805 // We are an enum, namespace, or translation unit,
806 // we cannot be the base of anything.
807 return false;
808 }
809 const CXXRecordDecl *baseCRD =
810 llvm::dyn_cast<CXXRecordDecl>(base.GetDecl());
811 return CRD->isDerivedFrom(baseCRD);
812}
813
814bool TClingClassInfo::IsEnum(cling::Interpreter *interp, const char *name)
815{
817 // Note: This is a static member function.
818 TClingClassInfo info(interp, name);
819 if (info.IsValid() && (info.Property() & kIsEnum)) {
820 return true;
821 }
822 return false;
823}
824
826{
827 if (auto *ED = llvm::dyn_cast<clang::EnumDecl>(GetDecl()))
828 return ED->isScoped();
829 return false;
830}
831
833{
834 if (!IsValid())
835 return kNumDataTypes;
836 if (GetDecl() == 0)
837 return kNumDataTypes;
838
839 if (auto ED = llvm::dyn_cast<EnumDecl>(GetDecl())) {
841 auto Ty = ED->getIntegerType().getTypePtrOrNull();
842 if (auto BTy = llvm::dyn_cast_or_null<BuiltinType>(Ty)) {
843 switch (BTy->getKind()) {
844 case BuiltinType::Bool:
845 return kBool_t;
846
847 case BuiltinType::Char_U:
848 case BuiltinType::UChar:
849 return kUChar_t;
850
851 case BuiltinType::Char_S:
852 case BuiltinType::SChar:
853 return kChar_t;
854
855 case BuiltinType::UShort:
856 return kUShort_t;
857 case BuiltinType::Short:
858 return kShort_t;
859 case BuiltinType::UInt:
860 return kUInt_t;
861 case BuiltinType::Int:
862 return kInt_t;
863 case BuiltinType::ULong:
864 return kULong_t;
865 case BuiltinType::Long:
866 return kLong_t;
867 case BuiltinType::ULongLong:
868 return kULong64_t;
869 case BuiltinType::LongLong:
870 return kLong64_t;
871 default:
872 return kNumDataTypes;
873 };
874 }
875 }
876 return kNumDataTypes;
877}
878
879
881{
882 // IsLoaded in CINT was meaning is known to the interpreter
883 // and has a complete definition.
884 // IsValid in Cling (as in CING) means 'just' is known to the
885 // interpreter.
886 if (!IsValid()) {
887 return false;
888 }
889 if (GetDecl() == 0) {
890 return false;
891 }
892
894
895 const CXXRecordDecl *CRD = llvm::dyn_cast<CXXRecordDecl>(GetDecl());
896 if ( CRD ) {
897 if (!CRD->hasDefinition()) {
898 return false;
899 }
900 } else {
901 const TagDecl *TD = llvm::dyn_cast<TagDecl>(GetDecl());
902 if (TD && TD->getDefinition() == 0) {
903 return false;
904 }
905 }
906 // All clang classes are considered loaded.
907 return true;
908}
909
910bool TClingClassInfo::IsValidMethod(const char *method, const char *proto,
911 Bool_t objectIsConst,
912 long *offset,
913 EFunctionMatchMode mode /*= kConversionMatch*/) const
914{
915 // Check if the method with the given prototype exist.
916 if (!IsLoaded()) {
917 return false;
918 }
919 if (offset) {
920 *offset = 0L;
921 }
922 TClingMethodInfo mi = GetMethod(method, proto, offset, mode);
923 return mi.IsValid();
924}
925
927{
929
930 fDeclFileName.clear(); // invalidate decl file name.
931 fNameCache.clear(); // invalidate the cache.
932
933 cling::Interpreter::PushTransactionRAII RAII(fInterp);
934 if (fFirstTime) {
935 // GetDecl() must be a DeclContext in order to iterate.
936 const clang::DeclContext *DC = cast<DeclContext>(GetDecl());
937 if (fIterAll)
938 fIter = DC->decls_begin();
939 else
940 fIter = DC->noload_decls_begin();
941 }
942
943 if (!fIsIter) {
944 // Object was not setup for iteration.
945 if (GetDecl()) {
946 std::string buf;
947 if (const NamedDecl* ND =
948 llvm::dyn_cast<NamedDecl>(GetDecl())) {
949 PrintingPolicy Policy(GetDecl()->getASTContext().
950 getPrintingPolicy());
951 llvm::raw_string_ostream stream(buf);
952 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/false);
953 }
954 Error("TClingClassInfo::InternalNext",
955 "Next called but iteration not prepared for %s!", buf.c_str());
956 } else {
957 Error("TClingClassInfo::InternalNext",
958 "Next called but iteration not prepared!");
959 }
960 return 0;
961 }
962 while (true) {
963 // Advance to next usable decl, or return if there is no next usable decl.
964 if (fFirstTime) {
965 // The cint semantics are strange.
966 fFirstTime = false;
967 if (!*fIter) {
968 return 0;
969 }
970 }
971 else {
972 // Advance the iterator one decl, descending into the current decl
973 // context if necessary.
974 if (!fDescend) {
975 // Do not need to scan the decl context of the current decl,
976 // move on to the next decl.
977 ++fIter;
978 }
979 else {
980 // Descend into the decl context of the current decl.
981 fDescend = false;
982 //fprintf(stderr,
983 // "TClingClassInfo::InternalNext: "
984 // "pushing ...\n");
985 fIterStack.push_back(fIter);
986 DeclContext *DC = llvm::cast<DeclContext>(*fIter);
987 if (fIterAll)
988 fIter = DC->decls_begin();
989 else
990 fIter = DC->noload_decls_begin();
991 }
992 // Fix it if we went past the end.
993 while (!*fIter && fIterStack.size()) {
994 //fprintf(stderr,
995 // "TClingClassInfo::InternalNext: "
996 // "popping ...\n");
997 fIter = fIterStack.back();
998 fIterStack.pop_back();
999 ++fIter;
1000 }
1001 // Check for final termination.
1002 if (!*fIter) {
1003 // We have reached the end of the translation unit, all done.
1004 SetDecl(nullptr);
1005 fType = 0;
1006 return 0;
1007 }
1008 }
1009 // Return if this decl is a class, struct, union, enum, or namespace.
1010 Decl::Kind DK = fIter->getKind();
1011 if ((DK == Decl::Namespace) || (DK == Decl::Enum) ||
1012 (DK == Decl::CXXRecord) ||
1013 (DK == Decl::ClassTemplateSpecialization)) {
1014 const TagDecl *TD = llvm::dyn_cast<TagDecl>(*fIter);
1015 if (TD && !TD->isCompleteDefinition()) {
1016 // For classes and enums, stop only on definitions.
1017 continue;
1018 }
1019 if (DK == Decl::Namespace) {
1020 // For namespaces, stop only on the first definition.
1021 if (!fIter->isCanonicalDecl()) {
1022 // Not the first definition.
1023 fDescend = true;
1024 continue;
1025 }
1026 }
1027 if (DK != Decl::Enum) {
1028 // We do not descend into enums.
1029 DeclContext *DC = llvm::cast<DeclContext>(*fIter);
1030 if ((fIterAll && *DC->decls_begin())
1031 || (!fIterAll && *DC->noload_decls_begin())) {
1032 // Next iteration will begin scanning the decl context
1033 // contained by this decl.
1034 fDescend = true;
1035 }
1036 }
1037 // Iterator is now valid.
1038 SetDecl(*fIter);
1039 fType = 0;
1040 if (GetDecl()) {
1041 if (GetDecl()->isInvalidDecl()) {
1042 Warning("TClingClassInfo::Next()","Reached an invalid decl.");
1043 }
1044 if (const RecordDecl *RD =
1045 llvm::dyn_cast<RecordDecl>(GetDecl())) {
1046 fType = RD->getASTContext().getRecordType(RD).getTypePtr();
1047 }
1048 }
1049 return 1;
1050 }
1051 }
1052}
1053
1055{
1056 return InternalNext();
1057}
1058
1060{
1061 // Invoke a new expression to use the class constructor
1062 // that takes no arguments to create an object of this class type.
1063 if (!IsValid()) {
1064 Error("TClingClassInfo::New()", "Called while invalid!");
1065 return nullptr;
1066 }
1067 if (!IsLoaded()) {
1068 Error("TClingClassInfo::New()", "Class is not loaded: %s",
1069 FullyQualifiedName(GetDecl()).c_str());
1070 return nullptr;
1071 }
1072
1074 std::string type_name;
1075
1076 {
1078 auto RD = dyn_cast<CXXRecordDecl>(GetDecl());
1079 if (!RD) {
1080 Error("TClingClassInfo::New()", "This is a namespace!: %s",
1081 FullyQualifiedName(GetDecl()).c_str());
1082 return nullptr;
1083 }
1084
1085 kind = HasDefaultConstructor(true, &type_name);
1086
1088 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1089 // Error("TClingClassInfo::New()", "Class has no default constructor: %s",
1090 // FullyQualifiedName(GetDecl()).c_str());
1091 return nullptr;
1092 }
1093 } // End of Lock section.
1094 void* obj = nullptr;
1095 TClingCallFunc cf(fInterp,normCtxt);
1096 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1097 /*address=*/nullptr, /*nary=*/0);
1098 if (!obj) {
1099 Error("TClingClassInfo::New()", "Call of default constructor "
1100 "failed to return an object for class: %s",
1101 FullyQualifiedName(GetDecl()).c_str());
1102 return nullptr;
1103 }
1104 return obj;
1105}
1106
1108{
1109 // Invoke a new expression to use the class constructor
1110 // that takes no arguments to create an array object
1111 // of this class type.
1112 if (!IsValid()) {
1113 Error("TClingClassInfo::New(n)", "Called while invalid!");
1114 return nullptr;
1115 }
1116 if (!IsLoaded()) {
1117 Error("TClingClassInfo::New(n)", "Class is not loaded: %s",
1118 FullyQualifiedName(GetDecl()).c_str());
1119 return nullptr;
1120 }
1121
1123 std::string type_name;
1124
1125 {
1127
1128 auto RD = dyn_cast<CXXRecordDecl>(GetDecl());
1129 if (!RD) {
1130 Error("TClingClassInfo::New(n)", "This is a namespace!: %s",
1131 FullyQualifiedName(GetDecl()).c_str());
1132 return nullptr;
1133 }
1134
1135 kind = HasDefaultConstructor(true, &type_name);
1137 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1138 //Error("TClingClassInfo::New(n)",
1139 // "Class has no default constructor: %s",
1140 // FullyQualifiedName(GetDecl()).c_str());
1141 return nullptr;
1142 }
1143 } // End of Lock section.
1144 void* obj = nullptr;
1145 TClingCallFunc cf(fInterp,normCtxt);
1146 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1147 /*address=*/nullptr, /*nary=*/(unsigned long)n);
1148 if (!obj) {
1149 Error("TClingClassInfo::New(n)", "Call of default constructor "
1150 "failed to return an array of class: %s",
1151 FullyQualifiedName(GetDecl()).c_str());
1152 return nullptr;
1153 }
1154 return obj;
1155}
1156
1157void *TClingClassInfo::New(int n, void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
1158{
1159 // Invoke a placement new expression to use the class
1160 // constructor that takes no arguments to create an
1161 // array of objects of this class type in the given
1162 // memory arena.
1163 if (!IsValid()) {
1164 Error("TClingClassInfo::New(n, arena)", "Called while invalid!");
1165 return nullptr;
1166 }
1167 if (!IsLoaded()) {
1168 Error("TClingClassInfo::New(n, arena)", "Class is not loaded: %s",
1169 FullyQualifiedName(GetDecl()).c_str());
1170 return nullptr;
1171 }
1172
1174 std::string type_name;
1175
1176 {
1178
1179 auto RD = dyn_cast<CXXRecordDecl>(GetDecl());
1180 if (!RD) {
1181 Error("TClingClassInfo::New(n, arena)", "This is a namespace!: %s",
1182 FullyQualifiedName(GetDecl()).c_str());
1183 return nullptr;
1184 }
1185
1186 kind = HasDefaultConstructor(true, &type_name);
1188 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1189 //Error("TClingClassInfo::New(n, arena)",
1190 // "Class has no default constructor: %s",
1191 // FullyQualifiedName(GetDecl()).c_str());
1192 return nullptr;
1193 }
1194 } // End of Lock section
1195 void* obj = nullptr;
1196 TClingCallFunc cf(fInterp,normCtxt);
1197 // Note: This will always return arena.
1198 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1199 /*address=*/arena, /*nary=*/(unsigned long)n);
1200 return obj;
1201}
1202
1203void *TClingClassInfo::New(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
1204{
1205 // Invoke a placement new expression to use the class
1206 // constructor that takes no arguments to create an
1207 // object of this class type in the given memory arena.
1208 if (!IsValid()) {
1209 Error("TClingClassInfo::New(arena)", "Called while invalid!");
1210 return nullptr;
1211 }
1212 if (!IsLoaded()) {
1213 Error("TClingClassInfo::New(arena)", "Class is not loaded: %s",
1214 FullyQualifiedName(GetDecl()).c_str());
1215 return nullptr;
1216 }
1217
1219 std::string type_name;
1220
1221 {
1223
1224 auto RD = dyn_cast<CXXRecordDecl>(GetDecl());
1225 if (!RD) {
1226 Error("TClingClassInfo::New(arena)", "This is a namespace!: %s",
1227 FullyQualifiedName(GetDecl()).c_str());
1228 return nullptr;
1229 }
1230
1231 kind = HasDefaultConstructor(true, &type_name);
1233 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1234 //Error("TClingClassInfo::New(arena)",
1235 // "Class has no default constructor: %s",
1236 // FullyQualifiedName(GetDecl()).c_str());
1237 return nullptr;
1238 }
1239 } // End of Locked section.
1240 void* obj = nullptr;
1241 TClingCallFunc cf(fInterp,normCtxt);
1242 // Note: This will always return arena.
1243 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1244 /*address=*/arena, /*nary=*/0);
1245 return obj;
1246}
1247
1249{
1250 if (!IsValid()) {
1251 return 0L;
1252 }
1253
1255
1256 long property = 0L;
1257 property |= kIsCPPCompiled;
1258
1259 // Modules can deserialize while querying the various decls for information.
1260 cling::Interpreter::PushTransactionRAII RAII(fInterp);
1261
1262 const clang::DeclContext *ctxt = GetDecl()->getDeclContext();
1263 clang::NamespaceDecl *std_ns =fInterp->getSema().getStdNamespace();
1264 while (! ctxt->isTranslationUnit()) {
1265 if (ctxt->Equals(std_ns)) {
1266 property |= kIsDefinedInStd;
1267 break;
1268 }
1269 ctxt = ctxt->getParent();
1270 }
1271 Decl::Kind DK = GetDecl()->getKind();
1272 if ((DK == Decl::Namespace) || (DK == Decl::TranslationUnit)) {
1273 property |= kIsNamespace;
1274 return property;
1275 }
1276 // Note: Now we have class, enum, struct, union only.
1277 const TagDecl *TD = llvm::dyn_cast<TagDecl>(GetDecl());
1278 if (!TD) {
1279 return 0L;
1280 }
1281 if (TD->isEnum()) {
1282 property |= kIsEnum;
1283 return property;
1284 }
1285 // Note: Now we have class, struct, union only.
1286 const CXXRecordDecl *CRD =
1287 llvm::dyn_cast<CXXRecordDecl>(GetDecl());
1288 if (CRD->isClass()) {
1289 property |= kIsClass;
1290 }
1291 else if (CRD->isStruct()) {
1292 property |= kIsStruct;
1293 }
1294 else if (CRD->isUnion()) {
1295 property |= kIsUnion;
1296 }
1297 if (CRD->hasDefinition() && CRD->isAbstract()) {
1298 property |= kIsAbstract;
1299 }
1300 return property;
1301}
1302
1304{
1305 if (!IsValid()) {
1306 return 0;
1307 }
1308 // FIXME: Implement this when rootcling provides the value.
1309 return 0;
1310}
1311
1313{
1314 if (!IsValid()) {
1315 return -1;
1316 }
1317 if (!GetDecl()) {
1318 // A forward declared class.
1319 return 0;
1320 }
1321
1323
1324 Decl::Kind DK = GetDecl()->getKind();
1325 if (DK == Decl::Namespace) {
1326 // Namespaces are special for cint.
1327 return 1;
1328 }
1329 else if (DK == Decl::Enum) {
1330 // Enums are special for cint.
1331 return 0;
1332 }
1333 const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(GetDecl());
1334 if (!RD) {
1335 // Should not happen.
1336 return -1;
1337 }
1338 if (!RD->getDefinition()) {
1339 // Forward-declared class.
1340 return 0;
1341 }
1342 ASTContext &Context = GetDecl()->getASTContext();
1343 cling::Interpreter::PushTransactionRAII RAII(fInterp);
1344 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1345 int64_t size = Layout.getSize().getQuantity();
1346 int clang_size = static_cast<int>(size);
1347 return clang_size;
1348}
1349
1351{
1352 if (!IsValid()) {
1353 return -1L;
1354 }
1355 return reinterpret_cast<long>(GetDecl());
1356}
1357
1359{
1360 if (!IsValid()) {
1361 return 0;
1362 }
1363 if (fDeclFileName.empty())
1365 return fDeclFileName.c_str();
1366}
1367
1369{
1370 // Return QualifiedName.
1371 output.clear();
1372 if (!IsValid()) {
1373 return;
1374 }
1375 if (fType) {
1376 QualType type(fType, 0);
1378 }
1379 else {
1380 if (const NamedDecl* ND =
1381 llvm::dyn_cast<NamedDecl>(GetDecl())) {
1382 PrintingPolicy Policy(GetDecl()->getASTContext().
1383 getPrintingPolicy());
1384 llvm::raw_string_ostream stream(output);
1385 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true);
1386 }
1387 }
1388}
1389
1391{
1392 if (!IsValid()) {
1393 return 0;
1394 }
1395 // NOTE: We cannot cache the result, since we are really an iterator.
1396 // Try to get the comment either from the annotation or the header
1397 // file, if present.
1398 // Iterate over the redeclarations, we can have multiple definitions in the
1399 // redecl chain (came from merging of pcms).
1400
1402
1403 if (const TagDecl *TD = llvm::dyn_cast<TagDecl>(GetDecl())) {
1405 if (AnnotateAttr *A = TD->getAttr<AnnotateAttr>()) {
1406 std::string attr = A->getAnnotation().str();
1407 if (attr.find(TMetaUtils::propNames::separator) != std::string::npos) {
1409 fTitle = attr;
1410 return fTitle.c_str();
1411 }
1412 } else {
1413 fTitle = attr;
1414 return fTitle.c_str();
1415 }
1416 }
1417 }
1418 }
1419 // Try to get the comment from the header file, if present.
1420 // but not for decls from AST file, where rootcling would have
1421 // created an annotation
1422 const CXXRecordDecl *CRD =
1423 llvm::dyn_cast<CXXRecordDecl>(GetDecl());
1424 if (CRD && !CRD->isFromASTFile()) {
1426 }
1427 return fTitle.c_str();
1428}
1429
1431{
1432 if (!IsValid()) {
1433 return 0;
1434 }
1435
1437
1438 // Note: This *must* be static/thread_local because we are returning a pointer inside it!
1439 TTHREAD_TLS_DECL( std::string, buf);
1440 buf.clear();
1441 if (const NamedDecl* ND = llvm::dyn_cast<NamedDecl>(GetDecl())) {
1442 // Note: This does *not* include the template arguments!
1443 buf = ND->getNameAsString();
1444 }
1445 return buf.c_str();
1446}
1447
const Bool_t kTRUE
Definition RtypesCore.h:91
static std::string FullyQualifiedName(const Decl *decl)
ptrdiff_t(* OffsetPtrFunc_t)(void *, bool)
EDataType
Definition TDataType.h:28
@ kULong64_t
Definition TDataType.h:32
@ kInt_t
Definition TDataType.h:30
@ kNumDataTypes
Definition TDataType.h:40
@ kLong_t
Definition TDataType.h:30
@ kShort_t
Definition TDataType.h:29
@ kBool_t
Definition TDataType.h:32
@ kULong_t
Definition TDataType.h:30
@ kLong64_t
Definition TDataType.h:32
@ kUShort_t
Definition TDataType.h:29
@ kChar_t
Definition TDataType.h:29
@ kUChar_t
Definition TDataType.h:29
@ kUInt_t
Definition TDataType.h:30
@ kClassHasExplicitCtor
@ kClassHasAssignOpr
@ kClassHasImplicitCtor
@ kClassHasDefaultCtor
@ kClassIsValid
@ kClassIsAbstract
@ kClassHasVirtual
@ kClassHasExplicitDtor
@ kClassHasImplicitDtor
@ kIsCPPCompiled
Definition TDictionary.h:85
@ 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
@ kIsNamespace
Definition TDictionary.h:95
@ kIsDefinedInStd
Definition TDictionary.h:98
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:187
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:231
void Fatal(const char *location, const char *msgfmt,...)
Use this function in case of a fatal error. It will abort the program.
Definition TError.cxx:245
char name[80]
Definition TGX11.cxx:110
int type
Definition TGX11.cxx:121
R__EXTERN TVirtualMutex * gInterpreterMutex
Int_t gDebug
Definition TROOT.cxx:590
#define R__LOCKGUARD(mutex)
#define R__WRITE_LOCKGUARD(mutex)
const char * proto
Definition civetweb.c:16604
Emulation of the CINT BaseClassInfo class.
ptrdiff_t Offset(void *address=0, bool isDerivedObject=true) const
TClingClassInfo * GetBase() const
Emulation of the CINT CallFunc class.
void * ExecDefaultConstructor(const TClingClassInfo *info, ROOT::TMetaUtils::EIOCtorCategory kind, const std::string &type_name, void *address=nullptr, unsigned long nary=0UL)
void ExecDestructor(const TClingClassInfo *info, void *address=nullptr, unsigned long nary=0UL, bool withFree=true)
Emulation of the CINT ClassInfo class.
clang::DeclContext::decl_iterator fIter
const char * Title()
static bool IsEnum(cling::Interpreter *interp, const char *name)
long ClassProperty() const
void Init(const char *name)
std::string fTitle
void FullName(std::string &output, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
llvm::DenseMap< const clang::Decl *, std::pair< ptrdiff_t, OffsetPtrFunc_t > > fOffsetCache
EDataType GetUnderlyingType() const
std::mutex fOffsetCacheMutex
TClingMethodInfo GetMethodWithArgs(const char *fname, const char *arglist, long *poffset, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch, EInheritanceMode imode=kWithInheritance) const
const char * TmpltName() const
void AddBaseOffsetValue(const clang::Decl *decl, ptrdiff_t offset)
ptrdiff_t GetBaseOffset(TClingClassInfo *toBase, void *address, bool isDerivedObject)
void SetDecl(const clang::Decl *D)
bool IsScopedEnum() const
ROOT::TMetaUtils::EIOCtorCategory HasDefaultConstructor(bool checkio=false, std::string *type_name=nullptr) const
const clang::FunctionTemplateDecl * GetFunctionTemplate(const char *fname) const
int GetMethodNArg(const char *method, const char *proto, Bool_t objectIsConst, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch) const
bool HasMethod(const char *name) const
std::string fDeclFileName
void DeleteArray(void *arena, bool dtorOnly, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
void * New(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
bool IsValidMethod(const char *method, const char *proto, Bool_t objectIsConst, long *offset, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch) const
TClingMethodInfo GetMethod(const char *fname) const
bool IsLoaded() const
long GetOffset(const clang::CXXMethodDecl *md) const
const clang::ValueDecl * GetDataMember(const char *name) const
void Destruct(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
std::vector< std::string > GetUsingNamespaces()
cling::Interpreter * fInterp
const char * FileName()
std::vector< clang::DeclContext::decl_iterator > fIterStack
bool IsBase(const char *name) const
const clang::Type * fType
void Delete(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
const clang::Decl * fDecl
virtual bool IsValid() const
std::string fNameCache
virtual const clang::Decl * GetDecl() const
Emulation of the CINT MethodInfo class.
const clang::FunctionDecl * GetTargetFunctionDecl() const
Get the FunctionDecl, or if this represents a UsingShadowDecl, the underlying target FunctionDecl.
void Init(const clang::FunctionDecl *)
const Int_t n
Definition legend1.C:16
static const std::string separator("@@@")
static const std::string comment("comment")
llvm::StringRef GetClassComment(const clang::CXXRecordDecl &decl, clang::SourceLocation *loc, const cling::Interpreter &interpreter)
Return the class comment after the ClassDef: class MyClass { ... ClassDef(MyClass,...
const T * GetAnnotatedRedeclarable(const T *Redecl)
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,...
llvm::StringRef GetFileName(const clang::Decl &decl, const cling::Interpreter &interp)
Return the header file to be included to declare the Decl.
bool ExtractAttrPropertyFromName(const clang::Decl &decl, const std::string &propName, std::string &propValue)
This routine counts on the "propName<separator>propValue" format.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
R__EXTERN TVirtualRWMutex * gCoreMutex
EFunctionMatchMode
@ kExactMatch
@ kConversionMatch
std::string InsertStd(const char *tname)
static void output(int code)
Definition gifencode.c:226