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 (Ty)
848 Ty = Ty->getUnqualifiedDesugaredType();
849 if (auto BTy = llvm::dyn_cast_or_null<BuiltinType>(Ty)) {
850 switch (BTy->getKind()) {
851 case BuiltinType::Bool:
852 return kBool_t;
853
854 case BuiltinType::Char_U:
855 case BuiltinType::UChar:
856 return kUChar_t;
857
858 case BuiltinType::Char_S:
859 case BuiltinType::SChar:
860 return kChar_t;
861
862 case BuiltinType::UShort:
863 return kUShort_t;
864 case BuiltinType::Short:
865 return kShort_t;
866 case BuiltinType::UInt:
867 return kUInt_t;
868 case BuiltinType::Int:
869 return kInt_t;
870 case BuiltinType::ULong:
871 return kULong_t;
872 case BuiltinType::Long:
873 return kLong_t;
874 case BuiltinType::ULongLong:
875 return kULong64_t;
876 case BuiltinType::LongLong:
877 return kLong64_t;
878 default:
879 return kNumDataTypes;
880 };
881 }
882 }
883 return kNumDataTypes;
884}
885
886
888{
889 // IsLoaded in CINT was meaning is known to the interpreter
890 // and has a complete definition.
891 // IsValid in Cling (as in CING) means 'just' is known to the
892 // interpreter.
893 if (!IsValid()) {
894 return false;
895 }
896 if (GetDecl() == nullptr) {
897 return false;
898 }
899
901
902 const CXXRecordDecl *CRD = llvm::dyn_cast<CXXRecordDecl>(GetDecl());
903 if ( CRD ) {
904 if (!CRD->hasDefinition()) {
905 return false;
906 }
907 } else {
908 const TagDecl *TD = llvm::dyn_cast<TagDecl>(GetDecl());
909 if (TD && TD->getDefinition() == nullptr) {
910 return false;
911 }
912 }
913 // All clang classes are considered loaded.
914 return true;
915}
916
917bool TClingClassInfo::IsValidMethod(const char *method, const char *proto,
918 Bool_t objectIsConst,
920 EFunctionMatchMode mode /*= kConversionMatch*/) const
921{
922 // Check if the method with the given prototype exist.
923 if (!IsLoaded()) {
924 return false;
925 }
926 if (offset) {
927 *offset = 0L;
928 }
930 return mi.IsValid();
931}
932
934{
936
937 fDeclFileName.clear(); // invalidate decl file name.
938 fNameCache.clear(); // invalidate the cache.
939
940 cling::Interpreter::PushTransactionRAII RAII(fInterp);
941 if (fFirstTime) {
942 // GetDecl() must be a DeclContext in order to iterate.
943 const clang::DeclContext *DC = cast<DeclContext>(GetDecl());
944 if (fIterAll)
945 fIter = DC->decls_begin();
946 else
947 fIter = DC->noload_decls_begin();
948 }
949
950 if (!fIsIter) {
951 // Object was not setup for iteration.
952 if (GetDecl()) {
953 std::string buf;
954 if (const NamedDecl* ND =
955 llvm::dyn_cast<NamedDecl>(GetDecl())) {
956 PrintingPolicy Policy(GetDecl()->getASTContext().
957 getPrintingPolicy());
958 llvm::raw_string_ostream stream(buf);
959 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/false);
960 }
961 Error("TClingClassInfo::InternalNext",
962 "Next called but iteration not prepared for %s!", buf.c_str());
963 } else {
964 Error("TClingClassInfo::InternalNext",
965 "Next called but iteration not prepared!");
966 }
967 return 0;
968 }
969 while (true) {
970 // Advance to next usable decl, or return if there is no next usable decl.
971 if (fFirstTime) {
972 // The cint semantics are strange.
973 fFirstTime = false;
974 if (!*fIter) {
975 return 0;
976 }
977 }
978 else {
979 // Advance the iterator one decl, descending into the current decl
980 // context if necessary.
981 if (!fDescend) {
982 // Do not need to scan the decl context of the current decl,
983 // move on to the next decl.
984 ++fIter;
985 }
986 else {
987 // Descend into the decl context of the current decl.
988 fDescend = false;
989 //fprintf(stderr,
990 // "TClingClassInfo::InternalNext: "
991 // "pushing ...\n");
992 fIterStack.push_back(fIter);
993 DeclContext *DC = llvm::cast<DeclContext>(*fIter);
994 if (fIterAll)
995 fIter = DC->decls_begin();
996 else
997 fIter = DC->noload_decls_begin();
998 }
999 // Fix it if we went past the end.
1000 while (!*fIter && fIterStack.size()) {
1001 //fprintf(stderr,
1002 // "TClingClassInfo::InternalNext: "
1003 // "popping ...\n");
1004 fIter = fIterStack.back();
1005 fIterStack.pop_back();
1006 ++fIter;
1007 }
1008 // Check for final termination.
1009 if (!*fIter) {
1010 // We have reached the end of the translation unit, all done.
1011 SetDecl(nullptr);
1012 fType = nullptr;
1013 return 0;
1014 }
1015 }
1016 // Return if this decl is a class, struct, union, enum, or namespace.
1017 Decl::Kind DK = fIter->getKind();
1018 if ((DK == Decl::Namespace) || (DK == Decl::Enum) ||
1019 (DK == Decl::CXXRecord) ||
1020 (DK == Decl::ClassTemplateSpecialization)) {
1021 const TagDecl *TD = llvm::dyn_cast<TagDecl>(*fIter);
1022 if (TD && !TD->isCompleteDefinition()) {
1023 // For classes and enums, stop only on definitions.
1024 continue;
1025 }
1026 if (DK == Decl::Namespace) {
1027 // For namespaces, stop only on the first definition.
1028 if (!fIter->isCanonicalDecl()) {
1029 // Not the first definition.
1030 fDescend = true;
1031 continue;
1032 }
1033 }
1034 if (DK != Decl::Enum) {
1035 // We do not descend into enums.
1036 DeclContext *DC = llvm::cast<DeclContext>(*fIter);
1037 if ((fIterAll && *DC->decls_begin())
1038 || (!fIterAll && *DC->noload_decls_begin())) {
1039 // Next iteration will begin scanning the decl context
1040 // contained by this decl.
1041 fDescend = true;
1042 }
1043 }
1044 // Iterator is now valid.
1045 SetDecl(*fIter);
1046 fType = nullptr;
1047 if (GetDecl()) {
1048 if (GetDecl()->isInvalidDecl()) {
1049 Warning("TClingClassInfo::Next()","Reached an invalid decl.");
1050 }
1051 if (const RecordDecl *RD =
1052 llvm::dyn_cast<RecordDecl>(GetDecl())) {
1053 fType = RD->getASTContext().getRecordType(RD).getTypePtr();
1054 }
1055 }
1056 return 1;
1057 }
1058 }
1059}
1060
1062{
1063 return InternalNext();
1064}
1065
1067{
1068 // Invoke a new expression to use the class constructor
1069 // that takes no arguments to create an object of this class type.
1070 if (!IsValid()) {
1071 Error("TClingClassInfo::New()", "Called while invalid!");
1072 return nullptr;
1073 }
1074 if (!IsLoaded()) {
1075 Error("TClingClassInfo::New()", "Class is not loaded: %s",
1076 FullyQualifiedName(GetDecl()).c_str());
1077 return nullptr;
1078 }
1079
1081 std::string type_name;
1082
1083 {
1085 auto RD = dyn_cast<CXXRecordDecl>(GetDecl());
1086 if (!RD) {
1087 Error("TClingClassInfo::New()", "This is a namespace!: %s",
1088 FullyQualifiedName(GetDecl()).c_str());
1089 return nullptr;
1090 }
1091
1092 kind = HasDefaultConstructor(true, &type_name);
1093
1095 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1096 // Error("TClingClassInfo::New()", "Class has no default constructor: %s",
1097 // FullyQualifiedName(GetDecl()).c_str());
1098 return nullptr;
1099 }
1100 } // End of Lock section.
1101 void* obj = nullptr;
1103 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1104 /*address=*/nullptr, /*nary=*/0);
1105 if (!obj) {
1106 Error("TClingClassInfo::New()", "Call of default constructor "
1107 "failed to return an object for class: %s",
1108 FullyQualifiedName(GetDecl()).c_str());
1109 return nullptr;
1110 }
1111 return obj;
1112}
1113
1115{
1116 // Invoke a new expression to use the class constructor
1117 // that takes no arguments to create an array object
1118 // of this class type.
1119 if (!IsValid()) {
1120 Error("TClingClassInfo::New(n)", "Called while invalid!");
1121 return nullptr;
1122 }
1123 if (!IsLoaded()) {
1124 Error("TClingClassInfo::New(n)", "Class is not loaded: %s",
1125 FullyQualifiedName(GetDecl()).c_str());
1126 return nullptr;
1127 }
1128
1130 std::string type_name;
1131
1132 {
1134
1135 auto RD = dyn_cast<CXXRecordDecl>(GetDecl());
1136 if (!RD) {
1137 Error("TClingClassInfo::New(n)", "This is a namespace!: %s",
1138 FullyQualifiedName(GetDecl()).c_str());
1139 return nullptr;
1140 }
1141
1142 kind = HasDefaultConstructor(true, &type_name);
1144 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1145 //Error("TClingClassInfo::New(n)",
1146 // "Class has no default constructor: %s",
1147 // FullyQualifiedName(GetDecl()).c_str());
1148 return nullptr;
1149 }
1150 } // End of Lock section.
1151 void* obj = nullptr;
1153 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1154 /*address=*/nullptr, /*nary=*/(unsigned long)n);
1155 if (!obj) {
1156 Error("TClingClassInfo::New(n)", "Call of default constructor "
1157 "failed to return an array of class: %s",
1158 FullyQualifiedName(GetDecl()).c_str());
1159 return nullptr;
1160 }
1161 return obj;
1162}
1163
1164void *TClingClassInfo::New(int n, void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
1165{
1166 // Invoke a placement new expression to use the class
1167 // constructor that takes no arguments to create an
1168 // array of objects of this class type in the given
1169 // memory arena.
1170 if (!IsValid()) {
1171 Error("TClingClassInfo::New(n, arena)", "Called while invalid!");
1172 return nullptr;
1173 }
1174 if (!IsLoaded()) {
1175 Error("TClingClassInfo::New(n, arena)", "Class is not loaded: %s",
1176 FullyQualifiedName(GetDecl()).c_str());
1177 return nullptr;
1178 }
1179
1181 std::string type_name;
1182
1183 {
1185
1186 auto RD = dyn_cast<CXXRecordDecl>(GetDecl());
1187 if (!RD) {
1188 Error("TClingClassInfo::New(n, arena)", "This is a namespace!: %s",
1189 FullyQualifiedName(GetDecl()).c_str());
1190 return nullptr;
1191 }
1192
1193 kind = HasDefaultConstructor(true, &type_name);
1195 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1196 //Error("TClingClassInfo::New(n, arena)",
1197 // "Class has no default constructor: %s",
1198 // FullyQualifiedName(GetDecl()).c_str());
1199 return nullptr;
1200 }
1201 } // End of Lock section
1202 void* obj = nullptr;
1204 // Note: This will always return arena.
1205 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1206 /*address=*/arena, /*nary=*/(unsigned long)n);
1207 return obj;
1208}
1209
1210void *TClingClassInfo::New(void *arena, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
1211{
1212 // Invoke a placement new expression to use the class
1213 // constructor that takes no arguments to create an
1214 // object of this class type in the given memory arena.
1215 if (!IsValid()) {
1216 Error("TClingClassInfo::New(arena)", "Called while invalid!");
1217 return nullptr;
1218 }
1219 if (!IsLoaded()) {
1220 Error("TClingClassInfo::New(arena)", "Class is not loaded: %s",
1221 FullyQualifiedName(GetDecl()).c_str());
1222 return nullptr;
1223 }
1224
1226 std::string type_name;
1227
1228 {
1230
1231 auto RD = dyn_cast<CXXRecordDecl>(GetDecl());
1232 if (!RD) {
1233 Error("TClingClassInfo::New(arena)", "This is a namespace!: %s",
1234 FullyQualifiedName(GetDecl()).c_str());
1235 return nullptr;
1236 }
1237
1238 kind = HasDefaultConstructor(true, &type_name);
1240 // FIXME: We fail roottest root/io/newdelete if we issue this message!
1241 //Error("TClingClassInfo::New(arena)",
1242 // "Class has no default constructor: %s",
1243 // FullyQualifiedName(GetDecl()).c_str());
1244 return nullptr;
1245 }
1246 } // End of Locked section.
1247 void* obj = nullptr;
1249 // Note: This will always return arena.
1250 obj = cf.ExecDefaultConstructor(this, kind, type_name,
1251 /*address=*/arena, /*nary=*/0);
1252 return obj;
1253}
1254
1256{
1257 if (!IsValid()) {
1258 return 0L;
1259 }
1260
1262
1263 long property = 0L;
1264 property |= kIsCPPCompiled;
1265
1266 // Modules can deserialize while querying the various decls for information.
1267 cling::Interpreter::PushTransactionRAII RAII(fInterp);
1268
1269 const clang::DeclContext *ctxt = GetDecl()->getDeclContext();
1270 clang::NamespaceDecl *std_ns =fInterp->getSema().getStdNamespace();
1271 while (ctxt && ! ctxt->isTranslationUnit()) {
1272 if (ctxt->Equals(std_ns)) {
1273 property |= kIsDefinedInStd;
1274 break;
1275 }
1276 ctxt = ctxt->getParent();
1277 }
1278 Decl::Kind DK = GetDecl()->getKind();
1279 if ((DK == Decl::Namespace) || (DK == Decl::TranslationUnit)) {
1280 property |= kIsNamespace;
1281 return property;
1282 }
1283 // Note: Now we have class, enum, struct, union only.
1284 const TagDecl *TD = llvm::dyn_cast<TagDecl>(GetDecl());
1285 if (!TD) {
1286 return 0L;
1287 }
1288 if (TD->isEnum()) {
1289 property |= kIsEnum;
1290 return property;
1291 }
1292 // Note: Now we have class, struct, union only.
1293 const CXXRecordDecl *CRD =
1294 llvm::dyn_cast<CXXRecordDecl>(GetDecl());
1295 if (!CRD)
1296 return property;
1297
1298 if (CRD->isClass()) {
1299 property |= kIsClass;
1300 } else if (CRD->isStruct()) {
1301 property |= kIsStruct;
1302 } else if (CRD->isUnion()) {
1303 property |= kIsUnion;
1304 }
1305 if (CRD->hasDefinition() && CRD->isAbstract()) {
1306 property |= kIsAbstract;
1307 }
1308 return property;
1309}
1310
1312{
1313 if (!IsValid()) {
1314 return 0;
1315 }
1316 // FIXME: Implement this when rootcling provides the value.
1317 return 0;
1318}
1319
1321{
1322 if (!IsValid()) {
1323 return -1;
1324 }
1325 if (!GetDecl()) {
1326 // A forward declared class.
1327 return 0;
1328 }
1329
1331
1332 Decl::Kind DK = GetDecl()->getKind();
1333 if (DK == Decl::Namespace) {
1334 // Namespaces are special for cint.
1335 return 1;
1336 }
1337 else if (DK == Decl::Enum) {
1338 // Enums are special for cint.
1339 return 0;
1340 }
1341 const RecordDecl *RD = llvm::dyn_cast<RecordDecl>(GetDecl());
1342 if (!RD) {
1343 // Should not happen.
1344 return -1;
1345 }
1346 if (!RD->getDefinition()) {
1347 // Forward-declared class.
1348 return 0;
1349 }
1350 ASTContext &Context = GetDecl()->getASTContext();
1351 cling::Interpreter::PushTransactionRAII RAII(fInterp);
1352 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1353 int64_t size = Layout.getSize().getQuantity();
1354 int clang_size = static_cast<int>(size);
1355 return clang_size;
1356}
1357
1359{
1360 if (!IsValid()) {
1361 return -1L;
1362 }
1363 return reinterpret_cast<Longptr_t>(GetDecl());
1364}
1365
1367{
1368 if (!IsValid()) {
1369 return nullptr;
1370 }
1371 if (fDeclFileName.empty())
1373 return fDeclFileName.c_str();
1374}
1375
1377{
1378 // Return QualifiedName.
1379 output.clear();
1380 if (!IsValid()) {
1381 return;
1382 }
1383 if (fType) {
1384 QualType type(fType, 0);
1386 }
1387 else {
1388 if (const NamedDecl* ND =
1389 llvm::dyn_cast<NamedDecl>(GetDecl())) {
1390 PrintingPolicy Policy(GetDecl()->getASTContext().
1391 getPrintingPolicy());
1392 llvm::raw_string_ostream stream(output);
1393 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true);
1394 }
1395 }
1396}
1397
1399{
1400 if (!IsValid()) {
1401 return nullptr;
1402 }
1403 // NOTE: We cannot cache the result, since we are really an iterator.
1404 // Try to get the comment either from the annotation or the header
1405 // file, if present.
1406 // Iterate over the redeclarations, we can have multiple definitions in the
1407 // redecl chain (came from merging of pcms).
1408
1410
1411 if (const TagDecl *TD = llvm::dyn_cast<TagDecl>(GetDecl())) {
1413 if (AnnotateAttr *A = TD->getAttr<AnnotateAttr>()) {
1414 std::string attr = A->getAnnotation().str();
1415 if (attr.find(TMetaUtils::propNames::separator) != std::string::npos) {
1417 fTitle = attr;
1418 return fTitle.c_str();
1419 }
1420 } else {
1421 fTitle = attr;
1422 return fTitle.c_str();
1423 }
1424 }
1425 }
1426 }
1427 // Try to get the comment from the header file, if present.
1428 // but not for decls from AST file, where rootcling would have
1429 // created an annotation
1430 const CXXRecordDecl *CRD =
1431 llvm::dyn_cast<CXXRecordDecl>(GetDecl());
1432 if (CRD && !CRD->isFromASTFile()) {
1433 fTitle = ROOT::TMetaUtils::GetClassComment(*CRD,nullptr,*fInterp).str();
1434 }
1435 return fTitle.c_str();
1436}
1437
1439{
1440 if (!IsValid()) {
1441 return nullptr;
1442 }
1443
1445
1446 // Note: This *must* be static/thread_local because we are returning a pointer inside it!
1447 TTHREAD_TLS_DECL( std::string, buf);
1448 buf.clear();
1449 if (const NamedDecl* ND = llvm::dyn_cast<NamedDecl>(GetDecl())) {
1450 // Note: This does *not* include the template arguments!
1451 buf = ND->getNameAsString();
1452 }
1453 return buf.c_str(); // NOLINT
1454}
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
long Longptr_t
Definition RtypesCore.h:75
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
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:597
#define R__LOCKGUARD(mutex)
#define R__WRITE_LOCKGUARD(mutex)
const char * proto
Definition civetweb.c:17535
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()