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