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