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 <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), fOffsetCache(0)
74{
75 TranslationUnitDecl *TU =
76 interp->getCI()->getASTContext().getTranslationUnitDecl();
77 fFirstTime = true;
78 SetDecl(TU);
79}
80
81TClingClassInfo::TClingClassInfo(cling::Interpreter *interp, const char *name, bool intantiateTemplate /* = true */)
82 : TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(kTRUE), fIsIter(false),
83 fOffsetCache(0)
84{
85 const cling::LookupHelper& lh = fInterp->getLookupHelper();
86 const Type *type = nullptr;
87 const Decl *decl = lh.findScope(name,
88 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
89 : cling::LookupHelper::NoDiagnostics,
90 &type, intantiateTemplate);
91 if (!decl) {
92 std::string buf = TClassEdit::InsertStd(name);
93 if (buf != name) {
94 decl = lh.findScope(buf,
95 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
96 : cling::LookupHelper::NoDiagnostics,
97 &type, intantiateTemplate);
98 }
99 }
100 if (!decl && type) {
101 const TagType *tagtype =type->getAs<TagType>();
102 if (tagtype) {
103 decl = tagtype->getDecl();
104 }
105 }
106 SetDecl(decl);
107 fType = type;
108 if (decl && decl->isInvalidDecl()) {
109 Error("TClingClassInfo", "Found an invalid decl for %s.",name);
110 SetDecl(nullptr);
111 fType = nullptr;
112 }
113}
114
115TClingClassInfo::TClingClassInfo(cling::Interpreter *interp,
116 const Type &tag)
117 : TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(kTRUE),
118 fIsIter(false), fOffsetCache(0)
119{
120 Init(tag);
121}
122
123TClingClassInfo::TClingClassInfo(cling::Interpreter *interp,
124 const Decl *D)
125 : TClingDeclInfo(nullptr), fInterp(interp), fFirstTime(true), fDescend(false), fIterAll(kTRUE),
126 fIsIter(false), fOffsetCache(0)
127{
128 Init(D);
129}
130
131void TClingClassInfo::AddBaseOffsetValue(const clang::Decl* decl, ptrdiff_t offset)
132{
133 // Add the offset value from this class to the non-virtual base class
134 // determined by the parameter decl.
135
136 OffsetPtrFunc_t executableFunc = nullptr;
137 std::unique_lock<std::mutex> lock(fOffsetCacheMutex);
138 fOffsetCache[decl] = std::make_pair(offset, executableFunc);
139}
140
142{
143 if (!IsValid()) {
144 return 0L;
145 }
146 long property = 0L;
147 const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(GetDecl());
148
149 // isAbstract and other calls can trigger deserialization
150 cling::Interpreter::PushTransactionRAII RAII(fInterp);
151
152 if (!RD) {
153 // We are an enum or namespace.
154 // The cint interface always returns 0L for these guys.
155 return property;
156 }
157 if (RD->isUnion()) {
158 // The cint interface always returns 0L for these guys.
159 return property;
160 }
161 // We now have a class or a struct.
162 const CXXRecordDecl *CRD =
163 llvm::dyn_cast<CXXRecordDecl>(GetDecl());
164 if (!CRD)
165 return property;
166 property |= kClassIsValid;
167 if (CRD->isAbstract()) {
168 property |= kClassIsAbstract;
169 }
170 if (CRD->hasUserDeclaredConstructor()) {
171 property |= kClassHasExplicitCtor;
172 }
173 if (
174 !CRD->hasUserDeclaredConstructor() &&
175 !CRD->hasTrivialDefaultConstructor()
176 ) {
177 property |= kClassHasImplicitCtor;
178 }
179 if (
180 CRD->hasUserProvidedDefaultConstructor() ||
181 !CRD->hasTrivialDefaultConstructor()
182 ) {
183 property |= kClassHasDefaultCtor;
184 }
185 if (CRD->hasUserDeclaredDestructor()) {
186 property |= kClassHasExplicitDtor;
187 }
188 else if (!CRD->hasTrivialDestructor()) {
189 property |= kClassHasImplicitDtor;
190 }
191 if (CRD->hasUserDeclaredCopyAssignment()) {
192 property |= kClassHasAssignOpr;
193 }
194 if (CRD->isPolymorphic()) {
195 property |= kClassHasVirtual;
196 }
197 return property;
198}
199
200void TClingClassInfo::Delete(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
201{
202 // Invoke operator delete on a pointer to an object
203 // of this class type.
204 if (!IsValid()) {
205 Error("TClingClassInfo::Delete()", "Called while invalid!");
206 return;
207 }
208 if (!IsLoaded()) {
209 Error("TClingClassInfo::Delete()", "Class is not loaded: %s",
210 FullyQualifiedName(GetDecl()).c_str());
211 return;
212 }
214 cf.ExecDestructor(this, arena, /*nary=*/0, /*withFree=*/true);
215}
216
217void TClingClassInfo::DeleteArray(void *arena, bool dtorOnly, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
218{
219 // Invoke operator delete[] on a pointer to an array object
220 // of this class type.
221 if (!IsLoaded()) {
222 return;
223 }
224 if (dtorOnly) {
225 // There is no syntax in C++ for invoking the placement delete array
226 // operator, so we have to placement destroy each element by hand.
227 // Unfortunately we do not know how many elements to delete.
228 //TClingCallFunc cf(fInterp);
229 //cf.ExecDestructor(this, arena, nary, /*withFree=*/false);
230 Error("DeleteArray", "Placement delete of an array is unsupported!\n");
231 return;
232 }
234 cf.ExecDestructor(this, arena, /*nary=*/1, /*withFree=*/true);
235}
236
237void TClingClassInfo::Destruct(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
238{
239 // Invoke placement operator delete on a pointer to an array object
240 // of this class type.
241 if (!IsLoaded()) {
242 return;
243 }
245 cf.ExecDestructor(this, arena, /*nary=*/0, /*withFree=*/false);
246}
247
248const FunctionTemplateDecl *TClingClassInfo::GetFunctionTemplate(const char *fname) const
249{
250 // Return any method or function in this scope with the name 'fname'.
251
252 if (!IsLoaded()) {
253 return nullptr;
254 }
255
256 if (fType) {
257 const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
258 if (TT) {
259 llvm::StringRef tname(TT->getDecl()->getName());
260 if (tname.equals(fname)) {
261 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(GetDecl());
262 if (ndecl && !ndecl->getName().equals(fname)) {
263 // Constructor name matching the typedef type, use the decl name instead.
264 return GetFunctionTemplate(ndecl->getName().str().c_str());
265 }
266 }
267 }
268 }
269 const cling::LookupHelper &lh = fInterp->getLookupHelper();
270 const FunctionTemplateDecl *fd
271 = lh.findFunctionTemplate(GetDecl(), fname,
272 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
273 : cling::LookupHelper::NoDiagnostics, false);
274 if (fd) return fd->getCanonicalDecl();
275 return nullptr;
276}
277
278const clang::ValueDecl *TClingClassInfo::GetDataMember(const char *name) const
279{
280 // Return the value decl (if any) corresponding to a data member which
281 // the given name declared in this scope.
282
283 const cling::LookupHelper &lh = fInterp->getLookupHelper();
284 const ValueDecl *vd
285 = lh.findDataMember(GetDecl(), name,
286 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
287 : cling::LookupHelper::NoDiagnostics);
288 if (vd) return llvm::dyn_cast<ValueDecl>(vd->getCanonicalDecl());
289 else return nullptr;
290}
291
293{
294 // Return any method or function in this scope with the name 'fname'.
295
296 if (!IsLoaded()) {
298 return tmi;
299 }
300
302
303 if (fType) {
304 const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
305 if (TT) {
306 llvm::StringRef tname(TT->getDecl()->getName());
307 if (tname.equals(fname)) {
308 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(GetDecl());
309 if (ndecl && !ndecl->getName().equals(fname)) {
310 // Constructor name matching the typedef type, use the decl name instead.
311 return GetMethod(ndecl->getName().str().c_str());
312 }
313 }
314 }
315 }
316 const cling::LookupHelper &lh = fInterp->getLookupHelper();
317 const FunctionDecl *fd
318 = lh.findAnyFunction(GetDecl(), fname,
319 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
320 : cling::LookupHelper::NoDiagnostics,
321 false);
322 if (!fd) {
323 // Function not found.
325 return tmi;
326 }
328 tmi.Init(fd);
329 return tmi;
330}
331
333 const char *proto, Longptr_t *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
334 EInheritanceMode imode /*= kWithInheritance*/) const
335{
336 return GetMethod(fname,proto,false,poffset,mode,imode);
337}
338
340 const char *proto, bool objectIsConst,
341 Longptr_t *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
342 EInheritanceMode imode /*= kWithInheritance*/) const
343{
344 if (poffset) {
345 *poffset = 0L;
346 }
347 if (!IsLoaded()) {
349 return tmi;
350 }
351
353
354 if (fType) {
355 const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
356 if (TT) {
357 llvm::StringRef tname(TT->getDecl()->getName());
358 if (tname.equals(fname)) {
359 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(GetDecl());
360 if (ndecl && !ndecl->getName().equals(fname)) {
361 // Constructor name matching the typedef type, use the decl name instead.
362 return GetMethod(ndecl->getName().str().c_str(),proto,
363 objectIsConst,poffset,
364 mode,imode);
365 }
366 }
367 }
368
369 }
370 const cling::LookupHelper& lh = fInterp->getLookupHelper();
371 const FunctionDecl *fd;
372 if (mode == kConversionMatch) {
373 fd = lh.findFunctionProto(GetDecl(), fname, proto,
374 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
375 : cling::LookupHelper::NoDiagnostics,
376 objectIsConst);
377 } else if (mode == kExactMatch) {
378 fd = lh.matchFunctionProto(GetDecl(), fname, proto,
379 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
380 : cling::LookupHelper::NoDiagnostics,
381 objectIsConst);
382 } else {
383 Error("TClingClassInfo::GetMethod",
384 "The MatchMode %d is not supported.", mode);
386 return tmi;
387 }
388 if (!fd) {
389 // Function not found.
391 return tmi;
392 }
393 if (imode == TClingClassInfo::kInThisScope) {
394 // If requested, check whether fd is a member function of this class.
395 // Even though this seems to be the wrong order (we should not allow the
396 // lookup to even collect candidates from the base) it does the right
397 // thing: if any function overload exists in the derived class, all
398 // (but explicitly used) will be hidden. Thus we will only find the
399 // derived class's function overloads (or used, which is fine). Only
400 // if there is none will we find those from the base, in which case
401 // we will reject them here:
402 const clang::DeclContext* ourDC = llvm::dyn_cast<clang::DeclContext>(GetDecl());
403 if (!fd->getDeclContext()->Equals(ourDC)
404 && !(fd->getDeclContext()->isTransparentContext()
405 && fd->getDeclContext()->getParent()->Equals(ourDC)))
407
408 // The offset must be 0 - the function must be ours.
409 if (poffset) *poffset = 0;
410 } else {
411 if (poffset) {
412 // We have been asked to return a this pointer adjustment.
413 if (const CXXMethodDecl *md =
414 llvm::dyn_cast<CXXMethodDecl>(fd)) {
415 // This is a class member function.
416 *poffset = GetOffset(md);
417 }
418 }
419 }
421 tmi.Init(fd);
422 return tmi;
423}
424
426 const llvm::SmallVectorImpl<clang::QualType> &proto,
427 Longptr_t *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
428 EInheritanceMode imode /*= kWithInheritance*/) const
429{
430 return GetMethod(fname,proto,false,poffset,mode,imode);
431}
432
434 const llvm::SmallVectorImpl<clang::QualType> &proto, bool objectIsConst,
435 Longptr_t *poffset, EFunctionMatchMode mode /*= kConversionMatch*/,
436 EInheritanceMode imode /*= kWithInheritance*/) const
437{
438 if (poffset) {
439 *poffset = 0L;
440 }
441 if (!IsLoaded()) {
443 return tmi;
444 }
445
447
448 if (fType) {
449 const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
450 if (TT) {
451 llvm::StringRef tname(TT->getDecl()->getName());
452 if (tname.equals(fname)) {
453 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(GetDecl());
454 if (ndecl && !ndecl->getName().equals(fname)) {
455 // Constructor name matching the typedef type, use the decl name instead.
456 return GetMethod(ndecl->getName().str().c_str(),proto,objectIsConst,poffset,
457 mode,imode);
458 }
459 }
460 }
461
462 }
463 const cling::LookupHelper& lh = fInterp->getLookupHelper();
464 const FunctionDecl *fd;
465 if (mode == kConversionMatch) {
466 fd = lh.findFunctionProto(GetDecl(), fname, proto,
467 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
468 : cling::LookupHelper::NoDiagnostics,
469 objectIsConst);
470 } else if (mode == kExactMatch) {
471 fd = lh.matchFunctionProto(GetDecl(), fname, proto,
472 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
473 : cling::LookupHelper::NoDiagnostics,
474 objectIsConst);
475 } else {
476 Error("TClingClassInfo::GetMethod",
477 "The MatchMode %d is not supported.", mode);
479 return tmi;
480 }
481 if (!fd) {
482 // Function not found.
484 return tmi;
485 }
486 if (poffset) {
487 // We have been asked to return a this pointer adjustment.
488 if (const CXXMethodDecl *md =
489 llvm::dyn_cast<CXXMethodDecl>(fd)) {
490 // This is a class member function.
491 *poffset = GetOffset(md);
492 }
493 }
495 tmi.Init(fd);
496 return tmi;
497}
498
500 const char *arglist, Longptr_t *poffset, EFunctionMatchMode mode /* = kConversionMatch*/,
501 EInheritanceMode imode /* = kWithInheritance*/) const
502{
503 return GetMethodWithArgs(fname,arglist,false,poffset,mode,imode);
504}
505
507 const char *arglist, bool objectIsConst,
508 Longptr_t *poffset, EFunctionMatchMode /*mode = kConversionMatch*/,
509 EInheritanceMode /* imode = kWithInheritance*/) const
510{
511
513
514 if (fType) {
515 const TypedefType *TT = llvm::dyn_cast<TypedefType>(fType);
516 if (TT) {
517 llvm::StringRef tname(TT->getDecl()->getName());
518 if (tname.equals(fname)) {
519 const NamedDecl *ndecl = llvm::dyn_cast<NamedDecl>(GetDecl());
520 if (ndecl && !ndecl->getName().equals(fname)) {
521 // Constructor name matching the typedef type, use the decl name instead.
522 return GetMethod(ndecl->getName().str().c_str(),arglist,
523 objectIsConst,poffset
524 /* ,mode,imode */);
525 }
526 }
527 }
528
529 }
530 if (poffset) {
531 *poffset = 0L;
532 }
533 if (!IsLoaded()) {
535 return tmi;
536 }
537 if (!strcmp(arglist, ")")) {
538 // CINT accepted a single right paren as meaning no arguments.
539 arglist = "";
540 }
541 const cling::LookupHelper &lh = fInterp->getLookupHelper();
542 const FunctionDecl *fd
543 = lh.findFunctionArgs(GetDecl(), fname, arglist,
544 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
545 : cling::LookupHelper::NoDiagnostics,
546 objectIsConst);
547 if (!fd) {
548 // Function not found.
550 return tmi;
551 }
552 if (poffset) {
553 // We have been asked to return a this pointer adjustment.
554 if (const CXXMethodDecl *md =
555 llvm::dyn_cast<CXXMethodDecl>(fd)) {
556 // This is a class member function.
557 *poffset = GetOffset(md);
558 }
559 }
561 tmi.Init(fd);
562 return tmi;
563}
564
565int TClingClassInfo::GetMethodNArg(const char *method, const char *proto,
566 Bool_t objectIsConst,
567 EFunctionMatchMode mode /*= kConversionMatch*/) const
568{
569 // Note: Used only by TQObject.cxx:170 and only for interpreted classes.
570 if (!IsLoaded()) {
571 return -1;
572 }
573
575
576 TClingMethodInfo mi = GetMethod(method, proto, objectIsConst, nullptr, mode);
577 int clang_val = -1;
578 if (mi.IsValid()) {
579 unsigned num_params = mi.GetTargetFunctionDecl()->getNumParams();
580 clang_val = static_cast<int>(num_params);
581 }
582 return clang_val;
583}
584
585Longptr_t TClingClassInfo::GetOffset(const CXXMethodDecl* md) const
586{
587
589
590 Longptr_t offset = 0L;
591 const CXXRecordDecl* definer = md->getParent();
592 const CXXRecordDecl* accessor =
593 llvm::cast<CXXRecordDecl>(GetDecl());
594 if (definer != accessor) {
595 // This function may not be accessible using a pointer
596 // to the declaring class, get the adjustment necessary
597 // to convert that to a pointer to the defining class.
598 TClingBaseClassInfo bi(fInterp, const_cast<TClingClassInfo*>(this));
599 while (bi.Next(0)) {
600 TClingClassInfo* bci = bi.GetBase();
601 if (bci->GetDecl() == definer) {
602 // We have found the right base class, now get the
603 // necessary adjustment.
604 offset = bi.Offset();
605 break;
606 }
607 }
608 }
609 return offset;
610}
611
612ptrdiff_t TClingClassInfo::GetBaseOffset(TClingClassInfo* base, void* address, bool isDerivedObject)
613{
614
615 {
616 std::unique_lock<std::mutex> lock(fOffsetCacheMutex);
617
618 // Check for the offset in the cache.
619 auto iter = fOffsetCache.find(base->GetDecl());
620 if (iter != fOffsetCache.end()) {
621 std::pair<ptrdiff_t, OffsetPtrFunc_t> offsetCache = (*iter).second;
622 if (OffsetPtrFunc_t executableFunc = offsetCache.second) {
623 if (address) {
624 return (*executableFunc)(address, isDerivedObject);
625 }
626 else {
627 Error("TClingBaseClassInfo::Offset", "The address of the object for virtual base offset calculation is not valid.");
628 return -1;
629 }
630 }
631 else {
632 return offsetCache.first;
633 }
634 }
635 }
636
637 // Compute the offset.
639 TClingBaseClassInfo binfo(fInterp, this, base);
640 return binfo.Offset(address, isDerivedObject);
641}
642
643std::vector<std::string> TClingClassInfo::GetUsingNamespaces()
644{
645 // Find and return all 'using' declarations of namespaces.
646 std::vector<std::string> res;
647
649
650 cling::Interpreter::PushTransactionRAII RAII(fInterp);
651 const auto DC = dyn_cast<DeclContext>(fDecl);
652 if (!DC)
653 return res;
654
655 clang::PrintingPolicy policy(fDecl->getASTContext().getPrintingPolicy());
656 for (auto UD : DC->using_directives()) {
657 NamespaceDecl *NS = UD->getNominatedNamespace();
658 if (NS) {
659 std::string nsName;
660 llvm::raw_string_ostream stream(nsName);
661
662 NS->getNameForDiagnostic(stream, policy, /*Qualified=*/true);
663
664 stream.flush();
665 res.push_back(nsName);
666 }
667 }
668
669 return res;
670}
671
673{
674 // Return true if there a constructor taking no arguments (including
675 // a constructor that has defaults for all of its arguments) which
676 // is callable. Either it has a body, or it is trivial and the
677 // compiler elides it.
678 //
679 // Note: This is could enhanced to also know about the ROOT ioctor
680 // but this was not the case in CINT.
681 //
682
683 using namespace ROOT::TMetaUtils;
684
685 if (!IsLoaded())
686 return EIOCtorCategory::kAbsent;
687
688 auto CRD = llvm::dyn_cast<CXXRecordDecl>(GetDecl());
689 // Namespaces do not have constructors.
690 if (!CRD)
691 return EIOCtorCategory::kAbsent;
692
693 if (checkio) {
694 auto kind = CheckIOConstructor(CRD, "TRootIOCtor", nullptr, *fInterp);
695 if ((kind == EIOCtorCategory::kIORefType) || (kind == EIOCtorCategory::kIOPtrType)) {
696 if (type_name) *type_name = "TRootIOCtor";
697 return kind;
698 }
699
700 kind = CheckIOConstructor(CRD, "__void__", nullptr, *fInterp);
701 if (kind == EIOCtorCategory::kIORefType) {
702 if (type_name) *type_name = "__void__";
703 return kind;
704 }
705 }
706
707 return CheckDefaultConstructor(CRD, *fInterp) ? EIOCtorCategory::kDefault : EIOCtorCategory::kAbsent;
708}
709
710bool TClingClassInfo::HasMethod(const char *name) const
711{
713 if (IsLoaded() && !llvm::isa<EnumDecl>(GetDecl())) {
714 return fInterp->getLookupHelper()
715 .hasFunction(GetDecl(), name,
716 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
717 : cling::LookupHelper::NoDiagnostics);
718 }
719 return false;
720}
721
723{
724 fFirstTime = true;
725 fDescend = false;
726 fIsIter = false;
727 fIter = DeclContext::decl_iterator();
728 SetDecl(nullptr);
729 fType = nullptr;
730 fIterStack.clear();
731 const cling::LookupHelper& lh = fInterp->getLookupHelper();
732 SetDecl(lh.findScope(name, gDebug > 5 ? cling::LookupHelper::WithDiagnostics
733 : cling::LookupHelper::NoDiagnostics,
734 &fType, /* intantiateTemplate= */ true ));
735 if (!GetDecl()) {
736 std::string buf = TClassEdit::InsertStd(name);
737 if (buf != name) {
738 SetDecl(lh.findScope(buf, gDebug > 5 ? cling::LookupHelper::WithDiagnostics
739 : cling::LookupHelper::NoDiagnostics,
740 &fType, /* intantiateTemplate= */ true ));
741 }
742 }
743 if (!GetDecl() && fType) {
744 const TagType *tagtype =fType->getAs<TagType>();
745 if (tagtype) {
746 SetDecl(tagtype->getDecl());
747 }
748 }
749}
750
751void TClingClassInfo::Init(const Decl* decl)
752{
753 fFirstTime = true;
754 fDescend = false;
755 fIsIter = false;
756 fIter = DeclContext::decl_iterator();
757 SetDecl(decl);
758 fType = nullptr;
759 fIterStack.clear();
760}
761
762void TClingClassInfo::Init(int tagnum)
763{
764 Fatal("TClingClassInfo::Init(tagnum)", "Should no longer be called");
765 return;
766}
767
768void TClingClassInfo::Init(const Type &tag)
769{
770 fType = &tag;
771
773
774 const TagType *tagtype = fType->getAs<TagType>();
775 if (tagtype) {
776 SetDecl(tagtype->getDecl());
777 }
778 else {
779 SetDecl(nullptr);
780 }
781 if (!GetDecl()) {
782 QualType qType(fType,0);
783 static PrintingPolicy printPol(fInterp->getCI()->getLangOpts());
784 printPol.SuppressScope = false;
785 Error("TClingClassInfo::Init(const Type&)",
786 "The given type %s does not point to a Decl",
787 qType.getAsString(printPol).c_str());
788 }
789}
790
791bool TClingClassInfo::IsBase(const char *name) const
792{
793 if (!IsLoaded()) {
794 return false;
795 }
797 if (!base.IsValid()) {
798 return false;
799 }
800
802
803 const CXXRecordDecl *CRD =
804 llvm::dyn_cast<CXXRecordDecl>(GetDecl());
805 if (!CRD) {
806 // We are an enum, namespace, or translation unit,
807 // we cannot be the base of anything.
808 return false;
809 }
810 const CXXRecordDecl *baseCRD =
811 llvm::dyn_cast<CXXRecordDecl>(base.GetDecl());
812 return CRD->isDerivedFrom(baseCRD);
813}
814
815bool TClingClassInfo::IsEnum(cling::Interpreter *interp, const char *name)
816{
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() == nullptr)
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()) {
845 case BuiltinType::Bool:
846 return kBool_t;
847
848 case BuiltinType::Char_U:
849 case BuiltinType::UChar:
850 return kUChar_t;
851
852 case BuiltinType::Char_S:
853 case BuiltinType::SChar:
854 return kChar_t;
855
856 case BuiltinType::UShort:
857 return kUShort_t;
858 case BuiltinType::Short:
859 return kShort_t;
860 case BuiltinType::UInt:
861 return kUInt_t;
862 case BuiltinType::Int:
863 return kInt_t;
864 case BuiltinType::ULong:
865 return kULong_t;
866 case BuiltinType::Long:
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() == nullptr) {
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() == nullptr) {
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,
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 }
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 = nullptr;
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 = nullptr;
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;
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;
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;
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;
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 && ! 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 nullptr;
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 nullptr;
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()) {
1427 fTitle = ROOT::TMetaUtils::GetClassComment(*CRD,nullptr,*fInterp).str();
1428 }
1429 return fTitle.c_str();
1430}
1431
1433{
1434 if (!IsValid()) {
1435 return nullptr;
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}
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
long Longptr_t
Definition RtypesCore.h:82
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
@ kClassHasAssignOpr
@ 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:185
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:229
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:244
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:110
R__EXTERN TVirtualMutex * gInterpreterMutex
Int_t gDebug
Definition TROOT.cxx:595
#define R__LOCKGUARD(mutex)
#define R__WRITE_LOCKGUARD(mutex)
const char * proto
Definition civetweb.c:17536
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
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 *)
const Int_t n
Definition legend1.C:16
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.
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
R__EXTERN TVirtualRWMutex * gCoreMutex
EFunctionMatchMode
@ kExactMatch
@ kConversionMatch
std::string InsertStd(const char *tname)
static void output()