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