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