Logo ROOT  
Reference Guide
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{
816 // Note: This is a static member function.
817 TClingClassInfo info(interp, name);
818 if (info.IsValid() && (info.Property() & kIsEnum)) {
819 return true;
820 }
821 return false;
822}
823
825{
826 if (auto *ED = llvm::dyn_cast<clang::EnumDecl>(GetDecl()))
827 return ED->isScoped();
828 return false;
829}
830
832{
833 if (!IsValid())
834 return kNumDataTypes;
835 if (GetDecl() == 0)
836 return kNumDataTypes;
837
838 if (auto ED = llvm::dyn_cast<EnumDecl>(GetDecl())) {
840 auto Ty = ED->getIntegerType().getTypePtrOrNull();
841 if (auto BTy = llvm::dyn_cast<BuiltinType>(Ty)) {
842 switch (BTy->getKind()) {
844 return kBool_t;
845
846 case BuiltinType::Char_U:
848 return kUChar_t;
849
850 case BuiltinType::Char_S:
851 case BuiltinType::SChar:
852 return kChar_t;
853
855 return kUShort_t;
857 return kShort_t;
859 return kUInt_t;
860 case BuiltinType::Int:
861 return kInt_t;
863 return kULong_t;
865 return kLong_t;
866 case BuiltinType::ULongLong:
867 return kULong64_t;
868 case BuiltinType::LongLong:
869 return kLong64_t;
870 default:
871 return kNumDataTypes;
872 };
873 }
874 }
875 return kNumDataTypes;
876}
877
878
880{
881 // IsLoaded in CINT was meaning is known to the interpreter
882 // and has a complete definition.
883 // IsValid in Cling (as in CING) means 'just' is known to the
884 // interpreter.
885 if (!IsValid()) {
886 return false;
887 }
888 if (GetDecl() == 0) {
889 return false;
890 }
891
893
894 const CXXRecordDecl *CRD = llvm::dyn_cast<CXXRecordDecl>(GetDecl());
895 if ( CRD ) {
896 if (!CRD->hasDefinition()) {
897 return false;
898 }
899 } else {
900 const TagDecl *TD = llvm::dyn_cast<TagDecl>(GetDecl());
901 if (TD && TD->getDefinition() == 0) {
902 return false;
903 }
904 }
905 // All clang classes are considered loaded.
906 return true;
907}
908
909bool TClingClassInfo::IsValidMethod(const char *method, const char *proto,
910 Bool_t objectIsConst,
911 long *offset,
912 EFunctionMatchMode mode /*= kConversionMatch*/) const
913{
914 // Check if the method with the given prototype exist.
915 if (!IsLoaded()) {
916 return false;
917 }
918 if (offset) {
919 *offset = 0L;
920 }
921 TClingMethodInfo mi = GetMethod(method, proto, offset, mode);
922 return mi.IsValid();
923}
924
926{
928
929 fDeclFileName.clear(); // invalidate decl file name.
930 fNameCache.clear(); // invalidate the cache.
931
932 cling::Interpreter::PushTransactionRAII RAII(fInterp);
933 if (fFirstTime) {
934 // GetDecl() must be a DeclContext in order to iterate.
935 const clang::DeclContext *DC = cast<DeclContext>(GetDecl());
936 if (fIterAll)
937 fIter = DC->decls_begin();
938 else
939 fIter = DC->noload_decls_begin();
940 }
941
942 if (!fIsIter) {
943 // Object was not setup for iteration.
944 if (GetDecl()) {
945 std::string buf;
946 if (const NamedDecl* ND =
947 llvm::dyn_cast<NamedDecl>(GetDecl())) {
948 PrintingPolicy Policy(GetDecl()->getASTContext().
949 getPrintingPolicy());
950 llvm::raw_string_ostream stream(buf);
951 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/false);
952 }
953 Error("TClingClassInfo::InternalNext",
954 "Next called but iteration not prepared for %s!", buf.c_str());
955 } else {
956 Error("TClingClassInfo::InternalNext",
957 "Next called but iteration not prepared!");
958 }
959 return 0;
960 }
961 while (true) {
962 // Advance to next usable decl, or return if there is no next usable decl.
963 if (fFirstTime) {
964 // The cint semantics are strange.
965 fFirstTime = false;
966 if (!*fIter) {
967 return 0;
968 }
969 }
970 else {
971 // Advance the iterator one decl, descending into the current decl
972 // context if necessary.
973 if (!fDescend) {
974 // Do not need to scan the decl context of the current decl,
975 // move on to the next decl.
976 ++fIter;
977 }
978 else {
979 // Descend into the decl context of the current decl.
980 fDescend = false;
981 //fprintf(stderr,
982 // "TClingClassInfo::InternalNext: "
983 // "pushing ...\n");
984 fIterStack.push_back(fIter);
985 DeclContext *DC = llvm::cast<DeclContext>(*fIter);
986 if (fIterAll)
987 fIter = DC->decls_begin();
988 else
989 fIter = DC->noload_decls_begin();
990 }
991 // Fix it if we went past the end.
992 while (!*fIter && fIterStack.size()) {
993 //fprintf(stderr,
994 // "TClingClassInfo::InternalNext: "
995 // "popping ...\n");
996 fIter = fIterStack.back();
997 fIterStack.pop_back();
998 ++fIter;
999 }
1000 // Check for final termination.
1001 if (!*fIter) {
1002 // We have reached the end of the translation unit, all done.
1003 SetDecl(nullptr);
1004 fType = 0;
1005 return 0;
1006 }
1007 }
1008 // Return if this decl is a class, struct, union, enum, or namespace.
1009 Decl::Kind DK = fIter->getKind();
1010 if ((DK == Decl::Namespace) || (DK == Decl::Enum) ||
1011 (DK == Decl::CXXRecord) ||
1012 (DK == Decl::ClassTemplateSpecialization)) {
1013 const TagDecl *TD = llvm::dyn_cast<TagDecl>(*fIter);
1014 if (TD && !TD->isCompleteDefinition()) {
1015 // For classes and enums, stop only on definitions.
1016 continue;
1017 }
1018 if (DK == Decl::Namespace) {
1019 // For namespaces, stop only on the first definition.
1020 if (!fIter->isCanonicalDecl()) {
1021 // Not the first definition.
1022 fDescend = true;
1023 continue;
1024 }
1025 }
1026 if (DK != Decl::Enum) {
1027 // We do not descend into enums.
1028 DeclContext *DC = llvm::cast<DeclContext>(*fIter);
1029 if ((fIterAll && *DC->decls_begin())
1030 || (!fIterAll && *DC->noload_decls_begin())) {
1031 // Next iteration will begin scanning the decl context
1032 // contained by this decl.
1033 fDescend = true;
1034 }
1035 }
1036 // Iterator is now valid.
1037 SetDecl(*fIter);
1038 fType = 0;
1039 if (GetDecl()) {
1040 if (GetDecl()->isInvalidDecl()) {
1041 Warning("TClingClassInfo::Next()","Reached an invalid decl.");
1042 }
1043 if (const RecordDecl *RD =
1044 llvm::dyn_cast<RecordDecl>(GetDecl())) {
1045 fType = RD->getASTContext().getRecordType(RD).getTypePtr();
1046 }
1047 }
1048 return 1;
1049 }
1050 }
1051}
1052
1054{
1055 return InternalNext();
1056}
1057
1059{
1060 // Invoke a new expression to use the class constructor
1061 // that takes no arguments to create an object of this class type.
1062 if (!IsValid()) {
1063 Error("TClingClassInfo::New()", "Called while invalid!");
1064 return nullptr;
1065 }
1066 if (!IsLoaded()) {
1067 Error("TClingClassInfo::New()", "Class is not loaded: %s",
1068 FullyQualifiedName(GetDecl()).c_str());
1069 return nullptr;
1070 }
1071
1073 std::string type_name;
1074
1075 {
1077 auto RD = dyn_cast<CXXRecordDecl>(GetDecl());
1078 if (!RD) {
1079 Error("TClingClassInfo::New()", "This is a namespace!: %s",
1080 FullyQualifiedName(GetDecl()).c_str());
1081 return nullptr;
1082 }
1083
1084 kind = HasDefaultConstructor(true, &type_name);
1085
1087 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1088 // Error("TClingClassInfo::New()", "Class has no default constructor: %s",
1089 // FullyQualifiedName(GetDecl()).c_str());
1090 return nullptr;
1091 }
1092 } // End of Lock section.
1093 void* obj = nullptr;
1094 TClingCallFunc cf(fInterp,normCtxt);
1095 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1096 /*address=*/nullptr, /*nary=*/0);
1097 if (!obj) {
1098 Error("TClingClassInfo::New()", "Call of default constructor "
1099 "failed to return an object for class: %s",
1100 FullyQualifiedName(GetDecl()).c_str());
1101 return nullptr;
1102 }
1103 return obj;
1104}
1105
1107{
1108 // Invoke a new expression to use the class constructor
1109 // that takes no arguments to create an array object
1110 // of this class type.
1111 if (!IsValid()) {
1112 Error("TClingClassInfo::New(n)", "Called while invalid!");
1113 return nullptr;
1114 }
1115 if (!IsLoaded()) {
1116 Error("TClingClassInfo::New(n)", "Class is not loaded: %s",
1117 FullyQualifiedName(GetDecl()).c_str());
1118 return nullptr;
1119 }
1120
1122 std::string type_name;
1123
1124 {
1126
1127 auto RD = dyn_cast<CXXRecordDecl>(GetDecl());
1128 if (!RD) {
1129 Error("TClingClassInfo::New(n)", "This is a namespace!: %s",
1130 FullyQualifiedName(GetDecl()).c_str());
1131 return nullptr;
1132 }
1133
1134 kind = HasDefaultConstructor(true, &type_name);
1136 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1137 //Error("TClingClassInfo::New(n)",
1138 // "Class has no default constructor: %s",
1139 // FullyQualifiedName(GetDecl()).c_str());
1140 return nullptr;
1141 }
1142 } // End of Lock section.
1143 void* obj = nullptr;
1144 TClingCallFunc cf(fInterp,normCtxt);
1145 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1146 /*address=*/nullptr, /*nary=*/(unsigned long)n);
1147 if (!obj) {
1148 Error("TClingClassInfo::New(n)", "Call of default constructor "
1149 "failed to return an array of class: %s",
1150 FullyQualifiedName(GetDecl()).c_str());
1151 return nullptr;
1152 }
1153 return obj;
1154}
1155
1156void *TClingClassInfo::New(int n, void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
1157{
1158 // Invoke a placement new expression to use the class
1159 // constructor that takes no arguments to create an
1160 // array of objects of this class type in the given
1161 // memory arena.
1162 if (!IsValid()) {
1163 Error("TClingClassInfo::New(n, arena)", "Called while invalid!");
1164 return nullptr;
1165 }
1166 if (!IsLoaded()) {
1167 Error("TClingClassInfo::New(n, arena)", "Class is not loaded: %s",
1168 FullyQualifiedName(GetDecl()).c_str());
1169 return nullptr;
1170 }
1171
1173 std::string type_name;
1174
1175 {
1177
1178 auto RD = dyn_cast<CXXRecordDecl>(GetDecl());
1179 if (!RD) {
1180 Error("TClingClassInfo::New(n, arena)", "This is a namespace!: %s",
1181 FullyQualifiedName(GetDecl()).c_str());
1182 return nullptr;
1183 }
1184
1185 kind = HasDefaultConstructor(true, &type_name);
1187 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1188 //Error("TClingClassInfo::New(n, arena)",
1189 // "Class has no default constructor: %s",
1190 // FullyQualifiedName(GetDecl()).c_str());
1191 return nullptr;
1192 }
1193 } // End of Lock section
1194 void* obj = nullptr;
1195 TClingCallFunc cf(fInterp,normCtxt);
1196 // Note: This will always return arena.
1197 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1198 /*address=*/arena, /*nary=*/(unsigned long)n);
1199 return obj;
1200}
1201
1202void *TClingClassInfo::New(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
1203{
1204 // Invoke a placement new expression to use the class
1205 // constructor that takes no arguments to create an
1206 // object of this class type in the given memory arena.
1207 if (!IsValid()) {
1208 Error("TClingClassInfo::New(arena)", "Called while invalid!");
1209 return nullptr;
1210 }
1211 if (!IsLoaded()) {
1212 Error("TClingClassInfo::New(arena)", "Class is not loaded: %s",
1213 FullyQualifiedName(GetDecl()).c_str());
1214 return nullptr;
1215 }
1216
1218 std::string type_name;
1219
1220 {
1222
1223 auto RD = dyn_cast<CXXRecordDecl>(GetDecl());
1224 if (!RD) {
1225 Error("TClingClassInfo::New(arena)", "This is a namespace!: %s",
1226 FullyQualifiedName(GetDecl()).c_str());
1227 return nullptr;
1228 }
1229
1230 kind = HasDefaultConstructor(true, &type_name);
1232 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1233 //Error("TClingClassInfo::New(arena)",
1234 // "Class has no default constructor: %s",
1235 // FullyQualifiedName(GetDecl()).c_str());
1236 return nullptr;
1237 }
1238 } // End of Locked section.
1239 void* obj = nullptr;
1240 TClingCallFunc cf(fInterp,normCtxt);
1241 // Note: This will always return arena.
1242 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1243 /*address=*/arena, /*nary=*/0);
1244 return obj;
1245}
1246
1248{
1249 if (!IsValid()) {
1250 return 0L;
1251 }
1252
1254
1255 long property = 0L;
1256 property |= kIsCPPCompiled;
1257
1258 // Modules can deserialize while querying the various decls for information.
1259 cling::Interpreter::PushTransactionRAII RAII(fInterp);
1260
1261 const clang::DeclContext *ctxt = GetDecl()->getDeclContext();
1262 clang::NamespaceDecl *std_ns =fInterp->getSema().getStdNamespace();
1263 while (! ctxt->isTranslationUnit()) {
1264 if (ctxt->Equals(std_ns)) {
1265 property |= kIsDefinedInStd;
1266 break;
1267 }
1268 ctxt = ctxt->getParent();
1269 }
1270 Decl::Kind DK = GetDecl()->getKind();
1271 if ((DK == Decl::Namespace) || (DK == Decl::TranslationUnit)) {
1272 property |= kIsNamespace;
1273 return property;
1274 }
1275 // Note: Now we have class, enum, struct, union only.
1276 const TagDecl *TD = llvm::dyn_cast<TagDecl>(GetDecl());
1277 if (!TD) {
1278 return 0L;
1279 }
1280 if (TD->isEnum()) {
1281 property |= kIsEnum;
1282 return property;
1283 }
1284 // Note: Now we have class, struct, union only.
1285 const CXXRecordDecl *CRD =
1286 llvm::dyn_cast<CXXRecordDecl>(GetDecl());
1287 if (CRD->isClass()) {
1288 property |= kIsClass;
1289 }
1290 else if (CRD->isStruct()) {
1291 property |= kIsStruct;
1292 }
1293 else if (CRD->isUnion()) {
1294 property |= kIsUnion;
1295 }
1296 if (CRD->hasDefinition() && CRD->isAbstract()) {
1297 property |= kIsAbstract;
1298 }
1299 return property;
1300}
1301
1303{
1304 if (!IsValid()) {
1305 return 0;
1306 }
1307 // FIXME: Implement this when rootcling provides the value.
1308 return 0;
1309}
1310
1312{
1313 if (!IsValid()) {
1314 return -1;
1315 }
1316 if (!GetDecl()) {
1317 // A forward declared class.
1318 return 0;
1319 }
1320
1322
1323 Decl::Kind DK = GetDecl()->getKind();
1324 if (DK == Decl::Namespace) {
1325 // Namespaces are special for cint.
1326 return 1;
1327 }
1328 else if (DK == Decl::Enum) {
1329 // Enums are special for cint.
1330 return 0;
1331 }
1332 const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(GetDecl());
1333 if (!RD) {
1334 // Should not happen.
1335 return -1;
1336 }
1337 if (!RD->getDefinition()) {
1338 // Forward-declared class.
1339 return 0;
1340 }
1341 ASTContext &Context = GetDecl()->getASTContext();
1342 cling::Interpreter::PushTransactionRAII RAII(fInterp);
1343 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1344 int64_t size = Layout.getSize().getQuantity();
1345 int clang_size = static_cast<int>(size);
1346 return clang_size;
1347}
1348
1350{
1351 if (!IsValid()) {
1352 return -1L;
1353 }
1354 return reinterpret_cast<long>(GetDecl());
1355}
1356
1358{
1359 if (!IsValid()) {
1360 return 0;
1361 }
1362 if (fDeclFileName.empty())
1364 return fDeclFileName.c_str();
1365}
1366
1368{
1369 // Return QualifiedName.
1370 output.clear();
1371 if (!IsValid()) {
1372 return;
1373 }
1374 if (fType) {
1375 QualType type(fType, 0);
1377 }
1378 else {
1379 if (const NamedDecl* ND =
1380 llvm::dyn_cast<NamedDecl>(GetDecl())) {
1381 PrintingPolicy Policy(GetDecl()->getASTContext().
1382 getPrintingPolicy());
1383 llvm::raw_string_ostream stream(output);
1384 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true);
1385 }
1386 }
1387}
1388
1390{
1391 if (!IsValid()) {
1392 return 0;
1393 }
1394 // NOTE: We cannot cache the result, since we are really an iterator.
1395 // Try to get the comment either from the annotation or the header
1396 // file, if present.
1397 // Iterate over the redeclarations, we can have multiple definitions in the
1398 // redecl chain (came from merging of pcms).
1399
1401
1402 if (const TagDecl *TD = llvm::dyn_cast<TagDecl>(GetDecl())) {
1404 if (AnnotateAttr *A = TD->getAttr<AnnotateAttr>()) {
1405 std::string attr = A->getAnnotation().str();
1406 if (attr.find(TMetaUtils::propNames::separator) != std::string::npos) {
1408 fTitle = attr;
1409 return fTitle.c_str();
1410 }
1411 } else {
1412 fTitle = attr;
1413 return fTitle.c_str();
1414 }
1415 }
1416 }
1417 }
1418 // Try to get the comment from the header file, if present.
1419 // but not for decls from AST file, where rootcling would have
1420 // created an annotation
1421 const CXXRecordDecl *CRD =
1422 llvm::dyn_cast<CXXRecordDecl>(GetDecl());
1423 if (CRD && !CRD->isFromASTFile()) {
1425 }
1426 return fTitle.c_str();
1427}
1428
1430{
1431 if (!IsValid()) {
1432 return 0;
1433 }
1434
1436
1437 // Note: This *must* be static/thread_local because we are returning a pointer inside it!
1438 TTHREAD_TLS_DECL( std::string, buf);
1439 buf.clear();
1440 if (const NamedDecl* ND = llvm::dyn_cast<NamedDecl>(GetDecl())) {
1441 // Note: This does *not* include the template arguments!
1442 buf = ND->getNameAsString();
1443 }
1444 return buf.c_str();
1445}
1446
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:117
const Bool_t kTRUE
Definition: RtypesCore.h:89
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
Definition: TDictionary.h:136
@ kClassHasAssignOpr
Definition: TDictionary.h:140
@ kClassHasImplicitCtor
Definition: TDictionary.h:137
@ kClassHasDefaultCtor
Definition: TDictionary.h:139
@ kClassIsValid
Definition: TDictionary.h:135
@ kClassIsAbstract
Definition: TDictionary.h:145
@ kClassHasVirtual
Definition: TDictionary.h:144
@ kClassHasExplicitDtor
Definition: TDictionary.h:141
@ kClassHasImplicitDtor
Definition: TDictionary.h:142
@ 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,...)
void Warning(const char *location, const char *msgfmt,...)
void Fatal(const char *location, const char *msgfmt,...)
char name[80]
Definition: TGX11.cxx:109
int type
Definition: TGX11.cxx:120
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:41
@ kDefault
Definition: TSystem.h:228
#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
TClingClassInfo()=delete
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
long Property() const
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 *)
RooCmdArg Layout(Double_t xmin, Double_t xmax=0.99, Double_t ymin=0.95)
Type
enumeration specifying the integration types.
const Int_t n
Definition: legend1.C:16
static double A[]
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)
Definition: TClingUtils.h:638
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 CheckDefaultConstructor(const clang::CXXRecordDecl *, const cling::Interpreter &interp)
Checks if default constructor exists and accessible.
EIOCtorCategory CheckIOConstructor(const clang::CXXRecordDecl *, const char *, const clang::CXXRecordDecl *, const cling::Interpreter &interp)
Checks IO constructor - must be public and with specified argument.
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...
Definition: StringConv.hxx:21
R__EXTERN TVirtualRWMutex * gCoreMutex
EFunctionMatchMode
Definition: TDictionary.h:159
@ kExactMatch
Definition: TDictionary.h:160
@ kConversionMatch
Definition: TDictionary.h:161
std::string InsertStd(const char *tname)
static constexpr double L
const char * Long
const char * ULong
const char * UChar
const char * Short
const char * Int
const char * UInt
const char * UShort
const char * Bool
static void output(int code)
Definition: gifencode.c:226