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