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