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 "ROOT/BitUtils.hxx"
55
56#include <sstream>
57#include <string>
58
59using namespace clang;
60using namespace ROOT;
61
62static std::string FullyQualifiedName(const Decl *decl) {
63 // Return the fully qualified name without worrying about normalizing it.
64 std::string buf;
65 if (const NamedDecl* ND = llvm::dyn_cast<NamedDecl>(decl)) {
66 PrintingPolicy Policy(decl->getASTContext().getPrintingPolicy());
67 llvm::raw_string_ostream stream(buf);
68 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true);
69 }
70 return buf;
71}
72
74 : TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(all),
75 fIsIter(true), fOffsetCache(0)
76{
78 interp->getCI()->getASTContext().getTranslationUnitDecl();
79 fFirstTime = true;
80 SetDecl(TU);
81}
82
83TClingClassInfo::TClingClassInfo(cling::Interpreter *interp, const char *name, bool intantiateTemplate /* = true */)
84 : TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(kTRUE), fIsIter(false),
85 fOffsetCache(0)
86{
87 const cling::LookupHelper& lh = fInterp->getLookupHelper();
88 const Type *type = nullptr;
89 const Decl *decl = lh.findScope(name,
90 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
91 : cling::LookupHelper::NoDiagnostics,
93 if (!decl) {
94 std::string buf = TClassEdit::InsertStd(name);
95 if (buf != name) {
96 decl = lh.findScope(buf,
97 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
98 : cling::LookupHelper::NoDiagnostics,
100 }
101 }
102 if (!decl && type) {
103 if (const auto *TD = type->getAsTagDecl()) {
104 decl = TD;
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), fOffsetCache(0)
120{
121 Init(tag);
122}
123
124TClingClassInfo::TClingClassInfo(cling::Interpreter *interp, const Decl *D, const Type *T)
125 : TClingDeclInfo(nullptr),
126 fInterp(interp),
127 fFirstTime(true),
128 fDescend(false),
129 fIterAll(kTRUE),
130 fIsIter(false),
131 fOffsetCache(0)
132{
133 Init(D);
134 // The type as found by the lookup, conserving typedefs like Double32_t
135 // (may be null).
136 fType = T;
137}
138
139void TClingClassInfo::AddBaseOffsetValue(const clang::Decl* decl, ptrdiff_t offset)
140{
141 // Add the offset value from this class to the non-virtual base class
142 // determined by the parameter decl.
143
145 std::unique_lock<std::mutex> lock(fOffsetCacheMutex);
146 fOffsetCache[decl] = std::make_pair(offset, executableFunc);
147}
148
150{
151 if (!IsValid()) {
152 return 0L;
153 }
154 long property = 0L;
155 const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(GetDecl());
156
157 // isAbstract and other calls can trigger deserialization
158 cling::Interpreter::PushTransactionRAII RAII(fInterp);
159
160 if (!RD) {
161 // We are an enum or namespace.
162 // The cint interface always returns 0L for these guys.
163 return property;
164 }
165 if (RD->isUnion()) {
166 // The cint interface always returns 0L for these guys.
167 return property;
168 }
169 // We now have a class or a struct.
170 const CXXRecordDecl *CRD =
171 llvm::dyn_cast<CXXRecordDecl>(GetDecl());
172 if (!CRD)
173 return property;
174 property |= kClassIsValid;
175 if (CRD->isAbstract()) {
176 property |= kClassIsAbstract;
177 }
178 if (CRD->hasUserDeclaredConstructor()) {
179 property |= kClassHasExplicitCtor;
180 }
181 if (
182 !CRD->hasUserDeclaredConstructor() &&
183 !CRD->hasTrivialDefaultConstructor()
184 ) {
185 property |= kClassHasImplicitCtor;
186 }
187 if (
188 CRD->hasUserProvidedDefaultConstructor() ||
189 !CRD->hasTrivialDefaultConstructor()
190 ) {
191 property |= kClassHasDefaultCtor;
192 }
193 if (CRD->hasUserDeclaredDestructor()) {
194 property |= kClassHasExplicitDtor;
195 }
196 else if (!CRD->hasTrivialDestructor()) {
197 property |= kClassHasImplicitDtor;
198 }
199 if (CRD->hasUserDeclaredCopyAssignment()) {
200 property |= kClassHasAssignOpr;
201 }
202 if (CRD->isPolymorphic()) {
203 property |= kClassHasVirtual;
204 }
205 if (CRD->isAggregate() || CRD->isPOD()) {
206 // according to the C++ standard, being a POD implies being an aggregate
207 property |= kClassIsAggregate;
208 }
209 if (CRD->hasDefinition() && fInterp->getSema().IsCXXTriviallyRelocatableType(*CRD)) {
210 // Trivial relocatability in the C++26 sense ([class.prop]), as computed by
211 // Sema. This is more accurate than isTriviallyCopyable(): every trivially
212 // copyable class is trivially relocatable, but not vice versa -- e.g. a
213 // polymorphic class whose bases and members are all trivially relocatable.
215 }
216 return property;
217}
218
220{
221 // Invoke operator delete on a pointer to an object
222 // of this class type.
223 if (!IsValid()) {
224 Error("TClingClassInfo::Delete()", "Called while invalid!");
225 return;
226 }
227 if (!IsLoaded()) {
228 Error("TClingClassInfo::Delete()", "Class is not loaded: %s",
229 FullyQualifiedName(GetDecl()).c_str());
230 return;
231 }
233 cf.ExecDestructor(this, arena, /*nary=*/0, /*withFree=*/true);
234}
235
237{
238 // Invoke operator delete[] on a pointer to an array object
239 // of this class type.
240 if (!IsLoaded()) {
241 return;
242 }
243 if (dtorOnly) {
244 // There is no syntax in C++ for invoking the placement delete array
245 // operator, so we have to placement destroy each element by hand.
246 // Unfortunately we do not know how many elements to delete.
247 //TClingCallFunc cf(fInterp);
248 //cf.ExecDestructor(this, arena, nary, /*withFree=*/false);
249 Error("DeleteArray", "Placement delete of an array is unsupported!\n");
250 return;
251 }
253 cf.ExecDestructor(this, arena, /*nary=*/1, /*withFree=*/true);
254}
255
257{
258 // Invoke placement operator delete on a pointer to an array object
259 // of this class type.
260 if (!IsLoaded()) {
261 return;
262 }
264 cf.ExecDestructor(this, arena, /*nary=*/0, /*withFree=*/false);
265}
266
268{
269 // Return any method or function in this scope with the name 'fname'.
270
271 if (!IsLoaded()) {
272 return nullptr;
273 }
274
275 if (fType) {
276 const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
277 if (TT) {
278 llvm::StringRef tname(TT->getDecl()->getName());
279 if (tname == fname) {
280 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(GetDecl());
281 if (ndecl && ndecl->getName() != fname) {
282 // Constructor name matching the typedef type, use the decl name instead.
283 return GetFunctionTemplate(ndecl->getName().str().c_str());
284 }
285 }
286 }
287 }
288 const cling::LookupHelper &lh = fInterp->getLookupHelper();
289 const FunctionTemplateDecl *fd
290 = lh.findFunctionTemplate(GetDecl(), fname,
291 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
292 : cling::LookupHelper::NoDiagnostics, false);
293 if (fd) return fd->getCanonicalDecl();
294 return nullptr;
295}
296
297const clang::ValueDecl *TClingClassInfo::GetDataMember(const char *name) const
298{
299 // Return the value decl (if any) corresponding to a data member which
300 // the given name declared in this scope.
301
302 const cling::LookupHelper &lh = fInterp->getLookupHelper();
303 const ValueDecl *vd
304 = lh.findDataMember(GetDecl(), name,
305 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
306 : cling::LookupHelper::NoDiagnostics);
307 if (vd) return llvm::dyn_cast<ValueDecl>(vd->getCanonicalDecl());
308 else return nullptr;
309}
310
312{
313 // Return any method or function in this scope with the name 'fname'.
314
315 if (!IsLoaded()) {
317 return tmi;
318 }
319
321
322 if (fType) {
323 const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
324 if (TT) {
325 llvm::StringRef tname(TT->getDecl()->getName());
326 if (tname == fname) {
327 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(GetDecl());
328 if (ndecl && ndecl->getName() != fname) {
329 // Constructor name matching the typedef type, use the decl name instead.
330 return GetMethod(ndecl->getName().str().c_str());
331 }
332 }
333 }
334 }
335 const cling::LookupHelper &lh = fInterp->getLookupHelper();
336 const FunctionDecl *fd
337 = lh.findAnyFunction(GetDecl(), fname,
338 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
339 : cling::LookupHelper::NoDiagnostics,
340 false);
341 if (!fd) {
342 // Function not found.
344 return tmi;
345 }
347 tmi.Init(fd);
348 return tmi;
349}
350
352 const char *proto, Longptr_t *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
353 EInheritanceMode imode /*= kWithInheritance*/) const
354{
355 return GetMethod(fname,proto,false,poffset,mode,imode);
356}
357
359 const char *proto, bool objectIsConst,
360 Longptr_t *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
361 EInheritanceMode imode /*= kWithInheritance*/) const
362{
363 if (poffset) {
364 *poffset = 0L;
365 }
366 if (!IsLoaded()) {
368 return tmi;
369 }
370
372
373 if (fType) {
374 const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
375 if (TT) {
376 llvm::StringRef tname(TT->getDecl()->getName());
377 if (tname == fname) {
378 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(GetDecl());
379 if (ndecl && ndecl->getName() != fname) {
380 // Constructor name matching the typedef type, use the decl name instead.
381 return GetMethod(ndecl->getName().str().c_str(),proto,
383 mode,imode);
384 }
385 }
386 }
387
388 }
389 const cling::LookupHelper& lh = fInterp->getLookupHelper();
390 const FunctionDecl *fd;
391 if (mode == kConversionMatch) {
392 fd = lh.findFunctionProto(GetDecl(), fname, proto,
393 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
394 : cling::LookupHelper::NoDiagnostics,
396 } else if (mode == kExactMatch) {
397 fd = lh.matchFunctionProto(GetDecl(), fname, proto,
398 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
399 : cling::LookupHelper::NoDiagnostics,
401 } else {
402 Error("TClingClassInfo::GetMethod",
403 "The MatchMode %d is not supported.", mode);
405 return tmi;
406 }
407 if (!fd) {
408 // Function not found.
410 return tmi;
411 }
413 // If requested, check whether fd is a member function of this class.
414 // Even though this seems to be the wrong order (we should not allow the
415 // lookup to even collect candidates from the base) it does the right
416 // thing: if any function overload exists in the derived class, all
417 // (but explicitly used) will be hidden. Thus we will only find the
418 // derived class's function overloads (or used, which is fine). Only
419 // if there is none will we find those from the base, in which case
420 // we will reject them here:
421 const clang::DeclContext* ourDC = llvm::dyn_cast<clang::DeclContext>(GetDecl());
422 if (!fd->getDeclContext()->Equals(ourDC)
423 && !(fd->getDeclContext()->isTransparentContext()
424 && fd->getDeclContext()->getParent()->Equals(ourDC)))
426
427 // The offset must be 0 - the function must be ours.
428 if (poffset) *poffset = 0;
429 } else {
430 if (poffset) {
431 // We have been asked to return a this pointer adjustment.
432 if (const CXXMethodDecl *md =
433 llvm::dyn_cast<CXXMethodDecl>(fd)) {
434 // This is a class member function.
435 *poffset = GetOffset(md);
436 }
437 }
438 }
440 tmi.Init(fd);
441 return tmi;
442}
443
445 const llvm::SmallVectorImpl<clang::QualType> &proto,
446 Longptr_t *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
447 EInheritanceMode imode /*= kWithInheritance*/) const
448{
449 return GetMethod(fname,proto,false,poffset,mode,imode);
450}
451
453 const llvm::SmallVectorImpl<clang::QualType> &proto, bool objectIsConst,
454 Longptr_t *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
455 EInheritanceMode imode /*= kWithInheritance*/) const
456{
457 if (poffset) {
458 *poffset = 0L;
459 }
460 if (!IsLoaded()) {
462 return tmi;
463 }
464
466
467 if (fType) {
468 const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
469 if (TT) {
470 llvm::StringRef tname(TT->getDecl()->getName());
471 if (tname == fname) {
472 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(GetDecl());
473 if (ndecl && ndecl->getName() != fname) {
474 // Constructor name matching the typedef type, use the decl name instead.
475 return GetMethod(ndecl->getName().str().c_str(),proto,objectIsConst,poffset,
476 mode,imode);
477 }
478 }
479 }
480
481 }
482 const cling::LookupHelper& lh = fInterp->getLookupHelper();
483 const FunctionDecl *fd;
484 if (mode == kConversionMatch) {
485 fd = lh.findFunctionProto(GetDecl(), fname, proto,
486 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
487 : cling::LookupHelper::NoDiagnostics,
489 } else if (mode == kExactMatch) {
490 fd = lh.matchFunctionProto(GetDecl(), fname, proto,
491 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
492 : cling::LookupHelper::NoDiagnostics,
494 } else {
495 Error("TClingClassInfo::GetMethod",
496 "The MatchMode %d is not supported.", mode);
498 return tmi;
499 }
500 if (!fd) {
501 // Function not found.
503 return tmi;
504 }
505 if (poffset) {
506 // We have been asked to return a this pointer adjustment.
507 if (const CXXMethodDecl *md =
508 llvm::dyn_cast<CXXMethodDecl>(fd)) {
509 // This is a class member function.
510 *poffset = GetOffset(md);
511 }
512 }
514 tmi.Init(fd);
515 return tmi;
516}
517
519 const char *arglist, Longptr_t *poffset, EFunctionMatchMode mode /* = kConversionMatch*/,
520 EInheritanceMode imode /* = kWithInheritance*/) const
521{
523}
524
526 const char *arglist, bool objectIsConst,
527 Longptr_t *poffset, EFunctionMatchMode /*mode = kConversionMatch*/,
528 EInheritanceMode /* imode = kWithInheritance*/) const
529{
530
532
533 if (fType) {
534 const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
535 if (TT) {
536 llvm::StringRef tname(TT->getDecl()->getName());
537 if (tname == fname) {
538 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(GetDecl());
539 if (ndecl && ndecl->getName() != fname) {
540 // Constructor name matching the typedef type, use the decl name instead.
541 return GetMethod(ndecl->getName().str().c_str(),arglist,
543 /* ,mode,imode */);
544 }
545 }
546 }
547
548 }
549 if (poffset) {
550 *poffset = 0L;
551 }
552 if (!IsLoaded()) {
554 return tmi;
555 }
556 if (!strcmp(arglist, ")")) {
557 // CINT accepted a single right paren as meaning no arguments.
558 arglist = "";
559 }
560 const cling::LookupHelper &lh = fInterp->getLookupHelper();
561 const FunctionDecl *fd
562 = lh.findFunctionArgs(GetDecl(), fname, arglist,
563 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
564 : cling::LookupHelper::NoDiagnostics,
566 if (!fd) {
567 // Function not found.
569 return tmi;
570 }
571 if (poffset) {
572 // We have been asked to return a this pointer adjustment.
573 if (const CXXMethodDecl *md =
574 llvm::dyn_cast<CXXMethodDecl>(fd)) {
575 // This is a class member function.
576 *poffset = GetOffset(md);
577 }
578 }
580 tmi.Init(fd);
581 return tmi;
582}
583
584int TClingClassInfo::GetMethodNArg(const char *method, const char *proto,
586 EFunctionMatchMode mode /*= kConversionMatch*/) const
587{
588 // Note: Used only by TQObject.cxx:170 and only for interpreted classes.
589 if (!IsLoaded()) {
590 return -1;
591 }
592
594
596 int clang_val = -1;
597 if (mi.IsValid()) {
598 unsigned num_params = mi.GetTargetFunctionDecl()->getNumParams();
599 clang_val = static_cast<int>(num_params);
600 }
601 return clang_val;
602}
603
605{
606
608
609 Longptr_t offset = 0L;
610 const CXXRecordDecl* definer = md->getParent();
611 const CXXRecordDecl* accessor =
612 llvm::cast<CXXRecordDecl>(GetDecl());
613 if (definer != accessor) {
614 // This function may not be accessible using a pointer
615 // to the declaring class, get the adjustment necessary
616 // to convert that to a pointer to the defining class.
617 TClingBaseClassInfo bi(fInterp, const_cast<TClingClassInfo*>(this));
618 while (bi.Next(0)) {
619 TClingClassInfo* bci = bi.GetBase();
620 if (bci->GetDecl() == definer) {
621 // We have found the right base class, now get the
622 // necessary adjustment.
623 offset = bi.Offset();
624 break;
625 }
626 }
627 }
628 return offset;
629}
630
632{
633
634 {
635 std::unique_lock<std::mutex> lock(fOffsetCacheMutex);
636
637 // Check for the offset in the cache.
638 auto iter = fOffsetCache.find(base->GetDecl());
639 if (iter != fOffsetCache.end()) {
640 std::pair<ptrdiff_t, OffsetPtrFunc_t> offsetCache = (*iter).second;
642 if (address) {
643 return (*executableFunc)(address, isDerivedObject);
644 }
645 else {
646 Error("TClingBaseClassInfo::Offset", "The address of the object for virtual base offset calculation is not valid.");
647 return -1;
648 }
649 }
650 else {
651 return offsetCache.first;
652 }
653 }
654 }
655
656 // Compute the offset.
658 TClingBaseClassInfo binfo(fInterp, this, base);
659 return binfo.Offset(address, isDerivedObject);
660}
661
662std::vector<std::string> TClingClassInfo::GetUsingNamespaces()
663{
664 // Find and return all 'using' declarations of namespaces.
665 std::vector<std::string> res;
666
668
669 cling::Interpreter::PushTransactionRAII RAII(fInterp);
670 const auto DC = dyn_cast<DeclContext>(fDecl);
671 if (!DC)
672 return res;
673
674 clang::PrintingPolicy policy(fDecl->getASTContext().getPrintingPolicy());
675 for (auto UD : DC->using_directives()) {
676 NamespaceDecl *NS = UD->getNominatedNamespace();
677 if (NS) {
678 std::string nsName;
679 llvm::raw_string_ostream stream(nsName);
680
681 NS->getNameForDiagnostic(stream, policy, /*Qualified=*/true);
682
683 stream.flush();
684 res.push_back(nsName);
685 }
686 }
687
688 return res;
689}
690
692{
693 // Return true if there a constructor taking no arguments (including
694 // a constructor that has defaults for all of its arguments) which
695 // is callable. Either it has a body, or it is trivial and the
696 // compiler elides it.
697 //
698 // Note: This is could enhanced to also know about the ROOT ioctor
699 // but this was not the case in CINT.
700 //
701
702 using namespace ROOT::TMetaUtils;
703
704 if (!IsLoaded())
705 return EIOCtorCategory::kAbsent;
706
707 auto CRD = llvm::dyn_cast<CXXRecordDecl>(GetDecl());
708 // Namespaces do not have constructors.
709 if (!CRD)
710 return EIOCtorCategory::kAbsent;
711
712 if (checkio) {
713 auto kind = CheckIOConstructor(CRD, "TRootIOCtor", nullptr, *fInterp);
714 if ((kind == EIOCtorCategory::kIORefType) || (kind == EIOCtorCategory::kIOPtrType)) {
715 if (type_name) *type_name = "TRootIOCtor";
716 return kind;
717 }
718
719 kind = CheckIOConstructor(CRD, "__void__", nullptr, *fInterp);
720 if (kind == EIOCtorCategory::kIORefType) {
721 if (type_name) *type_name = "__void__";
722 return kind;
723 }
724 }
725
726 return CheckDefaultConstructor(CRD, *fInterp) ? EIOCtorCategory::kDefault : EIOCtorCategory::kAbsent;
727}
728
729bool TClingClassInfo::HasMethod(const char *name) const
730{
732 if (IsLoaded() && !llvm::isa<EnumDecl>(GetDecl())) {
733 return fInterp->getLookupHelper()
734 .hasFunction(GetDecl(), name,
735 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
736 : cling::LookupHelper::NoDiagnostics);
737 }
738 return false;
739}
740
742{
743 fFirstTime = true;
744 fDescend = false;
745 fIsIter = false;
746 fIter = DeclContext::decl_iterator();
747 SetDecl(nullptr);
748 fType = nullptr;
749 fIterStack.clear();
750 const cling::LookupHelper& lh = fInterp->getLookupHelper();
751 SetDecl(lh.findScope(name, gDebug > 5 ? cling::LookupHelper::WithDiagnostics
752 : cling::LookupHelper::NoDiagnostics,
753 &fType, /* intantiateTemplate= */ true ));
754 if (!GetDecl()) {
755 std::string buf = TClassEdit::InsertStd(name);
756 if (buf != name) {
757 SetDecl(lh.findScope(buf, gDebug > 5 ? cling::LookupHelper::WithDiagnostics
758 : cling::LookupHelper::NoDiagnostics,
759 &fType, /* intantiateTemplate= */ true ));
760 }
761 }
762 if (!GetDecl() && fType) {
763 if (const auto *TD = fType->getAsTagDecl()) {
764 SetDecl(TD);
765 }
766 }
767}
768
770{
771 fFirstTime = true;
772 fDescend = false;
773 fIsIter = false;
774 fIter = DeclContext::decl_iterator();
775 SetDecl(decl);
776 fType = nullptr;
777 fIterStack.clear();
778}
779
781{
782 Fatal("TClingClassInfo::Init(tagnum)", "Should no longer be called");
783 return;
784}
785
786void TClingClassInfo::Init(const Type &tag)
787{
788 fType = &tag;
789
791
792 if (const auto *TD = fType->getAsTagDecl()) {
793 SetDecl(TD);
794 } else {
795 SetDecl(nullptr);
796 }
797 if (!GetDecl()) {
798 QualType qType(fType,0);
799 static PrintingPolicy printPol(fInterp->getCI()->getLangOpts());
800 printPol.SuppressScope = false;
801 Error("TClingClassInfo::Init(const Type&)",
802 "The given type %s does not point to a Decl",
803 qType.getAsString(printPol).c_str());
804 }
805}
806
807bool TClingClassInfo::IsBase(const char *name) const
808{
809 if (!IsLoaded()) {
810 return false;
811 }
813 if (!base.IsValid()) {
814 return false;
815 }
816
818
819 const CXXRecordDecl *CRD =
820 llvm::dyn_cast<CXXRecordDecl>(GetDecl());
821 if (!CRD) {
822 // We are an enum, namespace, or translation unit,
823 // we cannot be the base of anything.
824 return false;
825 }
826 const CXXRecordDecl *baseCRD =
827 llvm::dyn_cast<CXXRecordDecl>(base.GetDecl());
828 return CRD->isDerivedFrom(baseCRD);
829}
830
831bool TClingClassInfo::IsEnum(cling::Interpreter *interp, const char *name)
832{
834 // Note: This is a static member function.
836 if (info.IsValid() && (info.Property() & kIsEnum)) {
837 return true;
838 }
839 return false;
840}
841
843{
844 if (auto *ED = llvm::dyn_cast<clang::EnumDecl>(GetDecl()))
845 return ED->isScoped();
846 return false;
847}
848
850{
851 if (!IsValid())
852 return kNumDataTypes;
853 if (GetDecl() == nullptr)
854 return kNumDataTypes;
855
856 if (auto ED = llvm::dyn_cast<EnumDecl>(GetDecl())) {
858 auto Ty = ED->getIntegerType().getTypePtrOrNull();
859 if (Ty)
860 Ty = Ty->getUnqualifiedDesugaredType();
861 if (auto BTy = llvm::dyn_cast_or_null<BuiltinType>(Ty)) {
862 switch (BTy->getKind()) {
863 case BuiltinType::Bool:
864 return kBool_t;
865
866 case BuiltinType::Char_U:
867 case BuiltinType::UChar:
868 return kUChar_t;
869
870 case BuiltinType::Char_S:
871 case BuiltinType::SChar:
872 return kChar_t;
873
874 case BuiltinType::UShort:
875 return kUShort_t;
876 case BuiltinType::Short:
877 return kShort_t;
878 case BuiltinType::UInt:
879 return kUInt_t;
880 case BuiltinType::Int:
881 return kInt_t;
882 case BuiltinType::ULong:
883 return kULong_t;
884 case BuiltinType::Long:
885 return kLong_t;
886 case BuiltinType::ULongLong:
887 return kULong64_t;
888 case BuiltinType::LongLong:
889 return kLong64_t;
890 default:
891 return kNumDataTypes;
892 };
893 }
894 }
895 return kNumDataTypes;
896}
897
898
900{
901 // IsLoaded in CINT was meaning is known to the interpreter
902 // and has a complete definition.
903 // IsValid in Cling (as in CING) means 'just' is known to the
904 // interpreter.
905 if (!IsValid()) {
906 return false;
907 }
908 if (GetDecl() == nullptr) {
909 return false;
910 }
911
913
914 const CXXRecordDecl *CRD = llvm::dyn_cast<CXXRecordDecl>(GetDecl());
915 if ( CRD ) {
916 if (!CRD->hasDefinition()) {
917 return false;
918 }
919 } else {
920 const TagDecl *TD = llvm::dyn_cast<TagDecl>(GetDecl());
921 if (TD && TD->getDefinition() == nullptr) {
922 return false;
923 }
924 }
925 // All clang classes are considered loaded.
926 return true;
927}
928
929bool TClingClassInfo::IsValidMethod(const char *method, const char *proto,
932 EFunctionMatchMode mode /*= kConversionMatch*/) const
933{
934 // Check if the method with the given prototype exist.
935 if (!IsLoaded()) {
936 return false;
937 }
938 if (offset) {
939 *offset = 0L;
940 }
942 return mi.IsValid();
943}
944
946{
948
949 fDeclFileName.clear(); // invalidate decl file name.
950 fNameCache.clear(); // invalidate the cache.
951
952 cling::Interpreter::PushTransactionRAII RAII(fInterp);
953 if (fFirstTime) {
954 // GetDecl() must be a DeclContext in order to iterate.
955 const clang::DeclContext *DC = cast<DeclContext>(GetDecl());
956 if (fIterAll)
957 fIter = DC->decls_begin();
958 else
959 fIter = DC->noload_decls_begin();
960 }
961
962 if (!fIsIter) {
963 // Object was not setup for iteration.
964 if (GetDecl()) {
965 std::string buf;
966 if (const NamedDecl* ND =
967 llvm::dyn_cast<NamedDecl>(GetDecl())) {
970 llvm::raw_string_ostream stream(buf);
971 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/false);
972 }
973 Error("TClingClassInfo::InternalNext",
974 "Next called but iteration not prepared for %s!", buf.c_str());
975 } else {
976 Error("TClingClassInfo::InternalNext",
977 "Next called but iteration not prepared!");
978 }
979 return 0;
980 }
981 while (true) {
982 // Advance to next usable decl, or return if there is no next usable decl.
983 if (fFirstTime) {
984 // The cint semantics are strange.
985 fFirstTime = false;
986 if (!*fIter) {
987 return 0;
988 }
989 }
990 else {
991 // Advance the iterator one decl, descending into the current decl
992 // context if necessary.
993 if (!fDescend) {
994 // Do not need to scan the decl context of the current decl,
995 // move on to the next decl.
996 ++fIter;
997 }
998 else {
999 // Descend into the decl context of the current decl.
1000 fDescend = false;
1001 //fprintf(stderr,
1002 // "TClingClassInfo::InternalNext: "
1003 // "pushing ...\n");
1004 fIterStack.push_back(fIter);
1005 DeclContext *DC = llvm::cast<DeclContext>(*fIter);
1006 if (fIterAll)
1007 fIter = DC->decls_begin();
1008 else
1009 fIter = DC->noload_decls_begin();
1010 }
1011 // Fix it if we went past the end.
1012 while (!*fIter && fIterStack.size()) {
1013 //fprintf(stderr,
1014 // "TClingClassInfo::InternalNext: "
1015 // "popping ...\n");
1016 fIter = fIterStack.back();
1017 fIterStack.pop_back();
1018 ++fIter;
1019 }
1020 // Check for final termination.
1021 if (!*fIter) {
1022 // We have reached the end of the translation unit, all done.
1023 SetDecl(nullptr);
1024 fType = nullptr;
1025 return 0;
1026 }
1027 }
1028 // Return if this decl is a class, struct, union, enum, or namespace.
1029 Decl::Kind DK = fIter->getKind();
1030 if ((DK == Decl::Namespace) || (DK == Decl::Enum) ||
1031 (DK == Decl::CXXRecord) ||
1032 (DK == Decl::ClassTemplateSpecialization)) {
1033 const TagDecl *TD = llvm::dyn_cast<TagDecl>(*fIter);
1034 if (TD && !TD->isCompleteDefinition()) {
1035 // For classes and enums, stop only on definitions.
1036 continue;
1037 }
1038 if (DK == Decl::Namespace) {
1039 // For namespaces, stop only on the first definition.
1040 if (!fIter->isCanonicalDecl()) {
1041 // Not the first definition.
1042 fDescend = true;
1043 continue;
1044 }
1045 }
1046 if (DK != Decl::Enum) {
1047 // We do not descend into enums.
1048 DeclContext *DC = llvm::cast<DeclContext>(*fIter);
1049 if ((fIterAll && *DC->decls_begin())
1050 || (!fIterAll && *DC->noload_decls_begin())) {
1051 // Next iteration will begin scanning the decl context
1052 // contained by this decl.
1053 fDescend = true;
1054 }
1055 }
1056 // Iterator is now valid.
1057 SetDecl(*fIter);
1058 fType = nullptr;
1059 if (GetDecl()) {
1060 if (GetDecl()->isInvalidDecl()) {
1061 Warning("TClingClassInfo::Next()","Reached an invalid decl.");
1062 }
1063 if (const RecordDecl *RD =
1064 llvm::dyn_cast<RecordDecl>(GetDecl())) {
1065 fType = RD->getASTContext().getCanonicalTagType(RD).getTypePtr();
1066 }
1067 }
1068 return 1;
1069 }
1070 }
1071}
1072
1074{
1075 return InternalNext();
1076}
1077
1079{
1080 // Invoke a new expression to use the class constructor
1081 // that takes no arguments to create an object of this class type.
1082 if (!IsValid()) {
1083 Error("TClingClassInfo::New()", "Called while invalid!");
1084 return nullptr;
1085 }
1086 if (!IsLoaded()) {
1087 Error("TClingClassInfo::New()", "Class is not loaded: %s",
1088 FullyQualifiedName(GetDecl()).c_str());
1089 return nullptr;
1090 }
1091
1093 std::string type_name;
1094
1095 {
1098 if (!RD) {
1099 Error("TClingClassInfo::New()", "This is a namespace!: %s",
1100 FullyQualifiedName(GetDecl()).c_str());
1101 return nullptr;
1102 }
1103
1105
1107 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1108 // Error("TClingClassInfo::New()", "Class has no default constructor: %s",
1109 // FullyQualifiedName(GetDecl()).c_str());
1110 return nullptr;
1111 }
1112 } // End of Lock section.
1113 void* obj = nullptr;
1115 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1116 /*address=*/nullptr, /*nary=*/0);
1117 if (!obj) {
1118 Error("TClingClassInfo::New()", "Call of default constructor "
1119 "failed to return an object for class: %s",
1120 FullyQualifiedName(GetDecl()).c_str());
1121 return nullptr;
1122 }
1123 return obj;
1124}
1125
1127{
1128 // Invoke a new expression to use the class constructor
1129 // that takes no arguments to create an array object
1130 // of this class type.
1131 if (!IsValid()) {
1132 Error("TClingClassInfo::New(n)", "Called while invalid!");
1133 return nullptr;
1134 }
1135 if (!IsLoaded()) {
1136 Error("TClingClassInfo::New(n)", "Class is not loaded: %s",
1137 FullyQualifiedName(GetDecl()).c_str());
1138 return nullptr;
1139 }
1140
1142 std::string type_name;
1143
1144 {
1146
1148 if (!RD) {
1149 Error("TClingClassInfo::New(n)", "This is a namespace!: %s",
1150 FullyQualifiedName(GetDecl()).c_str());
1151 return nullptr;
1152 }
1153
1156 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1157 //Error("TClingClassInfo::New(n)",
1158 // "Class has no default constructor: %s",
1159 // FullyQualifiedName(GetDecl()).c_str());
1160 return nullptr;
1161 }
1162 } // End of Lock section.
1163 void* obj = nullptr;
1165 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1166 /*address=*/nullptr, /*nary=*/(unsigned long)n);
1167 if (!obj) {
1168 Error("TClingClassInfo::New(n)", "Call of default constructor "
1169 "failed to return an array of class: %s",
1170 FullyQualifiedName(GetDecl()).c_str());
1171 return nullptr;
1172 }
1173 return obj;
1174}
1175
1177{
1178 // Invoke a placement new expression to use the class
1179 // constructor that takes no arguments to create an
1180 // array of objects of this class type in the given
1181 // memory arena.
1182 if (!IsValid()) {
1183 Error("TClingClassInfo::New(n, arena)", "Called while invalid!");
1184 return nullptr;
1185 }
1186 if (!IsLoaded()) {
1187 Error("TClingClassInfo::New(n, arena)", "Class is not loaded: %s",
1188 FullyQualifiedName(GetDecl()).c_str());
1189 return nullptr;
1190 }
1191
1193 std::string type_name;
1194
1195 {
1197
1199 if (!RD) {
1200 Error("TClingClassInfo::New(n, arena)", "This is a namespace!: %s",
1201 FullyQualifiedName(GetDecl()).c_str());
1202 return nullptr;
1203 }
1204
1207 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1208 //Error("TClingClassInfo::New(n, arena)",
1209 // "Class has no default constructor: %s",
1210 // FullyQualifiedName(GetDecl()).c_str());
1211 return nullptr;
1212 }
1213 } // End of Lock section
1214 void* obj = nullptr;
1216 // Note: This will always return arena.
1217 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1218 /*address=*/arena, /*nary=*/(unsigned long)n);
1219 return obj;
1220}
1221
1223{
1224 // Invoke a placement new expression to use the class
1225 // constructor that takes no arguments to create an
1226 // object of this class type in the given memory arena.
1227 if (!IsValid()) {
1228 Error("TClingClassInfo::New(arena)", "Called while invalid!");
1229 return nullptr;
1230 }
1231 if (!IsLoaded()) {
1232 Error("TClingClassInfo::New(arena)", "Class is not loaded: %s",
1233 FullyQualifiedName(GetDecl()).c_str());
1234 return nullptr;
1235 }
1236
1238 std::string type_name;
1239
1240 {
1242
1244 if (!RD) {
1245 Error("TClingClassInfo::New(arena)", "This is a namespace!: %s",
1246 FullyQualifiedName(GetDecl()).c_str());
1247 return nullptr;
1248 }
1249
1252 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1253 //Error("TClingClassInfo::New(arena)",
1254 // "Class has no default constructor: %s",
1255 // FullyQualifiedName(GetDecl()).c_str());
1256 return nullptr;
1257 }
1258 } // End of Locked section.
1259 void* obj = nullptr;
1261 // Note: This will always return arena.
1262 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1263 /*address=*/arena, /*nary=*/0);
1264 return obj;
1265}
1266
1268{
1269 if (!IsValid()) {
1270 return 0L;
1271 }
1272
1274
1275 long property = 0L;
1276 property |= kIsCPPCompiled;
1277
1278 // Modules can deserialize while querying the various decls for information.
1279 cling::Interpreter::PushTransactionRAII RAII(fInterp);
1280
1281 const clang::DeclContext *ctxt = GetDecl()->getDeclContext();
1282 clang::NamespaceDecl *std_ns =fInterp->getSema().getStdNamespace();
1283 while (ctxt && ! ctxt->isTranslationUnit()) {
1284 if (ctxt->Equals(std_ns)) {
1285 property |= kIsDefinedInStd;
1286 break;
1287 }
1288 ctxt = ctxt->getParent();
1289 }
1290 Decl::Kind DK = GetDecl()->getKind();
1291 if ((DK == Decl::Namespace) || (DK == Decl::TranslationUnit)) {
1292 property |= kIsNamespace;
1293 return property;
1294 }
1295 // Note: Now we have class, enum, struct, union only.
1296 const TagDecl *TD = llvm::dyn_cast<TagDecl>(GetDecl());
1297 if (!TD) {
1298 return 0L;
1299 }
1300 if (TD->isEnum()) {
1301 property |= kIsEnum;
1302 return property;
1303 }
1304 // Note: Now we have class, struct, union only.
1305 const CXXRecordDecl *CRD =
1306 llvm::dyn_cast<CXXRecordDecl>(GetDecl());
1307 if (!CRD)
1308 return property;
1309
1310 if (CRD->isClass()) {
1311 property |= kIsClass;
1312 } else if (CRD->isStruct()) {
1313 property |= kIsStruct;
1314 } else if (CRD->isUnion()) {
1315 property |= kIsUnion;
1316 }
1317 if (CRD->hasDefinition() && CRD->isAbstract()) {
1318 property |= kIsAbstract;
1319 }
1320 return property;
1321}
1322
1324{
1325 if (!IsValid()) {
1326 return 0;
1327 }
1328 // FIXME: Implement this when rootcling provides the value.
1329 return 0;
1330}
1331
1332/// Return the size of the class in bytes as reported by clang.
1333///
1334/// Returns -1 if the class info is invalid, 0 for a forward-declared class,
1335/// an enum, or a class with no definition, and 1 for a namespace (a special
1336/// value inherited from CINT). For all other cases the actual byte size
1337/// obtained from the clang ASTRecordLayout is returned.
1339{
1340 if (!IsValid()) {
1341 return -1;
1342 }
1343 if (!GetDecl()) {
1344 // A forward declared class.
1345 return 0;
1346 }
1347
1349
1350 Decl::Kind DK = GetDecl()->getKind();
1351 if (DK == Decl::Namespace) {
1352 // Namespaces are special for cint.
1353 return 1;
1354 }
1355 else if (DK == Decl::Enum) {
1356 // Enums are special for cint.
1357 return 0;
1358 }
1359 const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(GetDecl());
1360 if (!RD) {
1361 // Should not happen.
1362 return -1;
1363 }
1364 if (!RD->getDefinition()) {
1365 // Forward-declared class.
1366 return 0;
1367 }
1368 ASTContext &Context = GetDecl()->getASTContext();
1369 cling::Interpreter::PushTransactionRAII RAII(fInterp);
1370 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1371 int64_t size = Layout.getSize().getQuantity();
1372 int clang_size = static_cast<int>(size);
1373 return clang_size;
1374}
1375
1376/// Return the alignment of the class in bytes as reported by clang.
1377///
1378/// Returns (size_t)-1 if the class info is invalid, 0 for a forward-declared
1379/// class, an enum, a namespace or or a class with no definition. For all other
1380/// cases the actual alignment obtained from the clang ASTRecordLayout is
1381/// returned.
1383{
1384 if (!IsValid()) {
1385 return -1;
1386 }
1387 if (!GetDecl()) {
1388 // A forward declared class.
1389 return 0;
1390 }
1391
1393
1394 Decl::Kind DK = GetDecl()->getKind();
1395 if (DK == Decl::Namespace) {
1396 return 0;
1397 } else if (DK == Decl::Enum) {
1398 return 0;
1399 }
1400 const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(GetDecl());
1401 if (!RD) {
1402 return -1;
1403 }
1404 if (!RD->getDefinition()) {
1405 // Forward-declared class.
1406 return 0;
1407 }
1408 ASTContext &Context = GetDecl()->getASTContext();
1409 cling::Interpreter::PushTransactionRAII RAII(fInterp);
1410 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1411 auto align = Layout.getAlignment().getQuantity();
1413 return align;
1414}
1415
1417{
1418 if (!IsValid()) {
1419 return -1L;
1420 }
1421 return reinterpret_cast<Longptr_t>(GetDecl());
1422}
1423
1425{
1426 if (!IsValid()) {
1427 return nullptr;
1428 }
1429 if (fDeclFileName.empty())
1431 return fDeclFileName.c_str();
1432}
1433
1435{
1436 // Return QualifiedName.
1437 output.clear();
1438 if (!IsValid()) {
1439 return;
1440 }
1441 if (fType) {
1442 QualType type(fType, 0);
1444 }
1445 else {
1446 if (const NamedDecl* ND =
1447 llvm::dyn_cast<NamedDecl>(GetDecl())) {
1450 llvm::raw_string_ostream stream(output);
1451 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true);
1452 }
1453 }
1454}
1455
1457{
1458 if (!IsValid()) {
1459 return nullptr;
1460 }
1461 // NOTE: We cannot cache the result, since we are really an iterator.
1462 // Try to get the comment either from the annotation or the header
1463 // file, if present.
1464 // Iterate over the redeclarations, we can have multiple definitions in the
1465 // redecl chain (came from merging of pcms).
1466
1468
1469 if (const TagDecl *TD = llvm::dyn_cast<TagDecl>(GetDecl())) {
1471 if (AnnotateAttr *A = TD->getAttr<AnnotateAttr>()) {
1472 std::string attr = A->getAnnotation().str();
1473 if (attr.find(TMetaUtils::propNames::separator) != std::string::npos) {
1475 fTitle = attr;
1476 return fTitle.c_str();
1477 }
1478 } else {
1479 fTitle = attr;
1480 return fTitle.c_str();
1481 }
1482 }
1483 }
1484 }
1485 // Try to get the comment from the header file, if present.
1486 // but not for decls from AST file, where rootcling would have
1487 // created an annotation
1488 const CXXRecordDecl *CRD =
1489 llvm::dyn_cast<CXXRecordDecl>(GetDecl());
1490 if (CRD && !CRD->isFromASTFile()) {
1492 }
1493 return fTitle.c_str();
1494}
1495
1497{
1498 if (!IsValid()) {
1499 return nullptr;
1500 }
1501
1503
1504 // Note: This *must* be static/thread_local because we are returning a pointer inside it!
1505 TTHREAD_TLS_DECL( std::string, buf);
1506 buf.clear();
1507 if (const NamedDecl* ND = llvm::dyn_cast<NamedDecl>(GetDecl())) {
1508 // Note: This does *not* include the template arguments!
1509 buf = ND->getNameAsString();
1510 }
1511 return buf.c_str(); // NOLINT
1512}
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
long Longptr_t
Integer large enough to hold a pointer (platform-dependent)
Definition RtypesCore.h:90
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
static std::string FullyQualifiedName(const Decl *decl)
ptrdiff_t(* OffsetPtrFunc_t)(void *, bool)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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
@ kClassIsAggregate
@ kClassHasImplicitCtor
@ kClassHasDefaultCtor
@ kClassIsValid
@ kClassIsAbstract
@ kClassHasVirtual
@ kClassHasExplicitDtor
@ kClassHasImplicitDtor
@ kClassIsTriviallyRelocatable
@ 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:208
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:252
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:267
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t attr
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t property
char name[80]
Definition TGX11.cxx:142
R__EXTERN TVirtualMutex * gInterpreterMutex
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:792
#define R__LOCKGUARD(mutex)
#define R__WRITE_LOCKGUARD(mutex)
Emulation of the CINT BaseClassInfo class.
Emulation of the CINT CallFunc class.
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
size_t GetAlignOf() const
Return the alignment of the class in bytes as reported by clang.
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
int Size() const
Return the size of the class in bytes as reported by clang.
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 Int_t n
Definition legend1.C:16
constexpr bool IsValidAlignment(std::size_t align) noexcept
Return true if align is a valid C++ alignment value: strictly positive and a power of two.
Definition BitUtils.hxx:36
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,...
std::string 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.
R__EXTERN TVirtualRWMutex * gCoreMutex
EFunctionMatchMode
@ kExactMatch
@ kConversionMatch
std::string InsertStd(const char *tname)