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