Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TClass.cxx
Go to the documentation of this file.
1// @(#)root/meta:$Id: 7109cb45f1219c2aae6be19906ae5a63e31972ef $
2// Author: Rene Brun 07/01/95
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 TClass
13TClass instances represent classes, structs and namespaces in the ROOT type system.
14
15TClass instances are created starting from different sources of information:
161. TStreamerInfo instances saved in a ROOT file which is opened. This is called in jargon an *emulated TClass*.
172. From TProtoClass instances saved in a ROOT pcm file created by the dictionary generator and the dictionary itself.
183. From a lookup in the AST built by cling.
19
20If a TClass instance is built through the mechanisms 1. and 2., it does not contain information about methods of the
21class/struct/namespace it represents. Conversely, if built through 3. or 1., it does not carry the information which is necessary
22to ROOT to perform I/O of instances of the class/struct it represents.
23The mechanisms 1., 2. and 3. are not mutually exclusive: it can happen that during the execution of the program, all
24the three are triggered, modifying the state of the TClass instance.
25
26In order to retrieve a TClass instance from the type system, a query can be executed as follows through the static
27TClass::GetClass method:
28
29~~~ {.cpp}
30auto myClassTClass_0 = TClass::GetClass("myClass");
31auto myClassTClass_1 = TClass::GetClass<myClass>();
32auto myClassTClass_2 = TClass::GetClass(myClassTypeInfo);
33~~~
34
35The name of classes is crucial for ROOT. A careful procedure of *name normalization* is carried out for
36each and every class. A *normalized name* is a valid C++ class name.
37In order to access the name of a class within the ROOT type system, the method TClass::GetName() can be used.
38*/
39
40//*-*x7.5 macros/layout_class
41
42#include "TClass.h"
43
44#include "strlcpy.h"
45#include "snprintf.h"
46#include "TBaseClass.h"
47#include "TBrowser.h"
48#include "TBuffer.h"
49#include "TClassGenerator.h"
50#include "TClassEdit.h"
51#include "TClassMenuItem.h"
52#include "TClassRef.h"
53#include "TClassTable.h"
54#include "TDataMember.h"
55#include "TDataType.h"
56#include "TDatime.h"
57#include "TEnum.h"
58#include "TError.h"
59#include "TExMap.h"
60#include "TFunctionTemplate.h"
61#include "THashList.h"
62#include "TInterpreter.h"
63#include "TMemberInspector.h"
64#include "TMethod.h"
65#include "TMethodArg.h"
66#include "TMethodCall.h"
67#include "TObjArray.h"
68#include "TObjString.h"
69#include "TProtoClass.h"
70#include "TROOT.h"
71#include "TRealData.h"
72#include "TCheckHashRecursiveRemoveConsistency.h" // Private header
73#include "TStreamer.h"
74#include "TStreamerElement.h"
77#include "TVirtualIsAProxy.h"
78#include "TVirtualRefProxy.h"
79#include "TVirtualMutex.h"
80#include "TVirtualPad.h"
81#include "THashTable.h"
82#include "TSchemaRuleSet.h"
83#include "TGenericClassInfo.h"
84#include "TIsAProxy.h"
85#include "TSchemaRule.h"
86#include "TSystem.h"
87#include "TThreadSlots.h"
88#include "ThreadLocalStorage.h"
89
90#include <cstdio>
91#include <cctype>
92#include <set>
93#include <iostream>
94#include <sstream>
95#include <string>
96#include <map>
97#include <typeinfo>
98#include <cmath>
99#include <cassert>
100#include <vector>
101#include <memory>
102
103#include "TSpinLockGuard.h"
104
105#ifdef WIN32
106#include <io.h>
107#include "Windows4Root.h"
108#include <Psapi.h>
109#define RTLD_DEFAULT ((void *)::GetModuleHandle(NULL))
110#define dlsym(library, function_name) ::GetProcAddress((HMODULE)library, function_name)
111#else
112#include <dlfcn.h>
113#endif
114
115#include "TListOfDataMembers.h"
116#include "TListOfFunctions.h"
118#include "TListOfEnums.h"
119#include "TListOfEnumsWithLock.h"
120#include "TViewPubDataMembers.h"
121#include "TViewPubFunctions.h"
122#include "TArray.h"
123#include "TClonesArray.h"
124#include "TRef.h"
125#include "TRefArray.h"
126
127using namespace std;
128
129// Mutex to protect CINT and META operations
130// (exported to be used for similar cases in related classes)
131
133
134namespace {
135
136 static constexpr const char kUndeterminedClassInfoName[] = "<NOT YET DETERMINED FROM fClassInfo>";
137
138 class TMmallocDescTemp {
139 private:
140 void *fSave;
141 public:
142 TMmallocDescTemp(void *value = nullptr) :
144 ~TMmallocDescTemp() { ROOT::Internal::gMmallocDesc = fSave; }
145 };
146
147 // When a new class is created, we need to be able to find
148 // if there are any existing classes that have the same name
149 // after any typedefs are expanded. (This only really affects
150 // template arguments.) To avoid having to search through all classes
151 // in that case, we keep a hash table mapping from the fully
152 // typedef-expanded names to the original class names.
153 // An entry is made in the table only if they are actually different.
154 //
155 // In these objects, the TObjString base holds the typedef-expanded
156 // name (the hash key), and fOrigName holds the original class name
157 // (the value to which the key maps).
158 //
159 class TNameMapNode : public TObjString {
160 public:
161 TString fOrigName;
162
163 TNameMapNode(const char *typedf, const char *orig) :
164 TObjString (typedf),
165 fOrigName (orig)
166 {
167 }
168 };
169
170}
171
172std::atomic<Int_t> TClass::fgClassCount;
173
174static bool IsFromRootCling() {
175 // rootcling also uses TCling for generating the dictionary ROOT files.
176 const static bool foundSymbol = dlsym(RTLD_DEFAULT, "usedToIdentifyRootClingByDlSym");
177 return foundSymbol;
178}
179
180// Implementation of the TDeclNameRegistry
181
182////////////////////////////////////////////////////////////////////////////////
183/// TDeclNameRegistry class constructor.
184
186{
187 // MSVC doesn't support fSpinLock=ATOMIC_FLAG_INIT; in the class definition
188 std::atomic_flag_clear( &fSpinLock );
189}
190
191////////////////////////////////////////////////////////////////////////////////
192/// Extract this part of the name
193/// 1. Templates ns::ns2::,,,::THISPART<...
194/// 2. Namespaces,classes ns::ns2::,,,::THISPART
195
197{
198 // Sanity check
199 auto strLen = strlen(name);
200 if (strLen == 0) return;
201 // find <. If none, put end of string
202 const char* endCharPtr = strchr(name, '<');
203 endCharPtr = !endCharPtr ? &name[strLen] : endCharPtr;
204 // find last : before the <. If not found, put begin of string
205 const char* beginCharPtr = endCharPtr;
206 while (beginCharPtr!=name){
207 if (*beginCharPtr==':'){
208 beginCharPtr++;
209 break;
210 }
211 beginCharPtr--;
212 }
213 beginCharPtr = beginCharPtr!=endCharPtr ? beginCharPtr : name;
214 std::string s(beginCharPtr, endCharPtr);
215 if (fVerbLevel>1)
216 printf("TDeclNameRegistry::AddQualifiedName Adding key %s for class/namespace %s\n", s.c_str(), name);
217 ROOT::Internal::TSpinLockGuard slg(fSpinLock);
218 fClassNamesSet.insert(s);
219}
220
221////////////////////////////////////////////////////////////////////////////////
222
224{
225 Bool_t found = false;
226 {
227 ROOT::Internal::TSpinLockGuard slg(fSpinLock);
228 found = fClassNamesSet.find(name) != fClassNamesSet.end();
229 }
230 return found;
231}
232
233////////////////////////////////////////////////////////////////////////////////
234
236{
237 if (fVerbLevel > 1) {
238 printf("TDeclNameRegistry Destructor. List of %lu names:\n",
239 (long unsigned int)fClassNamesSet.size());
240 for (auto const & key: fClassNamesSet) {
241 printf(" - %s\n", key.c_str());
242 }
243 }
244}
245
246////////////////////////////////////////////////////////////////////////////////
247
249 const char *name,
250 TDeclNameRegistry &emuRegistry): fState(state),fName(name), fNoInfoOrEmuOrFwdDeclNameRegistry(emuRegistry) {}
251
252////////////////////////////////////////////////////////////////////////////////
253
255 if (fState == TClass::kNoInfo ||
259 }
260 }
261
262// Initialise the global member of TClass
264
265//Intent of why/how TClass::New() is called
266//[Not a static data member because MacOS does not support static thread local data member ... who knows why]
268 TTHREAD_TLS(TClass::ENewType) fgCallingNew = TClass::kRealNew;
269 return fgCallingNew;
270}
271
273{
276
278 fCurrentValue(TClass__GetCallingNew()),
279 fOldValue(fCurrentValue)
280 {
281 fCurrentValue = newvalue;
282 }
283
285 {
286 fCurrentValue = fOldValue;
287 }
288};
289
290void TClass::RegisterAddressInRepository(const char * /*where*/, void *location, const TClass *what) const
291{
292 // Register the object for special handling in the destructor.
293
294 Version_t version = what->GetClassVersion();
295// if (!fObjectVersionRepository.count(location)) {
296// Info(where, "Registering address %p of class '%s' version %d", location, what->GetName(), version);
297// } else {
298// Warning(where, "Registering address %p again of class '%s' version %d", location, what->GetName(), version);
299// }
300 {
302 fObjectVersionRepository.insert(RepoCont_t::value_type(location, version));
303 }
304#if 0
305 // This code could be used to prevent an address to be registered twice.
306 std::pair<RepoCont_t::iterator, Bool_t> tmp = fObjectVersionRepository.insert(RepoCont_t::value_type>(location, version));
307 if (!tmp.second) {
308 Warning(where, "Reregistering an object of class '%s' version %d at address %p", what->GetName(), version, p);
309 fObjectVersionRepository.erase(tmp.first);
310 tmp = fObjectVersionRepository.insert(RepoCont_t::value_type>(location, version));
311 if (!tmp.second) {
312 Warning(where, "Failed to reregister an object of class '%s' version %d at address %p", what->GetName(), version, location);
313 }
314 }
315#endif
316}
317
318void TClass::UnregisterAddressInRepository(const char * /*where*/, void *location, const TClass *what) const
319{
320 // Remove an address from the repository of address/object.
321
323 RepoCont_t::iterator cur = fObjectVersionRepository.find(location);
324 for (; cur != fObjectVersionRepository.end();) {
325 RepoCont_t::iterator tmp = cur++;
326 if ((tmp->first == location) && (tmp->second == what->GetClassVersion())) {
327 // -- We still have an address, version match.
328 // Info(where, "Unregistering address %p of class '%s' version %d", location, what->GetName(), what->GetClassVersion());
329 fObjectVersionRepository.erase(tmp);
330 } else {
331 // -- No address, version match, we've reached the end.
332 break;
333 }
334 }
335}
336
337void TClass::MoveAddressInRepository(const char * /*where*/, void *oldadd, void *newadd, const TClass *what) const
338{
339 // Register in the repository that an object has moved.
340
341 // Move not only the object itself but also any base classes or sub-objects.
342 size_t objsize = what->Size();
343 long delta = (char*)newadd - (char*)oldadd;
345 RepoCont_t::iterator cur = fObjectVersionRepository.find(oldadd);
346 for (; cur != fObjectVersionRepository.end();) {
347 RepoCont_t::iterator tmp = cur++;
348 if (oldadd <= tmp->first && tmp->first < ( ((char*)oldadd) + objsize) ) {
349 // The location is within the object, let's move it.
350
351 fObjectVersionRepository.insert(RepoCont_t::value_type(((char*)tmp->first)+delta, tmp->second));
352 fObjectVersionRepository.erase(tmp);
353
354 } else {
355 // -- No address, version match, we've reached the end.
356 break;
357 }
358 }
359}
360
361//______________________________________________________________________________
362//______________________________________________________________________________
363namespace ROOT {
364#define R__USE_STD_MAP
366#if defined R__USE_STD_MAP
367 // This wrapper class allow to avoid putting #include <map> in the
368 // TROOT.h header file.
369 public:
370 typedef std::map<std::string,TClass*> IdMap_t;
374#ifdef R__WIN32
375 // Window's std::map does NOT defined mapped_type
376 typedef TClass* mapped_type;
377#else
379#endif
380
381 private:
383
384 public:
385 void Add(const key_type &key, mapped_type &obj)
386 {
387 // Add the <key,obj> pair to the map.
388 fMap[key] = obj;
389 }
390 mapped_type Find(const key_type &key) const
391 {
392 // Find the type corresponding to the key.
393 IdMap_t::const_iterator iter = fMap.find(key);
394 mapped_type cl = nullptr;
395 if (iter != fMap.end()) cl = iter->second;
396 return cl;
397 }
398 void Remove(const key_type &key) {
399 // Remove the type corresponding to the key.
400 fMap.erase(key);
401 }
402#else
403 private:
404 TMap fMap;
405
406 public:
407#ifdef R__COMPLETE_MEM_TERMINATION
409 TIter next(&fMap);
410 TObjString *key;
411 while((key = (TObjString*)next())) {
412 delete key;
413 }
414 }
415#endif
416 void Add(const char *key, TClass *&obj) {
417 TObjString *realkey = new TObjString(key);
418 fMap.Add(realkey, obj);
419 }
420 TClass* Find(const char *key) const {
421 const TPair *a = (const TPair *)fMap.FindObject(key);
422 if (a) return (TClass*) a->Value();
423 return 0;
424 }
425 void Remove(const char *key) {
426 TObjString realkey(key);
427 TObject *actual = fMap.Remove(&realkey);
428 delete actual;
429 }
430#endif
431 };
432
434 // Wrapper class for the multimap of DeclId_t and TClass.
435 public:
436 typedef multimap<TDictionary::DeclId_t, TClass*> DeclIdMap_t;
440 typedef std::pair <const_iterator, const_iterator> equal_range;
442
443 private:
445
446 public:
447 void Add(const key_type &key, mapped_type obj)
448 {
449 // Add the <key,obj> pair to the map.
450 std::pair<const key_type, mapped_type> pair = make_pair(key, obj);
451 fMap.insert(pair);
452 }
454 {
455 return fMap.count(key);
456 }
457 equal_range Find(const key_type &key) const
458 {
459 // Find the type corresponding to the key.
460 return fMap.equal_range(key);
461 }
462 void Remove(const key_type &key) {
463 // Remove the type corresponding to the key.
464 fMap.erase(key);
465 }
466 };
467}
468
470
471#ifdef R__COMPLETE_MEM_TERMINATION
472 static IdMap_t gIdMapObject;
473 return &gIdMapObject;
474#else
475 static IdMap_t *gIdMap = new IdMap_t;
476 return gIdMap;
477#endif
478}
479
481
482#ifdef R__COMPLETE_MEM_TERMINATION
483 static DeclIdMap_t gDeclIdMapObject;
484 return &gDeclIdMapObject;
485#else
486 static DeclIdMap_t *gDeclIdMap = new DeclIdMap_t;
487 return gDeclIdMap;
488#endif
489}
490
491////////////////////////////////////////////////////////////////////////////////
492/// static: Add a class to the list and map of classes.
493
495{
496 if (!cl) return;
497
499 gROOT->GetListOfClasses()->Add(cl);
500 if (cl->GetTypeInfo()) {
501 GetIdMap()->Add(cl->GetTypeInfo()->name(),cl);
502 }
503 if (cl->fClassInfo) {
504 GetDeclIdMap()->Add((void*)(cl->fClassInfo), cl);
505 }
506}
507
508////////////////////////////////////////////////////////////////////////////////
509/// static: Add a TClass* to the map of classes.
510
512{
513 if (!cl || !id) return;
514 GetDeclIdMap()->Add(id, cl);
515}
516
517////////////////////////////////////////////////////////////////////////////////
518/// static: Remove a class from the list and map of classes
519
521{
522 if (!oldcl) return;
523
525 gROOT->GetListOfClasses()->Remove(oldcl);
526 if (oldcl->GetTypeInfo()) {
527 GetIdMap()->Remove(oldcl->GetTypeInfo()->name());
528 }
529 if (oldcl->fClassInfo) {
530 //GetDeclIdMap()->Remove((void*)(oldcl->fClassInfo));
531 }
532}
533
534////////////////////////////////////////////////////////////////////////////////
535
537{
538 if (!id) return;
539 GetDeclIdMap()->Remove(id);
540}
541
542////////////////////////////////////////////////////////////////////////////////
543/// Indirect call to the implementation of ShowMember allowing [forward]
544/// declaration with out a full definition of the TClass class.
545
546void ROOT::Class_ShowMembers(TClass *cl, const void *obj, TMemberInspector&insp)
547{
548 gInterpreter->InspectMembers(insp, obj, cl, kFALSE);
549}
550
551//______________________________________________________________________________
552//______________________________________________________________________________
553
556public:
557 TDumpMembers(bool noAddr): fNoAddr(noAddr) { }
558
560 void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient);
561};
562
563////////////////////////////////////////////////////////////////////////////////
564/// Print value of member mname.
565///
566/// This method is called by the ShowMembers() method for each
567/// data member when object.Dump() is invoked.
568///
569/// - cl is the pointer to the current class
570/// - pname is the parent name (in case of composed objects)
571/// - mname is the data member name
572/// - add is the data member address
573
574void TDumpMembers::Inspect(TClass *cl, const char *pname, const char *mname, const void *add, Bool_t /* isTransient */)
575{
576 const Int_t kvalue = 30;
577#ifdef R__B64
578 const Int_t ktitle = 50;
579#else
580 const Int_t ktitle = 42;
581#endif
582 const Int_t kline = 1024;
583 Int_t cdate = 0;
584 Int_t ctime = 0;
585 UInt_t *cdatime = nullptr;
586 char line[kline];
587
588 TDataType *membertype;
589 EDataType memberDataType = kNoType_t;
590 const char *memberName;
591 const char *memberFullTypeName;
592 const char *memberTitle;
593 Bool_t isapointer;
594 Bool_t isbasic;
595 Bool_t isarray;
596
597 if (TDataMember *member = cl->GetDataMember(mname)) {
598 if (member->GetDataType()) {
599 memberDataType = (EDataType)member->GetDataType()->GetType();
600 }
601 memberName = member->GetName();
602 memberFullTypeName = member->GetFullTypeName();
603 memberTitle = member->GetTitle();
604 isapointer = member->IsaPointer();
605 isbasic = member->IsBasic();
606 membertype = member->GetDataType();
607 isarray = member->GetArrayDim();
608 } else if (!cl->IsLoaded()) {
609 // The class is not loaded, hence it is 'emulated' and the main source of
610 // information is the StreamerInfo.
612 if (!info) return;
613 const char *cursor = mname;
614 while ( (*cursor)=='*' ) ++cursor;
615 TString elname( cursor );
616 Ssiz_t pos = elname.Index("[");
617 if ( pos != kNPOS ) {
618 elname.Remove( pos );
619 }
620 TStreamerElement *element = (TStreamerElement*)info->GetElements()->FindObject(elname.Data());
621 if (!element) return;
622 memberFullTypeName = element->GetTypeName();
623
624 memberDataType = (EDataType)element->GetType();
625
626 memberName = element->GetName();
627 memberTitle = element->GetTitle();
628 isapointer = element->IsaPointer() || element->GetType() == TVirtualStreamerInfo::kCharStar;
629 membertype = gROOT->GetType(memberFullTypeName);
630
631 isbasic = membertype !=nullptr;
632 isarray = element->GetArrayDim();
633 } else {
634 return;
635 }
636
637
638 Bool_t isdate = kFALSE;
639 if (strcmp(memberName,"fDatime") == 0 && memberDataType == kUInt_t) {
640 isdate = kTRUE;
641 }
642 Bool_t isbits = kFALSE;
643 if (strcmp(memberName,"fBits") == 0 && memberDataType == kUInt_t) {
644 isbits = kTRUE;
645 }
646 TClass * dataClass = TClass::GetClass(memberFullTypeName);
647 Bool_t isTString = (dataClass == TString::Class());
648 static TClassRef stdClass("std::string");
649 Bool_t isStdString = (dataClass == stdClass);
650
651 Int_t i;
652 for (i = 0;i < kline; i++) line[i] = ' ';
653 line[kline-1] = 0;
654 snprintf(line,kline,"%s%s ",pname,mname);
655 i = strlen(line); line[i] = ' ';
656
657 // Encode data value or pointer value
658 char *pointer = (char*)add;
659 char **ppointer = (char**)(pointer);
660
661 if (isapointer) {
662 char **p3pointer = (char**)(*ppointer);
663 if (!p3pointer)
664 snprintf(&line[kvalue],kline-kvalue,"->0");
665 else if (!isbasic) {
666 if (!fNoAddr) {
667 snprintf(&line[kvalue],kline-kvalue,"->%zx ", (size_t)p3pointer);
668 }
669 } else if (membertype) {
670 if (!strcmp(membertype->GetTypeName(), "char")) {
671 i = strlen(*ppointer);
672 if (kvalue+i > kline) i=kline-1-kvalue;
673 Bool_t isPrintable = kTRUE;
674 for (Int_t j = 0; j < i; j++) {
675 if (!std::isprint((*ppointer)[j])) {
676 isPrintable = kFALSE;
677 break;
678 }
679 }
680 if (isPrintable) {
681 strncpy(line + kvalue, *ppointer, i);
682 line[kvalue+i] = 0;
683 } else {
684 line[kvalue] = 0;
685 }
686 } else {
687 strncpy(&line[kvalue], membertype->AsString(p3pointer), TMath::Min(kline-1-kvalue,(int)strlen(membertype->AsString(p3pointer))));
688 }
689 } else if (!strcmp(memberFullTypeName, "char*") ||
690 !strcmp(memberFullTypeName, "const char*")) {
691 i = strlen(*ppointer);
692 if (kvalue+i >= kline) i=kline-1-kvalue;
693 Bool_t isPrintable = kTRUE;
694 for (Int_t j = 0; j < i; j++) {
695 if (!std::isprint((*ppointer)[j])) {
696 isPrintable = kFALSE;
697 break;
698 }
699 }
700 if (isPrintable) {
701 strncpy(line + kvalue, *ppointer, std::min( i, kline - kvalue));
702 line[kvalue+i] = 0;
703 } else {
704 line[kvalue] = 0;
705 }
706 } else {
707 if (!fNoAddr) {
708 snprintf(&line[kvalue],kline-kvalue,"->%zx ", (size_t)p3pointer);
709 }
710 }
711 } else if (membertype) {
712 if (isdate) {
713 cdatime = (UInt_t*)pointer;
714 TDatime::GetDateTime(cdatime[0],cdate,ctime);
715 snprintf(&line[kvalue],kline-kvalue,"%d/%d",cdate,ctime);
716 } else if (isbits) {
717 snprintf(&line[kvalue],kline-kvalue,"0x%08x", *(UInt_t*)pointer);
718 } else {
719 strncpy(&line[kvalue], membertype->AsString(pointer), TMath::Min(kline-1-kvalue,(int)strlen(membertype->AsString(pointer))));
720 }
721 } else {
722 if (isStdString) {
723 std::string *str = (std::string*)pointer;
724 snprintf(&line[kvalue],kline-kvalue,"%s",str->c_str());
725 } else if (isTString) {
726 TString *str = (TString*)pointer;
727 snprintf(&line[kvalue],kline-kvalue,"%s",str->Data());
728 } else {
729 if (!fNoAddr) {
730 snprintf(&line[kvalue],kline-kvalue,"->%zx ", (size_t)pointer);
731 }
732 }
733 }
734 // Encode data member title
735 if (isdate == kFALSE && strcmp(memberFullTypeName, "char*") && strcmp(memberFullTypeName, "const char*")) {
736 i = strlen(&line[0]); line[i] = ' ';
737 assert(250 > ktitle);
738 strlcpy(&line[ktitle],memberTitle,250-ktitle+1); // strlcpy copy 'size-1' characters.
739 }
740 if (isarray) {
741 // Should iterate over the element
742 strncat(line, " ...", kline-strlen(line)-1);
743 }
744 Printf("%s", line);
745}
746
748
749//______________________________________________________________________________
750
752
753private:
756
757public:
758 TBuildRealData(void *obj, TClass *cl) {
759 // Main constructor.
760 fRealDataObject = obj;
761 fRealDataClass = cl;
762 }
764 void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient);
765
766};
767
768////////////////////////////////////////////////////////////////////////////////
769/// This method is called from ShowMembers() via BuildRealdata().
770
771void TBuildRealData::Inspect(TClass* cl, const char* pname, const char* mname, const void* add, Bool_t isTransient)
772{
773 TDataMember* dm = cl->GetDataMember(mname);
774 if (!dm) {
775 return;
776 }
777
778 Bool_t isTransientMember = kFALSE;
779
780 if (!dm->IsPersistent()) {
781 // For the DataModelEvolution we need access to the transient member.
782 // so we now record them in the list of RealData.
783 isTransientMember = kTRUE;
784 isTransient = kTRUE;
785 }
786
787 TString rname( pname );
788 // Take into account cases like TPaveStats->TPaveText->TPave->TBox.
789 // Check that member is in a derived class or an object in the class.
790 if (cl != fRealDataClass) {
791 if (!fRealDataClass->InheritsFrom(cl)) {
792 Ssiz_t dot = rname.Index('.');
793 if (dot == kNPOS) {
794 return;
795 }
796 rname[dot] = '\0';
797 if (!fRealDataClass->GetDataMember(rname)) {
798 //could be a data member in a base class like in this example
799 // class Event : public Data {
800 // class Data : public TObject {
801 // EventHeader fEvtHdr;
802 // class EventHeader {
803 // Int_t fEvtNum;
804 // Int_t fRun;
805 // Int_t fDate;
806 // EventVertex fVertex;
807 // class EventVertex {
808 // EventTime fTime;
809 // class EventTime {
810 // Int_t fSec;
811 // Int_t fNanoSec;
812 if (!fRealDataClass->GetBaseDataMember(rname)) {
813 return;
814 }
815 }
816 rname[dot] = '.';
817 }
818 }
819
820 Longptr_t offset = Longptr_t(((Longptr_t) add) - ((Longptr_t) fRealDataObject));
821
822 if (TClassEdit::IsStdArray(dm->GetTypeName())){ // We tackle the std array case
823 TString rdName;
824 TRealData::GetName(rdName,dm);
825 rname += rdName;
826 TRealData* rd = new TRealData(rname.Data(), offset, dm);
827 fRealDataClass->GetListOfRealData()->Add(rd);
828 return;
829 }
830
831 rname += mname;
832
833 if (dm->IsaPointer()) {
834 // Data member is a pointer.
835 TRealData* rd = new TRealData(rname, offset, dm);
836 if (isTransientMember) { rd->SetBit(TRealData::kTransient); };
837 fRealDataClass->GetListOfRealData()->Add(rd);
838 } else {
839 // Data Member is a basic data type.
840 TRealData* rd = new TRealData(rname, offset, dm);
841 if (isTransientMember) { rd->SetBit(TRealData::kTransient); };
842 if (!dm->IsBasic()) {
843 rd->SetIsObject(kTRUE);
844
845 // Make sure that BuildReadData is called for any abstract
846 // bases classes involved in this object, i.e for all the
847 // classes composing this object (base classes, type of
848 // embedded object and same for their data members).
849 //
850 TClass* dmclass = TClass::GetClass(dm->GetTypeName(), kTRUE, isTransient);
851 if (!dmclass) {
852 dmclass = TClass::GetClass(dm->GetTrueTypeName(), kTRUE, isTransient);
853 }
854 if (dmclass) {
855 if ((dmclass != cl) && !dm->IsaPointer()) {
856 if (dmclass->GetCollectionProxy()) {
857 TClass* valcl = dmclass->GetCollectionProxy()->GetValueClass();
858 // We create the real data for the content of the collection to help the case
859 // of split branches in a TTree (where the node for the data member itself
860 // might have been elided). However, in some cases, like transient members
861 // and/or classes, the content might not be create-able. An example is the
862 // case of a map<A,B> where either A or B does not have default constructor
863 // and thus the compilation of the default constructor for pair<A,B> will
864 // fail (noisily) [This could also apply to any template instance, where it
865 // might have a default constructor definition that can not be compiled due
866 // to the template parameter]
867 if (valcl) {
868 Bool_t wantBuild = kTRUE;
869 if (valcl->Property() & kIsAbstract) wantBuild = kFALSE;
870 if ( (isTransient)
872 && (!valcl->IsLoaded()) ) {
873 // Case where the collection dictionary was not requested and
874 // the content's dictionary was also not requested.
875 // [This is a super set of what we need, but we can't really detect it :(]
876 wantBuild = kFALSE;
877 }
878
879 if (wantBuild) valcl->BuildRealData(nullptr, isTransient);
880 }
881 } else {
882 void* addrForRecursion = nullptr;
883 if (GetObjectValidity() == kValidObjectGiven)
884 addrForRecursion = const_cast<void*>(add);
885
886 dmclass->BuildRealData(addrForRecursion, isTransient);
887 }
888 }
889 }
890 }
891 fRealDataClass->GetListOfRealData()->Add(rd);
892 }
893}
894
895//______________________________________________________________________________
896//______________________________________________________________________________
897//______________________________________________________________________________
898
899////////////////////////////////////////////////////////////////////////////////
900
902public:
905
907 // main constructor.
908 fBrowser = b; fCount = 0; }
909 virtual ~TAutoInspector() { }
911 virtual void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient);
913};
914
915////////////////////////////////////////////////////////////////////////////////
916/// This method is called from ShowMembers() via AutoBrowse().
917
918void TAutoInspector::Inspect(TClass *cl, const char *tit, const char *name,
919 const void *addr, Bool_t /* isTransient */)
920{
921 if(tit && strchr(tit,'.')) return ;
922 if (fCount && !fBrowser) return;
923
924 TString ts;
925
926 if (!cl) return;
927 //if (*(cl->GetName()) == 'T') return;
928 if (*name == '*') name++;
929 int ln = strcspn(name,"[ ");
930 TString iname(name,ln);
931
932 ClassInfo_t *classInfo = cl->GetClassInfo();
933 if (!classInfo) return;
934
935 // Browse data members
937 TString mname;
938
939 int found=0;
940 while (gCling->DataMemberInfo_Next(m)) { // MemberLoop
941 mname = gCling->DataMemberInfo_Name(m);
942 mname.ReplaceAll("*","");
943 if ((found = (iname==mname))) break;
944 }
945 assert(found);
946
947 // we skip: non static members and non objects
948 // - the member G__virtualinfo inserted by the CINT RTTI system
949
950 //Long_t prop = m.Property() | m.Type()->Property();
952 if (prop & kIsStatic) return;
953 if (prop & kIsFundamental) return;
954 if (prop & kIsEnum) return;
955 if (mname == "G__virtualinfo") return;
956
957 int size = sizeof(void*);
958
959 int nmax = 1;
960 if (prop & kIsArray) {
961 for (int dim = 0; dim < gCling->DataMemberInfo_ArrayDim(m); dim++) nmax *= gCling->DataMemberInfo_MaxIndex(m,dim);
962 }
963
966 TClass * clm = TClass::GetClass(clmName.c_str());
967 R__ASSERT(clm);
968 if (!(prop & kIsPointer)) {
969 size = clm->Size();
971 }
972
973
976
977 for(int i=0; i<nmax; i++) {
978
979 char *ptr = (char*)addr + i*size;
980
981 void *obj = (prop & kIsPointer) ? *((void**)ptr) : (TObject*)ptr;
982
983 if (!obj) continue;
984
985 fCount++;
986 if (!fBrowser) return;
987
988 TString bwname;
989 TClass *actualClass = clm->GetActualClass(obj);
990 if (clm->IsTObject()) {
991 TObject *tobj = (TObject*)clm->DynamicCast(TObject::Class(),obj);
992 bwname = tobj->GetName();
993 } else {
994 bwname = actualClass->GetName();
995 bwname += "::";
996 bwname += mname;
997 }
998
999 if (!clm->IsTObject() ||
1000 bwname.Length()==0 ||
1001 strcmp(bwname.Data(),actualClass->GetName())==0) {
1002 bwname = name;
1003 int l = strcspn(bwname.Data(),"[ ");
1004 if (l<bwname.Length() && bwname[l]=='[') {
1005 char cbuf[13]; snprintf(cbuf,13,"[%02d]",i);
1006 ts.Replace(0,999,bwname,l);
1007 ts += cbuf;
1008 bwname = (const char*)ts;
1009 }
1010 }
1011
1012 if (proxy==nullptr) {
1013
1014 fBrowser->Add(obj,clm,bwname);
1015
1016 } else {
1017 TClass *valueCl = proxy->GetValueClass();
1018
1019 if (valueCl==nullptr) {
1020
1021 fBrowser->Add( obj, clm, bwname );
1022
1023 } else {
1024 TVirtualCollectionProxy::TPushPop env(proxy, obj);
1025 TClass *actualCl = nullptr;
1026
1027 int sz = proxy->Size();
1028
1029 char fmt[] = {"#%09d"};
1030 fmt[3] = '0'+(int)log10(double(sz))+1;
1031 char buf[20];
1032 for (int ii=0;ii<sz;ii++) {
1033 void *p = proxy->At(ii);
1034
1035 if (proxy->HasPointers()) {
1036 p = *((void**)p);
1037 if(!p) continue;
1038 actualCl = valueCl->GetActualClass(p);
1039 p = actualCl->DynamicCast(valueCl,p,0);
1040 }
1041 fCount++;
1042 snprintf(buf,20,fmt,ii);
1043 ts = bwname;
1044 ts += buf;
1045 fBrowser->Add( p, actualCl, ts );
1046 }
1047 }
1048 }
1049 }
1050}
1051
1052//______________________________________________________________________________
1053//______________________________________________________________________________
1054//______________________________________________________________________________
1055
1057
1058////////////////////////////////////////////////////////////////////////////////
1059/// Internal, default constructor.
1060///
1061/// \note Use `TClass::GetClass("ClassName")` to get access to a TClass object for a certain class!
1062
1064 TDictionary(),
1065 fPersistentRef(nullptr),
1066 fStreamerInfo(nullptr), fConversionStreamerInfo(nullptr), fRealData(nullptr),
1067 fBase(nullptr), fData(nullptr), fUsingData(nullptr), fEnums(nullptr), fFuncTemplate(nullptr), fMethod(nullptr), fAllPubData(nullptr),
1068 fAllPubMethod(nullptr), fClassMenuList(nullptr),
1070 fInstanceCount(0), fOnHeap(0),
1071 fCheckSum(0), fCollectionProxy(nullptr), fClassVersion(0), fClassInfo(nullptr),
1072 fTypeInfo(nullptr), fShowMembers(nullptr),
1073 fStreamer(nullptr), fIsA(nullptr), fGlobalIsA(nullptr), fIsAMethod(nullptr),
1074 fMerge(nullptr), fResetAfterMerge(nullptr), fNew(nullptr), fNewArray(nullptr), fDelete(nullptr), fDeleteArray(nullptr),
1075 fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fSizeof(-1),
1078 fState(kNoInfo),
1079 fCurrentInfo(nullptr), fLastReadInfo(nullptr), fRefProxy(nullptr),
1081
1082{
1083 // Default ctor.
1084
1086 {
1087 TMmallocDescTemp setreset;
1088 fStreamerInfo = new TObjArray(1, -2);
1089 }
1090 fDeclFileLine = -2; // -2 for standalone TClass (checked in dtor)
1091}
1092
1093////////////////////////////////////////////////////////////////////////////////
1094/// Create a TClass object. This object contains the full dictionary
1095/// of a class. It has list to baseclasses, datamembers and methods.
1096/// Use this ctor to create a standalone TClass object. Only useful
1097/// to get a temporary TClass interface to an interpreted class. Used by TTabCom.
1098///
1099/// \note Use `TClass::GetClass("ClassName")` to get access to a TClass object for a certain class!
1100
1101TClass::TClass(const char *name, Bool_t silent) :
1103 fPersistentRef(nullptr),
1104 fStreamerInfo(nullptr), fConversionStreamerInfo(nullptr), fRealData(nullptr),
1105 fBase(nullptr), fData(nullptr), fUsingData(nullptr), fEnums(nullptr), fFuncTemplate(nullptr), fMethod(nullptr), fAllPubData(nullptr),
1106 fAllPubMethod(nullptr), fClassMenuList(nullptr),
1107 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1108 fInstanceCount(0), fOnHeap(0),
1109 fCheckSum(0), fCollectionProxy(nullptr), fClassVersion(0), fClassInfo(nullptr),
1110 fTypeInfo(nullptr), fShowMembers(nullptr),
1111 fStreamer(nullptr), fIsA(nullptr), fGlobalIsA(nullptr), fIsAMethod(nullptr),
1112 fMerge(nullptr), fResetAfterMerge(nullptr), fNew(nullptr), fNewArray(nullptr), fDelete(nullptr), fDeleteArray(nullptr),
1113 fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fSizeof(-1),
1114 fCanSplit(-1), fIsSyntheticPair(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1115 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1116 fState(kNoInfo),
1117 fCurrentInfo(nullptr), fLastReadInfo(nullptr), fRefProxy(nullptr),
1118 fSchemaRules(nullptr), fStreamerImpl(&TClass::StreamerDefault)
1119{
1121
1122 if (!gROOT)
1123 ::Fatal("TClass::TClass", "ROOT system not initialized");
1124
1125 {
1126 TMmallocDescTemp setreset;
1127 fStreamerInfo = new TObjArray(1, -2);
1128 }
1129 fDeclFileLine = -2; // -2 for standalone TClass (checked in dtor)
1130
1132 if (!gInterpreter)
1133 ::Fatal("TClass::TClass", "gInterpreter not initialized");
1134
1135 gInterpreter->SetClassInfo(this); // sets fClassInfo pointer
1136 if (!silent && !fClassInfo && !TClassEdit::IsArtificial(name))
1137 ::Warning("TClass::TClass", "no dictionary for class %s is available", name);
1139
1141 fConversionStreamerInfo = nullptr;
1142}
1143
1144////////////////////////////////////////////////////////////////////////////////
1145/// Internal constructor.
1146///
1147/// \note Use `TClass::GetClass("ClassName")` to get access to a TClass object for a certain class!
1148
1149TClass::TClass(const char *name, Version_t cversion, Bool_t silent) :
1151 fPersistentRef(nullptr),
1152 fStreamerInfo(nullptr), fConversionStreamerInfo(nullptr), fRealData(nullptr),
1153 fBase(nullptr), fData(nullptr), fUsingData(nullptr), fEnums(nullptr), fFuncTemplate(nullptr), fMethod(nullptr), fAllPubData(nullptr),
1154 fAllPubMethod(nullptr), fClassMenuList(nullptr),
1155 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1156 fInstanceCount(0), fOnHeap(0),
1157 fCheckSum(0), fCollectionProxy(nullptr), fClassVersion(0), fClassInfo(nullptr),
1158 fTypeInfo(nullptr), fShowMembers(nullptr),
1159 fStreamer(nullptr), fIsA(nullptr), fGlobalIsA(nullptr), fIsAMethod(nullptr),
1160 fMerge(nullptr), fResetAfterMerge(nullptr), fNew(nullptr), fNewArray(nullptr), fDelete(nullptr), fDeleteArray(nullptr),
1161 fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fSizeof(-1),
1162 fCanSplit(-1), fIsSyntheticPair(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1163 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1164 fState(kNoInfo),
1165 fCurrentInfo(nullptr), fLastReadInfo(nullptr), fRefProxy(nullptr),
1166 fSchemaRules(nullptr), fStreamerImpl(&TClass::StreamerDefault)
1167{
1169 Init(name, cversion, nullptr, nullptr, nullptr, nullptr, -1, -1, nullptr, silent);
1170}
1171
1172////////////////////////////////////////////////////////////////////////////////
1173/// Internal constructor, mimicing the case of a class fwd declared in the interpreter.
1174///
1175/// \note Use `TClass::GetClass("ClassName")` to get access to a TClass object for a certain class!
1176
1177TClass::TClass(const char *name, Version_t cversion, EState theState, Bool_t silent) :
1179 fPersistentRef(nullptr),
1180 fStreamerInfo(nullptr), fConversionStreamerInfo(nullptr), fRealData(nullptr),
1181 fBase(nullptr), fData(nullptr), fUsingData(nullptr), fEnums(nullptr), fFuncTemplate(nullptr), fMethod(nullptr), fAllPubData(nullptr),
1182 fAllPubMethod(nullptr), fClassMenuList(nullptr),
1183 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1184 fInstanceCount(0), fOnHeap(0),
1185 fCheckSum(0), fCollectionProxy(nullptr), fClassVersion(0), fClassInfo(nullptr),
1186 fTypeInfo(nullptr), fShowMembers(nullptr),
1187 fStreamer(nullptr), fIsA(nullptr), fGlobalIsA(nullptr), fIsAMethod(nullptr),
1188 fMerge(nullptr), fResetAfterMerge(nullptr), fNew(nullptr), fNewArray(nullptr), fDelete(nullptr), fDeleteArray(nullptr),
1189 fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fSizeof(-1),
1190 fCanSplit(-1), fIsSyntheticPair(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1191 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1192 fState(theState),
1193 fCurrentInfo(nullptr), fLastReadInfo(nullptr), fRefProxy(nullptr),
1194 fSchemaRules(nullptr), fStreamerImpl(&TClass::StreamerDefault)
1195{
1197
1198 // Treat the case in which a TClass instance is created for a namespace
1199 if (theState == kNamespaceForMeta){
1201 theState = kForwardDeclared; // it immediately decays in kForwardDeclared
1202 }
1203
1204 if (theState != kForwardDeclared && theState != kEmulated)
1205 ::Fatal("TClass::TClass",
1206 "A TClass entry cannot be initialized in a state different from kForwardDeclared or kEmulated.");
1207 Init(name, cversion, nullptr, nullptr, nullptr, nullptr, -1, -1, nullptr, silent);
1208}
1209
1210////////////////////////////////////////////////////////////////////////////////
1211/// Internal constructor.
1212///
1213/// Create a TClass object. This object contains the full dictionary
1214/// of a class. It has list to baseclasses, datamembers and methods.
1215/// Use this ctor to create a standalone TClass object. Most useful
1216/// to get a TClass interface to an interpreted class. Used by TTabCom.
1217///
1218/// This copies the ClassInfo (i.e. does *not* take ownership of it).
1219///
1220/// \note Use `TClass::GetClass("class")` to get access to a TClass object for a certain class!
1221
1222TClass::TClass(ClassInfo_t *classInfo, Version_t cversion,
1223 const char *dfil, const char *ifil, Int_t dl, Int_t il, Bool_t silent) :
1224 TDictionary(""),
1225 fPersistentRef(nullptr),
1226 fStreamerInfo(nullptr), fConversionStreamerInfo(nullptr), fRealData(nullptr),
1227 fBase(nullptr), fData(nullptr), fUsingData(nullptr), fEnums(nullptr), fFuncTemplate(nullptr), fMethod(nullptr), fAllPubData(nullptr),
1228 fAllPubMethod(nullptr), fClassMenuList(nullptr),
1229 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1230 fInstanceCount(0), fOnHeap(0),
1231 fCheckSum(0), fCollectionProxy(nullptr), fClassVersion(0), fClassInfo(nullptr),
1232 fTypeInfo(nullptr), fShowMembers(nullptr),
1233 fStreamer(nullptr), fIsA(nullptr), fGlobalIsA(nullptr), fIsAMethod(nullptr),
1234 fMerge(nullptr), fResetAfterMerge(nullptr), fNew(nullptr), fNewArray(nullptr), fDelete(nullptr), fDeleteArray(nullptr),
1235 fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fSizeof(-1),
1236 fCanSplit(-1), fIsSyntheticPair(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1237 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1238 fState(kNoInfo),
1239 fCurrentInfo(nullptr), fLastReadInfo(nullptr), fRefProxy(nullptr),
1240 fSchemaRules(nullptr), fStreamerImpl(&TClass::StreamerDefault)
1241{
1243
1244 if (!gROOT)
1245 ::Fatal("TClass::TClass", "ROOT system not initialized");
1246
1247 fDeclFileLine = -2; // -2 for standalone TClass (checked in dtor)
1248
1250 if (!gInterpreter)
1251 ::Fatal("TClass::TClass", "gInterpreter not initialized");
1252
1253 if (!classInfo || !gInterpreter->ClassInfo_IsValid(classInfo)) {
1254 MakeZombie();
1255 fState = kNoInfo;
1256 } else {
1257 fName = gInterpreter->ClassInfo_FullName(classInfo);
1258
1260 Init(fName, cversion, nullptr, nullptr, dfil, ifil, dl, il, classInfo, silent);
1261 }
1263
1264 fConversionStreamerInfo = nullptr;
1265}
1266
1267
1268////////////////////////////////////////////////////////////////////////////////
1269/// Internal constructor.
1270///
1271/// \note Use `TClass::GetClass("class")` to get access to a TClass object for a certain class!
1272
1273TClass::TClass(const char *name, Version_t cversion,
1274 const char *dfil, const char *ifil, Int_t dl, Int_t il, Bool_t silent) :
1276 fPersistentRef(nullptr),
1277 fStreamerInfo(nullptr), fConversionStreamerInfo(nullptr), fRealData(nullptr),
1278 fBase(nullptr), fData(nullptr), fUsingData(nullptr), fEnums(nullptr), fFuncTemplate(nullptr), fMethod(nullptr), fAllPubData(nullptr),
1279 fAllPubMethod(nullptr), fClassMenuList(nullptr),
1280 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1281 fInstanceCount(0), fOnHeap(0),
1282 fCheckSum(0), fCollectionProxy(nullptr), fClassVersion(0), fClassInfo(nullptr),
1283 fTypeInfo(nullptr), fShowMembers(nullptr),
1284 fStreamer(nullptr), fIsA(nullptr), fGlobalIsA(nullptr), fIsAMethod(nullptr),
1285 fMerge(nullptr), fResetAfterMerge(nullptr), fNew(nullptr), fNewArray(nullptr), fDelete(nullptr), fDeleteArray(nullptr),
1286 fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fSizeof(-1),
1287 fCanSplit(-1), fIsSyntheticPair(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1288 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1289 fState(kNoInfo),
1290 fCurrentInfo(nullptr), fLastReadInfo(nullptr), fRefProxy(nullptr),
1291 fSchemaRules(nullptr), fStreamerImpl(&TClass::StreamerDefault)
1292{
1294 Init(name,cversion, nullptr, nullptr, dfil, ifil, dl, il, nullptr, silent);
1295}
1296
1297////////////////////////////////////////////////////////////////////////////////
1298/// Internal constructor.
1299///
1300/// \note Use `TClass::GetClass("class")` to get access to a TClass object for a certain class!
1301
1302TClass::TClass(const char *name, Version_t cversion,
1303 const std::type_info &info, TVirtualIsAProxy *isa,
1304 const char *dfil, const char *ifil, Int_t dl, Int_t il,
1305 Bool_t silent) :
1307 fPersistentRef(nullptr),
1308 fStreamerInfo(nullptr), fConversionStreamerInfo(nullptr), fRealData(nullptr),
1309 fBase(nullptr), fData(nullptr), fUsingData(nullptr), fEnums(nullptr), fFuncTemplate(nullptr), fMethod(nullptr), fAllPubData(nullptr),
1310 fAllPubMethod(nullptr),
1311 fClassMenuList(nullptr),
1312 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1313 fInstanceCount(0), fOnHeap(0),
1314 fCheckSum(0), fCollectionProxy(nullptr), fClassVersion(0), fClassInfo(nullptr),
1315 fTypeInfo(nullptr), fShowMembers(nullptr),
1316 fStreamer(nullptr), fIsA(nullptr), fGlobalIsA(nullptr), fIsAMethod(nullptr),
1317 fMerge(nullptr), fResetAfterMerge(nullptr), fNew(nullptr), fNewArray(nullptr), fDelete(nullptr), fDeleteArray(nullptr),
1318 fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fSizeof(-1),
1319 fCanSplit(-1), fIsSyntheticPair(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1320 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1321 fState(kHasTClassInit),
1322 fCurrentInfo(nullptr), fLastReadInfo(nullptr), fRefProxy(nullptr),
1323 fSchemaRules(nullptr), fStreamerImpl(&TClass::StreamerDefault)
1324{
1326 // use info
1327 Init(name, cversion, &info, isa, dfil, ifil, dl, il, nullptr, silent);
1328}
1329
1330////////////////////////////////////////////////////////////////////////////////
1331/// we found at least one equivalent.
1332/// let's force a reload
1333
1335{
1336 TClass::RemoveClass(oldcl);
1337
1338 if (oldcl->CanIgnoreTObjectStreamer()) {
1340 }
1341
1343 TIter next(oldcl->GetStreamerInfos());
1344 while ((info = (TVirtualStreamerInfo*)next())) {
1345 info->Clear("build");
1346 info->SetClass(this);
1347 if (IsSyntheticPair()) {
1348 // Some pair's StreamerInfo were inappropriately marked as versioned
1349 info->SetClassVersion(1);
1350 // There is already a TStreamerInfo put there by the synthetic
1351 // creation.
1352 fStreamerInfo->Add(info);
1353 } else {
1355 }
1356 }
1357 oldcl->fStreamerInfo->Clear();
1358
1359 oldcl->ReplaceWith(this);
1360 delete oldcl;
1361}
1362
1363////////////////////////////////////////////////////////////////////////////////
1364/// Initialize a TClass object. This object contains the full dictionary
1365/// of a class. It has list to baseclasses, datamembers and methods.
1366
1367void TClass::Init(const char *name, Version_t cversion,
1368 const std::type_info *typeinfo, TVirtualIsAProxy *isa,
1369 const char *dfil, const char *ifil, Int_t dl, Int_t il,
1370 ClassInfo_t *givenInfo,
1371 Bool_t silent)
1372{
1373 if (!gROOT)
1374 ::Fatal("TClass::TClass", "ROOT system not initialized");
1375 if (!name || !name[0]) {
1376 ::Error("TClass::Init", "The name parameter is invalid (null or empty)");
1377 MakeZombie();
1378 return;
1379 }
1380 // Always strip the default STL template arguments (from any template argument or the class name)
1382 fName = name; // We can assume that the artificial class name is already normalized.
1383 else
1385
1386 fClassVersion = cversion;
1387 fDeclFileName = dfil ? dfil : "";
1388 fImplFileName = ifil ? ifil : "";
1389 fDeclFileLine = dl;
1390 fImplFileLine = il;
1391 fTypeInfo = typeinfo;
1392 fIsA = isa;
1393 if ( fIsA ) fIsA->SetClass(this);
1394 // See also TCling::GenerateTClass() which will update fClassVersion after creation!
1395 fStreamerInfo = new TObjArray(fClassVersion+2+10,-1); // +10 to read new data by old
1396 fProperty = -1;
1397 fClassProperty = 0;
1398 const bool ispair = TClassEdit::IsStdPair(fName);
1399 if (ispair)
1401
1403
1404 TClass *oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(fName.Data());
1405
1407
1408 if (oldcl && oldcl->TestBit(kLoading)) {
1409 // Do not recreate a class while it is already being created!
1410
1411 // We can no longer reproduce this case, to check whether we are, we use
1412 // this code:
1413 // Fatal("Init","A bad replacement for %s was requested\n",name);
1414 return;
1415 }
1416
1417 TClass **persistentRef = nullptr;
1418 if (oldcl) {
1419
1420 persistentRef = oldcl->fPersistentRef.exchange(nullptr);
1421
1422 // The code from here is also in ForceReload.
1423 TClass::RemoveClass(oldcl);
1424 // move the StreamerInfo immediately so that there are
1425 // properly updated!
1426
1427 if (oldcl->CanIgnoreTObjectStreamer()) {
1429 }
1431
1432 TIter next(oldcl->GetStreamerInfos());
1433 while ((info = (TVirtualStreamerInfo*)next())) {
1434 // We need to force a call to BuildOld
1435 info->Clear("build");
1436 info->SetClass(this);
1438 }
1439 oldcl->fStreamerInfo->Clear();
1440 // The code diverges here from ForceReload.
1441
1442 // Move the Schema Rules too.
1443 fSchemaRules = oldcl->fSchemaRules;
1444 oldcl->fSchemaRules = nullptr;
1445
1446 // Move the TFunctions.
1448 if (fFuncTemplate)
1449 fFuncTemplate->fClass = this;
1450 oldcl->fFuncTemplate = nullptr;
1451 fMethod.store( oldcl->fMethod );
1452 if (fMethod)
1453 (*fMethod).fClass = this;
1454 oldcl->fMethod = nullptr;
1455
1456 }
1457
1459 // Advertise ourself as the loading class for this class name
1460 TClass::AddClass(this);
1461
1463
1464 if (!gInterpreter)
1465 ::Fatal("TClass::Init", "gInterpreter not initialized");
1466
1467 if (givenInfo) {
1468 bool invalid = !gInterpreter->ClassInfo_IsValid(givenInfo);
1469 bool notloaded = !gInterpreter->ClassInfo_IsLoaded(givenInfo);
1470 auto property = gInterpreter->ClassInfo_Property(givenInfo);
1471
1472 if (invalid || (notloaded && (property & kIsNamespace)) ||
1473 !(property & (kIsClass | kIsStruct | kIsNamespace))) {
1475 MakeZombie();
1476 fState = kNoInfo;
1477 TClass::RemoveClass(this);
1478 return;
1479 }
1480 }
1481
1482 if (!invalid) {
1483 fClassInfo = gInterpreter->ClassInfo_Factory(givenInfo);
1484 fCanLoadClassInfo = false; // avoids calls to LoadClassInfo() if info is already loaded
1485 if (fState <= kEmulated)
1487 }
1488 }
1489
1490 // We need to check if the class it is not fwd declared for the cases where we
1491 // created a TClass directly in the kForwardDeclared state. Indeed in those cases
1492 // fClassInfo will always be nullptr.
1494
1495 if (fState == kHasTClassInit) {
1496 // If the TClass is being generated from a ROOT dictionary,
1497 // even though we do not seem to have a CINT dictionary for
1498 // the class, we will will try to load it anyway UNLESS
1499 // the class is an STL container (or string).
1500 // This is because we do not expect the CINT dictionary
1501 // to be present for all STL classes (and we can handle
1502 // the lack of CINT dictionary in that cases).
1503 // However, the cling the dictionary no longer carries
1504 // an instantiation with it, unless we request the loading
1505 // here *or* the user explicitly instantiate the template
1506 // we would not have a ClassInfo for the template
1507 // instantiation.
1509 // Here we check and grab the info from the rootpcm.
1511 if (proto)
1512 proto->FillTClass(this);
1513 }
1514 if (!fHasRootPcmInfo && gInterpreter->CheckClassInfo(fName, /* autoload = */ kTRUE)) {
1515 gInterpreter->SetClassInfo(this); // sets fClassInfo pointer
1516 if (fClassInfo) {
1517 // This should be moved out of GetCheckSum itself however the last time
1518 // we tried this cause problem, in particular in the end-of-process operation.
1519 // fCheckSum = GetCheckSum(kLatestCheckSum);
1520 } else {
1521 if (!fClassInfo) {
1522 if (IsZombie()) {
1523 TClass::RemoveClass(this);
1524 return;
1525 }
1526 }
1527 }
1528 }
1529 }
1530 if (!silent && (!fClassInfo && !fCanLoadClassInfo) && !isStl && !TClassEdit::IsArtificial(fName) &&
1532 if (fState == kHasTClassInit) {
1533 if (fImplFileLine == -1 && fClassVersion == 0) {
1534 // We have a 'transient' class with a ClassDefInline and apparently no interpreter
1535 // information. Since it is transient, it is more than likely that the lack
1536 // will be harmles.
1537 } else {
1538 ::Error("TClass::Init", "no interpreter information for class %s is available even though it has a TClass "
1539 "initialization routine.",
1540 fName.Data());
1541 }
1542 } else {
1543 const bool ispairbase = TClassEdit::IsStdPairBase(fName.Data()) && !IsFromRootCling();
1544 if (!ispairbase)
1545 ::Warning("TClass::Init", "no dictionary for class %s is available", fName.Data());
1546 }
1547 }
1548
1549 fgClassCount++;
1551
1552 // Make the typedef-expanded -> original hash table entries.
1553 // There may be several entries for any given key.
1554 // We only make entries if the typedef-expanded name
1555 // is different from the original name.
1556 TString resolvedThis;
1557 if (!givenInfo && strchr (name, '<')) {
1558 if ( fName != name) {
1559 if (!fgClassTypedefHash) {
1560 fgClassTypedefHash = new THashTable (100, 5);
1562 }
1563
1564 fgClassTypedefHash->Add (new TNameMapNode (name, fName));
1566
1567 }
1568 resolvedThis = TClassEdit::ResolveTypedef (name, kTRUE);
1569 if (resolvedThis != name) {
1570 if (!fgClassTypedefHash) {
1571 fgClassTypedefHash = new THashTable (100, 5);
1573 }
1574
1575 fgClassTypedefHash->Add (new TNameMapNode (resolvedThis, fName));
1577 }
1578
1579 }
1580
1581 //In case a class with the same name had been created by TVirtualStreamerInfo
1582 //we must delete the old class, importing only the StreamerInfo structure
1583 //from the old dummy class.
1584 if (oldcl) {
1585
1586 oldcl->ReplaceWith(this);
1587 delete oldcl;
1588
1589 } else if (!givenInfo && resolvedThis.Length() > 0 && fgClassTypedefHash) {
1590
1591 // Check for existing equivalent.
1592
1593 if (resolvedThis != fName) {
1594 oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(resolvedThis);
1595 if (oldcl && oldcl != this) {
1596 persistentRef = oldcl->fPersistentRef.exchange(nullptr);
1597 ForceReload (oldcl);
1598 }
1599 }
1600 TIter next( fgClassTypedefHash->GetListForObject(resolvedThis) );
1601 while ( TNameMapNode* htmp = static_cast<TNameMapNode*> (next()) ) {
1602 if (resolvedThis != htmp->String()) continue;
1603 oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(htmp->fOrigName); // gROOT->GetClass (htmp->fOrigName, kFALSE);
1604 if (oldcl && oldcl != this) {
1605 persistentRef = oldcl->fPersistentRef.exchange(nullptr);
1606 ForceReload (oldcl);
1607 }
1608 }
1609 }
1610 if (fClassInfo) {
1612 if ( fDeclFileName == nullptr || fDeclFileName[0] == '\0' ) {
1613 fDeclFileName = kUndeterminedClassInfoName;
1614 // Missing interface:
1615 // fDeclFileLine = gInterpreter->ClassInfo_FileLine( fClassInfo );
1616
1617 // But really do not want to set ImplFileLine as it is currently the
1618 // marker of being 'loaded' or not (reminder loaded == has a TClass bootstrap).
1619 }
1620 }
1621
1622 if (persistentRef) {
1623 fPersistentRef = persistentRef;
1624 } else {
1625 fPersistentRef = new TClass*;
1626 }
1627 *fPersistentRef = this;
1628
1629 if ( isStl || !strncmp(GetName(),"stdext::hash_",13) || !strncmp(GetName(),"__gnu_cxx::hash_",16) ) {
1630 if (fState != kHasTClassInit) {
1631 // If we have a TClass compiled initialization, we can safely assume that
1632 // there will also be a collection proxy.
1634 if (fCollectionProxy) {
1636
1637 // Numeric Collections have implicit conversions:
1639
1640 } else if (!silent) {
1641 Warning("Init","Collection proxy for %s was not properly initialized!",GetName());
1642 }
1643 if (fStreamer==nullptr) {
1645 }
1646 }
1647 } else if (TClassEdit::IsStdPair(GetName())) {
1648 // std::pairs have implicit conversions
1650 }
1651
1653}
1654
1655////////////////////////////////////////////////////////////////////////////////
1656/// TClass dtor. Deletes all list that might have been created.
1657
1659{
1661
1662 // Remove from the typedef hashtables.
1664 TString resolvedThis = TClassEdit::ResolveTypedef (GetName(), kTRUE);
1665 TIter next (fgClassTypedefHash->GetListForObject (resolvedThis));
1666 while ( TNameMapNode* htmp = static_cast<TNameMapNode*> (next()) ) {
1667 if (resolvedThis == htmp->String() && htmp->fOrigName == GetName()) {
1668 fgClassTypedefHash->Remove (htmp);
1669 delete htmp;
1670 break;
1671 }
1672 }
1673 }
1674
1675 // Not owning lists, don't call Delete()
1676 // But this still need to be done first because the TList destructor
1677 // does access the object contained (via GetObject()->TestBit(kCanDelete))
1678 delete fStreamer; fStreamer =nullptr;
1679 delete fAllPubData; fAllPubData =nullptr;
1680 delete fAllPubMethod; fAllPubMethod=nullptr;
1681
1682 delete fPersistentRef.load();
1683
1684 if (fBase.load())
1685 (*fBase).Delete();
1686 delete fBase.load(); fBase = nullptr;
1687
1688 if (fData.load())
1689 (*fData).Delete();
1690 delete fData.load(); fData = nullptr;
1691
1692 if (fUsingData.load())
1693 (*fUsingData).Delete();
1694 delete fUsingData.load(); fUsingData = nullptr;
1695
1696 if (fEnums.load())
1697 (*fEnums).Delete();
1698 delete fEnums.load(); fEnums = nullptr;
1699
1700 if (fFuncTemplate)
1702 delete fFuncTemplate; fFuncTemplate = nullptr;
1703
1704 if (fMethod.load())
1705 (*fMethod).Delete();
1706 delete fMethod.load(); fMethod=nullptr;
1707
1708 if (fRealData)
1709 fRealData->Delete();
1710 delete fRealData; fRealData=nullptr;
1711
1712 if (fStreamerInfo)
1714 delete fStreamerInfo; fStreamerInfo = nullptr;
1715
1716 if (fDeclFileLine >= -1)
1717 TClass::RemoveClass(this);
1718
1720 fClassInfo=nullptr;
1721
1722 if (fClassMenuList)
1724 delete fClassMenuList; fClassMenuList=nullptr;
1725
1727
1728 if ( fIsA ) delete fIsA;
1729
1730 if ( fRefProxy ) fRefProxy->Release();
1731 fRefProxy = nullptr;
1732
1733 delete fStreamer;
1734 delete fCollectionProxy;
1735 delete fIsAMethod.load();
1736 delete fSchemaRules;
1737 if (fConversionStreamerInfo.load()) {
1738 std::map<std::string, TObjArray*>::iterator it;
1739 std::map<std::string, TObjArray*>::iterator end = (*fConversionStreamerInfo).end();
1740 for( it = (*fConversionStreamerInfo).begin(); it != end; ++it ) {
1741 delete it->second;
1742 }
1743 delete fConversionStreamerInfo.load();
1744 }
1745}
1746
1747////////////////////////////////////////////////////////////////////////////////
1748
1749namespace {
1750 Int_t ReadRulesContent(FILE *f)
1751 {
1752 // Read a class.rules file which contains one rule per line with comment
1753 // starting with a #
1754 // Returns the number of rules loaded.
1755 // Returns -1 in case of error.
1756
1757 R__ASSERT(f!=nullptr);
1758 TString rule(1024);
1759 int c, state = 0;
1760 Int_t count = 0;
1761
1762 while ((c = fgetc(f)) != EOF) {
1763 if (c == 13) // ignore CR
1764 continue;
1765 if (c == '\n') {
1766 if (state != 3) {
1767 state = 0;
1768 if (rule.Length() > 0) {
1769 if (TClass::AddRule(rule)) {
1770 ++count;
1771 }
1772 rule.Clear();
1773 }
1774 }
1775 continue;
1776 }
1777 switch (state) {
1778 case 0: // start of line
1779 switch (c) {
1780 case ' ':
1781 case '\t':
1782 break;
1783 case '#':
1784 state = 1;
1785 break;
1786 default:
1787 state = 2;
1788 break;
1789 }
1790 break;
1791
1792 case 1: // comment
1793 break;
1794
1795 case 2: // rule
1796 switch (c) {
1797 case '\\':
1798 state = 3; // Continuation request
1799 default:
1800 break;
1801 }
1802 break;
1803 }
1804 switch (state) {
1805 case 2:
1806 rule.Append(c);
1807 break;
1808 }
1809 }
1810 return count;
1811 }
1812}
1813
1814////////////////////////////////////////////////////////////////////////////////
1815/// Read the class.rules files from the default location:.
1816/// $ROOTSYS/etc/class.rules (or ROOTETCDIR/class.rules)
1817
1819{
1820 static const char *suffix = "class.rules";
1821 TString sname = suffix;
1823
1824 Int_t res = -1;
1825
1826 FILE * f = fopen(sname,"r");
1827 if (f != nullptr) {
1828 res = ReadRulesContent(f);
1829 fclose(f);
1830 } else {
1831 ::Error("TClass::ReadRules()", "Cannot find rules file %s", sname.Data());
1832 }
1833 return res;
1834}
1835
1836////////////////////////////////////////////////////////////////////////////////
1837/// Read a class.rules file which contains one rule per line with comment
1838/// starting with a #
1839/// - Returns the number of rules loaded.
1840/// - Returns -1 in case of error.
1841
1842Int_t TClass::ReadRules( const char *filename )
1843{
1844 if (!filename || !filename[0]) {
1845 ::Error("TClass::ReadRules", "no file name specified");
1846 return -1;
1847 }
1848
1849 FILE * f = fopen(filename,"r");
1850 if (f == nullptr) {
1851 ::Error("TClass::ReadRules","Failed to open %s\n",filename);
1852 return -1;
1853 }
1854 Int_t count = ReadRulesContent(f);
1855
1856 fclose(f);
1857 return count;
1858
1859}
1860
1861////////////////////////////////////////////////////////////////////////////////
1862/// Add a schema evolution customization rule.
1863/// The syntax of the rule can be either the short form:
1864/// ~~~ {.cpp}
1865/// [type=Read] classname membername [attributes=... ] [version=[...] ] [checksum=[...] ] [oldtype=...] [code={...}]
1866/// ~~~
1867/// or the long form
1868/// ~~~ {.cpp}
1869/// [type=Read] sourceClass=classname [targetclass=newClassname] [ source="type membername; [type2 membername2]" ]
1870/// [target="membername3;membername4"] [attributes=... ] [version=...] [checksum=...] [code={...}|functionname]
1871/// ~~~
1872///
1873/// For example to set HepMC::GenVertex::m_event to _not_ owned the object it is pointing to:
1874/// HepMC::GenVertex m_event attributes=NotOwner
1875///
1876/// Semantic of the tags:
1877/// - type : the type of the rule, valid values: Read, ReadRaw, Write, WriteRaw, the default is 'Read'.
1878/// - sourceClass : the name of the class as it is on the rule file
1879/// - targetClass : the name of the class as it is in the current code ; defaults to the value of sourceClass
1880/// - source : the types and names of the data members from the class on file that are needed, the list is separated by semi-colons ';'
1881/// - oldtype: in the short form only, indicates the type on disk of the data member.
1882/// - target : the names of the data members updated by this rule, the list is separated by semi-colons ';'
1883/// - attributes : list of possible qualifiers among: Owner, NotOwner
1884/// - version : list of the version of the class layout that this rule applies to. The syntax can be [1,4,5] or [2-] or [1-3] or [-3]
1885/// - checksum : comma delimited list of the checksums of the class layout that this rule applies to.
1886/// - code={...} : code to be executed for the rule or name of the function implementing it.
1887
1888Bool_t TClass::AddRule( const char *rule )
1889{
1890 ROOT::TSchemaRule *ruleobj = new ROOT::TSchemaRule();
1891 if (! ruleobj->SetFromRule( rule ) ) {
1892 delete ruleobj;
1893 return kFALSE;
1894 }
1895
1897
1898 TClass *cl = TClass::GetClass( ruleobj->GetTargetClass() );
1899 if (!cl) {
1900 // Create an empty emulated class for now.
1901 cl = gInterpreter->GenerateTClass(ruleobj->GetTargetClass(), /* emulation = */ kTRUE, /*silent = */ kTRUE);
1902 }
1904
1905 TString errmsg;
1906 if( !rset->AddRule( ruleobj, ROOT::Detail::TSchemaRuleSet::kCheckConflict, &errmsg ) ) {
1907 ::Warning( "TClass::AddRule", "The rule for class: \"%s\": version, \"%s\" and data members: \"%s\" has been skipped because it conflicts with one of the other rules (%s).",
1908 ruleobj->GetTargetClass(), ruleobj->GetVersion(), ruleobj->GetTargetString(), errmsg.Data() );
1909 delete ruleobj;
1910 return kFALSE;
1911 }
1912 return kTRUE;
1913}
1914
1915////////////////////////////////////////////////////////////////////////////////
1916/// Adopt a new set of Data Model Evolution rules.
1917
1919{
1921
1922 delete fSchemaRules;
1923 fSchemaRules = rules;
1924 fSchemaRules->SetClass( this );
1925}
1926
1927////////////////////////////////////////////////////////////////////////////////
1928/// Return the set of the schema rules if any.
1929
1931{
1932 return fSchemaRules;
1933}
1934
1935////////////////////////////////////////////////////////////////////////////////
1936/// Return the set of the schema rules if any.
1937/// If create is true, create an empty set
1938
1940{
1941 if (create && fSchemaRules == nullptr) {
1943 fSchemaRules->SetClass( this );
1944 }
1945 return fSchemaRules;
1946}
1947
1948////////////////////////////////////////////////////////////////////////////////
1949
1950void TClass::AddImplFile(const char* filename, int line) {
1951 // Currently reset the implementation file and line.
1952 // In the close future, it will actually add this file and line
1953 // to a "list" of implementation files.
1954
1955 fImplFileName = filename;
1957}
1958
1959////////////////////////////////////////////////////////////////////////////////
1960/// Browse external object inherited from TObject.
1961/// It passes through inheritance tree and calls TBrowser::Add
1962/// in appropriate cases. Static function.
1963
1965{
1966 if (!obj) return 0;
1967
1968 TAutoInspector insp(b);
1969 obj->ShowMembers(insp);
1970 return insp.fCount;
1971}
1972
1973////////////////////////////////////////////////////////////////////////////////
1974/// Browse objects of of the class described by this TClass object.
1975
1976Int_t TClass::Browse(void *obj, TBrowser *b) const
1977{
1978 if (!obj) return 0;
1979
1980 TClass *actual = GetActualClass(obj);
1981 if (IsTObject()) {
1982 // Call TObject::Browse.
1983
1984 if (!fIsOffsetStreamerSet) {
1986 }
1987 TObject* realTObject = (TObject*)((size_t)obj + fOffsetStreamer);
1988 realTObject->Browse(b);
1989 return 1;
1990 } else if (actual != this) {
1991 return actual->Browse(obj, b);
1992 } else if (GetCollectionProxy()) {
1993
1994 // do something useful.
1995
1996 } else {
1997 TAutoInspector insp(b);
1998 CallShowMembers(obj,insp,kFALSE);
1999 return insp.fCount;
2000 }
2001
2002 return 0;
2003}
2004
2005////////////////////////////////////////////////////////////////////////////////
2006/// This method is called by a browser to get the class information.
2007
2009{
2010 if (!HasInterpreterInfo()) return;
2011
2012 if (b) {
2013 if (!fRealData) BuildRealData();
2014
2015 b->Add(GetListOfDataMembers(), "Data Members");
2016 b->Add(GetListOfRealData(), "Real Data Members");
2017 b->Add(GetListOfMethods(), "Methods");
2018 b->Add(GetListOfBases(), "Base Classes");
2019 }
2020}
2021
2022////////////////////////////////////////////////////////////////////////////////
2023/// Build a full list of persistent data members.
2024/// Scans the list of all data members in the class itself and also
2025/// in all base classes. For each persistent data member, inserts a
2026/// TRealData object in the list fRealData.
2027///
2028
2029void TClass::BuildRealData(void* pointer, Bool_t isTransient)
2030{
2031
2033
2034 // Only do this once.
2035 if (fRealData) {
2036 return;
2037 }
2038
2039 if (fClassVersion == 0) {
2040 isTransient = kTRUE;
2041 }
2042
2043 // When called via TMapFile (e.g. Update()) make sure that the dictionary
2044 // gets allocated on the heap and not in the mapped file.
2045 TMmallocDescTemp setreset;
2046
2047 // Handle emulated classes and STL containers specially.
2049 // We are an emulated class or an STL container.
2050 fRealData = new TList;
2051 BuildEmulatedRealData("", 0, this, isTransient);
2052 return;
2053 }
2054
2055 // return early on string
2056 static TClassRef clRefString("std::string");
2057 if (clRefString == this) {
2058 return;
2059 }
2060
2061 // Complain about stl classes ending up here (unique_ptr etc) - except for
2062 // pair where we will build .first, .second just fine
2063 // and those for which the user explicitly requested a dictionary.
2064 if (!isTransient && GetState() != kHasTClassInit
2067 Error("BuildRealData", "Inspection for %s not supported!", GetName());
2068 }
2069
2070 // The following statement will recursively call
2071 // all the subclasses of this class.
2072 fRealData = new TList;
2073 TBuildRealData brd(pointer, this);
2074
2075 // CallShowMember will force a call to InheritsFrom, which indirectly
2076 // calls TClass::GetClass. It forces the loading of new typedefs in
2077 // case some of them were not yet loaded.
2078 if ( ! CallShowMembers(pointer, brd, isTransient) ) {
2079 if ( isTransient ) {
2080 // This is a transient data member, so it is probably fine to not have
2081 // access to its content. However let's no mark it as definitively setup,
2082 // since another class might use this class for a persistent data member and
2083 // in this case we really want the error message.
2084 delete fRealData;
2085 fRealData = nullptr;
2086 } else {
2087 Error("BuildRealData", "Cannot find any ShowMembers function for %s!", GetName());
2088 }
2089 }
2090
2091 // Take this opportunity to build the real data for base classes.
2092 // In case one base class is abstract, it would not be possible later
2093 // to create the list of real data for this abstract class.
2094 TBaseClass* base = nullptr;
2095 TIter next(GetListOfBases());
2096 while ((base = (TBaseClass*) next())) {
2097 if (base->IsSTLContainer()) {
2098 continue;
2099 }
2100 TClass* c = base->GetClassPointer();
2101 if (c) {
2102 c->BuildRealData(nullptr, isTransient);
2103 }
2104 }
2105}
2106
2107////////////////////////////////////////////////////////////////////////////////
2108/// Build the list of real data for an emulated class
2109
2110void TClass::BuildEmulatedRealData(const char *name, Longptr_t offset, TClass *cl, Bool_t isTransient)
2111{
2113
2115 if (Property() & kIsAbstract) {
2117 } else {
2118 info = GetStreamerInfoImpl(fClassVersion, isTransient);
2119 }
2120 if (!info) {
2121 // This class is abstract, but we don't yet have a SteamerInfo for it ...
2122 Error("BuildEmulatedRealData","Missing StreamerInfo for %s",GetName());
2123 // Humm .. no information ... let's bail out
2124 return;
2125 }
2126
2127 TIter next(info->GetElements());
2128 TStreamerElement *element;
2129 while ((element = (TStreamerElement*)next())) {
2130 Int_t etype = element->GetType();
2131 Longptr_t eoffset = element->GetOffset();
2132 TClass *cle = element->GetClassPointer();
2133 if (element->IsBase() || etype == TVirtualStreamerInfo::kBase) {
2134 //base class are skipped in this loop, they will be added at the end.
2135 continue;
2136 } else if (etype == TVirtualStreamerInfo::kTObject ||
2139 etype == TVirtualStreamerInfo::kAny) {
2140 //member class
2141 TString rdname; rdname.Form("%s%s",name,element->GetFullName());
2142 TRealData *rd = new TRealData(rdname,offset+eoffset,nullptr);
2143 if (gDebug > 0) printf(" Class: %s, adding TRealData=%s, offset=%ld\n",cl->GetName(),rd->GetName(),rd->GetThisOffset());
2144 cl->GetListOfRealData()->Add(rd);
2145 // Now we a dot
2146 rdname.Form("%s%s.",name,element->GetFullName());
2147 if (cle) cle->BuildEmulatedRealData(rdname,offset+eoffset,cl, isTransient);
2148 } else {
2149 //others
2150 TString rdname; rdname.Form("%s%s",name,element->GetFullName());
2151 TRealData *rd = new TRealData(rdname,offset+eoffset,nullptr);
2152 if (gDebug > 0) printf(" Class: %s, adding TRealData=%s, offset=%ld\n",cl->GetName(),rd->GetName(),rd->GetThisOffset());
2153 cl->GetListOfRealData()->Add(rd);
2154 }
2155 //if (fClassInfo==0 && element->IsBase()) {
2156 // if (fBase==0) fBase = new TList;
2157 // TClass *base = element->GetClassPointer();
2158 // fBase->Add(new TBaseClass(this, cl, eoffset));
2159 //}
2160 }
2161 // The base classes must added last on the list of real data (to help with ambiguous data member names)
2162 next.Reset();
2163 while ((element = (TStreamerElement*)next())) {
2164 Int_t etype = element->GetType();
2165 if (element->IsBase() || etype == TVirtualStreamerInfo::kBase) {
2166 //base class
2167 Longptr_t eoffset = element->GetOffset();
2168 TClass *cle = element->GetClassPointer();
2169 if (cle) cle->BuildEmulatedRealData(name,offset+eoffset,cl, isTransient);
2170 }
2171 }
2172}
2173
2174
2175////////////////////////////////////////////////////////////////////////////////
2176/// Calculate the offset between an object of this class to
2177/// its base class TObject. The pointer can be adjusted by
2178/// that offset to access any virtual method of TObject like
2179/// Streamer() and ShowMembers().
2180
2182{
2185 // When called via TMapFile (e.g. Update()) make sure that the dictionary
2186 // gets allocated on the heap and not in the mapped file.
2187
2188 TMmallocDescTemp setreset;
2189 fOffsetStreamer = const_cast<TClass*>(this)->GetBaseClassOffsetRecurse(TObject::Class());
2190 if (fStreamerType == kTObject) {
2192 }
2194 }
2195}
2196
2197
2198////////////////////////////////////////////////////////////////////////////////
2199/// Call ShowMembers() on the obj of this class type, passing insp and parent.
2200/// isATObject is -1 if unknown, 0 if it is not a TObject, and 1 if it is a TObject.
2201/// The function returns whether it was able to call ShowMembers().
2202
2203Bool_t TClass::CallShowMembers(const void* obj, TMemberInspector &insp, Bool_t isTransient) const
2204{
2205 if (fShowMembers) {
2206 // This should always works since 'pointer' should be pointing
2207 // to an object of the actual type of this TClass object.
2208 fShowMembers(obj, insp, isTransient);
2209 return kTRUE;
2210 } else {
2211
2213 if (fClassInfo) {
2214
2215 if (strcmp(GetName(), "string") == 0) {
2216 // For std::string we know that we do not have a ShowMembers
2217 // function and that it's okay.
2218 return kTRUE;
2219 }
2220 // Since we do have some dictionary information, let's
2221 // call the interpreter's ShowMember.
2222 // This works with Cling to support interpreted classes.
2223 gInterpreter->InspectMembers(insp, obj, this, isTransient);
2224 return kTRUE;
2225
2226 } else if (TVirtualStreamerInfo* sinfo = GetStreamerInfo()) {
2227 sinfo->CallShowMembers(obj, insp, isTransient);
2228 return kTRUE;
2229 } // isATObject
2230 } // fShowMembers is set
2231
2232 return kFALSE;
2233}
2234
2235////////////////////////////////////////////////////////////////////////////////
2236/// Do a ShowMembers() traversal of all members and base classes' members
2237/// using the reflection information from the interpreter. Works also for
2238/// interpreted objects.
2239
2240void TClass::InterpretedShowMembers(void* obj, TMemberInspector &insp, Bool_t isTransient)
2241{
2242 return gInterpreter->InspectMembers(insp, obj, this, isTransient);
2243}
2244
2246{
2247 if (fCanSplit >= 0) {
2248 return ! ( fCanSplit & 0x2 );
2249 }
2250
2252
2253 if (GetCollectionProxy() != nullptr) {
2254 // A collection can never affect its derived class 'splittability'
2255 return kTRUE;
2256 }
2257
2258 if (this == TRef::Class()) { fCanSplit = 2; return kFALSE; }
2259 if (this == TRefArray::Class()) { fCanSplit = 2; return kFALSE; }
2260 if (this == TArray::Class()) { fCanSplit = 2; return kFALSE; }
2261 if (this == TClonesArray::Class()) { fCanSplit = 1; return kTRUE; }
2262 if (this == TCollection::Class()) { fCanSplit = 2; return kFALSE; }
2263
2264 // TTree is not always available (for example in rootcling), so we need
2265 // to grab it silently.
2266 auto refTreeClass( TClass::GetClass("TTree",kTRUE,kTRUE) );
2267 if (this == refTreeClass) { fCanSplit = 2; return kFALSE; }
2268
2269 if (!HasDataMemberInfo()) {
2270 TVirtualStreamerInfo *sinfo = ((TClass *)this)->GetCurrentStreamerInfo();
2271 if (sinfo==nullptr) sinfo = GetStreamerInfo();
2272 TIter next(sinfo->GetElements());
2273 TStreamerElement *element;
2274 while ((element = (TStreamerElement*)next())) {
2275 if (element->IsA() == TStreamerBase::Class()) {
2276 TClass *clbase = element->GetClassPointer();
2277 if (!clbase) {
2278 // If there is a missing base class, we can't split the immediate
2279 // derived class.
2280 fCanSplit = 0;
2281 return kFALSE;
2282 } else if (!clbase->CanSplitBaseAllow()) {
2283 fCanSplit = 2;
2284 return kFALSE;
2285 }
2286 }
2287 }
2288 }
2289
2290 // If we don't have data member info there is no more information
2291 // we can find out.
2292 if (!HasDataMemberInfo()) return kTRUE;
2293
2294 TObjLink *lnk = GetListOfBases() ? fBase.load()->FirstLink() : nullptr;
2295
2296 // Look at inheritance tree
2297 while (lnk) {
2298 TClass *c;
2299 TBaseClass *base = (TBaseClass*) lnk->GetObject();
2300 c = base->GetClassPointer();
2301 if(!c) {
2302 // If there is a missing base class, we can't split the immediate
2303 // derived class.
2304 fCanSplit = 0;
2305 return kFALSE;
2306 } else if (!c->CanSplitBaseAllow()) {
2307 fCanSplit = 2;
2308 return kFALSE;
2309 }
2310 lnk = lnk->Next();
2311 }
2312 return kTRUE;
2313}
2314
2315////////////////////////////////////////////////////////////////////////////////
2316/// Return true if the data member of this TClass can be saved separately.
2317
2319{
2320 // Note: add the possibility to set it for the class and the derived class.
2321 // save the info in TVirtualStreamerInfo
2322 // deal with the info in MakeProject
2323 if (fCanSplit >= 0) {
2324 // The user explicitly set the value
2325 return (fCanSplit & 0x1) == 1;
2326 }
2327
2329 TClass *This = const_cast<TClass*>(this);
2330
2331 if (this == TObject::Class()) { This->fCanSplit = 1; return kTRUE; }
2332 if (fName == "TClonesArray") { This->fCanSplit = 1; return kTRUE; }
2333 if (fRefProxy) { This->fCanSplit = 0; return kFALSE; }
2334 if (fName.BeginsWith("TVectorT<")) { This->fCanSplit = 0; return kFALSE; }
2335 if (fName.BeginsWith("TMatrixT<")) { This->fCanSplit = 0; return kFALSE; }
2336 if (fName == "string") { This->fCanSplit = 0; return kFALSE; }
2337 if (fName == "std::string") { This->fCanSplit = 0; return kFALSE; }
2338
2339 if (GetCollectionProxy()!=nullptr) {
2340 // For STL collection we need to look inside.
2341
2342 // However we do not split collections of collections
2343 // nor collections of strings
2344 // nor collections of pointers (unless explicit request (see TBranchSTL)).
2345
2346 if (GetCollectionProxy()->HasPointers()) { This->fCanSplit = 0; return kFALSE; }
2347
2348 TClass *valueClass = GetCollectionProxy()->GetValueClass();
2349 if (valueClass == nullptr) { This->fCanSplit = 0; return kFALSE; }
2350 static TClassRef stdStringClass("std::string");
2351 if (valueClass==TString::Class() || valueClass==stdStringClass)
2352 { This->fCanSplit = 0; return kFALSE; }
2353 if (!valueClass->CanSplit()) { This->fCanSplit = 0; return kFALSE; }
2354 if (valueClass->GetCollectionProxy() != nullptr) { This->fCanSplit = 0; return kFALSE; }
2355
2356 This->fCanSplit = 1;
2357 return kTRUE;
2358
2359 }
2360
2361 if (GetStreamer() != nullptr || fStreamerFunc != nullptr) {
2362
2363 // We have an external custom streamer provided by the user, we must not
2364 // split it.
2365 This->fCanSplit = 0;
2366 return kFALSE;
2367
2369
2370 // We have a custom member function streamer or
2371 // an older (not StreamerInfo based) automatic streamer.
2372 This->fCanSplit = 0;
2373 return kFALSE;
2374 }
2375
2376 if (Size()==1) {
2377 // 'Empty' class there is nothing to split!.
2378 This->fCanSplit = 0;
2379 return kFALSE;
2380 }
2381
2382
2383 if ( !This->CanSplitBaseAllow() ) {
2384 return kFALSE;
2385 }
2386
2387 This->fCanSplit = 1;
2388 return kTRUE;
2389}
2390
2391////////////////////////////////////////////////////////////////////////////////
2392/// Return the C++ property of this class, eg. is abstract, has virtual base
2393/// class, see EClassProperty in TDictionary.h
2394
2396{
2397 if (fProperty == -1) Property();
2398 return fClassProperty;
2399}
2400
2401////////////////////////////////////////////////////////////////////////////////
2402/// Create a Clone of this TClass object using a different name but using the same 'dictionary'.
2403/// This effectively creates a hard alias for the class name.
2404
2405TObject *TClass::Clone(const char *new_name) const
2406{
2407 if (new_name == nullptr || new_name[0]=='\0' || fName == new_name) {
2408 Error("Clone","The name of the class must be changed when cloning a TClass object.");
2409 return nullptr;
2410 }
2411
2412 // Need to lock access to TROOT::GetListOfClasses so the cloning happens atomically
2414 // Temporarily remove the original from the list of classes.
2415 TClass::RemoveClass(const_cast<TClass*>(this));
2416
2417 TClass *copy;
2418 if (fTypeInfo) {
2419 copy = new TClass(GetName(),
2421 *fTypeInfo,
2422 new TIsAProxy(*fTypeInfo),
2426 GetImplFileLine());
2427 } else {
2428 copy = new TClass(GetName(),
2433 GetImplFileLine());
2434 }
2435 copy->fShowMembers = fShowMembers;
2436 // Remove the copy before renaming it
2437 TClass::RemoveClass(copy);
2438 copy->fName = new_name;
2439 TClass::AddClass(copy);
2440
2441 copy->SetNew(fNew);
2442 copy->SetNewArray(fNewArray);
2443 copy->SetDelete(fDelete);
2449 if (fStreamer) {
2451 }
2452 // If IsZombie is true, something went wrong and we will not be
2453 // able to properly copy the collection proxy
2454 if (fCollectionProxy && !copy->IsZombie()) {
2456 }
2457 copy->SetClassSize(fSizeof);
2458 if (fRefProxy) {
2460 }
2461 TClass::AddClass(const_cast<TClass*>(this));
2462 return copy;
2463}
2464
2465////////////////////////////////////////////////////////////////////////////////
2466/// Copy the argument.
2467
2469{
2470// // This code was used too quickly test the STL Emulation layer
2471// Int_t k = TClassEdit::IsSTLCont(GetName());
2472// if (k==1||k==-1) return;
2473
2474 delete fCollectionProxy;
2475 fCollectionProxy = orig.Generate();
2476}
2477
2478////////////////////////////////////////////////////////////////////////////////
2479/// Draw detailed class inheritance structure.
2480/// If a class B inherits from a class A, the description of B is drawn
2481/// on the right side of the description of A.
2482/// Member functions overridden by B are shown in class A with a blue line
2483/// erasing the corresponding member function
2484
2486{
2487 if (!HasInterpreterInfo()) return;
2488
2489 TVirtualPad *padsav = gPad;
2490
2491 // Should we create a new canvas?
2492 TString opt=option;
2493 if (!padsav || !opt.Contains("same")) {
2494 TVirtualPad *padclass = (TVirtualPad*)(gROOT->GetListOfCanvases())->FindObject("R__class");
2495 if (!padclass) {
2496 gROOT->ProcessLine("new TCanvas(\"R__class\",\"class\",20,20,1000,750);");
2497 } else {
2498 padclass->cd();
2499 }
2500 }
2501
2502 if (gPad) gPad->DrawClassObject(this,option);
2503
2504 if (padsav) padsav->cd();
2505}
2506
2507////////////////////////////////////////////////////////////////////////////////
2508/// Dump contents of object on stdout.
2509/// Using the information in the object dictionary
2510/// each data member is interpreted.
2511/// If a data member is a pointer, the pointer value is printed
2512/// 'obj' is assume to point to an object of the class describe by this TClass
2513///
2514/// The following output is the Dump of a TArrow object:
2515/// ~~~ {.cpp}
2516/// fAngle 0 Arrow opening angle (degrees)
2517/// fArrowSize 0.2 Arrow Size
2518/// fOption.*fData
2519/// fX1 0.1 X of 1st point
2520/// fY1 0.15 Y of 1st point
2521/// fX2 0.67 X of 2nd point
2522/// fY2 0.83 Y of 2nd point
2523/// fUniqueID 0 object unique identifier
2524/// fBits 50331648 bit field status word
2525/// fLineColor 1 line color
2526/// fLineStyle 1 line style
2527/// fLineWidth 1 line width
2528/// fFillColor 19 fill area color
2529/// fFillStyle 1001 fill area style
2530/// ~~~
2531///
2532/// If noAddr is true, printout of all pointer values is skipped.
2533
2534void TClass::Dump(const void *obj, Bool_t noAddr /*=kFALSE*/) const
2535{
2536
2537 Longptr_t prObj = noAddr ? 0 : (Longptr_t)obj;
2538 if (IsTObject()) {
2539 if (!fIsOffsetStreamerSet) {
2541 }
2542 TObject *tobj = (TObject*)((Longptr_t)obj + fOffsetStreamer);
2543
2544
2545 if (sizeof(this) == 4)
2546 Printf("==> Dumping object at: 0x%08lx, name=%s, class=%s\n",prObj,tobj->GetName(),GetName());
2547 else
2548 Printf("==> Dumping object at: 0x%016lx, name=%s, class=%s\n",prObj,tobj->GetName(),GetName());
2549 } else {
2550
2551 if (sizeof(this) == 4)
2552 Printf("==> Dumping object at: 0x%08lx, class=%s\n",prObj,GetName());
2553 else
2554 Printf("==> Dumping object at: 0x%016lx, class=%s\n",prObj,GetName());
2555 }
2556
2557 TDumpMembers dm(noAddr);
2558 if (!CallShowMembers(obj, dm, kFALSE)) {
2559 Info("Dump", "No ShowMembers function, dumping disabled");
2560 }
2561}
2562
2563////////////////////////////////////////////////////////////////////////////////
2564/// Introduce an escape character (@) in front of a special chars.
2565/// You need to use the result immediately before it is being overwritten.
2566
2567char *TClass::EscapeChars(const char *text) const
2568{
2569 static const UInt_t maxsize = 255;
2570 static char name[maxsize+2]; //One extra if last char needs to be escaped
2571
2572 UInt_t nch = strlen(text);
2573 UInt_t icur = 0;
2574 for (UInt_t i = 0; i < nch && icur < maxsize; ++i, ++icur) {
2575 if (text[i] == '\"' || text[i] == '[' || text[i] == '~' ||
2576 text[i] == ']' || text[i] == '&' || text[i] == '#' ||
2577 text[i] == '!' || text[i] == '^' || text[i] == '<' ||
2578 text[i] == '?' || text[i] == '>') {
2579 name[icur] = '@';
2580 ++icur;
2581 }
2582 name[icur] = text[i];
2583 }
2584 name[icur] = 0;
2585 return name;
2586}
2587
2588////////////////////////////////////////////////////////////////////////////////
2589/// Return a pointer the the real class of the object.
2590/// This is equivalent to object->IsA() when the class has a ClassDef.
2591/// It is REQUIRED that object is coming from a proper pointer to the
2592/// class represented by 'this'.
2593/// Example: Special case:
2594/// ~~~ {.cpp}
2595/// class MyClass : public AnotherClass, public TObject
2596/// ~~~
2597/// then on return, one must do:
2598/// ~~~ {.cpp}
2599/// TObject *obj = (TObject*)((void*)myobject)directory->Get("some object of MyClass");
2600/// MyClass::Class()->GetActualClass(obj); // this would be wrong!!!
2601/// ~~~
2602/// Also if the class represented by 'this' and NONE of its parents classes
2603/// have a virtual ptr table, the result will be 'this' and NOT the actual
2604/// class.
2605
2606TClass *TClass::GetActualClass(const void *object) const
2607{
2608 if (object==nullptr) return (TClass*)this;
2609 if (fIsA) {
2610 return (*fIsA)(object); // ROOT::IsA((ThisClass*)object);
2611 } else if (fGlobalIsA) {
2612 return fGlobalIsA(this,object);
2613 } else {
2614 if (IsTObject()) {
2615
2616 if (!fIsOffsetStreamerSet) {
2618 }
2619 TObject* realTObject = (TObject*)((size_t)object + fOffsetStreamer);
2620
2621 return realTObject->IsA();
2622 }
2623
2624 if (HasInterpreterInfo()) {
2625
2626 TVirtualIsAProxy *isa = nullptr;
2628 isa = (TVirtualIsAProxy*)gROOT->ProcessLineFast(TString::Format("new ::TInstrumentedIsAProxy<%s>(0);",GetName()));
2629 }
2630 else {
2631 isa = (TVirtualIsAProxy*)gROOT->ProcessLineFast(TString::Format("new ::TIsAProxy(typeid(%s));",GetName()));
2632 }
2633 if (isa) {
2635 const_cast<TClass*>(this)->fIsA = isa;
2636 }
2637 if (fIsA) {
2638 return (*fIsA)(object); // ROOT::IsA((ThisClass*)object);
2639 }
2640 }
2642 if (sinfo) {
2643 return sinfo->GetActualClass(object);
2644 }
2645 return (TClass*)this;
2646 }
2647}
2648
2649////////////////////////////////////////////////////////////////////////////////
2650/// Return pointer to the base class "classname". Returns 0 in case
2651/// "classname" is not a base class. Takes care of multiple inheritance.
2652
2653TClass *TClass::GetBaseClass(const char *classname)
2654{
2655 // check if class name itself is equal to classname
2656 if (strcmp(GetName(), classname) == 0) return this;
2657
2658 if (!HasDataMemberInfo()) return nullptr;
2659
2660 // Make sure we deal with possible aliases, we could also have normalized
2661 // the name.
2662 TClass *search = TClass::GetClass(classname,kTRUE,kTRUE);
2663
2664 if (search) return GetBaseClass(search);
2665 else return nullptr;
2666}
2667
2668////////////////////////////////////////////////////////////////////////////////
2669/// Return pointer to the base class "cl". Returns 0 in case "cl"
2670/// is not a base class. Takes care of multiple inheritance.
2671
2673{
2674 // check if class name itself is equal to classname
2675 if (cl == this) return this;
2676
2677 if (!HasDataMemberInfo()) return nullptr;
2678
2679 TObjLink *lnk = GetListOfBases() ? fBase.load()->FirstLink() : nullptr;
2680
2681 // otherwise look at inheritance tree
2682 while (lnk) {
2683 TClass *c, *c1;
2684 TBaseClass *base = (TBaseClass*) lnk->GetObject();
2685 c = base->GetClassPointer();
2686 if (c) {
2687 if (cl == c) return c;
2688 c1 = c->GetBaseClass(cl);
2689 if (c1) return c1;
2690 }
2691 lnk = lnk->Next();
2692 }
2693 return nullptr;
2694}
2695
2696////////////////////////////////////////////////////////////////////////////////
2697/// Return data member offset to the base class "cl".
2698/// - Returns -1 in case "cl" is not a base class.
2699/// - Returns -2 if cl is a base class, but we can't find the offset
2700/// because it's virtual.
2701/// Takes care of multiple inheritance.
2702
2704{
2705 // check if class name itself is equal to classname
2706 if (cl == this) return 0;
2707
2708 if (!fBase.load()) {
2710 // If the information was not provided by the root pcm files and
2711 // if we can not find the ClassInfo, we have to fall back to the
2712 // StreamerInfo
2713 if (!fClassInfo) {
2715 if (!sinfo) return -1;
2716 TStreamerElement *element;
2717 Int_t offset = 0;
2718
2719 TObjArray &elems = *(sinfo->GetElements());
2720 Int_t size = elems.GetLast()+1;
2721 for(Int_t i=0; i<size; i++) {
2722 element = (TStreamerElement*)elems[i];
2723 if (element->IsBase()) {
2724 if (element->IsA() == TStreamerBase::Class()) {
2725 TStreamerBase *base = (TStreamerBase*)element;
2726 TClass *baseclass = base->GetClassPointer();
2727 if (!baseclass) return -1;
2728 Int_t subOffset = baseclass->GetBaseClassOffsetRecurse(cl);
2729 if (subOffset == -2) return -2;
2730 if (subOffset != -1) return offset+subOffset;
2731 offset += baseclass->Size();
2732 } else if (element->IsA() == TStreamerSTL::Class()) {
2733 TStreamerSTL *base = (TStreamerSTL*)element;
2734 TClass *baseclass = base->GetClassPointer();
2735 if (!baseclass) return -1;
2736 Int_t subOffset = baseclass->GetBaseClassOffsetRecurse(cl);
2737 if (subOffset == -2) return -2;
2738 if (subOffset != -1) return offset+subOffset;
2739 offset += baseclass->Size();
2740
2741 } else {
2742 Error("GetBaseClassOffsetRecurse","Unexpected element type for base class: %s\n",element->IsA()->GetName());
2743 }
2744 }
2745 }
2746 return -1;
2747 }
2748 }
2749
2750 TClass *c;
2751 Int_t off;
2752 TBaseClass *inh;
2753 TObjLink *lnk = nullptr;
2754 if (fBase.load() == nullptr)
2755 lnk = GetListOfBases()->FirstLink();
2756 else
2757 lnk = fBase.load()->FirstLink();
2758
2759 // otherwise look at inheritance tree
2760 while (lnk) {
2761 inh = (TBaseClass *)lnk->GetObject();
2762 //use option load=kFALSE to avoid a warning like:
2763 //"Warning in <TClass::TClass>: no dictionary for class TRefCnt is available"
2764 //We can not afford to not have the class if it exist, so we
2765 //use kTRUE.
2766 c = inh->GetClassPointer(kTRUE); // kFALSE);
2767 if (c) {
2768 if (cl == c) {
2769 if ((inh->Property() & kIsVirtualBase) != 0)
2770 return -2;
2771 return inh->GetDelta();
2772 }
2773 off = c->GetBaseClassOffsetRecurse(cl);
2774 if (off == -2) return -2;
2775 if (off != -1) {
2776 return off + inh->GetDelta();
2777 }
2778 }
2779 lnk = lnk->Next();
2780 }
2781 return -1;
2782}
2783
2784////////////////////////////////////////////////////////////////////////////////
2785/// - Return data member offset to the base class "cl".
2786/// - Returns -1 in case "cl" is not a base class.
2787/// Takes care of multiple inheritance.
2788
2789Int_t TClass::GetBaseClassOffset(const TClass *toBase, void *address, bool isDerivedObject)
2790{
2791 // Warning("GetBaseClassOffset","Requires the use of fClassInfo for %s to %s",GetName(),toBase->GetName());
2792
2793 if (this == toBase) return 0;
2794
2795 if ((!address /* || !has_virtual_base */) &&
2797 // At least of the ClassInfo have not been loaded in memory yet and
2798 // since there is no virtual base class (or we don't have enough so it
2799 // would not make a difference) we can use the 'static' information
2800 Int_t offset = GetBaseClassOffsetRecurse (toBase);
2801 if (offset != -2) {
2802 return offset;
2803 }
2804 return offset;
2805 }
2806
2807 ClassInfo_t* derived = GetClassInfo();
2808 ClassInfo_t* base = toBase->GetClassInfo();
2809 if(derived && base) {
2810 // TClingClassInfo::GetBaseOffset takes the lock.
2811 return gCling->ClassInfo_GetBaseOffset(derived, base, address, isDerivedObject);
2812 }
2813 else {
2814 Int_t offset = GetBaseClassOffsetRecurse (toBase);
2815 if (offset != -2) {
2816 return offset;
2817 }
2818 }
2819 return -1;
2820}
2821
2822////////////////////////////////////////////////////////////////////////////////
2823/// Return pointer to (base) class that contains datamember.
2824
2825TClass *TClass::GetBaseDataMember(const char *datamember)
2826{
2827 if (!HasDataMemberInfo()) return nullptr;
2828
2829 // Check if data member exists in class itself
2830 TDataMember *dm = GetDataMember(datamember);
2831 if (dm) return this;
2832
2833 // if datamember not found in class, search in next base classes
2834 TBaseClass *inh;
2835 TIter next(GetListOfBases());
2836 while ((inh = (TBaseClass *) next())) {
2837 TClass *c = inh->GetClassPointer();
2838 if (c) {
2839 TClass *cdm = c->GetBaseDataMember(datamember);
2840 if (cdm) return cdm;
2841 }
2842 }
2843
2844 return nullptr;
2845}
2846
2847namespace {
2848 // A local Helper class used to keep 2 pointer (the collection proxy
2849 // and the class streamer) in the thread local storage.
2850
2851 struct TClassLocalStorage {
2852 TClassLocalStorage() : fCollectionProxy(nullptr), fStreamer(nullptr) {};
2853
2854 TVirtualCollectionProxy *fCollectionProxy;
2855 TClassStreamer *fStreamer;
2856
2857 static TClassLocalStorage *GetStorage(const TClass *cl)
2858 {
2859 // Return the thread storage for the TClass.
2860
2861 void **thread_ptr = (*gThreadTsd)(nullptr,ROOT::kClassThreadSlot);
2862 if (thread_ptr) {
2863 if (*thread_ptr==nullptr) *thread_ptr = new TExMap();
2864 TExMap *lmap = (TExMap*)(*thread_ptr);
2865 ULong_t hash = TString::Hash(&cl, sizeof(void*));
2866 ULongptr_t local = 0;
2867 UInt_t slot;
2868 if ((local = (ULongptr_t)lmap->GetValue(hash, (Longptr_t)cl, slot)) != 0) {
2869 } else {
2870 local = (ULongptr_t) new TClassLocalStorage();
2871 lmap->AddAt(slot, hash, (Longptr_t)cl, local);
2872 }
2873 return (TClassLocalStorage*)local;
2874 }
2875 return nullptr;
2876 }
2877 };
2878}
2879
2880////////////////////////////////////////////////////////////////////////////////
2881/// Return the 'type' of the STL the TClass is representing.
2882/// and return ROOT::kNotSTL if it is not representing an STL collection.
2883
2885{
2886 auto proxy = GetCollectionProxy();
2887 if (proxy) return (ROOT::ESTLType)proxy->GetCollectionType();
2888 return ROOT::kNotSTL;
2889}
2890
2891
2892////////////////////////////////////////////////////////////////////////////////
2893/// Return the proxy describing the collection (if any).
2894
2896{
2897 // Use assert, so that this line (slow because of the TClassEdit) is completely
2898 // removed in optimized code.
2899 //assert(TestBit(kLoading) || !TClassEdit::IsSTLCont(fName) || fCollectionProxy || 0 == "The TClass for the STL collection has no collection proxy!");
2901 TClassLocalStorage *local = TClassLocalStorage::GetStorage(this);
2902 if (local == nullptr) return fCollectionProxy;
2903 if (local->fCollectionProxy==nullptr) local->fCollectionProxy = fCollectionProxy->Generate();
2904 return local->fCollectionProxy;
2905 }
2906 return fCollectionProxy;
2907}
2908
2909////////////////////////////////////////////////////////////////////////////////
2910/// Return the Streamer Class allowing streaming (if any).
2911
2913{
2914 if (gThreadTsd && fStreamer) {
2915 TClassLocalStorage *local = TClassLocalStorage::GetStorage(this);
2916 if (local==nullptr) return fStreamer;
2917 if (local->fStreamer==nullptr) {
2918 local->fStreamer = fStreamer->Generate();
2919 const std::type_info &orig = ( typeid(*fStreamer) );
2920 if (!local->fStreamer) {
2921 Warning("GetStreamer","For %s, the TClassStreamer (%s) passed's call to Generate failed!",GetName(),orig.name());
2922 } else {
2923 const std::type_info &copy = ( typeid(*local->fStreamer) );
2924 if (strcmp(orig.name(),copy.name())!=0) {
2925 Warning("GetStreamer","For %s, the TClassStreamer passed does not properly implement the Generate method (%s vs %s)\n",GetName(),orig.name(),copy.name());
2926 }
2927 }
2928 }
2929 return local->fStreamer;
2930 }
2931 return fStreamer;
2932}
2933
2934////////////////////////////////////////////////////////////////////////////////
2935/// Get a wrapper/accessor function around this class custom streamer (member function).
2936
2938{
2939 return fStreamerFunc;
2940}
2941
2942////////////////////////////////////////////////////////////////////////////////
2943/// Get a wrapper/accessor function around this class custom conversion streamer (member function).
2944
2946{
2947 return fConvStreamerFunc;
2948}
2949
2950////////////////////////////////////////////////////////////////////////////////
2951/// Return the proxy implementing the IsA functionality.
2952
2954{
2955 return fIsA;
2956}
2957
2958////////////////////////////////////////////////////////////////////////////////
2959/// Static method returning pointer to TClass of the specified class name.
2960/// If load is true an attempt is made to obtain the class by loading
2961/// the appropriate shared library (directed by the rootmap file).
2962/// If silent is 'true', do not warn about missing dictionary for the class.
2963/// (typically used for class that are used only for transient members)
2964/// Returns 0 in case class is not found.
2965
2966TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent)
2967{
2968 return TClass::GetClass(name, load, silent, 0, 0);
2969}
2970
2971TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent, size_t hint_pair_offset, size_t hint_pair_size)
2972{
2973 if (!name || !name[0]) return nullptr;
2974
2975 if (strstr(name, "(anonymous)")) return nullptr;
2976 if (strncmp(name,"class ",6)==0) name += 6;
2977 if (strncmp(name,"struct ",7)==0) name += 7;
2978
2979 if (!gROOT->GetListOfClasses()) return nullptr;
2980
2981 // FindObject will take the read lock before actually getting the
2982 // TClass pointer so we will need not get a partially initialized
2983 // object.
2984 TClass *cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
2985
2986 // Early return to release the lock without having to execute the
2987 // long-ish normalization.
2988 if (cl && (cl->IsLoaded() || cl->TestBit(kUnloading))) return cl;
2989
2991
2992 // Now that we got the write lock, another thread may have constructed the
2993 // TClass while we were waiting, so we need to do the checks again.
2994
2995 cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
2996 if (cl) {
2997 if (cl->IsLoaded() || cl->TestBit(kUnloading)) return cl;
2998
2999 // We could speed-up some of the search by adding (the equivalent of)
3000 //
3001 // if (cl->GetState() == kInterpreter) return cl
3002 //
3003 // In this case, if a ROOT dictionary was available when the TClass
3004 // was first requested it would have been used and if a ROOT dictionary is
3005 // loaded later on TClassTable::Add will take care of updating the TClass.
3006 // So as far as ROOT dictionary are concerned, if the current TClass is
3007 // in interpreted state, we are sure there is nothing to load.
3008 //
3009 // However (see TROOT::LoadClass), the TClass can also be loaded/provided
3010 // by a user provided TClassGenerator. We have no way of knowing whether
3011 // those do (or even can) behave the same way as the ROOT dictionary and
3012 // have the 'dictionary is now available for use' step informs the existing
3013 // TClass that their dictionary is now available.
3014
3015 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
3016 load = kTRUE;
3017 }
3018
3020 // If there is a @ symbol (followed by a version number) then this is a synthetic class name created
3021 // from an already normalized name for the purpose of supporting schema evolution.
3022 // There is no dictionary or interpreter information about this kind of class, the only
3023 // (undesirable) side-effect of doing the search would be a waste of CPU time and potential
3024 // auto-loading or auto-parsing based on the scope of the name.
3025 return cl;
3026 }
3027
3028 // To avoid spurious auto parsing, let's check if the name as-is is
3029 // known in the TClassTable.
3031 if (dict) {
3032 // The name is normalized, so the result of the first search is
3033 // authoritative.
3034 if (!cl && !load) return nullptr;
3035
3036 TClass *loadedcl = (dict)();
3037 if (loadedcl) {
3038 loadedcl->PostLoadCheck();
3039 return loadedcl;
3040 }
3041
3042 // We should really not fall through to here, but if we do, let's just
3043 // continue as before ...
3044 }
3045
3046 std::string normalizedName;
3047 Bool_t checkTable = kFALSE;
3048
3049 if (!cl) {
3050 {
3052 TClassEdit::GetNormalizedName(normalizedName, name);
3053 }
3054 // Try the normalized name.
3055 if (normalizedName != name) {
3056 cl = (TClass*)gROOT->GetListOfClasses()->FindObject(normalizedName.c_str());
3057
3058 if (cl) {
3059 if (cl->IsLoaded() || cl->TestBit(kUnloading)) return cl;
3060
3061 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
3062 load = kTRUE;
3063 }
3064 checkTable = kTRUE;
3065 }
3066 } else {
3067 normalizedName = cl->GetName(); // Use the fact that all TClass names are normalized.
3068 checkTable = load && (normalizedName != name);
3069 }
3070
3071 if (!load) return nullptr;
3072
3073// This assertion currently fails because of
3074// TClass *c1 = TClass::GetClass("basic_iostream<char,char_traits<char> >");
3075// TClass *c2 = TClass::GetClass("std::iostream");
3076// where the TClassEdit normalized name of iostream is basic_iostream<char>
3077// i.e missing the addition of the default parameter. This is because TClingLookupHelper
3078// uses only 'part' of TMetaUtils::GetNormalizedName.
3079
3080// if (!cl) {
3081// TDataType* dataType = (TDataType*)gROOT->GetListOfTypes()->FindObject(name);
3082// TClass *altcl = dataType ? (TClass*)gROOT->GetListOfClasses()->FindObject(dataType->GetFullTypeName()) : 0;
3083// if (altcl && normalizedName != altcl->GetName())
3084// ::Fatal("TClass::GetClass","The existing name (%s) for %s is different from the normalized name: %s\n",
3085// altcl->GetName(), name, normalizedName.c_str());
3086// }
3087
3088 // We want to avoid auto-parsing due to intentionally missing dictionary for std::pair.
3089 // However, we don't need this special treatement in rootcling (there is no auto-parsing)
3090 // and we want to make that the TClass for the pair goes through the regular creation
3091 // mechanism (i.e. in rootcling they should be in kInterpreted state and never in
3092 // kEmulated state) so that they have proper interpreter (ClassInfo) information which
3093 // will be used to create the TProtoClass (if one is requested for the pair).
3094 const bool ispair = TClassEdit::IsStdPair(normalizedName) && !IsFromRootCling();
3095 const bool ispairbase = TClassEdit::IsStdPairBase(normalizedName) && !IsFromRootCling();
3096
3097 TClass *loadedcl = nullptr;
3098 if (checkTable) {
3099 loadedcl = LoadClassDefault(normalizedName.c_str(),silent);
3100 } else {
3101 if (gInterpreter->AutoLoad(normalizedName.c_str(),kTRUE)) {
3102 loadedcl = LoadClassDefault(normalizedName.c_str(),silent);
3103 }
3104 auto e = TEnum::GetEnum(normalizedName.c_str(), TEnum::kNone);
3105 if (e)
3106 return nullptr;
3107 // Maybe this was a typedef: let's try to see if this is the case
3108 if (!loadedcl && !ispair && !ispairbase) {
3109 if (TDataType* theDataType = gROOT->GetType(normalizedName.c_str())){
3110 // We have a typedef: we get the name of the underlying type
3111 auto underlyingTypeName = theDataType->GetTypeName();
3112 // We see if we can bootstrap a class with it
3113 auto underlyingTypeDict = TClassTable::GetDictNorm(underlyingTypeName.Data());
3114 if (underlyingTypeDict){
3115 loadedcl = underlyingTypeDict();
3116 }
3117
3118 }
3119 }
3120 }
3121 if (loadedcl) return loadedcl;
3122
3123 // See if the TClassGenerator can produce the TClass we need.
3124 loadedcl = LoadClassCustom(normalizedName.c_str(),silent);
3125 if (loadedcl) return loadedcl;
3126
3127 // We have not been able to find a loaded TClass, return the Emulated
3128 // TClass if we have one.
3129 if (cl) return cl;
3130
3131 if (ispair) {
3132 if (hint_pair_offset && hint_pair_size) {
3133 auto pairinfo = TVirtualStreamerInfo::Factory()->GenerateInfoForPair(normalizedName, silent, hint_pair_offset, hint_pair_size);
3134 // Fall-through to allow TClass to be created when known by the interpreter
3135 // This is used in the case where TStreamerInfo can not handle them.
3136 if (pairinfo)
3137 return pairinfo->GetClass();
3138 } else {
3139 // Check if we have an STL container that might provide it.
3140 static const size_t slen = strlen("pair");
3141 static const char *associativeContainer[] = { "map", "unordered_map", "multimap",
3142 "unordered_multimap", "set", "unordered_set", "multiset", "unordered_multiset" };
3143 for(auto contname : associativeContainer) {
3144 std::string collname = contname;
3145 collname.append( normalizedName.c_str() + slen );
3146 TClass *collcl = TClass::GetClass(collname.c_str(), false, silent);
3147 if (!collcl)
3148 collcl = LoadClassDefault(collname.c_str(), silent);
3149 if (collcl) {
3150 auto p = collcl->GetCollectionProxy();
3151 if (p)
3152 cl = p->GetValueClass();
3153 if (cl)
3154 return cl;
3155 }
3156 }
3157 }
3158 } else if (TClassEdit::IsSTLCont( normalizedName.c_str() )) {
3159
3160 return gInterpreter->GenerateTClass(normalizedName.c_str(), kTRUE, silent);
3161 }
3162
3163 // Check the interpreter only after autoparsing the template if any.
3164 if (!ispairbase) {
3165 std::string::size_type posLess = normalizedName.find('<');
3166 if (posLess != std::string::npos) {
3167 gCling->AutoParse(normalizedName.substr(0, posLess).c_str());
3168 }
3169 }
3170
3171 //last attempt. Look in CINT list of all (compiled+interpreted) classes
3172 if (gDebug>0){
3173 printf("TClass::GetClass: Header Parsing - The representation of %s was not found in the type system. A lookup in the interpreter is about to be tried: this can cause parsing. This can be avoided selecting %s in the linkdef/selection file.\n",normalizedName.c_str(), normalizedName.c_str());
3174 }
3175 if (normalizedName.length()) {
3176 auto cci = gInterpreter->CheckClassInfo(normalizedName.c_str(), kTRUE /* autoload */,
3177 kTRUE /*Only class, structs and ns*/);
3178
3179 // We could have an interpreted class with an inline ClassDef, in this case we do not
3180 // want to create an 'interpreted' TClass but we want the one triggered via the call to
3181 // the Dictionary member. If we go ahead and generate the 'interpreted' version it will
3182 // replace if/when there is a call to IsA on an object of this type.
3183
3185 auto ci = gInterpreter->ClassInfo_Factory(normalizedName.c_str());
3186 auto funcDecl = gInterpreter->GetFunctionWithPrototype(ci, "Dictionary", "", false, ROOT::kExactMatch);
3187 auto method = gInterpreter->MethodInfo_Factory(funcDecl);
3188 typedef void (*tcling_callfunc_Wrapper_t)(void *, int, void **, void *);
3189 auto funcPtr = (tcling_callfunc_Wrapper_t)gInterpreter->MethodInfo_InterfaceMethod(method);
3190
3191 TClass *res = nullptr;
3192 if (funcPtr)
3193 funcPtr(nullptr, 0, nullptr, &res);
3194 // else
3195 // We could fallback to the interpreted case ...
3196 // For now just 'fail' (return nullptr)
3197
3198 gInterpreter->MethodInfo_Delete(method);
3199 gInterpreter->ClassInfo_Delete(ci);
3200
3201 return res;
3202 } else if (cci) {
3203 // Get the normalized name based on the decl (currently the only way
3204 // to get the part to add or drop the default arguments as requested by the user)
3205 std::string alternative;
3206 gInterpreter->GetInterpreterTypeName(normalizedName.c_str(), alternative, kTRUE);
3207 if (alternative.empty())
3208 return nullptr;
3209 const char *altname = alternative.c_str();
3210 if (strncmp(altname, "std::", 5) == 0) {
3211 // For namespace (for example std::__1), GetInterpreterTypeName does
3212 // not strip std::, so we must do it explicitly here.
3213 altname += 5;
3214 }
3215 if (altname != normalizedName && strcmp(altname, name) != 0) {
3216 // altname now contains the full name of the class including a possible
3217 // namespace if there has been a using namespace statement.
3218
3219 // At least in the case C<string [2]> (normalized) vs C<string[2]> (altname)
3220 // the TClassEdit normalization and the TMetaUtils normalization leads to
3221 // two different space layout. To avoid an infinite recursion, we also
3222 // add the test on (altname != name)
3223
3224 return GetClass(altname, load);
3225 }
3226
3227 TClass *ncl = gInterpreter->GenerateTClass(normalizedName.c_str(), /* emulation = */ kFALSE, silent);
3228 if (!ncl->IsZombie()) {
3229 return ncl;
3230 }
3231 delete ncl;
3232 }
3233 }
3234 return nullptr;
3235}
3236
3237////////////////////////////////////////////////////////////////////////////////
3238/// Return pointer to class with name.
3239
3240TClass *TClass::GetClass(const std::type_info& typeinfo, Bool_t load, Bool_t /* silent */, size_t hint_pair_offset, size_t hint_pair_size)
3241{
3242 if (!gROOT->GetListOfClasses())
3243 return nullptr;
3244
3245 //protect access to TROOT::GetIdMap
3247
3248 TClass* cl = GetIdMap()->Find(typeinfo.name());
3249
3250 if (cl && cl->IsLoaded()) return cl;
3251
3253
3254 // Now that we got the write lock, another thread may have constructed the
3255 // TClass while we were waiting, so we need to do the checks again.
3256
3257 cl = GetIdMap()->Find(typeinfo.name());
3258
3259 if (cl) {
3260 if (cl->IsLoaded()) return cl;
3261 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
3262 load = kTRUE;
3263 } else {
3264 // Note we might need support for typedefs and simple types!
3265
3266 // TDataType *objType = GetType(name, load);
3267 //if (objType) {
3268 // const char *typdfName = objType->GetTypeName();
3269 // if (typdfName && strcmp(typdfName, name)) {
3270 // cl = GetClass(typdfName, load);
3271 // return cl;
3272 // }
3273 // }
3274 }
3275
3276 if (!load) return nullptr;
3277
3278 DictFuncPtr_t dict = TClassTable::GetDict(typeinfo);
3279 if (dict) {
3280 cl = (dict)();
3281 if (cl) cl->PostLoadCheck();
3282 return cl;
3283 }
3284 if (cl) return cl;
3285
3286 TIter next(gROOT->GetListOfClassGenerators());
3287 TClassGenerator *gen;
3288 while( (gen = (TClassGenerator*) next()) ) {
3289 cl = gen->GetClass(typeinfo,load);
3290 if (cl) {
3291 cl->PostLoadCheck();
3292 return cl;
3293 }
3294 }
3295
3296 // try AutoLoading the typeinfo
3297 int autoload_old = gCling->SetClassAutoLoading(1);
3298 if (!autoload_old) {
3299 // Re-disable, we just meant to test
3301 }
3302 if (autoload_old && gInterpreter->AutoLoad(typeinfo,kTRUE)) {
3303 // Disable autoload to avoid potential infinite recursion
3305 cl = GetClass(typeinfo, load, hint_pair_offset, hint_pair_size);
3306 if (cl) {
3307 return cl;
3308 }
3309 }
3310
3311 if (hint_pair_offset) {
3312 int err = 0;
3313 char* demangled_name = TClassEdit::DemangleTypeIdName(typeinfo, err);
3314 if (!err) {
3315 cl = TClass::GetClass(demangled_name, load, kTRUE, hint_pair_offset, hint_pair_size);
3316 free(demangled_name);
3317 if (cl)
3318 return cl;
3319 }
3320 }
3321
3322 // last attempt. Look in the interpreter list of all (compiled+interpreted)
3323 // classes
3324 cl = gInterpreter->GetClass(typeinfo, load);
3325
3326 return cl; // Can be zero.
3327}
3328
3329////////////////////////////////////////////////////////////////////////////////
3330/// Static method returning pointer to TClass of the specified ClassInfo.
3331/// If load is true an attempt is made to obtain the class by loading
3332/// the appropriate shared library (directed by the rootmap file).
3333/// If silent is 'true', do not warn about missing dictionary for the class.
3334/// (typically used for class that are used only for transient members)
3335/// Returns 0 in case class is not found.
3336
3337TClass *TClass::GetClass(ClassInfo_t *info, Bool_t load, Bool_t silent)
3338{
3339 if (!info || !gCling->ClassInfo_IsValid(info)) return nullptr;
3340 if (!gROOT->GetListOfClasses()) return nullptr;
3341
3342 // Technically we need the write lock only for the call to ClassInfo_FullName
3343 // and GenerateTClass but FindObject will take the read lock (and LoadClass will
3344 // take the write lock). Since taking/releasing the lock is expensive, let just
3345 // take the write guard and keep it.
3347
3348 // Get the normalized name.
3350
3351 TClass *cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
3352
3353 if (cl) {
3354 if (cl->IsLoaded()) return cl;
3355
3356 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
3357 load = kTRUE;
3358
3359 }
3360
3361 if (!load) return nullptr;
3362
3363 TClass *loadedcl = nullptr;
3364 if (cl) loadedcl = gROOT->LoadClass(cl->GetName(),silent);
3365 else loadedcl = gROOT->LoadClass(name,silent);
3366
3367 if (loadedcl) return loadedcl;
3368
3369 if (cl) return cl; // If we found the class but we already have a dummy class use it.
3370
3371 // We did not find a proper TClass but we do know (we have a valid
3372 // ClassInfo) that the class is known to the interpreter.
3373 TClass *ncl = gInterpreter->GenerateTClass(info, silent);
3374 if (!ncl->IsZombie()) {
3375 return ncl;
3376 } else {
3377 delete ncl;
3378 return nullptr;
3379 }
3380}
3381
3382////////////////////////////////////////////////////////////////////////////////
3383
3386}
3387
3388////////////////////////////////////////////////////////////////////////////////
3389
3390Bool_t TClass::GetClass(DeclId_t id, std::vector<TClass*> &classes)
3391{
3392 if (!gROOT->GetListOfClasses()) return 0;
3393
3394 DeclIdMap_t* map = GetDeclIdMap();
3395 // Get all the TClass pointer that have the same DeclId.
3396 DeclIdMap_t::equal_range iter = map->Find(id);
3397 if (iter.first == iter.second) return false;
3398 std::vector<TClass*>::iterator vectIt = classes.begin();
3399 for (DeclIdMap_t::const_iterator it = iter.first; it != iter.second; ++it)
3400 vectIt = classes.insert(vectIt, it->second);
3401 return true;
3402}
3403
3404////////////////////////////////////////////////////////////////////////////////
3405/// Return a pointer to the dictionary loading function generated by
3406/// rootcint
3407
3409{
3410 return TClassTable::GetDict(cname);
3411}
3412
3413////////////////////////////////////////////////////////////////////////////////
3414/// Return a pointer to the dictionary loading function generated by
3415/// rootcint
3416
3417DictFuncPtr_t TClass::GetDict (const std::type_info& info)
3418{
3419 return TClassTable::GetDict(info);
3420}
3421
3422////////////////////////////////////////////////////////////////////////////////
3423/// Return pointer to datamember object with name "datamember".
3424
3425TDataMember *TClass::GetDataMember(const char *datamember) const
3426{
3427 if ((!(fData.load() && (*fData).IsLoaded()) && !HasInterpreterInfo())
3428 || datamember == nullptr) return nullptr;
3429
3430 // Strip off leading *'s and trailing [
3431 const char *start_name = datamember;
3432 while (*start_name == '*') ++start_name;
3433
3434 // Empty name are 'legal', they represent anonymous unions.
3435 // if (*start_name == 0) return 0;
3436
3437 if (const char *s = strchr(start_name, '[')){
3438 UInt_t len = s-start_name;
3439 TString name(start_name,len);
3440 return (TDataMember *)((TClass*)this)->GetListOfDataMembers(kFALSE)->FindObject(name.Data());
3441 } else {
3442 return (TDataMember *)((TClass*)this)->GetListOfDataMembers(kFALSE)->FindObject(start_name);
3443 }
3444}
3445
3446////////////////////////////////////////////////////////////////////////////////
3447/// Return name of the file containing the declaration of this class.
3448
3449const char *TClass::GetDeclFileName() const
3450{
3451 if (fDeclFileName == kUndeterminedClassInfoName)
3452 return gInterpreter->ClassInfo_FileName( fClassInfo );
3453 return fDeclFileName;
3454}
3455
3456////////////////////////////////////////////////////////////////////////////////
3457/// return offset for member name. name can be a data member in
3458/// the class itself, one of its base classes, or one member in
3459/// one of the aggregated classes.
3460///
3461/// In case of an emulated class, the list of emulated TRealData is built
3462
3464{
3465 TRealData *rd = GetRealData(name);
3466 if (rd) return rd->GetThisOffset();
3467 if (strchr(name,'[')==nullptr) {
3468 // If this is a simple name there is a chance to find it in the
3469 // StreamerInfo even if we did not find it in the RealData.
3470 // For example an array name would be fArray[3] in RealData but
3471 // just fArray in the streamerInfo.
3472 TVirtualStreamerInfo *info = const_cast<TClass*>(this)->GetCurrentStreamerInfo();
3473 if (info) {
3474 return info->GetOffset(name);
3475 }
3476 }
3477 return 0;
3478}
3479
3480////////////////////////////////////////////////////////////////////////////////
3481/// Return pointer to TRealData element with name "name".
3482///
3483/// Name can be a data member in the class itself,
3484/// one of its base classes, or a member in
3485/// one of the aggregated classes.
3486///
3487/// In case of an emulated class, the list of emulated TRealData is built.
3488
3490{
3491 if (!fRealData) {
3492 const_cast<TClass*>(this)->BuildRealData();
3493 }
3494
3495 if (!fRealData) {
3496 return nullptr;
3497 }
3498
3499 if (!name) {
3500 return nullptr;
3501 }
3502
3503 // First try just the whole name.
3505 if (rd) {
3506 return rd;
3507 }
3508
3509 std::string givenName(name);
3510
3511 // Try ignoring the array dimensions.
3512 std::string::size_type firstBracket = givenName.find_first_of("[");
3513 if (firstBracket != std::string::npos) {
3514 // -- We are looking for an array data member.
3515 std::string nameNoDim(givenName.substr(0, firstBracket));
3516 TObjLink* lnk = fRealData->FirstLink();
3517 while (lnk) {
3518 TObject* obj = lnk->GetObject();
3519 std::string objName(obj->GetName());
3520 std::string::size_type pos = objName.find_first_of("[");
3521 // Only match arrays to arrays for now.
3522 if (pos != std::string::npos) {
3523 objName.erase(pos);
3524 if (objName == nameNoDim) {
3525 return static_cast<TRealData*>(obj);
3526 }
3527 }
3528 lnk = lnk->Next();
3529 }
3530 }
3531
3532 // Now try it as a pointer.
3533 std::ostringstream ptrname;
3534 ptrname << "*" << givenName;
3535 rd = (TRealData*) fRealData->FindObject(ptrname.str().c_str());
3536 if (rd) {
3537 return rd;
3538 }
3539
3540 // Check for a dot in the name.
3541 std::string::size_type firstDot = givenName.find_first_of(".");
3542 if (firstDot == std::string::npos) {
3543 // -- Not found, a simple name, all done.
3544 return nullptr;
3545 }
3546
3547 //
3548 // At this point the name has a dot in it, so it is the name
3549 // of some contained sub-object.
3550 //
3551
3552 // May be a pointer like in TH1: fXaxis.fLabels (in TRealdata is named fXaxis.*fLabels)
3553 std::string::size_type lastDot = givenName.find_last_of(".");
3554 std::ostringstream starname;
3555 starname << givenName.substr(0, lastDot) << ".*" << givenName.substr(lastDot + 1);
3556 rd = (TRealData*) fRealData->FindObject(starname.str().c_str());
3557 if (rd) {
3558 return rd;
3559 }
3560
3561 // Last attempt in case a member has been changed from
3562 // a static array to a pointer, for example the member
3563 // was arr[20] and is now *arr.
3564 //
3565 // Note: In principle, one could also take into account
3566 // the opposite situation where a member like *arr has
3567 // been converted to arr[20].
3568 //
3569 // FIXME: What about checking after the first dot as well?
3570 //
3571 std::string::size_type bracket = starname.str().find_first_of("[");
3572 if (bracket != std::string::npos) {
3573 rd = (TRealData*) fRealData->FindObject(starname.str().substr(0, bracket).c_str());
3574 if (rd) {
3575 return rd;
3576 }
3577 }
3578
3579 // Strip the first component, it may be the name of
3580 // the branch (old TBranchElement code), and try again.
3581 std::string firstDotName(givenName.substr(firstDot + 1));
3582
3583 rd = GetRealData(firstDotName.c_str());
3584 if (rd)
3585 return rd;
3586
3587 // Not found;
3588 return nullptr;
3589}
3590
3591////////////////////////////////////////////////////////////////////////////////
3592
3594{
3595 if (!gInterpreter || !HasInterpreterInfo()) return nullptr;
3596
3597 // The following
3599
3601}
3602
3603////////////////////////////////////////////////////////////////////////////////
3604/// Get the list of shared libraries containing the code for class cls.
3605/// The first library in the list is the one containing the class, the
3606/// others are the libraries the first one depends on. Returns 0
3607/// in case the library is not found.
3608
3610{
3611 if (!gInterpreter) return nullptr;
3612
3613 if (fSharedLibs.IsNull())
3614 fSharedLibs = gInterpreter->GetClassSharedLibs(fName);
3615
3616 return !fSharedLibs.IsNull() ? fSharedLibs.Data() : nullptr;
3617}
3618
3619////////////////////////////////////////////////////////////////////////////////
3620/// Return list containing the TBaseClass(es) of a class.
3621
3623{
3624 if (!fBase.load()) {
3625 if (fCanLoadClassInfo) {
3626 if (fState == kHasTClassInit) {
3627
3629 if (!fHasRootPcmInfo) {
3630 // The bases are in our ProtoClass; we don't need the class info.
3632 if (proto && proto->FillTClass(this))
3633 return fBase;
3634 }
3635 }
3636 // We test again on fCanLoadClassInfo has another thread may have executed it.
3638 LoadClassInfo();
3639 }
3640 }
3641 if (!fClassInfo)
3642 return nullptr;
3643
3644 if (!gInterpreter)
3645 Fatal("GetListOfBases", "gInterpreter not initialized");
3646
3648 if (!fBase.load()) {
3649 gInterpreter->CreateListOfBaseClasses(this);
3650 }
3651 }
3652 return fBase;
3653}
3654
3655////////////////////////////////////////////////////////////////////////////////
3656/// Return a list containing the TEnums of a class.
3657///
3658/// The list returned is safe to use from multiple thread without explicitly
3659/// taking the ROOT global lock.
3660///
3661/// In the case the TClass represents a namespace, the returned list will
3662/// implicit take the ROOT global lock upon any access (see TListOfEnumsWithLock)
3663///
3664/// In the case the TClass represents a class or struct and requestListLoading
3665/// is true, the list is immutable (and thus safe to access from multiple thread
3666/// without taking the global lock at all).
3667///
3668/// In the case the TClass represents a class or struct and requestListLoading
3669/// is false, the list is mutable and thus we return a TListOfEnumsWithLock
3670/// which will implicit take the ROOT global lock upon any access.
3671
3672TList *TClass::GetListOfEnums(Bool_t requestListLoading /* = kTRUE */)
3673{
3674 auto temp = fEnums.load();
3675 if (temp) {
3676 if (requestListLoading) {
3677 if (fProperty == -1) Property();
3678 if (! ((kIsClass | kIsStruct | kIsUnion) & fProperty) ) {
3680 temp->Load();
3681 } else if ( temp->IsA() == TListOfEnumsWithLock::Class() ) {
3682 // We have a class for which the list was not loaded fully at
3683 // first use.
3685 temp->Load();
3686 }
3687 }
3688 return temp;
3689 }
3690
3691 if (!requestListLoading) {
3692 if (fProperty == -1) Property();
3694 if (fEnums.load()) {
3695 return fEnums.load();
3696 }
3697
3698 if (IsFromRootCling()) // rootcling is single thread (this save some space in the rootpcm).
3699 fEnums = new TListOfEnums(this);
3700 else
3701 fEnums = new TListOfEnumsWithLock(this);
3702 return fEnums;
3703 }
3704
3706 if (fEnums.load()) {
3707 (*fEnums).Load();
3708 return fEnums.load();
3709 }
3710 if (fProperty == -1) Property();
3711 if ( (kIsClass | kIsStruct | kIsUnion) & fProperty) {
3712 // For this case, the list will be immutable
3713 temp = new TListOfEnums(this);
3714 } else {
3715 //namespaces can have enums added to them
3716 temp = new TListOfEnumsWithLock(this);
3717 }
3718 temp->Load();
3719 fEnums = temp;
3720 return temp;
3721}
3722
3723////////////////////////////////////////////////////////////////////////////////
3724/// Create the list containing the TDataMembers (of actual data members or members
3725/// pulled in through using declarations) of a class.
3726
3727TList *TClass::CreateListOfDataMembers(std::atomic<TListOfDataMembers*> &data, TDictionary::EMemberSelection selection, bool load)
3728{
3730
3731 if (!data) {
3733 // The members are in our ProtoClass; we don't need the class info.
3735 if (proto && proto->FillTClass(this))
3736 return data;
3737 }
3738
3739 data = new TListOfDataMembers(this, selection);
3740 }
3741 if (IsClassStructOrUnion()) {
3742 // If the we have a class or struct or union, the order
3743 // of data members is the list is essential since it determines their
3744 // order on file. So we must always load. Also, the list is fixed
3745 // since the language does not allow to add members.
3746 if (!(*data).IsLoaded())
3747 (*data).Load();
3748
3749 } else if (load) (*data).Load();
3750 return data;
3751}
3752
3753////////////////////////////////////////////////////////////////////////////////
3754/// Return list containing the TDataMembers of a class.
3755
3757{
3758 // Fast path, no lock? Classes load at creation time.
3759 if (IsClassStructOrUnion()) {
3760 auto data = fData.load();
3761 if (data && data->IsLoaded())
3762 return data;
3763 } else if (!load && fData)
3764 return fData;
3765
3767}
3768
3769////////////////////////////////////////////////////////////////////////////////
3770/// Return list containing the TDataMembers of using declarations of a class.
3771
3773{
3774 // Fast path, no lock? Classes load at creation time.
3775 if ((!load || IsClassStructOrUnion()) && fUsingData)
3776 return fUsingData;
3777
3779}
3780
3781////////////////////////////////////////////////////////////////////////////////
3782/// Return TListOfFunctionTemplates for a class.
3783
3785{
3787
3789 if (load) fFuncTemplate->Load();
3790 return fFuncTemplate;
3791}
3792
3793////////////////////////////////////////////////////////////////////////////////
3794/// Return list containing the TMethods of a class.
3795/// If load is true, the list is populated with all the defined function
3796/// and currently instantiated function template.
3797
3799{
3801
3802 if (!fMethod.load()) GetMethodList();
3803 if (load) {
3804 if (gDebug>0) Info("GetListOfMethods","Header Parsing - Asking for all the methods of class %s: this can involve parsing.",GetName());
3805 (*fMethod).Load();
3806 }
3807 return fMethod;
3808}
3809
3810////////////////////////////////////////////////////////////////////////////////
3811/// Return the collection of functions named "name".
3812
3814{
3815 return const_cast<TClass*>(this)->GetMethodList()->GetListForObject(name);
3816}
3817
3818
3819////////////////////////////////////////////////////////////////////////////////
3820/// Returns a list of all public methods of this class and its base classes.
3821/// Refers to a subset of the methods in GetListOfMethods() so don't do
3822/// GetListOfAllPublicMethods()->Delete().
3823/// Algorithm used to get the list is:
3824/// - put all methods of the class in the list (also protected and private
3825/// ones).
3826/// - loop over all base classes and add only those methods not already in the
3827/// list (also protected and private ones).
3828/// - once finished, loop over resulting list and remove all private and
3829/// protected methods.
3830
3832{
3834
3836 if (load) {
3837 if (gDebug>0) Info("GetListOfAllPublicMethods","Header Parsing - Asking for all the methods of class %s: this can involve parsing.",GetName());
3839 }
3840 return fAllPubMethod;
3841}
3842
3843////////////////////////////////////////////////////////////////////////////////
3844/// Returns a list of all public data members of this class and its base
3845/// classes. Refers to a subset of the data members in GetListOfDatamembers()
3846/// so don't do GetListOfAllPublicDataMembers()->Delete().
3847
3849{
3851
3853 if (load) fAllPubData->Load();
3854 return fAllPubData;
3855}
3856
3857////////////////////////////////////////////////////////////////////////////////
3858/// Returns list of methods accessible by context menu.
3859
3861{
3862 if (!HasInterpreterInfo()) return;
3863
3864 // get the base class
3865 TIter nextBase(GetListOfBases(), kIterBackward);
3866 TBaseClass *baseClass;
3867 while ((baseClass = (TBaseClass *) nextBase())) {
3868 TClass *base = baseClass->GetClassPointer();
3869 if (base) base->GetMenuItems(list);
3870 }
3871
3872 // remove methods redefined in this class with no menu
3873 TMethod *method, *m;
3875 while ((method = (TMethod*)next())) {
3876 m = (TMethod*)list->FindObject(method->GetName());
3877 if (method->IsMenuItem() != kMenuNoMenu) {
3878 if (!m)
3879 list->AddFirst(method);
3880 } else {
3881 if (m && m->GetNargs() == method->GetNargs())
3882 list->Remove(m);
3883 }
3884 }
3885}
3886
3887////////////////////////////////////////////////////////////////////////////////
3888/// Check whether a class has a dictionary or not.
3889/// This is equivalent to ask if a class is coming from a bootstrapping
3890/// procedure initiated during the loading of a library.
3891
3893{
3894 return IsLoaded();
3895}
3896
3897////////////////////////////////////////////////////////////////////////////////
3898/// Check whether a class has a dictionary or ROOT can load one.
3899/// This is equivalent to ask HasDictionary() or whether a library is known
3900/// where it can be loaded from, or whether a Dictionary function is
3901/// available because the class's dictionary library was already loaded.
3902
3904{
3905 if (TClass* cl = (TClass*)gROOT->GetListOfClasses()->FindObject(clname))
3906 return cl->IsLoaded();
3907 return gClassTable->GetDict(clname) || gInterpreter->GetClassSharedLibs(clname);
3908}
3909
3910////////////////////////////////////////////////////////////////////////////////
3911/// Verify the base classes always.
3912
3914{
3915 TList* lb = GetListOfBases();
3916 if (!lb) return;
3917 TIter nextBase(lb);
3918 TBaseClass* base = nullptr;
3919 while ((base = (TBaseClass*)nextBase())) {
3920 TClass* baseCl = base->GetClassPointer();
3921 if (baseCl) {
3922 baseCl->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3923 }
3924 }
3925}
3926
3927////////////////////////////////////////////////////////////////////////////////
3928/// Verify the Data Members.
3929
3931{
3933 if (!ldm) return ;
3934 TIter nextMemb(ldm);
3935 TDataMember * dm = nullptr;
3936 while ((dm = (TDataMember*)nextMemb())) {
3937 // If it is a transient
3938 if(!dm->IsPersistent()) {
3939 continue;
3940 }
3941 if (dm->Property() & kIsStatic) {
3942 continue;
3943 }
3944 // If it is a built-in data type.
3945 TClass* dmTClass = nullptr;
3946 if (dm->GetDataType()) {
3947 // We have a basic datatype.
3948 dmTClass = nullptr;
3949 // Otherwise get the string representing the type.
3950 } else if (dm->GetTypeName()) {
3951 dmTClass = TClass::GetClass(dm->GetTypeName());
3952 }
3953 if (dmTClass) {
3954 dmTClass->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3955 }
3956 }
3957}
3958
3960{
3961 // Pair is a special case and we have to check its elements for missing dictionaries
3962 // Pair is a transparent container so we should always look at its.
3963
3965 for (int i = 0; i < 2; i++) {
3966 TClass* pairElement = ((TStreamerElement*)SI->GetElements()->At(i))->GetClass();
3967 if (pairElement) {
3968 pairElement->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3969 }
3970 }
3971}
3972
3973////////////////////////////////////////////////////////////////////////////////
3974/// From the second level of recursion onwards it is different state check.
3975
3977{
3978 if (result.FindObject(this) || visited.FindObject(this)) return;
3979
3980 static TClassRef sCIString("string");
3981 if (this == sCIString) return;
3982
3983 TClassEdit::TSplitType splitType(fName);
3984 if (splitType.IsTemplate()) {
3985 // We now treat special cases:
3986 // - pair
3987 // - unique_ptr
3988 // - array
3989 // - tuple
3990
3991 // Small helper to get the TClass instance from a classname and recursively
3992 // investigate it
3993 auto checkDicts = [&](const string &clName){
3994 auto cl = TClass::GetClass(clName.c_str());
3995 if (!cl) {
3996 // We try to remove * and const from the type name if any
3997 const auto clNameShortType = TClassEdit::ShortType(clName.c_str(), 1);
3998 cl = TClass::GetClass(clNameShortType.c_str());
3999 }
4000 if (cl && !cl->HasDictionary()) {
4001 cl->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
4002 }
4003 };
4004
4005 const auto &elements = splitType.fElements;
4006 const auto &templName = elements[0];
4007
4008 // Special treatment for pair.
4009 if (templName == "pair") {
4010 GetMissingDictionariesForPairElements(result, visited, recurse);
4011 return;
4012 }
4013
4014 // Special treatment of unique_ptr or array
4015 // They are treated together since they have 1 single template argument
4016 // which is interesting when checking for missing dictionaries.
4017 if (templName == "unique_ptr" || templName == "array") {
4018 checkDicts(elements[1]);
4019 return;
4020 }
4021
4022 // Special treatment of tuple
4023 // This type must be treated separately since it can have N template
4024 // arguments which are interesting, unlike unique_ptr or array.
4025 if (templName == "tuple") {
4026 // -1 because the elements end with a list of the "stars", i.e. number of
4027 // * after the type name
4028 const auto nTemplArgs = elements.size() - 1;
4029 // loop starts at 1 because the first element is the template name
4030 for (auto iTemplArg = 1U; iTemplArg < nTemplArgs; ++iTemplArg) {
4031 checkDicts(elements[iTemplArg]);
4032 }
4033 return;
4034 }
4035 } // this is not a template
4036
4037 if (!HasDictionary()) {
4038 result.Add(this);
4039 }
4040
4041 visited.Add(this);
4042 //Check whether a custom streamer
4044 if (GetCollectionProxy()) {
4045 // We need to look at the collection's content
4046 // The collection has different kind of elements the check would be required.
4047 TClass* t = nullptr;
4048 if ((t = GetCollectionProxy()->GetValueClass())) {
4049 if (!t->HasDictionary()) {
4050 t->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
4051 }
4052 }
4053 } else {
4054 if (recurse) {
4055 GetMissingDictionariesForMembers(result, visited, recurse);
4056 }
4057 GetMissingDictionariesForBaseClasses(result, visited, recurse);
4058 }
4059 }
4060}
4061
4062////////////////////////////////////////////////////////////////////////////////
4063/// Get the classes that have a missing dictionary starting from this one.
4064/// - With recurse = false the classes checked for missing dictionaries are:
4065/// the class itself, all base classes, direct data members,
4066/// and for collection proxies the container's
4067/// elements without iterating over the element's data members;
4068/// - With recurse = true the classes checked for missing dictionaries are:
4069/// the class itself, all base classes, recursing on the data members,
4070/// and for the collection proxies recursion on the elements of the
4071/// collection and iterating over the element's data members.
4072
4074{
4075 // Top level recursion it different from the following levels of recursion.
4076
4077 if (result.FindObject(this)) return;
4078
4079 static TClassRef sCIString("string");
4080 if (this == sCIString) return;
4081
4082 THashTable visited;
4083
4085 GetMissingDictionariesForPairElements(result, visited, recurse);
4086 return;
4087 }
4088
4089 if (strncmp(fName, "unique_ptr<", 11) == 0 || strncmp(fName, "array<", 6) == 0 || strncmp(fName, "tuple<", 6) == 0) {
4090 GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
4091 return;
4092 }
4093
4094 if (!HasDictionary()) {
4095 result.Add(this);
4096 }
4097
4098 visited.Add(this);
4099
4100 //Check whether a custom streamer
4102 if (GetCollectionProxy()) {
4103 // We need to look at the collection's content
4104 // The collection has different kind of elements the check would be required.
4105 TClass* t = nullptr;
4106 if ((t = GetCollectionProxy()->GetValueClass())) {
4107 if (!t->HasDictionary()) {
4108 t->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
4109 }
4110 }
4111 } else {
4112 GetMissingDictionariesForMembers(result, visited, recurse);
4113 GetMissingDictionariesForBaseClasses(result, visited, recurse);
4114 }
4115 }
4116}
4117
4118////////////////////////////////////////////////////////////////////////////////
4119/// Return kTRUE if the class has elements.
4120
4121Bool_t TClass::IsFolder(void *obj) const
4122{
4123 return Browse(obj,(TBrowser*)nullptr);
4124}
4125
4126//______________________________________________________________________________
4127//______________________________________________________________________________
4128void TClass::ReplaceWith(TClass *newcl) const
4129{
4130 // Inform the other objects to replace this object by the new TClass (newcl)
4131
4133 //we must update the class pointers pointing to 'this' in all TStreamerElements
4134 TIter nextClass(gROOT->GetListOfClasses());
4135 TClass *acl;
4137
4138 // Since we are in the process of replacing a TClass by a TClass
4139 // coming from a dictionary, there is no point in loading any
4140 // libraries during this search.
4142 while ((acl = (TClass*)nextClass())) {
4143 if (acl == newcl) continue;
4144
4145 TIter nextInfo(acl->GetStreamerInfos());
4146 while ((info = (TVirtualStreamerInfo*)nextInfo())) {
4147
4148 info->Update(this, newcl);
4149 }
4150 }
4151
4152 gInterpreter->UnRegisterTClassUpdate(this);
4153}
4154
4155////////////////////////////////////////////////////////////////////////////////
4156/// Make sure that the current ClassInfo is up to date.
4157
4159{
4160 Warning("ResetClassInfo(Long_t tagnum)","Call to deprecated interface (does nothing)");
4161}
4162
4163////////////////////////////////////////////////////////////////////////////////
4164/// Make sure that the current ClassInfo is up to date.
4165
4167{
4169
4171
4172 if (fClassInfo) {
4174 gInterpreter->ClassInfo_Delete(fClassInfo);
4175 fClassInfo = nullptr;
4176 }
4177 // We can not check at this point whether after the unload there will
4178 // still be interpreter information about this class (as v5 was doing),
4179 // instead this function must only be called if the definition is (about)
4180 // to be unloaded.
4181
4182 ResetCaches();
4183
4184 // We got here because the definition Decl is about to be unloaded.
4186 if (fStreamerInfo->GetEntries() != 0) {
4188 } else {
4190 }
4191 } else {
4192 // if the ClassInfo was loaded for a class with a TClass Init and it
4193 // gets unloaded, should we guess it can be reloaded?
4195 }
4196}
4197
4198////////////////////////////////////////////////////////////////////////////////
4199/// To clean out all caches.
4200
4202{
4203 R__ASSERT(!TestBit(kLoading) && "Resetting the caches does not make sense during loading!" );
4204
4205 // Not owning lists, don't call Delete(), but unload
4206 if (fData.load())
4207 (*fData).Unload();
4208 if (fUsingData.load())
4209 (*fUsingData).Unload();
4210 if (fEnums.load())
4211 (*fEnums).Unload();
4212 if (fMethod.load())
4213 (*fMethod).Unload();
4214
4215 delete fAllPubData; fAllPubData = nullptr;
4216
4217 if (fBase.load())
4218 (*fBase).Delete();
4219 delete fBase.load(); fBase = nullptr;
4220
4221 if (fRealData)
4222 fRealData->Delete();
4223 delete fRealData; fRealData=nullptr;
4224}
4225
4226////////////////////////////////////////////////////////////////////////////////
4227/// Resets the menu list to it's standard value.
4228
4230{
4231 if (fClassMenuList)
4233 else
4234 fClassMenuList = new TList();
4236}
4237
4238////////////////////////////////////////////////////////////////////////////////
4239/// The ls function lists the contents of a class on stdout. Ls output
4240/// is typically much less verbose then Dump().
4241/// If options contains 'streamerinfo', run ls on the list of streamerInfos
4242/// and the list of conversion streamerInfos.
4243
4244void TClass::ls(Option_t *options) const
4245{
4246 TNamed::ls(options);
4247 if (options==nullptr || options[0]==0) return;
4248
4249 if (strstr(options,"streamerinfo")!=nullptr) {
4250 GetStreamerInfos()->ls(options);
4251
4252 if (fConversionStreamerInfo.load()) {
4253 std::map<std::string, TObjArray*>::iterator it;
4254 std::map<std::string, TObjArray*>::iterator end = (*fConversionStreamerInfo).end();
4255 for( it = (*fConversionStreamerInfo).begin(); it != end; ++it ) {
4256 it->second->ls(options);
4257 }
4258 }
4259 }
4260}
4261
4262////////////////////////////////////////////////////////////////////////////////
4263/// Makes a customizable version of the popup menu list, i.e. makes a list
4264/// of TClassMenuItem objects of methods accessible by context menu.
4265/// The standard (and different) way consists in having just one element
4266/// in this list, corresponding to the whole standard list.
4267/// Once the customizable version is done, one can remove or add elements.
4268
4270{
4272 TClassMenuItem *menuItem;
4273
4274 // Make sure fClassMenuList is initialized and empty.
4275 GetMenuList()->Delete();
4276
4277 TList* methodList = new TList;
4278 GetMenuItems(methodList);
4279
4280 TMethod *method;
4281 TMethodArg *methodArg;
4282 TClass *classPtr = nullptr;
4283 TIter next(methodList);
4284
4285 while ((method = (TMethod*) next())) {
4286 // if go to a mother class method, add separator
4287 if (classPtr != method->GetClass()) {
4288 menuItem = new TClassMenuItem(TClassMenuItem::kPopupSeparator, this);
4289 fClassMenuList->AddLast(menuItem);
4290 classPtr = method->GetClass();
4291 }
4292 // Build the signature of the method
4293 TString sig;
4294 TList* margsList = method->GetListOfMethodArgs();
4295 TIter nextarg(margsList);
4296 while ((methodArg = (TMethodArg*)nextarg())) {
4297 sig = sig+","+methodArg->GetFullTypeName();
4298 }
4299 if (sig.Length()!=0) sig.Remove(0,1); // remove first comma
4301 method->GetName(), method->GetName(),nullptr,
4302 sig.Data(),-1,TClassMenuItem::kIsSelf);
4303 if (method->IsMenuItem() == kMenuToggle) menuItem->SetToggle();
4304 fClassMenuList->Add(menuItem);
4305 }
4306 delete methodList;
4307}
4308
4309////////////////////////////////////////////////////////////////////////////////
4310/// Register the fact that an object was moved from the memory location
4311/// 'arenaFrom' to the memory location 'arenaTo'.
4312
4313void TClass::Move(void *arenaFrom, void *arenaTo) const
4314{
4315 // If/when we have access to a copy constructor (or better to a move
4316 // constructor), this function should also perform the data move.
4317 // For now we just information the repository.
4318
4319 if ((GetState() <= kEmulated) && !fCollectionProxy) {
4320 MoveAddressInRepository("TClass::Move",arenaFrom,arenaTo,this);
4321 }
4322}
4323
4324////////////////////////////////////////////////////////////////////////////////
4325/// Return the list of menu items associated with the class.
4326
4328 if (!fClassMenuList) {
4329 fClassMenuList = new TList();
4331 }
4332 return fClassMenuList;
4333}
4334
4335////////////////////////////////////////////////////////////////////////////////
4336/// Return (create an empty one if needed) the list of functions.
4337/// The major difference with GetListOfMethod is that this returns
4338/// the internal type of fMethod and thus can not be made public.
4339/// It also never 'loads' the content of the list.
4340
4342{
4343 if (!fMethod.load()) {
4344 std::unique_ptr<TListOfFunctions> temp{ new TListOfFunctions(this) };
4345 TListOfFunctions* expected = nullptr;
4346 if(fMethod.compare_exchange_strong(expected, temp.get()) ) {
4347 temp.release();
4348 }
4349 }
4350 return fMethod;
4351}
4352
4353
4354////////////////////////////////////////////////////////////////////////////////
4355/// Return pointer to method without looking at parameters.
4356/// Does not look in (possible) base classes.
4357/// Has the side effect of loading all the TMethod object in the list
4358/// of the class.
4359
4360TMethod *TClass::GetMethodAny(const char *method)
4361{
4362 if (!HasInterpreterInfo()) return nullptr;
4363 return (TMethod*) GetMethodList()->FindObject(method);
4364}
4365
4366////////////////////////////////////////////////////////////////////////////////
4367/// Return pointer to method without looking at parameters.
4368/// Does look in all base classes.
4369
4371{
4372 if (!HasInterpreterInfo()) return nullptr;
4373
4374 TMethod* m = GetMethodAny(method);
4375 if (m) return m;
4376
4377 TBaseClass *base;
4378 TIter nextb(GetListOfBases());
4379 while ((base = (TBaseClass *) nextb())) {
4380 TClass *c = base->GetClassPointer();
4381 if (c) {
4382 m = c->GetMethodAllAny(method);
4383 if (m) return m;
4384 }
4385 }
4386
4387 return nullptr;
4388}
4389
4390////////////////////////////////////////////////////////////////////////////////
4391/// Find the best method (if there is one) matching the parameters.
4392/// The params string must contain argument values, like "3189, \"aap\", 1.3".
4393/// The function invokes GetClassMethod to search for a possible method
4394/// in the class itself or in its base classes. Returns 0 in case method
4395/// is not found.
4396
4397TMethod *TClass::GetMethod(const char *method, const char *params,
4398 Bool_t objectIsConst /* = kFALSE */)
4399{
4401 if (!fClassInfo) return nullptr;
4402
4403 if (!gInterpreter)
4404 Fatal("GetMethod", "gInterpreter not initialized");
4405
4406 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithValues(fClassInfo,
4407 method, params,
4408 objectIsConst);
4409
4410 if (!decl) return nullptr;
4411
4412 // search recursively in this class or its base classes
4414 if (f) return f;
4415
4416 Error("GetMethod",
4417 "\nDid not find matching TMethod <%s> with \"%s\" %sfor %s",
4418 method,params,objectIsConst ? "const " : "", GetName());
4419 return nullptr;
4420}
4421
4422
4423////////////////////////////////////////////////////////////////////////////////
4424/// Find a method with decl id in this class or its bases.
4425
4427 if (TFunction* method = GetMethodList()->Get(declId))
4428 return static_cast<TMethod *>(method);
4429
4430 for (auto item : *GetListOfBases())
4431 if (auto base = static_cast<TBaseClass *>(item)->GetClassPointer())
4432 if (TFunction* method = base->FindClassOrBaseMethodWithId(declId))
4433 return static_cast<TMethod *>(method);
4434
4435 return nullptr;
4436}
4437
4438////////////////////////////////////////////////////////////////////////////////
4439/// Find the method with a given prototype. The proto string must be of the
4440/// form: "char*,int,double". Returns 0 in case method is not found.
4441
4442TMethod *TClass::GetMethodWithPrototype(const char *method, const char *proto,
4443 Bool_t objectIsConst /* = kFALSE */,
4444 ROOT::EFunctionMatchMode mode /* = ROOT::kConversionMatch */)
4445{
4447 if (!fClassInfo) return nullptr;
4448
4449 if (!gInterpreter)
4450 Fatal("GetMethodWithPrototype", "gInterpreter not initialized");
4451
4452 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithPrototype(fClassInfo,
4453 method, proto,
4454 objectIsConst, mode);
4455
4456 if (!decl) return nullptr;
4458 if (f) return f;
4459 Error("GetMethodWithPrototype",
4460 "\nDid not find matching TMethod <%s> with \"%s\" %sfor %s",
4461 method,proto,objectIsConst ? "const " : "", GetName());
4462 return nullptr;
4463}
4464
4465////////////////////////////////////////////////////////////////////////////////
4466/// Look for a method in this class that has the interface function
4467/// address faddr.
4468
4470{
4471 if (!HasInterpreterInfo()) return nullptr;
4472
4473 TMethod *m;
4474 TIter next(GetListOfMethods());
4475 while ((m = (TMethod *) next())) {
4476 if (faddr == (Longptr_t)m->InterfaceMethod())
4477 return m;
4478 }
4479 return nullptr;
4480}
4481
4482////////////////////////////////////////////////////////////////////////////////
4483/// Look for a method in this class that has the name and matches the parameters.
4484/// The params string must contain argument values, like "3189, \"aap\", 1.3".
4485/// Returns 0 in case method is not found.
4486/// See TClass::GetMethod to also search the base classes.
4487
4488TMethod *TClass::GetClassMethod(const char *name, const char* params,
4489 Bool_t objectIsConst /* = kFALSE */)
4490{
4492 if (!fClassInfo) return nullptr;
4493
4494 if (!gInterpreter)
4495 Fatal("GetClassMethod", "gInterpreter not initialized");
4496
4497 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithValues(fClassInfo,
4498 name, params,
4499 objectIsConst);
4500
4501 if (!decl) return nullptr;
4502
4503 TFunction *f = GetMethodList()->Get(decl);
4504
4505 return (TMethod*)f; // Could be zero if the decl is actually in a base class.
4506}
4507
4508////////////////////////////////////////////////////////////////////////////////
4509/// Find the method with a given prototype. The proto string must be of the
4510/// form: "char*,int,double". Returns 0 in case method is not found.
4511/// See TClass::GetMethodWithPrototype to also search the base classes.
4512
4514 Bool_t objectIsConst /* = kFALSE */,
4515 ROOT::EFunctionMatchMode mode /* = ROOT::kConversionMatch */)
4516{
4518 if (!fClassInfo) return nullptr;
4519
4520 if (!gInterpreter)
4521 Fatal("GetClassMethodWithPrototype", "gInterpreter not initialized");
4522
4523 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithPrototype(fClassInfo,
4524 name, proto,
4525 objectIsConst,
4526 mode);
4527
4528 if (!decl) return nullptr;
4529
4530 TFunction *f = GetMethodList()->Get(decl);
4531
4532 return (TMethod*)f; // Could be zero if the decl is actually in a base class.
4533}
4534
4535////////////////////////////////////////////////////////////////////////////////
4536/// Return the number of data members of this class
4537/// Note that in case the list of data members is not yet created, it will be done
4538/// by GetListOfDataMembers().
4539
4541{
4542 if (!HasDataMemberInfo()) return 0;
4543
4545 if (lm)
4546 return lm->GetSize();
4547 else
4548 return 0;
4549}
4550
4551////////////////////////////////////////////////////////////////////////////////
4552/// Return the number of methods of this class
4553/// Note that in case the list of methods is not yet created, it will be done
4554/// by GetListOfMethods().
4555/// This will also load/populate the list of methods, to get 'just' the
4556/// number of currently loaded methods use:
4557/// cl->GetListOfMethods(false)->GetSize();
4558
4560{
4561 if (!HasInterpreterInfo()) return 0;
4562
4563 TList *lm = GetListOfMethods();
4564 if (lm)
4565 return lm->GetSize();
4566 else
4567 return 0;
4568}
4569
4570////////////////////////////////////////////////////////////////////////////////
4571/// returns a pointer to the TVirtualStreamerInfo object for version
4572/// If the object does not exist, it is created
4573///
4574/// Note: There are two special version numbers:
4575///
4576/// - 0: Use the class version from the currently loaded class library.
4577/// - -1: Assume no class library loaded (emulated class).
4578///
4579/// Warning: If we create a new streamer info, whether or not the build
4580/// optimizes is controlled externally to us by a global variable!
4581/// Don't call us unless you have set that variable properly
4582/// with TStreamer::Optimize()!
4583///
4584
4585TVirtualStreamerInfo* TClass::GetStreamerInfo(Int_t version /* = 0 */, Bool_t isTransient /* = false */) const
4586{
4588
4589 // Version 0 is special, it means the currently loaded version.
4590 // We need to set it at the beginning to be able to guess it correctly.
4591
4592 if (version == 0)
4593 version = fClassVersion;
4594
4595 // If the StreamerInfo is assigned to the fLastReadInfo, we are
4596 // guaranteed it was built and compiled.
4597 if (sinfo && sinfo->GetClassVersion() == version)
4598 return sinfo;
4599
4600 // Note that the access to fClassVersion above is technically not thread-safe with a low probably of problems.
4601 // fClassVersion is not an atomic and is modified TClass::SetClassVersion (called from RootClassVersion via
4602 // ROOT::ResetClassVersion) and is 'somewhat' protected by the atomic fVersionUsed.
4603 // However, direct access to fClassVersion should be replaced by calls to GetClassVersion to set fVersionUsed.
4604 // Even with such a change the code here and in these functions need to be reviewed as a cursory look seem
4605 // to indicates they are not yet properly protection against mutli-thread access.
4606 //
4607 // However, the use of these functions is rare and mostly done at library loading time which should
4608 // in almost all cases preceeds the possibility of GetStreamerInfo being called from multiple thread
4609 // on that same TClass object.
4610 //
4611 // Summary: need careful review but risk of problem is extremely low.
4612
4614
4615 return GetStreamerInfoImpl(version, isTransient);
4616};
4617
4618// Implementation of/for TStreamerInfo::GetStreamerInfo.
4619// This routine assumes the global lock has been taken.
4621{
4622 // Warning: version may be -1 for an emulated class, or -2 if the
4623 // user requested the emulated streamerInfo for an abstract
4624 // base class, even though we have a dictionary for it.
4625
4626 if ((version < -1) || (version >= (fStreamerInfo->GetSize()-1))) {
4627 Error("GetStreamerInfo", "class: %s, attempting to access a wrong version: %d", GetName(), version);
4628 // FIXME: Shouldn't we go to -1 here, or better just abort?
4629 version = fClassVersion;
4630 }
4631
4633
4634 if (!sinfo && (version != fClassVersion)) {
4635 // When the requested version does not exist we return
4636 // the TVirtualStreamerInfo for the currently loaded class version.
4637 // FIXME: This arguably makes no sense, we should warn and return nothing instead.
4638 // Note: This is done for STL collections
4639 // Note: fClassVersion could be -1 here (for an emulated class).
4640 // This is also the code path take for unversioned classes.
4642 }
4643
4644 if (!sinfo) {
4645 // We just were not able to find a streamer info, we have to make a new one.
4646 TMmallocDescTemp setreset;
4647 sinfo = TVirtualStreamerInfo::Factory()->NewInfo(const_cast<TClass*>(this));
4649 if (gDebug > 0) {
4650 printf("Creating StreamerInfo for class: %s, version: %d\n", GetName(), fClassVersion);
4651 }
4653 // If we do not have a StreamerInfo for this version and we do not
4654 // have dictionary information nor a proxy, there is nothing to build!
4655 sinfo->Build(silent);
4656 }
4657 } else {
4658 if (!sinfo->IsCompiled()) {
4659 // Streamer info has not been compiled, but exists.
4660 // Therefore it was read in from a file and we have to do schema evolution?
4661 // Or it didn't have a dictionary before, but does now?
4662 sinfo->BuildOld();
4663 }
4664 }
4665
4666 // Cache the current info if we now have it.
4667 if (version == fClassVersion)
4668 fCurrentInfo = sinfo;
4669
4670 // If the compilation succeeded, remember this StreamerInfo.
4671 if (sinfo->IsCompiled())
4672 fLastReadInfo = sinfo;
4673
4674 return sinfo;
4675}
4676
4677////////////////////////////////////////////////////////////////////////////////
4678/// For the case where the requestor class is emulated and this class is abstract,
4679/// returns a pointer to the TVirtualStreamerInfo object for version with an emulated
4680/// representation whether or not the class is loaded.
4681///
4682/// If the object does not exist, it is created
4683///
4684/// Note: There are two special version numbers:
4685///
4686/// - 0: Use the class version from the currently loaded class library.
4687/// - -1: Assume no class library loaded (emulated class).
4688///
4689/// Warning: If we create a new streamer info, whether or not the build
4690/// optimizes is controlled externally to us by a global variable!
4691/// Don't call us unless you have set that variable properly
4692/// with TStreamer::Optimize()!
4693///
4694
4696{
4697 TVirtualStreamerInfo *sinfo = nullptr;
4698
4699 TString newname(GetName());
4700 newname += "@@emulated";
4701
4703
4704 TClass *emulated = TClass::GetClass(newname);
4705
4706 if (emulated)
4707 sinfo = emulated->GetStreamerInfo(version);
4708
4709 if (!sinfo) {
4710 // The emulated version of the streamerInfo is explicitly requested and has
4711 // not been built yet.
4712
4713 sinfo = (TVirtualStreamerInfo*) fStreamerInfo->At(version);
4714
4715 if (!sinfo && (version != fClassVersion)) {
4716 // When the requested version does not exist we return
4717 // the TVirtualStreamerInfo for the currently loaded class version.
4718 // FIXME: This arguably makes no sense, we should warn and return nothing instead.
4720 }
4721
4722 if (!sinfo) {
4723 // Let's take the first available StreamerInfo as a start
4724 Int_t ninfos = fStreamerInfo->GetEntriesFast() - 1;
4725 for (Int_t i = -1; sinfo == nullptr && i < ninfos; ++i)
4727 }
4728
4729 if (sinfo) {
4730 sinfo = dynamic_cast<TVirtualStreamerInfo *>(sinfo->Clone());
4731 if (sinfo) {
4732 sinfo->SetClass(nullptr);
4733 sinfo->SetName(newname);
4734 sinfo->BuildCheck();
4735 sinfo->BuildOld();
4736 sinfo->GetClass()->AddRule(TString::Format("sourceClass=%s targetClass=%s",GetName(),newname.Data()));
4737 } else {
4738 Error("GetStreamerInfoAbstractEmulated", "could not create TVirtualStreamerInfo");
4739 }
4740 }
4741 }
4742 return sinfo;
4743}
4744
4745////////////////////////////////////////////////////////////////////////////////
4746/// For the case where the requestor class is emulated and this class is abstract,
4747/// returns a pointer to the TVirtualStreamerInfo object for version with an emulated
4748/// representation whether or not the class is loaded.
4749///
4750/// If the object does not exist, it is created
4751///
4752/// Warning: If we create a new streamer info, whether or not the build
4753/// optimizes is controlled externally to us by a global variable!
4754/// Don't call us unless you have set that variable properly
4755/// with TStreamer::Optimize()!
4756///
4757
4759{
4760 TVirtualStreamerInfo *sinfo = nullptr;
4761
4762 TString newname(GetName());
4763 newname += "@@emulated";
4764
4766
4767 TClass *emulated = TClass::GetClass(newname);
4768
4769 if (emulated)
4770 sinfo = emulated->FindStreamerInfo(checksum);
4771
4772 if (!sinfo) {
4773 // The emulated version of the streamerInfo is explicitly requested and has
4774 // not been built yet.
4775
4776 sinfo = (TVirtualStreamerInfo*) FindStreamerInfo(checksum);
4777
4778 if (!sinfo && (checksum != fCheckSum)) {
4779 // When the requested version does not exist we return
4780 // the TVirtualStreamerInfo for the currently loaded class version.
4781 // FIXME: This arguably makes no sense, we should warn and return nothing instead.
4783 }
4784
4785 if (!sinfo) {
4786 // Let's take the first available StreamerInfo as a start
4787 Int_t ninfos = fStreamerInfo->GetEntriesFast() - 1;
4788 for (Int_t i = -1; sinfo == nullptr && i < ninfos; ++i)
4790 }
4791
4792 if (sinfo) {
4793 sinfo = dynamic_cast<TVirtualStreamerInfo*>( sinfo->Clone() );
4794 if (sinfo) {
4795 sinfo->SetClass(nullptr);
4796 sinfo->SetName( newname );
4797 sinfo->BuildCheck();
4798 sinfo->BuildOld();
4799 sinfo->GetClass()->AddRule(TString::Format("sourceClass=%s targetClass=%s",GetName(),newname.Data()));
4800 } else {
4801 Error("GetStreamerInfoAbstractEmulated", "could not create TVirtualStreamerInfo");
4802 }
4803 }
4804 }
4805 return sinfo;
4806}
4807
4808////////////////////////////////////////////////////////////////////////////////
4809/// When the class kIgnoreTObjectStreamer bit is set, the automatically
4810/// generated Streamer will not call TObject::Streamer.
4811/// This option saves the TObject space overhead on the file.
4812/// However, the information (fBits, fUniqueID) of TObject is lost.
4813///
4814/// Note that to be effective for objects streamed object-wise this function
4815/// must be called for the class deriving directly from TObject, eg, assuming
4816/// that BigTrack derives from Track and Track derives from TObject, one must do:
4817/// ~~~ {.cpp}
4818/// Track::Class()->IgnoreTObjectStreamer();
4819/// ~~~
4820/// and not:
4821/// ~~~ {.cpp}
4822/// BigTrack::Class()->IgnoreTObjectStreamer();
4823/// ~~~
4824/// To be effective for object streamed member-wise or split in a TTree,
4825/// this function must be called for the most derived class (i.e. BigTrack).
4826
4828{
4829 // We need to tak the lock since we are test and then setting fBits
4830 // and TStreamerInfo::fBits (and the StreamerInfo state in general)
4831 // which can also be modified by another thread.
4833
4834 if ( doIgnore && TestBit(kIgnoreTObjectStreamer)) return;
4835 if (!doIgnore && !TestBit(kIgnoreTObjectStreamer)) return;
4837 if (sinfo) {
4838 if (sinfo->IsCompiled()) {
4839 // -- Warn the user that what they are doing cannot work.
4840 // Note: The reason is that TVirtualStreamerInfo::Build() examines
4841 // the kIgnoreTObjectStreamer bit and sets the TStreamerElement
4842 // type for the TObject base class streamer element it creates
4843 // to -1 as a flag. Later on the TStreamerInfo::Compile()
4844 // member function sees the flag and does not insert the base
4845 // class element into the compiled streamer info. None of this
4846 // machinery works correctly if we are called after the streamer
4847 // info has already been built and compiled.
4848 Error("IgnoreTObjectStreamer","Must be called before the creation of StreamerInfo");
4849 return;
4850 }
4851 }
4852 if (doIgnore) SetBit (kIgnoreTObjectStreamer);
4854}
4855
4856////////////////////////////////////////////////////////////////////////////////
4857/// Return kTRUE if this class inherits from a class with name "classname".
4858/// note that the function returns kTRUE in case classname is the class itself
4859
4860Bool_t TClass::InheritsFrom(const char *classname) const
4861{
4862 if (strcmp(GetName(), classname) == 0) return kTRUE;
4863
4864 return InheritsFrom(TClass::GetClass(classname,kTRUE,kTRUE));
4865}
4866
4867////////////////////////////////////////////////////////////////////////////////
4868/// Return kTRUE if this class inherits from class cl.
4869/// note that the function returns KTRUE in case cl is the class itself
4870
4872{
4873 if (!cl) return kFALSE;
4874 if (cl == this) return kTRUE;
4875
4876 if (!HasDataMemberInfo()) {
4877 TVirtualStreamerInfo *sinfo = ((TClass *)this)->GetCurrentStreamerInfo();
4878 if (sinfo==nullptr) sinfo = GetStreamerInfo();
4879 TIter next(sinfo->GetElements());
4880 TStreamerElement *element;
4881 while ((element = (TStreamerElement*)next())) {
4882 if (element->IsA() == TStreamerBase::Class()) {
4883 TClass *clbase = element->GetClassPointer();
4884 if (!clbase) return kFALSE; //missing class
4885 if (clbase->InheritsFrom(cl)) return kTRUE;
4886 }
4887 }
4888 return kFALSE;
4889 }
4890 // cast const away (only for member fBase which can be set in GetListOfBases())
4891 if (((TClass *)this)->GetBaseClass(cl)) return kTRUE;
4892 return kFALSE;
4893}
4894
4895////////////////////////////////////////////////////////////////////////////////
4896/// Cast obj of this class type up to baseclass cl if up is true.
4897/// Cast obj of this class type down from baseclass cl if up is false.
4898/// If this class is not a baseclass of cl return 0, else the pointer
4899/// to the cl part of this (up) or to this (down).
4900
4901void *TClass::DynamicCast(const TClass *cl, void *obj, Bool_t up)
4902{
4903 if (cl == this) return obj;
4904
4905 if (!HasDataMemberInfo()) return nullptr;
4906
4907 Int_t off;
4908 if ((off = GetBaseClassOffset(cl, obj)) != -1) {
4909 if (up)
4910 return (void*)((Longptr_t)obj+off);
4911 else
4912 return (void*)((Longptr_t)obj-off);
4913 }
4914 return nullptr;
4915}
4916
4917////////////////////////////////////////////////////////////////////////////////
4918/// Cast obj of this class type up to baseclass cl if up is true.
4919/// Cast obj of this class type down from baseclass cl if up is false.
4920/// If this class is not a baseclass of cl return 0, else the pointer
4921/// to the cl part of this (up) or to this (down).
4922
4923const void *TClass::DynamicCast(const TClass *cl, const void *obj, Bool_t up)
4924{
4925 return DynamicCast(cl,const_cast<void*>(obj),up);
4926}
4927
4928////////////////////////////////////////////////////////////////////////////////
4929/// Return a pointer to a newly allocated object of this class.
4930/// The class must have a default constructor. For meaning of
4931/// defConstructor, see TClass::IsCallingNew().
4932///
4933/// If quiet is true, do no issue a message via Error on case
4934/// of problems, just return 0.
4935///
4936/// The constructor actually called here can be customized by
4937/// using the rootcint pragma:
4938/// ~~~ {.cpp}
4939/// #pragma link C++ ioctortype UserClass;
4940/// ~~~
4941/// For example, with this pragma and a class named MyClass,
4942/// this method will called the first of the following 3
4943/// constructors which exists and is public:
4944/// ~~~ {.cpp}
4945/// MyClass(UserClass*);
4946/// MyClass(TRootIOCtor*);
4947/// MyClass(); // Or a constructor with all its arguments defaulted.
4948/// ~~~
4949///
4950/// When more than one pragma ioctortype is used, the first seen as priority
4951/// For example with:
4952/// ~~~ {.cpp}
4953/// #pragma link C++ ioctortype UserClass1;
4954/// #pragma link C++ ioctortype UserClass2;
4955/// ~~~
4956/// We look in the following order:
4957/// ~~~ {.cpp}
4958/// MyClass(UserClass1*);
4959/// MyClass(UserClass2*);
4960/// MyClass(TRootIOCtor*);
4961/// MyClass(); // Or a constructor with all its arguments defaulted.
4962/// ~~~
4963
4964void *TClass::New(ENewType defConstructor, Bool_t quiet) const
4965{
4966 auto obj = NewObject(defConstructor, quiet);
4967 if (obj.GetPtr() && obj.GetAllocator()) {
4968 // Register the object for special handling in the destructor.
4969 RegisterAddressInRepository("TClass::New", obj.GetPtr(), this);
4970 }
4971 return obj.GetPtr();
4972}
4973
4974// See TClass:New
4975// returns a TClass::ObjectPtr which remembers if the object was allocated
4976// via a TStreamerInfo.
4977
4979{
4980 ObjectPtr p;
4981
4982 if (fNew) {
4983 // We have the new operator wrapper function,
4984 // so there is a dictionary and it was generated
4985 // by rootcint, so there should be a default
4986 // constructor we can call through the wrapper.
4987 {
4988 TClass__GetCallingNewRAII callingNew(defConstructor);
4989 p = fNew(nullptr);
4990 }
4991 if (!p && !quiet) {
4992 //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
4993 Error("New", "cannot create object of class %s", GetName());
4994 }
4995 } else if (HasInterpreterInfo()) {
4996 // We have the dictionary but do not have the
4997 // constructor wrapper, so the dictionary was
4998 // not generated by rootcint. Let's try to
4999 // create the object by having the interpreter
5000 // call the new operator, hopefully the class
5001 // library is loaded and there will be a default
5002 // constructor we can call.
5003 // [This is very unlikely to work, but who knows!]
5004 {
5005 TClass__GetCallingNewRAII callingNew(defConstructor);
5007 }
5008 if (!p && !quiet) {
5009 //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
5010 Error("New", "cannot create object of class %s", GetName());
5011 }
5012 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5013 // There is no dictionary at all, so this is an emulated
5014 // class; however we do have the services of a collection proxy,
5015 // so this is an emulated STL class.
5016 {
5017 TClass__GetCallingNewRAII callingNew(defConstructor);
5019 }
5020 if (!p && !quiet) {
5021 //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
5022 Error("New", "cannot create object of class %s", GetName());
5023 }
5024 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5025 // There is no dictionary at all and we do not have
5026 // the services of a collection proxy available, so
5027 // use the streamer info to approximate calling a
5028 // constructor (basically we just make sure that the
5029 // pointer data members are null, unless they are marked
5030 // as preallocated with the "->" comment, in which case
5031 // we default-construct an object to point at).
5032
5033 // Do not register any TObject's that we create
5034 // as a result of creating this object.
5035 // FIXME: Why do we do this?
5036 // FIXME: Partial Answer: Is this because we may never actually deregister them???
5037
5038 Bool_t statsave = GetObjectStat();
5039 if(statsave) {
5041 }
5043 if (!sinfo) {
5044 if (!quiet)
5045 Error("New", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
5046 return nullptr;
5047 }
5048
5049 {
5050 TClass__GetCallingNewRAII callingNew(defConstructor);
5051 p = { sinfo->New(), sinfo};
5052 }
5053
5054 // FIXME: Mistake? See note above at the GetObjectStat() call.
5055 // Allow TObject's to be registered again.
5056 if(statsave) {
5057 SetObjectStat(statsave);
5058 }
5059
5060 if (!p) {
5061 Error("New", "Failed to construct class '%s' using streamer info", GetName());
5062 }
5063
5064 return p;
5065 } else {
5066 Fatal("New", "This cannot happen!");
5067 }
5068
5069 return p;
5070}
5071
5072////////////////////////////////////////////////////////////////////////////////
5073/// Return a pointer to a newly allocated object of this class.
5074/// The class must have a default constructor. For meaning of
5075/// defConstructor, see TClass::IsCallingNew().
5076
5077void *TClass::New(void *arena, ENewType defConstructor) const
5078{
5079 auto obj = NewObject(arena, defConstructor);
5080 if (obj.GetPtr() && obj.GetAllocator()) {
5081 // Register the object for special handling in the destructor.
5082 RegisterAddressInRepository("TClass::New with placement", obj.GetPtr(), this);
5083 }
5084 return obj.GetPtr();
5085}
5086
5087////////////////////////////////////////////////////////////////////////////////
5088/// Return a pointer to a newly allocated object of this class.
5089/// The class must have a default constructor. For meaning of
5090/// defConstructor, see TClass::IsCallingNew().
5091
5092TClass::ObjectPtr TClass::NewObject(void *arena, ENewType defConstructor) const
5093{
5094 ObjectPtr p;
5095
5096 if (fNew) {
5097 // We have the new operator wrapper function,
5098 // so there is a dictionary and it was generated
5099 // by rootcint, so there should be a default
5100 // constructor we can call through the wrapper.
5101 {
5102 TClass__GetCallingNewRAII callingNew(defConstructor);
5103 p = fNew(arena);
5104 }
5105 if (!p) {
5106 Error("New with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
5107 }
5108 } else if (HasInterpreterInfo()) {
5109 // We have the dictionary but do not have the
5110 // constructor wrapper, so the dictionary was
5111 // not generated by rootcint. Let's try to
5112 // create the object by having the interpreter
5113 // call the new operator, hopefully the class
5114 // library is loaded and there will be a default
5115 // constructor we can call.
5116 // [This is very unlikely to work, but who knows!]
5117 {
5118 TClass__GetCallingNewRAII callingNew(defConstructor);
5119 p = gCling->ClassInfo_New(GetClassInfo(),arena);
5120 }
5121 if (!p) {
5122 Error("New with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
5123 }
5124 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5125 // There is no dictionary at all, so this is an emulated
5126 // class; however we do have the services of a collection proxy,
5127 // so this is an emulated STL class.
5128 {
5129 TClass__GetCallingNewRAII callingNew(defConstructor);
5130 p = fCollectionProxy->NewObject(arena);
5131 }
5132 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5133 // There is no dictionary at all and we do not have
5134 // the services of a collection proxy available, so
5135 // use the streamer info to approximate calling a
5136 // constructor (basically we just make sure that the
5137 // pointer data members are null, unless they are marked
5138 // as preallocated with the "->" comment, in which case
5139 // we default-construct an object to point at).
5140
5141 // ???BUG??? ???WHY???
5142 // Do not register any TObject's that we create
5143 // as a result of creating this object.
5144 Bool_t statsave = GetObjectStat();
5145 if(statsave) {
5147 }
5148
5150 if (!sinfo) {
5151 Error("New with placement", "Cannot construct class '%s' version %d at address %p, no streamer info available!", GetName(), fClassVersion, arena);
5152 return nullptr;
5153 }
5154
5155 {
5156 TClass__GetCallingNewRAII callingNew(defConstructor);
5157 p = { sinfo->New(arena), sinfo };
5158 }
5159
5160 // ???BUG???
5161 // Allow TObject's to be registered again.
5162 if(statsave) {
5163 SetObjectStat(statsave);
5164 }
5165
5166 } else {
5167 Error("New with placement", "This cannot happen!");
5168 }
5169
5170 return p;
5171}
5172
5173////////////////////////////////////////////////////////////////////////////////
5174/// Return a pointer to a newly allocated array of objects
5175/// of this class.
5176/// The class must have a default constructor. For meaning of
5177/// defConstructor, see TClass::IsCallingNew().
5178
5179void *TClass::NewArray(Long_t nElements, ENewType defConstructor) const
5180{
5181 auto obj = NewObjectArray(nElements, defConstructor);
5182 if (obj.GetPtr() && obj.GetAllocator()) {
5183 // Register the object for special handling in the destructor.
5184 RegisterAddressInRepository("TClass::NewArray", obj.GetPtr(), this);
5185 }
5186 return obj.GetPtr();
5187}
5188
5189////////////////////////////////////////////////////////////////////////////////
5190/// Return a pointer to a newly allocated array of objects
5191/// of this class.
5192/// The class must have a default constructor. For meaning of
5193/// defConstructor, see TClass::IsCallingNew().
5194
5196{
5197 ObjectPtr p;
5198
5199 if (fNewArray) {
5200 // We have the new operator wrapper function,
5201 // so there is a dictionary and it was generated
5202 // by rootcint, so there should be a default
5203 // constructor we can call through the wrapper.
5204 {
5205 TClass__GetCallingNewRAII callingNew(defConstructor);
5206 p = fNewArray(nElements, nullptr);
5207 }
5208 if (!p) {
5209 Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
5210 }
5211 } else if (HasInterpreterInfo()) {
5212 // We have the dictionary but do not have the
5213 // constructor wrapper, so the dictionary was
5214 // not generated by rootcint. Let's try to
5215 // create the object by having the interpreter
5216 // call the new operator, hopefully the class
5217 // library is loaded and there will be a default
5218 // constructor we can call.
5219 // [This is very unlikely to work, but who knows!]
5220 {
5221 TClass__GetCallingNewRAII callingNew(defConstructor);
5222 p = gCling->ClassInfo_New(GetClassInfo(),nElements);
5223 }
5224 if (!p) {
5225 Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
5226 }
5227 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5228 // There is no dictionary at all, so this is an emulated
5229 // class; however we do have the services of a collection proxy,
5230 // so this is an emulated STL class.
5231 {
5232 TClass__GetCallingNewRAII callingNew(defConstructor);
5233 p = fCollectionProxy->NewObjectArray(nElements);
5234 }
5235 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5236 // There is no dictionary at all and we do not have
5237 // the services of a collection proxy available, so
5238 // use the streamer info to approximate calling a
5239 // constructor (basically we just make sure that the
5240 // pointer data members are null, unless they are marked
5241 // as preallocated with the "->" comment, in which case
5242 // we default-construct an object to point at).
5243
5244 // ???BUG??? ???WHY???
5245 // Do not register any TObject's that we create
5246 // as a result of creating this object.
5247 Bool_t statsave = GetObjectStat();
5248 if(statsave) {
5250 }
5251
5253 if (!sinfo) {
5254 Error("NewArray", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
5255 return nullptr;
5256 }
5257
5258 {
5259 TClass__GetCallingNewRAII callingNew(defConstructor);
5260 p = { sinfo->NewArray(nElements), sinfo };
5261 }
5262
5263 // ???BUG???
5264 // Allow TObject's to be registered again.
5265 if(statsave) {
5266 SetObjectStat(statsave);
5267 }
5268
5269 } else {
5270 Error("NewArray", "This cannot happen!");
5271 }
5272
5273 return p;
5274}
5275
5276////////////////////////////////////////////////////////////////////////////////
5277/// Return a pointer to a newly allocated object of this class.
5278/// The class must have a default constructor. For meaning of
5279/// defConstructor, see TClass::IsCallingNew().
5280
5281void *TClass::NewArray(Long_t nElements, void *arena, ENewType defConstructor) const
5282{
5283 auto obj = NewObjectArray(nElements, arena, defConstructor);
5284 if (obj.GetPtr() && obj.GetAllocator()) {
5285 // Register the object for special handling in the destructor.
5286 RegisterAddressInRepository("TClass::NewArray with placement", obj.GetPtr(), this);
5287 }
5288 return obj.GetPtr();
5289}
5290
5291////////////////////////////////////////////////////////////////////////////////
5292/// Return a pointer to a newly allocated object of this class.
5293/// The class must have a default constructor. For meaning of
5294/// defConstructor, see TClass::IsCallingNew().
5295
5296TClass::ObjectPtr TClass::NewObjectArray(Long_t nElements, void *arena, ENewType defConstructor) const
5297{
5298 ObjectPtr p;
5299
5300 if (fNewArray) {
5301 // We have the new operator wrapper function,
5302 // so there is a dictionary and it was generated
5303 // by rootcint, so there should be a default
5304 // constructor we can call through the wrapper.
5305 {
5306 TClass__GetCallingNewRAII callingNew(defConstructor);
5307 p = fNewArray(nElements, arena);
5308 }
5309 if (!p) {
5310 Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
5311 }
5312 } else if (HasInterpreterInfo()) {
5313 // We have the dictionary but do not have the constructor wrapper,
5314 // so the dictionary was not generated by rootcint (it was made either
5315 // by cint or by some external mechanism). Let's try to create the
5316 // object by having the interpreter call the new operator, either the
5317 // class library is loaded and there is a default constructor we can
5318 // call, or the class is interpreted and we will call the default
5319 // constructor that way, or no default constructor is available and
5320 // we fail.
5321 {
5322 TClass__GetCallingNewRAII callingNew(defConstructor);
5323 p = gCling->ClassInfo_New(GetClassInfo(),nElements, arena);
5324 }
5325 if (!p) {
5326 Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
5327 }
5328 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5329 // There is no dictionary at all, so this is an emulated
5330 // class; however we do have the services of a collection proxy,
5331 // so this is an emulated STL class.
5332 {
5333 TClass__GetCallingNewRAII callingNew(defConstructor);
5334 p = fCollectionProxy->NewObjectArray(nElements, arena);
5335 }
5336 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5337 // There is no dictionary at all and we do not have
5338 // the services of a collection proxy available, so
5339 // use the streamer info to approximate calling a
5340 // constructor (basically we just make sure that the
5341 // pointer data members are null, unless they are marked
5342 // as preallocated with the "->" comment, in which case
5343 // we default-construct an object to point at).
5344
5345 // ???BUG??? ???WHY???
5346 // Do not register any TObject's that we create
5347 // as a result of creating this object.
5348 Bool_t statsave = GetObjectStat();
5349 if(statsave) {
5351 }
5352
5354 if (!sinfo) {
5355 Error("NewArray with placement", "Cannot construct class '%s' version %d at address %p, no streamer info available!", GetName(), fClassVersion, arena);
5356 return nullptr;
5357 }
5358
5359 {
5360 TClass__GetCallingNewRAII callingNew(defConstructor);
5361 p = { sinfo->NewArray(nElements, arena), sinfo };
5362 }
5363
5364 // ???BUG???
5365 // Allow TObject's to be registered again.
5366 if(statsave) {
5367 SetObjectStat(statsave);
5368 }
5369
5371 // We always register emulated objects, we need to always
5372 // use the streamer info to destroy them.
5373 }
5374
5375 return p;
5376 } else {
5377 Error("NewArray with placement", "This cannot happen!");
5378 }
5379
5380 return p;
5381}
5382
5383////////////////////////////////////////////////////////////////////////////////
5384/// Explicitly call destructor for object.
5385
5386void TClass::Destructor(void *obj, Bool_t dtorOnly)
5387{
5388 // Do nothing if passed a null pointer.
5389 if (obj == nullptr) return;
5390
5391 void* p = obj;
5392
5393 if (dtorOnly && fDestructor) {
5394 // We have the destructor wrapper, use it.
5395 fDestructor(p);
5396 } else if ((!dtorOnly) && fDelete) {
5397 // We have the delete wrapper, use it.
5398 fDelete(p);
5399 } else if (HasInterpreterInfo()) {
5400 // We have the dictionary but do not have the
5401 // destruct/delete wrapper, so the dictionary was
5402 // not generated by rootcint (it could have been
5403 // created by cint or by some external mechanism).
5404 // Let's have the interpreter call the destructor,
5405 // either the code will be in a loaded library,
5406 // or it will be interpreted, otherwise we fail
5407 // because there is no destructor code at all.
5408 if (dtorOnly) {
5410 } else {
5412 }
5413 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5414 // There is no dictionary at all, so this is an emulated
5415 // class; however we do have the services of a collection proxy,
5416 // so this is an emulated STL class.
5417 GetCollectionProxy()->Destructor(p, dtorOnly);
5418 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5419 // There is no dictionary at all and we do not have
5420 // the services of a collection proxy available, so
5421 // use the streamer info to approximate calling a
5422 // destructor.
5423
5424 Bool_t inRepo = kTRUE;
5425 Bool_t currentVersion = kFALSE;
5426
5427 // Was this object allocated through TClass?
5428 Version_t objVer = -1;
5429 {
5431 RepoCont_t::iterator iter = fObjectVersionRepository.find(p);
5432 if (iter == fObjectVersionRepository.end()) {
5433 // No, it wasn't, skip special version handling.
5434 //Error("Destructor2", "Attempt to delete unregistered object of class '%s' at address %p!", GetName(), p);
5435 inRepo = kFALSE;
5436 } else {
5437 //objVer = iter->second;
5438 for (; (iter != fObjectVersionRepository.end()) && (iter->first == p); ++iter) {
5439 objVer = iter->second;
5440 if (objVer == fClassVersion) {
5441 currentVersion = kTRUE;
5442 break;
5443 }
5444 }
5445 }
5446 }
5447
5448 if (!inRepo || currentVersion) {
5449 // The object was allocated using code for the same class version
5450 // as is loaded now. We may proceed without worry.
5452 if (si) {
5453 si->Destructor(p, dtorOnly);
5454 } else {
5455 Error("Destructor", "No streamer info available for class '%s' version %d at address %p, cannot destruct emulated object!", GetName(), fClassVersion, p);
5456 Error("Destructor", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5458 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5459 Error("Destructor", "fStreamerInfo->At(%d): %p", i, fStreamerInfo->At(i));
5460 if (fStreamerInfo->At(i) != nullptr) {
5461 Error("Destructor", "Doing Dump() ...");
5463 }
5464 }
5465 }
5466 } else {
5467 // The loaded class version is not the same as the version of the code
5468 // which was used to allocate this object. The best we can do is use
5469 // the TVirtualStreamerInfo to try to free up some of the allocated memory.
5471 if (si) {
5472 si->Destructor(p, dtorOnly);
5473 } else {
5474 Error("Destructor", "No streamer info available for class '%s' version %d, cannot destruct object at addr: %p", GetName(), objVer, p);
5475 Error("Destructor", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5477 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5478 Error("Destructor2", "fStreamerInfo->At(%d): %p", i, fStreamerInfo->At(i));
5479 if (fStreamerInfo->At(i) != nullptr) {
5480 // Do some debugging output.
5481 Error("Destructor2", "Doing Dump() ...");
5483 }
5484 }
5485 }
5486 }
5487
5488 if (inRepo && p) {
5489 UnregisterAddressInRepository("TClass::Destructor",p,this);
5490 }
5491 } else {
5492 Error("Destructor", "This cannot happen! (class %s)", GetName());
5493 }
5494}
5495
5496////////////////////////////////////////////////////////////////////////////////
5497/// Explicitly call destructor for object.
5498
5500{
5501 // Do nothing if passed a null pointer.
5502 if (obj.GetPtr() == nullptr)
5503 return;
5504
5505 if (obj.GetAllocator()) {
5506 obj.GetAllocator()->Destructor(obj.GetPtr(), dtorOnly);
5507 } else {
5508 Destructor(obj.GetPtr(), dtorOnly);
5509 }
5510}
5511
5512////////////////////////////////////////////////////////////////////////////////
5513/// Explicitly call operator delete[] for an array.
5514
5515void TClass::DeleteArray(void *ary, Bool_t dtorOnly)
5516{
5517 // Do nothing if passed a null pointer.
5518 if (ary == nullptr) return;
5519
5520 // Make a copy of the address.
5521 void* p = ary;
5522
5523 if (fDeleteArray) {
5524 if (dtorOnly) {
5525 Error("DeleteArray", "Destructor only is not supported!");
5526 } else {
5527 // We have the array delete wrapper, use it.
5528 fDeleteArray(ary);
5529 }
5530 } else if (HasInterpreterInfo()) {
5531 // We have the dictionary but do not have the
5532 // array delete wrapper, so the dictionary was
5533 // not generated by rootcint. Let's try to
5534 // delete the array by having the interpreter
5535 // call the array delete operator, hopefully
5536 // the class library is loaded and there will be
5537 // a destructor we can call.
5538 gCling->ClassInfo_DeleteArray(GetClassInfo(),ary, dtorOnly);
5539 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5540 // There is no dictionary at all, so this is an emulated
5541 // class; however we do have the services of a collection proxy,
5542 // so this is an emulated STL class.
5543 GetCollectionProxy()->DeleteArray(ary, dtorOnly);
5544 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5545 // There is no dictionary at all and we do not have
5546 // the services of a collection proxy available, so
5547 // use the streamer info to approximate calling the
5548 // array destructor.
5549
5550 Bool_t inRepo = kTRUE;
5551 Bool_t currentVersion = kFALSE;
5552
5553 // Was this array object allocated through TClass?
5554 Version_t objVer = -1;
5555 {
5557 RepoCont_t::iterator iter = fObjectVersionRepository.find(p);
5558 if (iter == fObjectVersionRepository.end()) {
5559 // No, it wasn't, we cannot know what to do.
5560 //Error("DeleteArray", "Attempt to delete unregistered array object, element type '%s', at address %p!", GetName(), p);
5561 inRepo = kFALSE;
5562 } else {
5563 for (; (iter != fObjectVersionRepository.end()) && (iter->first == p); ++iter) {
5564 objVer = iter->second;
5565 if (objVer == fClassVersion) {
5566 currentVersion = kTRUE;
5567 break;
5568 }
5569 }
5570 }
5571 }
5572
5573 if (!inRepo || currentVersion) {
5574 // The object was allocated using code for the same class version
5575 // as is loaded now. We may proceed without worry.
5577 if (si) {
5578 si->DeleteArray(ary, dtorOnly);
5579 } else {
5580 Error("DeleteArray", "No streamer info available for class '%s' version %d at address %p, cannot destruct object!", GetName(), fClassVersion, ary);
5581 Error("DeleteArray", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5583 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5584 Error("DeleteArray", "fStreamerInfo->At(%d): %p", v, fStreamerInfo->At(i));
5585 if (fStreamerInfo->At(i)) {
5586 Error("DeleteArray", "Doing Dump() ...");
5588 }
5589 }
5590 }
5591 } else {
5592 // The loaded class version is not the same as the version of the code
5593 // which was used to allocate this array. The best we can do is use
5594 // the TVirtualStreamerInfo to try to free up some of the allocated memory.
5596 if (si) {
5597 si->DeleteArray(ary, dtorOnly);
5598 } else {
5599 Error("DeleteArray", "No streamer info available for class '%s' version %d at address %p, cannot destruct object!", GetName(), objVer, ary);
5600 Error("DeleteArray", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5602 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5603 Error("DeleteArray", "fStreamerInfo->At(%d): %p", v, fStreamerInfo->At(i));
5604 if (fStreamerInfo->At(i)) {
5605 // Print some debugging info.
5606 Error("DeleteArray", "Doing Dump() ...");
5608 }
5609 }
5610 }
5611 }
5612
5613 // Deregister the object for special handling in the destructor.
5614 if (inRepo && p) {
5615 UnregisterAddressInRepository("TClass::DeleteArray",p,this);
5616 }
5617 } else {
5618 Error("DeleteArray", "This cannot happen! (class '%s')", GetName());
5619 }
5620}
5621
5622////////////////////////////////////////////////////////////////////////////////
5623/// Explicitly call operator delete[] for an array.
5624
5626{
5627 // Do nothing if passed a null pointer.
5628 if (obj.GetPtr() == nullptr) return;
5629
5630 if (obj.GetAllocator()) {
5631 obj.GetAllocator()->DeleteArray(obj.GetPtr(), dtorOnly);
5632 } else {
5633 DeleteArray(obj.GetPtr(), dtorOnly);
5634 }
5635}
5636
5637////////////////////////////////////////////////////////////////////////////////
5638/// Set the splitability of this class:
5639/// - -1: Use the default calculation
5640/// - 0: Disallow splitting
5641/// - 1: Always allow splitting.
5642/// - 2: Disallow splitting of the class and splitting of any it's derived classes.
5643
5645{
5646 fCanSplit = splitmode;
5647}
5648
5649////////////////////////////////////////////////////////////////////////////////
5650/// Private function. Set the class version for the 'class' represented by
5651/// this TClass object. See the public interface:
5652/// ROOT::ResetClassVersion
5653/// defined in TClassTable.cxx
5654///
5655/// Note on class version numbers:
5656/// - If no class number has been specified, TClass::GetVersion will return -1
5657/// - The Class Version 0 request the whole object to be transient
5658/// - The Class Version 1, unless specified via ClassDef indicates that the
5659/// I/O should use the TClass checksum to distinguish the layout of the class
5660
5662{
5663 fClassVersion = version;
5664 fCurrentInfo = nullptr;
5665}
5666
5667////////////////////////////////////////////////////////////////////////////////
5668/// Determine and set pointer to current TVirtualStreamerInfo
5669
5671{
5672 if(!fCurrentInfo.load()) {
5675 }
5676 return fCurrentInfo;
5677}
5678
5679////////////////////////////////////////////////////////////////////////////////
5680/// Set pointer to current TVirtualStreamerInfo
5681
5683{
5684 fCurrentInfo = info;
5685}
5686
5687////////////////////////////////////////////////////////////////////////////////
5688/// Return size of object of this class.
5689
5691{
5692 if (fSizeof!=-1) return fSizeof;
5695 return GetStreamerInfo()->GetSize();
5696}
5697
5698////////////////////////////////////////////////////////////////////////////////
5699/// Load class description from I/O buffer and return class object.
5700
5702{
5703 UInt_t maxsize = 256;
5704 char *s = new char[maxsize];
5705
5706 Int_t pos = b.Length();
5707
5708 b.ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end.
5709 while (strlen(s) == (maxsize - 1)) {
5710 // The classname is too large, try again with a large buffer.
5711 b.SetBufferOffset(pos);
5712 maxsize = 2*maxsize;
5713 delete [] s;
5714 s = new char[maxsize];
5715 b.ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end.
5716 }
5717
5718 TClass *cl = TClass::GetClass(s, kTRUE);
5719 if (!cl)
5720 ::Error("TClass::Load", "dictionary of class %s not found", s);
5721
5722 delete [] s;
5723 return cl;
5724}
5725
5726////////////////////////////////////////////////////////////////////////////////
5727/// Helper function used by TClass::GetClass().
5728/// This function attempts to load the dictionary for 'classname'
5729/// either from the TClassTable or from the list of generator.
5730/// If silent is 'true', do not warn about missing dictionary for the class.
5731/// (typically used for class that are used only for transient members)
5732///
5733/// The 'requestedname' is expected to be already normalized.
5734
5735TClass *TClass::LoadClass(const char *requestedname, Bool_t silent)
5736{
5737 // This function does not (and should not) attempt to check in the
5738 // list of loaded classes or in the typedef.
5739
5741
5742 TClass *result = LoadClassDefault(requestedname, silent);
5743
5744 if (result) return result;
5745 else return LoadClassCustom(requestedname,silent);
5746}
5747
5748////////////////////////////////////////////////////////////////////////////////
5749/// Helper function used by TClass::GetClass().
5750/// This function attempts to load the dictionary for 'classname' from
5751/// the TClassTable or the autoloader.
5752/// If silent is 'true', do not warn about missing dictionary for the class.
5753/// (typically used for class that are used only for transient members)
5754///
5755/// The 'requestedname' is expected to be already normalized.
5756
5757TClass *TClass::LoadClassDefault(const char *requestedname, Bool_t /* silent */)
5758{
5759 // This function does not (and should not) attempt to check in the
5760 // list of loaded classes or in the typedef.
5761
5762 DictFuncPtr_t dict = TClassTable::GetDictNorm(requestedname);
5763
5764 if (!dict) {
5765 if (gInterpreter->AutoLoad(requestedname,kTRUE)) {
5766 dict = TClassTable::GetDictNorm(requestedname);
5767 }
5768 }
5769
5770 if (dict) {
5771 TClass *ncl = (dict)();
5772 if (ncl) ncl->PostLoadCheck();
5773 return ncl;
5774 }
5775 return nullptr;
5776}
5777
5778////////////////////////////////////////////////////////////////////////////////
5779/// Helper function used by TClass::GetClass().
5780/// This function attempts to load the dictionary for 'classname'
5781/// from the list of generator.
5782/// If silent is 'true', do not warn about missing dictionary for the class.
5783/// (typically used for class that are used only for transient members)
5784///
5785/// The 'requestedname' is expected to be already normalized.
5786
5787TClass *TClass::LoadClassCustom(const char *requestedname, Bool_t silent)
5788{
5789 // This function does not (and should not) attempt to check in the
5790 // list of loaded classes or in the typedef.
5791
5792 TIter next(gROOT->GetListOfClassGenerators());
5793 TClassGenerator *gen;
5794 while ((gen = (TClassGenerator*) next())) {
5795 TClass *cl = gen->GetClass(requestedname, kTRUE, silent);
5796 if (cl) {
5797 cl->PostLoadCheck();
5798 return cl;
5799 }
5800 }
5801 return nullptr;
5802}
5803
5804////////////////////////////////////////////////////////////////////////////////
5805/// Try to load the ClassInfo if available. This function may require parsing
5806/// the header file and/or loading data from the clang pcm. If further calls to
5807/// this function cannot affect the value of fClassInfo, fCanLoadClassInfo is set
5808/// to false.
5809
5811{
5813
5814 // Return if another thread already loaded the info
5815 // while we were waiting for the lock
5816 if (!fCanLoadClassInfo)
5817 return;
5818
5819 bool autoParse = !gInterpreter->IsAutoParsingSuspended();
5820
5821 if (autoParse)
5822 gInterpreter->AutoParse(GetName());
5823
5824 if (!fClassInfo)
5825 gInterpreter->SetClassInfo(const_cast<TClass *>(this));
5826
5827 if (autoParse && !fClassInfo) {
5828 if (fImplFileLine == -1 && fClassVersion == 0) {
5829 // We have a 'transient' class with a ClassDefInline and apparently no interpreter
5830 // information. Since it is transient, it is more than likely that the lack
5831 // will be harmles.
5832 } else {
5833 ::Error("TClass::LoadClassInfo", "no interpreter information for class %s is available"
5834 " even though it has a TClass initialization routine.",
5835 fName.Data());
5836 }
5837 return;
5838 }
5839
5840 fCanLoadClassInfo = false;
5841}
5842
5843////////////////////////////////////////////////////////////////////////////////
5844/// Store class description on I/O buffer.
5845
5847{
5848 b.WriteString(GetName());
5849}
5850
5851////////////////////////////////////////////////////////////////////////////////
5852/// Global function called by a class' static Dictionary() method
5853/// (see the ClassDef macro).
5854
5855TClass *ROOT::CreateClass(const char *cname, Version_t id,
5856 const std::type_info &info, TVirtualIsAProxy *isa,
5857 const char *dfil, const char *ifil,
5858 Int_t dl, Int_t il)
5859{
5860 // When called via TMapFile (e.g. Update()) make sure that the dictionary
5861 // gets allocated on the heap and not in the mapped file.
5862 TMmallocDescTemp setreset;
5863 return new TClass(cname, id, info, isa, dfil, ifil, dl, il);
5864}
5865
5866////////////////////////////////////////////////////////////////////////////////
5867/// Global function called by a class' static Dictionary() method
5868/// (see the ClassDef macro).
5869
5870TClass *ROOT::CreateClass(const char *cname, Version_t id,
5871 const char *dfil, const char *ifil,
5872 Int_t dl, Int_t il)
5873{
5874 // When called via TMapFile (e.g. Update()) make sure that the dictionary
5875 // gets allocated on the heap and not in the mapped file.
5876 TMmallocDescTemp setreset;
5877 return new TClass(cname, id, dfil, ifil, dl, il);
5878}
5879
5880////////////////////////////////////////////////////////////////////////////////
5881/// Static method returning the defConstructor flag passed to TClass::New().
5882/// New type is either:
5883/// - TClass::kRealNew - when called via plain new
5884/// - TClass::kClassNew - when called via TClass::New()
5885/// - TClass::kDummyNew - when called via TClass::New() but object is a dummy,
5886/// in which case the object ctor might take short cuts
5887
5889{
5890 return TClass__GetCallingNew();
5891}
5892
5893////////////////////////////////////////////////////////////////////////////////
5894/// Return true if the shared library of this class is currently in the a
5895/// process's memory. Return false, after the shared library has been
5896/// unloaded or if this is an 'emulated' class created from a file's StreamerInfo.
5897
5899{
5900 return fState == kHasTClassInit;
5901}
5902
5903////////////////////////////////////////////////////////////////////////////////
5904/// Returns true if this class inherits from TObject and if the start of
5905/// the TObject parts is at the very beginning of the objects.
5906/// Concretely this means that the following code is proper for this class:
5907/// ~~~ {.cpp}
5908/// ThisClass *ptr;
5909/// void *void_ptr = (void)ptr;
5910/// TObject *obj = (TObject*)void_ptr;
5911/// ~~~
5912/// This code would be wrong if 'ThisClass' did not inherit 'first' from
5913/// TObject.
5914
5916{
5917 if (fProperty==(-1)) Property();
5918 return TestBit(kStartWithTObject);
5919}
5920
5921////////////////////////////////////////////////////////////////////////////////
5922/// Return kTRUE is the class inherits from TObject.
5923
5925{
5926 if (fProperty==(-1)) Property();
5927 return TestBit(kIsTObject);
5928}
5929
5930////////////////////////////////////////////////////////////////////////////////
5931/// Return kTRUE is the class is Foreign (the class does not have a Streamer method).
5932
5934{
5935 if (fProperty==(-1)) Property();
5936 // If the property are not set and the class is a pair, hard code that
5937 // it is a unversioned/Foreign class.
5938 return TestBit(kIsForeign);
5939}
5940
5941////////////////////////////////////////////////////////////////////////////////
5942/// Do the initialization that can only be done after the CINT dictionary has
5943/// been fully populated and can not be delayed efficiently.
5944
5946{
5947 // In the case of a Foreign class (loaded class without a Streamer function)
5948 // we reset fClassVersion to be -1 so that the current TVirtualStreamerInfo will not
5949 // be confused with a previously loaded streamerInfo.
5950
5951 if (IsLoaded() && HasInterpreterInfo() && fClassVersion==1 /*&& fStreamerInfo
5952 && fStreamerInfo->At(1)*/ && IsForeign() )
5953 {
5954 SetClassVersion(-1);
5955 }
5956 // Note: We are careful to check the class version first because checking
5957 // for foreign can trigger an AutoParse.
5958 else if (IsLoaded() && HasDataMemberInfo() && fStreamerInfo && ((fClassVersion > 1) || !IsForeign()))
5959 {
5961
5963 // Here we need to check whether this TVirtualStreamerInfo (which presumably has been
5964 // loaded from a file) is consistent with the definition in the library we just loaded.
5965 // BuildCheck is not appropriate here since it check a streamerinfo against the
5966 // 'current streamerinfo' which, at time point, would be the same as 'info'!
5967 if (info && GetListOfDataMembers() && !GetCollectionProxy()
5968 && (info->GetCheckSum()!=GetCheckSum() && !info->CompareContent(this,nullptr,kFALSE,kFALSE, nullptr) && !(MatchLegacyCheckSum(info->GetCheckSum()))))
5969 {
5970 Bool_t warn = ! TestBit(kWarned);
5971 if (warn && info->GetOldVersion()<=2) {
5972 // Names of STL base classes was modified in vers==3. Allocators removed
5973 //
5974 TIter nextBC(GetListOfBases());
5975 TBaseClass *bc;
5976 while ((bc=(TBaseClass*)nextBC()))
5977 {if (TClassEdit::IsSTLCont(bc->GetName())) warn = kFALSE;}
5978 }
5979
5980 if (warn) {
5981 if (info->GetOnFileClassVersion()==1 && fClassVersion>1) {
5982 Warning("PostLoadCheck","\n\
5983 The class %s transitioned from not having a specified class version\n\
5984 to having a specified class version (the current class version is %d).\n\
5985 However too many different non-versioned layouts of the class have\n\
5986 already been loaded so far. To work around this problem you can\n\
5987 load fewer 'old' file in the same ROOT session or load the C++ library\n\
5988 describing the class %s before opening the files or increase the version\n\
5989 number of the class for example ClassDef(%s,%d).\n\
5990 Do not try to write objects with the current class definition,\n\
5991 the files might not be readable.\n",
5993 } else {
5994 Warning("PostLoadCheck","\n\
5995 The StreamerInfo version %d for the class %s which was read\n\
5996 from a file previously opened has the same version as the active class\n\
5997 but a different checksum. You should update the version to ClassDef(%s,%d).\n\
5998 Do not try to write objects with the current class definition,\n\
5999 the files will not be readable.\n"
6001 }
6002 info->CompareContent(this,nullptr,kTRUE,kTRUE,nullptr);
6003 SetBit(kWarned);
6004 }
6005 }
6006 }
6007 if (fCollectionProxy) {
6008 // Update the related pair's TClass if it has already been created.
6009 size_t noffset = 0;
6010 if (strncmp(GetName(), "map<", 4) == 0)
6011 noffset = 3;
6012 else if (strncmp(GetName(), "multimap<", 9) == 0)
6013 noffset = 8;
6014 else if (strncmp(GetName(), "unordered_map<", 14) == 0)
6015 noffset = 13;
6016 else if (strncmp(GetName(), "unordered_multimap<", 19) == 0)
6017 noffset = 18;
6018 if (noffset) {
6019 std::string pairname("pair");
6020 pairname.append(GetName() + noffset);
6021 auto pcl = TClass::GetClass(pairname.c_str(), false, false);
6022 if ( pcl && !pcl->IsLoaded() && !pcl->IsSyntheticPair() )
6023 {
6025
6027 TIter nextClass(gROOT->GetListOfClasses());
6028 while (auto acl = (TClass*)nextClass()) {
6029 if (acl == this) continue;
6030 if (acl->fCollectionProxy && acl->fCollectionProxy->GetValueClass() == pcl) {
6031 acl->fCollectionProxy->Reset();
6032 }
6033 }
6034
6035 TIter next(pcl->GetStreamerInfos());
6036 while (auto info = (TVirtualStreamerInfo*)next()) {
6037 if (info->IsBuilt()) {
6038 info->Clear("build");
6039 info->BuildOld();
6040 }
6041 }
6043 }
6044 }
6045 }
6046}
6047
6048////////////////////////////////////////////////////////////////////////////////
6049/// Returns the properties of the TClass as a bit field stored as a `Long_t` value.
6050///
6051/// The bit values used for the return value are defined in the enum EProperty (in TDictionary.h)
6052///
6053/// Also sets `TObject::fBits` and `fStreamerType` to cache information about the
6054/// class. The bits stored in `TObject::fBits` are
6055/// ~~~ {.cpp}
6056/// kIsTObject : the class inherits from TObject
6057/// kStartWithTObject: TObject is the left-most class in the inheritance tree
6058/// kIsForeign : the class doe not have a Streamer method
6059/// ~~~
6060/// The value of `fStreamerType` are
6061/// ~~~ {.cpp}
6062/// kTObject : the class inherits from TObject
6063/// kForeign : the class does not have a Streamer method
6064/// kInstrumented: the class does have a Streamer method
6065/// kExternal: the class has a free standing way of streaming itself
6066/// kEmulatedStreamer: the class is missing its shared library.
6067/// ~~~
6068///
6069/// Implementation note: the data member fProperty has the value -1
6070/// until it is initialized.
6071
6073{
6074 // Check if we can return without taking the lock,
6075 // this is valid since fProperty is atomic and set as
6076 // the last operation before return.
6077 if (fProperty!=(-1)) return fProperty;
6078
6080
6081 // Check if another thread set fProperty while we
6082 // were waiting.
6083 if (fProperty!=(-1)) return fProperty;
6084
6085 // Avoid asking about the class when it is still building
6086 if (TestBit(kLoading)) return fProperty;
6087
6088 // When called via TMapFile (e.g. Update()) make sure that the dictionary
6089 // gets allocated on the heap and not in the mapped file.
6090 TMmallocDescTemp setreset;
6091
6092 TClass *kl = const_cast<TClass*>(this);
6093
6096
6097 if (InheritsFrom(TObject::Class())) {
6098 kl->SetBit(kIsTObject);
6099
6100 // Is it DIRECT inheritance from TObject?
6101 Int_t delta = kl->GetBaseClassOffsetRecurse(TObject::Class());
6102 if (delta==0) kl->SetBit(kStartWithTObject);
6103
6104 kl->fStreamerType = kTObject;
6106 }
6107
6108 if (HasInterpreterInfo()) {
6109
6110 // This code used to use ClassInfo_Has|IsValidMethod but since v6
6111 // they return true if the routine is defined in the class or any of
6112 // its parent. We explicitly want to know whether the function is
6113 // defined locally.
6114 if (!const_cast<TClass*>(this)->GetClassMethodWithPrototype("Streamer","TBuffer&",kFALSE)) {
6115
6116 kl->SetBit(kIsForeign);
6117 kl->fStreamerType = kForeign;
6119
6120 } else if ( kl->fStreamerType == TClass::kDefault ) {
6121 if (kl->fConvStreamerFunc) {
6124 } else if (kl->fStreamerFunc) {
6127 } else {
6128 // We have an automatic streamer using the StreamerInfo .. no need to go through the
6129 // Streamer method function itself.
6132 }
6133 }
6134
6135 if (fStreamer) {
6138 }
6139
6140 if (const_cast<TClass *>(this)->GetClassMethodWithPrototype("Hash", "", kTRUE)) {
6142 }
6143
6144 if (GetClassInfo()) {
6145 // In the case where the TClass for one of ROOT's core class
6146 // (eg TClonesArray for map<int,TClonesArray*>) is requested
6147 // during the execution of rootcling, we could end up in a situation
6148 // where we should have the information (since TClonesArray has
6149 // a dictionary as part of libCore) but do not because the user
6150 // only include a forward declaration of TClonesArray and we do not
6151 // forcefully load the header file either (because the autoparsing
6152 // is intentionally disabled).
6154 // Must set this last since other threads may read fProperty
6155 // and think all test bits have been properly set.
6157 }
6158 } else {
6159
6160 if (fStreamer) {
6163 }
6164
6166 kl->SetStreamerImpl();
6167 // fProperty was *not* set so that it can be forced to be recalculated
6168 // next time.
6169 return 0;
6170 }
6171
6172 return fProperty;
6173}
6174
6175////////////////////////////////////////////////////////////////////////////////
6176/// Internal routine to set calculate the class properties that can only be
6177/// known at run-time, for example whether the Hash member function and the
6178/// destructor are consistent.
6179
6181{
6182 // For now, no need to lock this routines as fRuntimeProperties is
6183 // the only atomic set here and this is done at the end
6184 // and there is no downside if the execution is done twice.
6185
6186 // Note SetRuntimeProperties is set to const as it is technically
6187 // thread-safe.
6188
6189 UChar_t properties = static_cast<UChar_t>(ERuntimeProperties::kSet);
6190
6192 properties |= static_cast<UChar_t>(ERuntimeProperties::kConsistentHash);
6193
6194 const_cast<TClass *>(this)->fRuntimeProperties = properties;
6195}
6196
6197////////////////////////////////////////////////////////////////////////////////
6198/// Internal routine to set fStreamerImpl based on the value of
6199/// fStreamerType.
6200
6202{
6203 switch (fStreamerType) {
6207 case kInstrumented: {
6211 break;
6212 }
6213
6214 case kEmulatedStreamer: // intentional fall through
6215 case kForeign|kEmulatedStreamer: // intentional fall through
6220 default:
6221 Error("SetStreamerImpl","Unexpected value of fStreamerType: %d",fStreamerType);
6222 }
6223}
6224
6225
6226////////////////////////////////////////////////////////////////////////////////
6227/// Create the collection proxy object (and the streamer object) from
6228/// using the information in the TCollectionProxyInfo.
6229
6231{
6233
6234 delete fCollectionProxy;
6235
6236 // We can not use GetStreamerInfo() instead of TVirtualStreamerInfo::Factory()
6237 // because GetStreamerInfo call TStreamerInfo::Build which need to have fCollectionProxy
6238 // set correctly.
6239
6241 fCollectionProxy = p;
6242
6243 AdoptStreamer(TVirtualStreamerInfo::Factory()->GenExplicitClassStreamer(info,this));
6244
6246 // Numeric Collections have implicit conversions:
6248 }
6249 fCanSplit = -1;
6250}
6251
6252////////////////////////////////////////////////////////////////////////////////
6253/// Change (i.e. set) the title of the TNamed.
6254
6255void TClass::SetContextMenuTitle(const char *title)
6256{
6257 fContextMenuTitle = title;
6258}
6259
6260////////////////////////////////////////////////////////////////////////////////
6261/// This function installs a global IsA function for this class.
6262/// The global IsA function will be used if there is no local IsA function (fIsA)
6263///
6264/// A global IsA function has the signature:
6265///
6266/// ~~~ {.cpp}
6267/// TClass *func( TClass *cl, const void *obj);
6268/// ~~~
6269///
6270/// 'cl' is a pointer to the TClass object that corresponds to the
6271/// 'pointer type' used to retrieve the value 'obj'
6272///
6273/// For example with:
6274/// ~~~ {.cpp}
6275/// TNamed * m = new TNamed("example","test");
6276/// TObject* o = m
6277/// ~~~
6278/// and
6279/// the global IsA function would be called with TObject::Class() as
6280/// the first parameter and the exact numerical value in the pointer
6281/// 'o'.
6282///
6283/// In other word, inside the global IsA function. it is safe to C-style
6284/// cast the value of 'obj' into a pointer to the class described by 'cl'.
6285
6287{
6288 fGlobalIsA = func;
6289}
6290
6291////////////////////////////////////////////////////////////////////////////////
6292/// Call this method to indicate that the shared library containing this
6293/// class's code has been removed (unloaded) from the process's memory
6294
6296{
6297 if (TestBit(kUnloaded) && !TestBit(kUnloading)) {
6298 // Don't redo the work.
6299 return;
6300 }
6302
6303 //R__ASSERT(fState == kLoaded);
6304 if (fState != kLoaded) {
6305 Fatal("SetUnloaded","The TClass for %s is being unloaded when in state %d\n",
6306 GetName(),(int)fState);
6307 }
6308
6310
6311 // Make sure SetClassInfo, re-calculated the state.
6313
6314 delete fIsA; fIsA = nullptr;
6315 // Disable the autoloader while calling SetClassInfo, to prevent
6316 // the library from being reloaded!
6317 {
6320 gInterpreter->SetClassInfo(this,kTRUE);
6321 }
6322 fDeclFileName = nullptr;
6323 fDeclFileLine = 0;
6324 fImplFileName = nullptr;
6325 fImplFileLine = 0;
6326 fTypeInfo = nullptr;
6327
6328 if (fMethod.load()) {
6329 (*fMethod).Unload();
6330 }
6331 if (fData.load()) {
6332 (*fData).Unload();
6333 }
6334 if (fUsingData.load()) {
6335 (*fUsingData).Unload();
6336 }
6337 if (fEnums.load()) {
6338 (*fEnums).Unload();
6339 }
6340
6341 if (fState <= kForwardDeclared && !fStreamerInfo->IsEmpty()) {
6342 fState = kEmulated;
6343 }
6344
6347}
6348
6349////////////////////////////////////////////////////////////////////////////////
6350/// Info is a string describing the names and types of attributes
6351/// written by the class Streamer function.
6352/// If info is an empty string (when called by TObject::StreamerInfo)
6353/// the default Streamer info string is build. This corresponds to
6354/// the case of an automatically generated Streamer.
6355/// In case of user defined Streamer function, it is the user responsibility
6356/// to implement a StreamerInfo function (override TObject::StreamerInfo).
6357/// The user must call IsA()->SetStreamerInfo(info) from this function.
6358
6359TVirtualStreamerInfo *TClass::SetStreamerInfo(Int_t /*version*/, const char * /*info*/)
6360{
6361 // info is specified, nothing to do, except that we should verify
6362 // that it contains a valid descriptor.
6363
6364/*
6365 TDataMember *dm;
6366 Int_t nch = strlen(info);
6367 Bool_t update = kTRUE;
6368 if (nch != 0) {
6369 //decode strings like "TObject;TAttLine;fA;fB;Int_t i,j,k;"
6370 char *save, *temp, *blank, *colon, *comma;
6371 save = new char[10000];
6372 temp = save;
6373 strlcpy(temp,info,10000);
6374 //remove heading and trailing blanks
6375 while (*temp == ' ') temp++;
6376 while (save[nch-1] == ' ') {nch--; save[nch] = 0;}
6377 if (nch == 0) {delete [] save; return;}
6378 if (save[nch-1] != ';') {save[nch] = ';'; save[nch+1] = 0;}
6379 //remove blanks around , or ;
6380 while ((blank = strstr(temp,"; "))) strcpy(blank+1,blank+2);
6381 while ((blank = strstr(temp," ;"))) strcpy(blank, blank+1);
6382 while ((blank = strstr(temp,", "))) strcpy(blank+1,blank+2);
6383 while ((blank = strstr(temp," ,"))) strcpy(blank, blank+1);
6384 while ((blank = strstr(temp," "))) strcpy(blank, blank+1);
6385 //loop on tokens separated by ;
6386 char *final = new char[1000];
6387 char token[100];
6388 while ((colon=strchr(temp,';'))) {
6389 *colon = 0;
6390 strlcpy(token,temp,100);
6391 blank = strchr(token,' ');
6392 if (blank) {
6393 *blank = 0;
6394 if (!gROOT->GetType(token)) {
6395 Error("SetStreamerInfo","Illegal type: %s in %s",token,info);
6396 return;
6397 }
6398 while (blank) {
6399 strlcat(final,token,1000);
6400 strlcat(final," ",1000);
6401 comma = strchr(blank+1,','); if (comma) *comma=0;
6402 strlcat(final,blank+1,1000);
6403 strlcat(final,";",1000);
6404 blank = comma;
6405 }
6406
6407 } else {
6408 if (TClass::GetClass(token,update)) {
6409 //a class name
6410 strlcat(final,token,1000); strlcat(final,";",1000);
6411 } else {
6412 //a data member name
6413 dm = (TDataMember*)GetListOfDataMembers()->FindObject(token);
6414 if (dm) {
6415 strlcat(final,dm->GetFullTypeName(),1000);
6416 strlcat(final," ",1000);
6417 strlcat(final,token,1000); strlcat(final,";",1000);
6418 } else {
6419 Error("SetStreamerInfo","Illegal name: %s in %s",token,info);
6420 return;
6421 }
6422 }
6423 update = kFALSE;
6424 }
6425 temp = colon+1;
6426 if (*temp == 0) break;
6427 }
6428 //// fStreamerInfo = final;
6429 delete [] final;
6430 delete [] save;
6431 return;
6432 }
6433
6434 //info is empty. Let's build the default Streamer descriptor
6435
6436 char *temp = new char[10000];
6437 temp[0] = 0;
6438 char local[100];
6439
6440 //add list of base classes
6441 TIter nextb(GetListOfBases());
6442 TBaseClass *base;
6443 while ((base = (TBaseClass*) nextb())) {
6444 snprintf(local,100,"%s;",base->GetName());
6445 strlcat(temp,local,10000);
6446 }
6447
6448 //add list of data members and types
6449 TIter nextd(GetListOfDataMembers());
6450 while ((dm = (TDataMember *) nextd())) {
6451 if (dm->IsEnum()) continue;
6452 if (!dm->IsPersistent()) continue;
6453 Long_t property = dm->Property();
6454 if (property & kIsStatic) continue;
6455 TClass *acl = TClass::GetClass(dm->GetTypeName(),update);
6456 update = kFALSE;
6457 if (acl) {
6458 if (acl->GetClassVersion() == 0) continue;
6459 }
6460
6461 // dm->GetArrayIndex() returns an empty string if it does not
6462 // applies
6463 const char * index = dm->GetArrayIndex();
6464 if (strlen(index)==0)
6465 snprintf(local,100,"%s %s;",dm->GetFullTypeName(),dm->GetName());
6466 else
6467 snprintf(local,100,"%s %s[%s];",dm->GetFullTypeName(),dm->GetName(),index);
6468 strlcat(temp,local,10000);
6469 }
6470 //fStreamerInfo = temp;
6471 delete [] temp;
6472*/
6473 return nullptr;
6474}
6475
6476////////////////////////////////////////////////////////////////////////////////
6477/// Return true if the checksum passed as argument is one of the checksum
6478/// value produced by the older checksum calculation algorithm.
6479
6481{
6482 for(UInt_t i = 1; i < kLatestCheckSum; ++i) {
6483 if ( checksum == GetCheckSum( (ECheckSum) i ) ) return kTRUE;
6484 }
6485 return kFALSE;
6486}
6487
6488////////////////////////////////////////////////////////////////////////////////
6489/// Call GetCheckSum with validity check.
6490
6492{
6493 bool isvalid;
6494 return GetCheckSum(code,isvalid);
6495}
6496
6497////////////////////////////////////////////////////////////////////////////////
6498/// Return GetCheckSum(kCurrentCheckSum,isvalid);
6499
6501{
6502 return GetCheckSum(kCurrentCheckSum,isvalid);
6503}
6504
6505////////////////////////////////////////////////////////////////////////////////
6506/// Compute and/or return the class check sum.
6507///
6508/// isvalid is set to false, if the function is unable to calculate the
6509/// checksum.
6510///
6511/// The class ckecksum is used by the automatic schema evolution algorithm
6512/// to uniquely identify a class version.
6513/// The check sum is built from the names/types of base classes and
6514/// data members.
6515/// Original algorithm from Victor Perevovchikov (perev@bnl.gov).
6516///
6517/// The valid range of code is determined by ECheckSum.
6518///
6519/// - kNoEnum: data members of type enum are not counted in the checksum
6520/// - kNoRange: return the checksum of data members and base classes, not including the ranges and array size found in comments.
6521/// - kWithTypeDef: use the sugared type name in the calculation.
6522///
6523/// This is needed for backward compatibility.
6524///
6525/// WARNING: this function must be kept in sync with TStreamerInfo::GetCheckSum.
6526/// They are both used to handle backward compatibility and should both return the same values.
6527/// TStreamerInfo uses the information in TStreamerElement while TClass uses the information
6528/// from TClass::GetListOfBases and TClass::GetListOfDataMembers.
6529
6531{
6532 // fCheckSum is an atomic variable. Also once it has
6533 // transition from a zero Value it never changes. If two
6534 // thread reach past this if statement and calculated the
6535 // 'kLastestCheckSum', they will by definition obtain the
6536 // same value, so technically we could simply have:
6537 // if (fCheckSum && code == kCurrentCheckSum) return fCheckSum;
6538 // However save a little bit of barrier time by calling load()
6539 // only once.
6540
6541 isvalid = kTRUE;
6542
6543 UInt_t currentChecksum = fCheckSum.load();
6544 if (currentChecksum && code == kCurrentCheckSum) return currentChecksum;
6545
6547
6548 // kCurrentCheckSum (0) is the default parameter value and should be kept
6549 // for backward compatibility, too be able to use the inequality checks,
6550 // we need to set the code to the largest value.
6551 if (code == kCurrentCheckSum) code = kLatestCheckSum;
6552
6553 UInt_t id = 0;
6554
6555 int il;
6556 TString name = GetName();
6557 TString type;
6558 il = name.Length();
6559 for (int i=0; i<il; i++) id = id*3+name[i];
6560
6561 // Here we skip he base classes in case this is a pair or STL collection,
6562 // otherwise, on some STL implementations, it can happen that pair has
6563 // base classes which are an internal implementation detail.
6564 TList *tlb = ((TClass*)this)->GetListOfBases();
6565 if (tlb && !GetCollectionProxy() && !TClassEdit::IsStdPair(GetName())) {
6566 // Loop over bases if not a proxied collection or a pair
6567
6568 TIter nextBase(tlb);
6569
6570 TBaseClass *tbc=nullptr;
6571 while((tbc=(TBaseClass*)nextBase())) {
6572 name = tbc->GetName();
6574 if (isSTL)
6576 il = name.Length();
6577 for (int i=0; i<il; i++) id = id*3+name[i];
6578 if (code > kNoBaseCheckSum && !isSTL) {
6579 if (tbc->GetClassPointer() == nullptr) {
6580 Error("GetCheckSum","Calculating the checksum for (%s) requires the base class (%s) meta information to be available!",
6581 GetName(),tbc->GetName());
6582 isvalid = kFALSE;
6583 return 0;
6584 } else
6585 id = id*3 + tbc->GetClassPointer()->GetCheckSum();
6586 }
6587 }/*EndBaseLoop*/
6588 }
6589 TList *tlm = ((TClass*)this)->GetListOfDataMembers();
6590 if (tlm) { // Loop over members
6591 TIter nextMemb(tlm);
6592 TDataMember *tdm=nullptr;
6593 Long_t prop = 0;
6594 while((tdm=(TDataMember*)nextMemb())) {
6595 if (!tdm->IsPersistent()) continue;
6596 // combine properties
6597 prop = (tdm->Property());
6598 TDataType* tdt = tdm->GetDataType();
6599 if (tdt) prop |= tdt->Property();
6600
6601 if ( prop&kIsStatic) continue;
6602 name = tdm->GetName(); il = name.Length();
6603 if ( (code > kNoEnum) && code != kReflex && code != kReflexNoComment && prop&kIsEnum)
6604 id = id*3 + 1;
6605
6606 int i;
6607 for (i=0; i<il; i++) id = id*3+name[i];
6608
6609 if (code > kWithTypeDef || code == kReflexNoComment) {
6610 type = tdm->GetTrueTypeName();
6611 // GetTrueTypeName uses GetFullyQualifiedName which already drops
6612 // the default template parameter, so we no longer need to do this.
6613 //if (TClassEdit::IsSTLCont(type))
6614 // type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
6615 if (code == kReflex || code == kReflexNoComment) {
6616 if (prop&kIsEnum) {
6617 type = "int";
6618 } else {
6619 type.ReplaceAll("ULong64_t","unsigned long long");
6620 type.ReplaceAll("Long64_t","long long");
6621 type.ReplaceAll("<signed char","<char");
6622 type.ReplaceAll(",signed char",",char");
6623 if (type=="signed char") type = "char";
6624 }
6625 }
6626 } else {
6627 type = tdm->GetFullTypeName();
6628 // GetFullTypeName uses GetFullyQualifiedName which already drops
6629 // the default template parameter, so we no longer need to do this.
6630 //if (TClassEdit::IsSTLCont(type))
6631 // type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
6632 }
6633
6634 il = type.Length();
6635 for (i=0; i<il; i++) id = id*3+type[i];
6636
6637 int dim = tdm->GetArrayDim();
6638 if (prop&kIsArray) {
6639 for (int ii=0;ii<dim;ii++) id = id*3+tdm->GetMaxIndex(ii);
6640 }
6641 if (code > kNoRange) {
6642 const char *left;
6643 if (code > TClass::kNoRangeCheck)
6645 else
6646 left = strstr(tdm->GetTitle(),"[");
6647 if (left) {
6648 const char *right = strstr(left,"]");
6649 if (right) {
6650 ++left;
6651 while (left != right) {
6652 id = id*3 + *left;
6653 ++left;
6654 }
6655 }
6656 }
6657 }
6658 }/*EndMembLoop*/
6659 }
6660 // This should be moved to Initialization time however the last time
6661 // we tried this cause problem, in particular in the end-of-process operation.
6662 if (code==kLatestCheckSum) fCheckSum = id;
6663 return id;
6664}
6665
6666////////////////////////////////////////////////////////////////////////////////
6667/// Adopt the Reference proxy pointer to indicate that this class
6668/// represents a reference.
6669/// When a new proxy is adopted, the old one is deleted.
6670
6672{
6674
6675 if ( fRefProxy ) {
6676 fRefProxy->Release();
6677 }
6678 fRefProxy = proxy;
6679 if ( fRefProxy ) {
6680 fRefProxy->SetClass(this);
6681 }
6682 fCanSplit = -1;
6683}
6684
6685////////////////////////////////////////////////////////////////////////////////
6686/// Adopt the TMemberStreamer pointer to by p and use it to Stream non basic
6687/// member name.
6688
6690{
6691 if (fRealData) {
6692
6694
6695 TIter next(fRealData);
6696 TRealData *rd;
6697 while ((rd = (TRealData*)next())) {
6698 if (strcmp(rd->GetName(),name) == 0) {
6699 // If there is a TStreamerElement that took a pointer to the
6700 // streamer we should inform it!
6701 rd->AdoptStreamer(p);
6702 return;
6703 }
6704 }
6705 }
6706
6707 Error("AdoptMemberStreamer","Cannot adope member streamer for %s::%s",GetName(), name);
6708 delete p;
6709
6710// NOTE: This alternative was proposed but not is not used for now,
6711// One of the major difference with the code above is that the code below
6712// did not require the RealData to have been built
6713// if (!fData) return;
6714// const char *n = name;
6715// while (*n=='*') n++;
6716// TString ts(n);
6717// int i = ts.Index("[");
6718// if (i>=0) ts.Remove(i,999);
6719// TDataMember *dm = (TDataMember*)fData->FindObject(ts.Data());
6720// if (!dm) {
6721// Warning("SetStreamer","Can not find member %s::%s",GetName(),name);
6722// return;
6723// }
6724// dm->SetStreamer(p);
6725}
6726
6727////////////////////////////////////////////////////////////////////////////////
6728/// Install a new member streamer (p will be copied).
6729
6731{
6733}
6734
6735////////////////////////////////////////////////////////////////////////////////
6736/// Function called by the Streamer functions to deserialize information
6737/// from buffer b into object at p.
6738/// This function assumes that the class version and the byte count information
6739/// have been read.
6740/// - version is the version number of the class
6741/// - start is the starting position in the buffer b
6742/// - count is the number of bytes for this object in the buffer
6743
6744Int_t TClass::ReadBuffer(TBuffer &b, void *pointer, Int_t version, UInt_t start, UInt_t count)
6745{
6746 return b.ReadClassBuffer(this,pointer,version,start,count);
6747}
6748
6749////////////////////////////////////////////////////////////////////////////////
6750/// Function called by the Streamer functions to deserialize information
6751/// from buffer b into object at p.
6752
6754{
6755 return b.ReadClassBuffer(this,pointer);
6756}
6757
6758////////////////////////////////////////////////////////////////////////////////
6759/// Function called by the Streamer functions to serialize object at p
6760/// to buffer b. The optional argument info may be specified to give an
6761/// alternative StreamerInfo instead of using the default StreamerInfo
6762/// automatically built from the class definition.
6763/// For more information, see class TVirtualStreamerInfo.
6764
6765Int_t TClass::WriteBuffer(TBuffer &b, void *pointer, const char * /*info*/)
6766{
6767 b.WriteClassBuffer(this,pointer);
6768 return 0;
6769}
6770
6771////////////////////////////////////////////////////////////////////////////////
6772///There is special streamer for the class
6773
6774void TClass::StreamerExternal(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6775{
6776 // case kExternal:
6777 // case kExternal|kEmulatedStreamer:
6778
6779 TClassStreamer *streamer = gThreadTsd ? pThis->GetStreamer() : pThis->fStreamer;
6780 streamer->Stream(b,object,onfile_class);
6781}
6782
6783////////////////////////////////////////////////////////////////////////////////
6784/// Case of TObjects
6785
6786void TClass::StreamerTObject(const TClass* pThis, void *object, TBuffer &b, const TClass * /* onfile_class */)
6787{
6788 // case kTObject:
6789
6790 if (!pThis->fIsOffsetStreamerSet) {
6791 pThis->CalculateStreamerOffset();
6792 }
6793 TObject *tobj = (TObject*)((Longptr_t)object + pThis->fOffsetStreamer);
6794 tobj->Streamer(b);
6795}
6796
6797////////////////////////////////////////////////////////////////////////////////
6798/// Case of TObjects when fIsOffsetStreamerSet is known to have been set.
6799
6800void TClass::StreamerTObjectInitialized(const TClass* pThis, void *object, TBuffer &b, const TClass * /* onfile_class */)
6801{
6802 TObject *tobj = (TObject*)((Longptr_t)object + pThis->fOffsetStreamer);
6803 tobj->Streamer(b);
6804}
6805
6806////////////////////////////////////////////////////////////////////////////////
6807/// Case of TObjects when we do not have the library defining the class.
6808
6809void TClass::StreamerTObjectEmulated(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6810{
6811 // case kTObject|kEmulatedStreamer :
6812 if (b.IsReading()) {
6813 b.ReadClassEmulated(pThis, object, onfile_class);
6814 } else {
6815 b.WriteClassBuffer(pThis, object);
6816 }
6817}
6818
6819////////////////////////////////////////////////////////////////////////////////
6820/// Case of instrumented class with a library
6821
6822void TClass::StreamerInstrumented(const TClass* pThis, void *object, TBuffer &b, const TClass * /* onfile_class */)
6823{
6824 // case kInstrumented:
6825 pThis->fStreamerFunc(b,object);
6826}
6827
6828////////////////////////////////////////////////////////////////////////////////
6829/// Case of instrumented class with a library
6830
6831void TClass::ConvStreamerInstrumented(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6832{
6833 // case kInstrumented:
6834 pThis->fConvStreamerFunc(b,object,onfile_class);
6835}
6836
6837////////////////////////////////////////////////////////////////////////////////
6838/// Case of where we should directly use the StreamerInfo.
6839/// - case kForeign:
6840/// - case kForeign|kEmulatedStreamer:
6841/// - case kInstrumented|kEmulatedStreamer:
6842/// - case kEmulatedStreamer:
6843
6844void TClass::StreamerStreamerInfo(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6845{
6846 if (b.IsReading()) {
6847 b.ReadClassBuffer(pThis, object, onfile_class);
6848 //ReadBuffer (b, object);
6849 } else {
6850 //WriteBuffer(b, object);
6851 b.WriteClassBuffer(pThis, object);
6852 }
6853}
6854
6855////////////////////////////////////////////////////////////////////////////////
6856/// Default streaming in cases where either we have no way to know what to do
6857/// or if Property() has not yet been called.
6858
6859void TClass::StreamerDefault(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6860{
6861 if (pThis->fProperty==(-1)) {
6862 pThis->Property();
6863 }
6864
6865 // We could get here because after this thread started StreamerDefault
6866 // *and* before check fProperty, another thread might have call Property
6867 // and this fProperty when we read it, is not -1 and fStreamerImpl is
6868 // supposed to be set properly (no longer pointing to the default).
6869 if (pThis->fStreamerImpl.load() == &TClass::StreamerDefault) {
6870 pThis->Fatal("StreamerDefault", "fStreamerImpl not properly initialized (%d)", pThis->fStreamerType);
6871 } else {
6872 (*pThis->fStreamerImpl)(pThis,object,b,onfile_class);
6873 }
6874}
6875
6876////////////////////////////////////////////////////////////////////////////////
6877/// Adopt a TClassStreamer object. Ownership is transfered to this TClass
6878/// object.
6879
6881{
6882// // This code can be used to quickly test the STL Emulation layer
6883// Int_t k = TClassEdit::IsSTLCont(GetName());
6884// if (k==1||k==-1) { delete str; return; }
6885
6887
6888 if (fStreamer) delete fStreamer;
6889 if (str) {
6891 fStreamer = str;
6893 } else if (fStreamer) {
6894 // Case where there was a custom streamer and it is hereby removed,
6895 // we need to reset fStreamerType
6896 fStreamer = str;
6898 if (fProperty != -1) {
6899 fProperty = -1;
6900 Property();
6901 }
6902 }
6903}
6904
6905////////////////////////////////////////////////////////////////////////////////
6906/// Set a wrapper/accessor function around this class custom streamer.
6907
6909{
6911 if (fProperty != -1 && !fConvStreamerFunc &&
6912 ( (fStreamerFunc == nullptr && strm != nullptr) || (fStreamerFunc != nullptr && strm == nullptr) ) )
6913 {
6914 fStreamerFunc = strm;
6915
6916 // Since initialization has already been done, make sure to tweak it
6917 // for the new state.
6921 }
6922 } else {
6923 fStreamerFunc = strm;
6924 }
6925 fCanSplit = -1;
6926}
6927
6928////////////////////////////////////////////////////////////////////////////////
6929/// Set a wrapper/accessor function around this class custom conversion streamer.
6930
6932{
6934 if (fProperty != -1 &&
6935 ( (fConvStreamerFunc == nullptr && strm != nullptr) || (fConvStreamerFunc != nullptr && strm == nullptr) ) )
6936 {
6937 fConvStreamerFunc = strm;
6938
6939 // Since initialization has already been done, make sure to tweak it
6940 // for the new state.
6944 }
6945 } else {
6946 fConvStreamerFunc = strm;
6947 }
6948 fCanSplit = -1;
6949}
6950
6951
6952////////////////////////////////////////////////////////////////////////////////
6953/// Install a new wrapper around 'Merge'.
6954
6956{
6957 fMerge = newMerge;
6958}
6959
6960////////////////////////////////////////////////////////////////////////////////
6961/// Install a new wrapper around 'ResetAfterMerge'.
6962
6964{
6965 fResetAfterMerge = newReset;
6966}
6967
6968////////////////////////////////////////////////////////////////////////////////
6969/// Install a new wrapper around 'new'.
6970
6972{
6973 fNew = newFunc;
6974}
6975
6976////////////////////////////////////////////////////////////////////////////////
6977/// Install a new wrapper around 'new []'.
6978
6980{
6981 fNewArray = newArrayFunc;
6982}
6983
6984////////////////////////////////////////////////////////////////////////////////
6985/// Install a new wrapper around 'delete'.
6986
6988{
6989 fDelete = deleteFunc;
6990}
6991
6992////////////////////////////////////////////////////////////////////////////////
6993/// Install a new wrapper around 'delete []'.
6994
6996{
6997 fDeleteArray = deleteArrayFunc;
6998}
6999
7000////////////////////////////////////////////////////////////////////////////////
7001/// Install a new wrapper around the destructor.
7002
7004{
7005 fDestructor = destructorFunc;
7006}
7007
7008////////////////////////////////////////////////////////////////////////////////
7009/// Install a new wrapper around the directory auto add function.
7010/// The function autoAddFunc has the signature void (*)(void *obj, TDirectory dir)
7011/// and should register 'obj' to the directory if dir is not null
7012/// and unregister 'obj' from its current directory if dir is null
7013
7015{
7016 fDirAutoAdd = autoAddFunc;
7017}
7018
7019////////////////////////////////////////////////////////////////////////////////
7020/// Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum
7021
7023{
7025 if (guess && guess->GetCheckSum() == checksum) {
7026 return guess;
7027 } else {
7028 if (fCheckSum == checksum)
7029 return GetStreamerInfo(0, isTransient);
7030
7032
7033 Int_t ninfos = fStreamerInfo->GetEntriesFast()-1;
7034 for (Int_t i=-1;i<ninfos;++i) {
7035 // TClass::fStreamerInfos has a lower bound not equal to 0,
7036 // so we have to use At and should not use UncheckedAt
7038 if (info && info->GetCheckSum() == checksum) {
7039 // R__ASSERT(i==info->GetClassVersion() || (i==-1&&info->GetClassVersion()==1));
7040 info->BuildOld();
7041 if (info->IsCompiled()) fLastReadInfo = info;
7042 return info;
7043 }
7044 }
7045 return nullptr;
7046 }
7047}
7048
7049////////////////////////////////////////////////////////////////////////////////
7050/// Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum
7051
7053{
7055 Int_t ninfos = arr->GetEntriesFast()-1;
7056 for (Int_t i=-1;i<ninfos;i++) {
7057 // TClass::fStreamerInfos has a lower bound not equal to 0,
7058 // so we have to use At and should not use UncheckedAt
7060 if (!info) continue;
7061 if (info->GetCheckSum() == checksum) {
7062 R__ASSERT(i==info->GetClassVersion() || (i==-1&&info->GetClassVersion()==1));
7063 return info;
7064 }
7065 }
7066 return nullptr;
7067}
7068
7069////////////////////////////////////////////////////////////////////////////////
7070/// Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this class, if any.
7071
7072TVirtualStreamerInfo *TClass::GetConversionStreamerInfo( const char* classname, Int_t version ) const
7073{
7074 TClass *cl = TClass::GetClass( classname );
7075 if( !cl )
7076 return nullptr;
7077 return GetConversionStreamerInfo( cl, version );
7078}
7079
7080////////////////////////////////////////////////////////////////////////////////
7081/// Return a Conversion StreamerInfo from the class represented by cl for version number 'version' to this class, if any.
7082
7084{
7085 //----------------------------------------------------------------------------
7086 // Check if the classname was specified correctly
7087 /////////////////////////////////////////////////////////////////////////////
7088
7089 if( !cl )
7090 return nullptr;
7091
7092 if( cl == this )
7093 return GetStreamerInfo( version );
7094
7095 //----------------------------------------------------------------------------
7096 // Check if we already have it
7097 /////////////////////////////////////////////////////////////////////////////
7098
7099 TObjArray* arr = nullptr;
7100 if (fConversionStreamerInfo.load()) {
7101 std::map<std::string, TObjArray*>::iterator it;
7103
7104 it = (*fConversionStreamerInfo).find( cl->GetName() );
7105
7106 if( it != (*fConversionStreamerInfo).end() ) {
7107 arr = it->second;
7108 }
7109
7110 if( arr && version >= -1 && version < arr->GetSize() && arr->At( version ) )
7111 return (TVirtualStreamerInfo*) arr->At( version );
7112 }
7113
7115
7116 //----------------------------------------------------------------------------
7117 // We don't have the streamer info so find it in other class
7118 /////////////////////////////////////////////////////////////////////////////
7119
7120 const TObjArray *clSI = cl->GetStreamerInfos();
7121 TVirtualStreamerInfo* info = nullptr;
7122 if( version >= -1 && version < clSI->GetSize() )
7123 info = (TVirtualStreamerInfo*)clSI->At( version );
7124
7125 if (!info && cl->GetCollectionProxy()) {
7126 info = cl->GetStreamerInfo(); // instantiate the StreamerInfo for STL collections.
7127 }
7128
7129 if( !info )
7130 return nullptr;
7131
7132 //----------------------------------------------------------------------------
7133 // We have the right info so we need to clone it to create new object with
7134 // non artificial streamer elements and we should build it for current class
7135 /////////////////////////////////////////////////////////////////////////////
7136
7137 info = (TVirtualStreamerInfo*)info->Clone();
7138
7139 // When cloning the StreamerInfo we record (and thus restore)
7140 // the absolute value of the version, let's restore the sign.
7141 if (version == -1)
7142 info->SetClassVersion(-1);
7143
7144 if( !info->BuildFor( this ) ) {
7145 delete info;
7146 return nullptr;
7147 }
7148
7149 if (!info->IsCompiled()) {
7150 // Streamer info has not been compiled, but exists.
7151 // Therefore it was read in from a file and we have to do schema evolution?
7152 // Or it didn't have a dictionary before, but does now?
7153 info->BuildOld();
7154 }
7155
7156 //----------------------------------------------------------------------------
7157 // Cache this streamer info
7158 /////////////////////////////////////////////////////////////////////////////
7159
7160 if (!arr) {
7161 arr = new TObjArray(version+10, -1);
7162 if (!fConversionStreamerInfo.load()) {
7163 fConversionStreamerInfo = new std::map<std::string, TObjArray*>();
7164 }
7165 (*fConversionStreamerInfo)[cl->GetName()] = arr;
7166 }
7167 if (arr->At(info->GetClassVersion())) {
7168 Error("GetConversionStreamerInfo", "Conversion StreamerInfo from %s to %s version %d has already been created",
7169 this->GetName(), info->GetName(), info->GetClassVersion());
7170 delete arr->At(info->GetClassVersion());
7171 }
7172 arr->AddAtAndExpand( info, info->GetClassVersion() );
7173 return info;
7174}
7175
7176////////////////////////////////////////////////////////////////////////////////
7177/// Return a Conversion StreamerInfo from the class 'classname' for the layout represented by 'checksum' to this class, if any.
7178
7179TVirtualStreamerInfo *TClass::FindConversionStreamerInfo( const char* classname, UInt_t checksum ) const
7180{
7181 TClass *cl = TClass::GetClass( classname );
7182 if( !cl )
7183 return nullptr;
7184 return FindConversionStreamerInfo( cl, checksum );
7185}
7186
7187////////////////////////////////////////////////////////////////////////////////
7188/// Return a Conversion StreamerInfo from the class represented by cl for the layout represented by 'checksum' to this class, if any.
7189
7191{
7192 //---------------------------------------------------------------------------
7193 // Check if the classname was specified correctly
7194 /////////////////////////////////////////////////////////////////////////////
7195
7196 if( !cl )
7197 return nullptr;
7198
7199 if( cl == this )
7200 return FindStreamerInfo( checksum );
7201
7202 //----------------------------------------------------------------------------
7203 // Check if we already have it
7204 /////////////////////////////////////////////////////////////////////////////
7205
7206 TObjArray* arr = nullptr;
7207 TVirtualStreamerInfo* info = nullptr;
7208 if (fConversionStreamerInfo.load()) {
7209 std::map<std::string, TObjArray*>::iterator it;
7210
7212
7213 it = (*fConversionStreamerInfo).find( cl->GetName() );
7214
7215 if( it != (*fConversionStreamerInfo).end() ) {
7216 arr = it->second;
7217 }
7218 if (arr) {
7219 info = FindStreamerInfo( arr, checksum );
7220 }
7221 }
7222
7223 if( info )
7224 return info;
7225
7227
7228 //----------------------------------------------------------------------------
7229 // Get it from the foreign class
7230 /////////////////////////////////////////////////////////////////////////////
7231
7232 info = cl->FindStreamerInfo( checksum );
7233
7234 if( !info )
7235 return nullptr;
7236
7237 //----------------------------------------------------------------------------
7238 // We have the right info so we need to clone it to create new object with
7239 // non artificial streamer elements and we should build it for current class
7240 /////////////////////////////////////////////////////////////////////////////
7241
7242 int version = info->GetClassVersion();
7243 info = (TVirtualStreamerInfo*)info->Clone();
7244
7245 // When cloning the StreamerInfo we record (and thus restore)
7246 // the absolute value of the version, let's restore the sign.
7247 if (version == -1)
7248 info->SetClassVersion(-1);
7249
7250 if( !info->BuildFor( this ) ) {
7251 delete info;
7252 return nullptr;
7253 }
7254
7255 if (!info->IsCompiled()) {
7256 // Streamer info has not been compiled, but exists.
7257 // Therefore it was read in from a file and we have to do schema evolution?
7258 // Or it didn't have a dictionary before, but does now?
7259 info->BuildOld();
7260 }
7261
7262 //----------------------------------------------------------------------------
7263 // Cache this streamer info
7264 /////////////////////////////////////////////////////////////////////////////
7265
7266 if (!arr) {
7267 arr = new TObjArray(16, -2);
7268 if (!fConversionStreamerInfo.load()) {
7269 fConversionStreamerInfo = new std::map<std::string, TObjArray*>();
7270 }
7271 (*fConversionStreamerInfo)[cl->GetName()] = arr;
7272 }
7273 arr->AddAtAndExpand( info, info->GetClassVersion() );
7274
7275 return info;
7276}
7277
7278////////////////////////////////////////////////////////////////////////////////
7279/// Register the StreamerInfo in the given slot, change the State of the
7280/// TClass as appropriate.
7281
7283{
7284 if (info) {
7286 Int_t slot = info->GetClassVersion();
7288 && fStreamerInfo->At(slot) != nullptr
7289 && fStreamerInfo->At(slot) != info) {
7290 Error("RegisterStreamerInfo",
7291 "Register StreamerInfo for %s on non-empty slot (%d).",
7292 GetName(),slot);
7293 }
7294 fStreamerInfo->AddAtAndExpand(info, slot);
7295 if (fState <= kForwardDeclared) {
7296 fState = kEmulated;
7297 if (fCheckSum==0 && slot==fClassVersion) fCheckSum = info->GetCheckSum();
7298 }
7299 }
7300}
7301
7302////////////////////////////////////////////////////////////////////////////////
7303/// Remove and delete the StreamerInfo in the given slot.
7304/// Update the slot accordingly.
7305
7307{
7308 if (fStreamerInfo->GetSize() >= slot) {
7312 if (fLastReadInfo.load() == info)
7313 fLastReadInfo = nullptr;
7314 if (fCurrentInfo.load() == info)
7315 fCurrentInfo = nullptr;
7316 delete info;
7317 if (fState == kEmulated && fStreamerInfo->GetEntries() == 0) {
7319 }
7320 }
7321}
7322
7323////////////////////////////////////////////////////////////////////////////////
7324/// Return true is the Hash/RecursiveRemove setup is consistent, i.e. when all
7325/// classes in the class hierarchy that overload TObject::Hash do call
7326/// ROOT::CallRecursiveRemoveIfNeeded in their destructor.
7327/// i.e. it is safe to call the Hash virtual function during the RecursiveRemove operation.
7328/// This routines is used for a small subset of the class for which we need
7329/// the answer before gROOT is properly initialized.
7330
7332{
7333 // Hand selection of correct classes, those classes should be
7334 // cross-checked in testHashRecursiveRemove.cxx
7335 static const char *handVerified[] = {
7336 "TEnvRec", "TDataType", "TObjArray", "TList", "THashList",
7337 "TClass", "TCling", "TInterpreter", "TMethod", "ROOT::Internal::TCheckHashRecursiveRemoveConsistency",
7338 "TCheckHashRecursiveRemoveConsistency", "TGWindow",
7339 "TDirectory", "TDirectoryFile", "TObject", "TH1",
7340 "TQClass", "TGlobal" };
7341
7342 if (cname && cname[0]) {
7343 for (auto cursor : handVerified) {
7344 if (strcmp(cname, cursor) == 0)
7345 return true;
7346 }
7347 }
7348 return false;
7349}
7350
7351////////////////////////////////////////////////////////////////////////////////
7352/// Return true is the Hash/RecursiveRemove setup is consistent, i.e. when all
7353/// classes in the class hierarchy that overload TObject::Hash do call
7354/// ROOT::CallRecursiveRemoveIfNeeded in their destructor.
7355/// i.e. it is safe to call the Hash virtual function during the RecursiveRemove operation.
7356
7358{
7359 return clRef.HasConsistentHashMember();
7360}
7361
7362////////////////////////////////////////////////////////////////////////////////
7363/// Return true if we have access to a constructor usable for I/O. This is
7364/// typically the default constructor but can also be a constructor specifically
7365/// marked for I/O (for example a constructor taking a TRootIOCtor* as an
7366/// argument). In other words, if this routine returns true, TClass::New is
7367/// guarantee to succeed.
7368/// To know if the class described by this TClass has a default constructor
7369/// (public or not), use
7370/// \code{.cpp}
7371/// cl->GetProperty() & kClassHasDefaultCtor
7372/// \endcode
7373/// To know if the class described by this TClass has a public default
7374/// constructor use:
7375/// \code{.cpp}
7376/// gInterpreter->ClassInfo_HasDefaultConstructor(aClass->GetClassInfo());
7377/// \endcode
7378
7380{
7381
7382 if (fNew) return kTRUE;
7383
7384 if (HasInterpreterInfo()) {
7387 }
7388 if (fCollectionProxy) {
7389 return kTRUE;
7390 }
7391 if (fCurrentInfo.load()) {
7392 // Emulated class, we know how to construct them via the TStreamerInfo
7393 return kTRUE;
7394 }
7395 return kFALSE;
7396}
7397
7398////////////////////////////////////////////////////////////////////////////////
7399/// Returns true if this class has an definition and/or overload of the
7400/// member function Hash.
7401///
7402/// For example to test if the class overload TObject::Hash use
7403/// ~~~ {.cpp}
7404/// if (cl->IsTObject() && cl->HasLocalHashMember())
7405/// ~~~
7406
7408{
7409 if (fProperty == (-1))
7410 Property();
7412}
7413
7414////////////////////////////////////////////////////////////////////////////////
7415/// Return the wrapper around Merge.
7416
7418{
7419 return fMerge;
7420}
7421
7422////////////////////////////////////////////////////////////////////////////////
7423/// Return the wrapper around Merge.
7424
7426{
7427 return fResetAfterMerge;
7428}
7429
7430////////////////////////////////////////////////////////////////////////////////
7431/// Return the wrapper around new ThisClass().
7432
7434{
7435 return fNew;
7436}
7437
7438////////////////////////////////////////////////////////////////////////////////
7439/// Return the wrapper around new ThisClass[].
7440
7442{
7443 return fNewArray;
7444}
7445
7446////////////////////////////////////////////////////////////////////////////////
7447/// Return the wrapper around delete ThiObject.
7448
7450{
7451 return fDelete;
7452}
7453
7454////////////////////////////////////////////////////////////////////////////////
7455/// Return the wrapper around delete [] ThiObject.
7456
7458{
7459 return fDeleteArray;
7460}
7461
7462////////////////////////////////////////////////////////////////////////////////
7463/// Return the wrapper around the destructor
7464
7466{
7467 return fDestructor;
7468}
7469
7470////////////////////////////////////////////////////////////////////////////////
7471/// Return the wrapper around the directory auto add function.
7472
7474{
7475 return fDirAutoAdd;
7476}
typedef void(GLAPIENTRYP _GLUfuncptr)(void)
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
#define e(i)
Definition RSha256.hxx:103
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
const Ssiz_t kNPOS
Definition RtypesCore.h:124
int Int_t
Definition RtypesCore.h:45
long Longptr_t
Definition RtypesCore.h:82
short Version_t
Definition RtypesCore.h:65
unsigned char UChar_t
Definition RtypesCore.h:38
unsigned long ULongptr_t
Definition RtypesCore.h:83
unsigned int UInt_t
Definition RtypesCore.h:46
const Bool_t kFALSE
Definition RtypesCore.h:101
unsigned long ULong_t
Definition RtypesCore.h:55
long Long_t
Definition RtypesCore.h:54
bool Bool_t
Definition RtypesCore.h:63
const Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
TClass *(* DictFuncPtr_t)()
Definition Rtypes.h:80
#define ClassImp(name)
Definition Rtypes.h:364
void(* MemberStreamerFunc_t)(TBuffer &, void *, Int_t)
Definition Rtypes.h:74
TClass *(* IsAGlobalFunc_t)(const TClass *, const void *obj)
Definition Rtypes.h:96
void(* ClassStreamerFunc_t)(TBuffer &, void *)
Definition Rtypes.h:72
void(* ClassConvStreamerFunc_t)(TBuffer &, void *, const TClass *)
Definition Rtypes.h:73
R__EXTERN TClassTable * gClassTable
Definition TClassTable.h:97
TVirtualMutex * gInterpreterMutex
Definition TClass.cxx:132
TClass::ENewType & TClass__GetCallingNew()
Definition TClass.cxx:267
static bool IsFromRootCling()
Definition TClass.cxx:174
ROOT::TMapDeclIdToTClass DeclIdMap_t
Definition TClass.h:78
ROOT::TMapTypeToTClass IdMap_t
Definition TClass.h:77
void(* tcling_callfunc_Wrapper_t)(void *, int, void **, void *)
const Bool_t kIterBackward
Definition TCollection.h:43
EDataType
Definition TDataType.h:28
@ kNoType_t
Definition TDataType.h:33
@ kUInt_t
Definition TDataType.h:30
@ kIsPointer
Definition TDictionary.h:78
@ kIsClass
Definition TDictionary.h:65
@ kIsEnum
Definition TDictionary.h:68
@ kIsFundamental
Definition TDictionary.h:70
@ kIsAbstract
Definition TDictionary.h:71
@ kIsArray
Definition TDictionary.h:79
@ kIsStatic
Definition TDictionary.h:80
@ kIsStruct
Definition TDictionary.h:66
@ kIsUnion
Definition TDictionary.h:67
@ kIsNamespace
Definition TDictionary.h:95
@ kIsVirtualBase
Definition TDictionary.h:89
#define R__ASSERT(e)
Definition TError.h:118
XFontStruct * id
Definition TGX11.cxx:109
char name[80]
Definition TGX11.cxx:110
int type
Definition TGX11.cxx:121
R__EXTERN TVirtualMutex * gInterpreterMutex
R__EXTERN TInterpreter * gCling
#define gInterpreter
@ kMenuToggle
Definition TMethod.h:34
@ kMenuNoMenu
Definition TMethod.h:32
Int_t gDebug
Definition TROOT.cxx:592
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:404
void Printf(const char *fmt,...)
@ kDefault
Definition TSystem.h:229
R__EXTERN TSystem * gSystem
Definition TSystem.h:559
R__EXTERN void **(* gThreadTsd)(void *, Int_t)
#define R__LOCKGUARD2(mutex)
#define R__LOCKGUARD(mutex)
#define gPad
#define R__WRITE_LOCKGUARD(mutex)
#define R__READ_LOCKGUARD(mutex)
const char * proto
Definition civetweb.c:16613
#define free
Definition civetweb.c:1539
#define snprintf
Definition civetweb.c:1540
Bool_t AddRule(TSchemaRule *rule, EConsistencyCheck checkConsistency=kCheckAll, TString *errmsg=0)
The consistency check always fails if the TClass object was not set! if checkConsistency is: kNoCheck...
void SetClass(TClass *cls)
Set the TClass associated with this rule set.
A spin mutex-as-code-guard class.
DeclIdMap_t::key_type key_type
Definition TClass.cxx:437
DeclIdMap_t::size_type size_type
Definition TClass.cxx:441
multimap< TDictionary::DeclId_t, TClass * > DeclIdMap_t
Definition TClass.cxx:436
size_type CountElementsWithKey(const key_type &key)
Definition TClass.cxx:453
std::pair< const_iterator, const_iterator > equal_range
Definition TClass.cxx:440
equal_range Find(const key_type &key) const
Definition TClass.cxx:457
void Remove(const key_type &key)
Definition TClass.cxx:462
DeclIdMap_t::const_iterator const_iterator
Definition TClass.cxx:439
DeclIdMap_t::mapped_type mapped_type
Definition TClass.cxx:438
void Add(const key_type &key, mapped_type obj)
Definition TClass.cxx:447
mapped_type Find(const key_type &key) const
Definition TClass.cxx:390
IdMap_t::size_type size_type
Definition TClass.cxx:373
IdMap_t::mapped_type mapped_type
Definition TClass.cxx:378
IdMap_t::const_iterator const_iterator
Definition TClass.cxx:372
std::map< std::string, TClass * > IdMap_t
Definition TClass.cxx:370
IdMap_t::key_type key_type
Definition TClass.cxx:371
void Remove(const key_type &key)
Definition TClass.cxx:398
void Add(const key_type &key, mapped_type &obj)
Definition TClass.cxx:385
Bool_t SetFromRule(const char *rule)
Set the content fot this object from the rule See TClass::AddRule for details on the syntax.
const char * GetTargetString() const
Get the target data members of this rule as a simple string (i.e. the in memory data member).
const char * GetVersion() const
Get the version string.
const char * GetTargetClass() const
Get the targte class of this rule (i.e. the in memory class).
TBrowser * fBrowser
Definition TClass.cxx:904
virtual Bool_t IsTreatingNonAccessibleTypes()
Definition TClass.cxx:912
TAutoInspector(TBrowser *b)
Definition TClass.cxx:906
virtual ~TAutoInspector()
Definition TClass.cxx:909
virtual void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient)
This method is called from ShowMembers() via AutoBrowse().
Definition TClass.cxx:918
Each class (see TClass) has a linked list of its base class(es).
Definition TBaseClass.h:33
Int_t GetDelta()
Get offset from "this" to part of base class.
ROOT::ESTLType IsSTLContainer()
Return which type (if any) of STL container the data member is.
TClass * GetClassPointer(Bool_t load=kTRUE)
Get pointer to the base class TClass.
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
Buffer base class used for serializing objects.
Definition TBuffer.h:43
void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient)
This method is called from ShowMembers() via BuildRealdata().
Definition TClass.cxx:771
TClass * fRealDataClass
Definition TClass.cxx:755
void * fRealDataObject
Definition TClass.cxx:754
TBuildRealData(void *obj, TClass *cl)
Definition TClass.cxx:758
Objects following this interface can be passed onto the TROOT object to implement a user customized w...
virtual TClass * GetClass(const char *classname, Bool_t load)=0
Describes one element of the context menu associated to a class The menu item may describe.
virtual void SetToggle(Bool_t toggle=kTRUE)
TClassRef is used to implement a permanent reference to a TClass object.
Definition TClassRef.h:28
virtual void Stream(TBuffer &b, void *objp, const TClass *onfileClass)
virtual TClassStreamer * Generate() const
static DictFuncPtr_t GetDict(const char *cname)
Given the class name returns the Dictionary() function of a class (uses hash of name).
static TProtoClass * GetProtoNorm(const char *cname)
Given the class normalized name returns the TClassProto object for the class.
static DictFuncPtr_t GetDictNorm(const char *cname)
Given the normalized class name returns the Dictionary() function of a class (uses hash of name).
InsertTClassInRegistryRAII(TClass::EState &state, const char *name, TDeclNameRegistry &emuRegistry)
Definition TClass.cxx:248
Bool_t HasDeclName(const char *name) const
Definition TClass.cxx:223
void AddQualifiedName(const char *name)
Extract this part of the name.
Definition TClass.cxx:196
TDeclNameRegistry(Int_t verbLevel=0)
TDeclNameRegistry class constructor.
Definition TClass.cxx:185
std::atomic_flag fSpinLock
Definition TClass.h:170
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:80
UInt_t GetCheckSum(ECheckSum code=kCurrentCheckSum) const
Call GetCheckSum with validity check.
Definition TClass.cxx:6491
Bool_t IsSyntheticPair() const
Definition TClass.h:516
RepoCont_t fObjectVersionRepository
Definition TClass.h:342
ShowMembersFunc_t fShowMembers
Definition TClass.h:225
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition TClass.cxx:3425
TVirtualIsAProxy * fIsA
Definition TClass.h:229
TList * GetListOfUsingDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of using declarations of a class.
Definition TClass.cxx:3772
void ForceReload(TClass *oldcl)
we found at least one equivalent.
Definition TClass.cxx:1334
ROOT::DelArrFunc_t fDeleteArray
Definition TClass.h:238
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition TClass.cxx:2318
TClassStreamer * fStreamer
Definition TClass.h:226
void SetDirectoryAutoAdd(ROOT::DirAutoAdd_t dirAutoAddFunc)
Install a new wrapper around the directory auto add function.
Definition TClass.cxx:7014
Bool_t IsFolder() const
Returns kTRUE in case object contains browsable objects (like containers or lists of other objects).
Definition TClass.h:512
void * NewArray(Long_t nElements, ENewType defConstructor=kClassNew) const
Return a pointer to a newly allocated array of objects of this class.
Definition TClass.cxx:5179
static TDeclNameRegistry fNoInfoOrEmuOrFwdDeclNameRegistry
Definition TClass.h:326
TListOfFunctionTemplates * fFuncTemplate
Definition TClass.h:206
ClassStreamerFunc_t fStreamerFunc
Definition TClass.h:241
void AdoptReferenceProxy(TVirtualRefProxy *proxy)
Adopt the Reference proxy pointer to indicate that this class represents a reference.
Definition TClass.cxx:6671
TMethod * GetClassMethod(Longptr_t faddr)
Look for a method in this class that has the interface function address faddr.
Definition TClass.cxx:4469
TVirtualStreamerInfo * DetermineCurrentStreamerInfo()
Determine and set pointer to current TVirtualStreamerInfo.
Definition TClass.cxx:5670
EState GetState() const
Definition TClass.h:485
ROOT::ESTLType GetCollectionType() const
Return the 'type' of the STL the TClass is representing.
Definition TClass.cxx:2884
void AdoptMemberStreamer(const char *name, TMemberStreamer *strm)
Adopt the TMemberStreamer pointer to by p and use it to Stream non basic member name.
Definition TClass.cxx:6689
void ResetInstanceCount()
Definition TClass.h:542
ClassStreamerFunc_t GetStreamerFunc() const
Get a wrapper/accessor function around this class custom streamer (member function).
Definition TClass.cxx:2937
void RemoveStreamerInfo(Int_t slot)
Remove and delete the StreamerInfo in the given slot.
Definition TClass.cxx:7306
void SetCanSplit(Int_t splitmode)
Set the splitability of this class:
Definition TClass.cxx:5644
TObject * Clone(const char *newname="") const
Create a Clone of this TClass object using a different name but using the same 'dictionary'.
Definition TClass.cxx:2405
TList * CreateListOfDataMembers(std::atomic< TListOfDataMembers * > &data, TDictionary::EMemberSelection selection, bool load)
Create the list containing the TDataMembers (of actual data members or members pulled in through usin...
Definition TClass.cxx:3727
TVirtualStreamerInfo * GetStreamerInfoAbstractEmulated(Int_t version=0) const
For the case where the requestor class is emulated and this class is abstract, returns a pointer to t...
Definition TClass.cxx:4695
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:4964
void SetMerge(ROOT::MergeFunc_t mergeFunc)
Install a new wrapper around 'Merge'.
Definition TClass.cxx:6955
ConvSIMap_t fConversionStreamerInfo
Definition TClass.h:199
ROOT::DirAutoAdd_t fDirAutoAdd
Definition TClass.h:240
Bool_t HasDataMemberInfo() const
Definition TClass.h:404
TVirtualRefProxy * fRefProxy
cached streamer info used in the last read.
Definition TClass.h:277
TList * GetMenuList() const
Return the list of menu items associated with the class.
Definition TClass.cxx:4327
ROOT::MergeFunc_t fMerge
saved info to call a IsA member function
Definition TClass.h:233
TMethod * GetMethod(const char *method, const char *params, Bool_t objectIsConst=kFALSE)
Find the best method (if there is one) matching the parameters.
Definition TClass.cxx:4397
virtual void Browse(TBrowser *b)
This method is called by a browser to get the class information.
Definition TClass.cxx:2008
static TClass * Load(TBuffer &b)
Load class description from I/O buffer and return class object.
Definition TClass.cxx:5701
EState fState
cached of the streaming method to use
Definition TClass.h:274
ROOT::DesFunc_t GetDestructor() const
Return the wrapper around the destructor.
Definition TClass.cxx:7465
TMethod * GetMethodWithPrototype(const char *method, const char *proto, Bool_t objectIsConst=kFALSE, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch)
Find the method with a given prototype.
Definition TClass.cxx:4442
void CopyCollectionProxy(const TVirtualCollectionProxy &)
Copy the argument.
Definition TClass.cxx:2468
Int_t fStreamerType
saved info to call Streamer
Definition TClass.h:273
TList * fRealData
Definition TClass.h:200
UInt_t fOnHeap
Definition TClass.h:218
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition TClass.cxx:2029
std::atomic< TList * > fBase
Definition TClass.h:201
Bool_t HasDictionary() const
Check whether a class has a dictionary or not.
Definition TClass.cxx:3892
const TList * GetListOfAllPublicMethods(Bool_t load=kTRUE)
Returns a list of all public methods of this class and its base classes.
Definition TClass.cxx:3831
TList * GetListOfAllPublicDataMembers(Bool_t load=kTRUE)
Returns a list of all public data members of this class and its base classes.
Definition TClass.cxx:3848
static void AddClassToDeclIdMap(TDictionary::DeclId_t id, TClass *cl)
static: Add a TClass* to the map of classes.
Definition TClass.cxx:511
virtual ~TClass()
TClass dtor. Deletes all list that might have been created.
Definition TClass.cxx:1658
Bool_t fIsSyntheticPair
Indicates whether this class can be split or not. Values are -1, 0, 1, 2.
Definition TClass.h:250
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition TClass.cxx:5386
Version_t fClassVersion
Definition TClass.h:221
std::atomic< TVirtualStreamerInfo * > fCurrentInfo
Current 'state' of the class (Emulated,Interpreted,Loaded)
Definition TClass.h:275
TList * GetListOfFunctionTemplates(Bool_t load=kTRUE)
Return TListOfFunctionTemplates for a class.
Definition TClass.cxx:3784
void * DynamicCast(const TClass *base, void *obj, Bool_t up=kTRUE)
Cast obj of this class type up to baseclass cl if up is true.
Definition TClass.cxx:4901
const char * fImplFileName
Definition TClass.h:214
void RegisterStreamerInfo(TVirtualStreamerInfo *info)
Register the StreamerInfo in the given slot, change the State of the TClass as appropriate.
Definition TClass.cxx:7282
std::atomic< UInt_t > fCheckSum
Definition TClass.h:219
void UnregisterAddressInRepository(const char *where, void *location, const TClass *what) const
Definition TClass.cxx:318
std::atomic< TListOfFunctions * > fMethod
Definition TClass.h:207
static void RemoveClassDeclId(TDictionary::DeclId_t id)
Definition TClass.cxx:536
void SetNewArray(ROOT::NewArrFunc_t newArrayFunc)
Install a new wrapper around 'new []'.
Definition TClass.cxx:6979
Bool_t CallShowMembers(const void *obj, TMemberInspector &insp, Bool_t isTransient=kFALSE) const
Call ShowMembers() on the obj of this class type, passing insp and parent.
Definition TClass.cxx:2203
const char * fDeclFileName
Definition TClass.h:213
void SetCollectionProxy(const ROOT::Detail::TCollectionProxyInfo &)
Create the collection proxy object (and the streamer object) from using the information in the TColle...
Definition TClass.cxx:6230
Int_t fCanSplit
Definition TClass.h:246
static Bool_t HasDictionarySelection(const char *clname)
Check whether a class has a dictionary or ROOT can load one.
Definition TClass.cxx:3903
void AdoptSchemaRules(ROOT::Detail::TSchemaRuleSet *rules)
Adopt a new set of Data Model Evolution rules.
Definition TClass.cxx:1918
static void StreamerInstrumented(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of instrumented class with a library.
Definition TClass.cxx:6822
TVirtualStreamerInfo * SetStreamerInfo(Int_t version, const char *info="")
Info is a string describing the names and types of attributes written by the class Streamer function.
Definition TClass.cxx:6359
static std::atomic< Int_t > fgClassCount
Definition TClass.h:324
TVirtualStreamerInfo * GetCurrentStreamerInfo()
Definition TClass.h:436
ROOT::DirAutoAdd_t GetDirectoryAutoAdd() const
Return the wrapper around the directory auto add function.
Definition TClass.cxx:7473
void AddImplFile(const char *filename, int line)
Definition TClass.cxx:1950
TCollection * GetListOfMethodOverloads(const char *name) const
Return the collection of functions named "name".
Definition TClass.cxx:3813
std::atomic< TListOfEnums * > fEnums
Definition TClass.h:205
static Bool_t HasNoInfoOrEmuOrFwdDeclaredDecl(const char *)
Definition TClass.cxx:3384
TVirtualMutex * fOVRMutex
Definition TClass.h:340
TList * GetListOfEnums(Bool_t load=kTRUE)
Return a list containing the TEnums of a class.
Definition TClass.cxx:3672
Bool_t IsStartingWithTObject() const
Returns true if this class inherits from TObject and if the start of the TObject parts is at the very...
Definition TClass.cxx:5915
TList * GetListOfMethods(Bool_t load=kTRUE)
Return list containing the TMethods of a class.
Definition TClass.cxx:3798
TClass()
Internal, default constructor.
Definition TClass.cxx:1063
Short_t fDeclFileLine
Definition TClass.h:215
Int_t GetNmethods()
Return the number of methods of this class Note that in case the list of methods is not yet created,...
Definition TClass.cxx:4559
std::atomic< Bool_t > fIsOffsetStreamerSet
Indicates whether the ClassInfo is supposed to be available.
Definition TClass.h:258
void IgnoreTObjectStreamer(Bool_t ignore=kTRUE)
When the class kIgnoreTObjectStreamer bit is set, the automatically generated Streamer will not call ...
Definition TClass.cxx:4827
TClassStreamer * GetStreamer() const
Return the Streamer Class allowing streaming (if any).
Definition TClass.cxx:2912
static IdMap_t * GetIdMap()
Definition TClass.cxx:469
void SetDelete(ROOT::DelFunc_t deleteFunc)
Install a new wrapper around 'delete'.
Definition TClass.cxx:6987
static Int_t AutoBrowse(TObject *obj, TBrowser *browser)
Browse external object inherited from TObject.
Definition TClass.cxx:1964
ROOT::NewFunc_t GetNew() const
Return the wrapper around new ThisClass().
Definition TClass.cxx:7433
TClass * GetBaseClass(const char *classname)
Return pointer to the base class "classname".
Definition TClass.cxx:2653
Longptr_t GetDataMemberOffset(const char *membername) const
return offset for member name.
Definition TClass.cxx:3463
Int_t GetNdata()
Return the number of data members of this class Note that in case the list of data members is not yet...
Definition TClass.cxx:4540
void SetDestructor(ROOT::DesFunc_t destructorFunc)
Install a new wrapper around the destructor.
Definition TClass.cxx:7003
virtual void PostLoadCheck()
Do the initialization that can only be done after the CINT dictionary has been fully populated and ca...
Definition TClass.cxx:5945
void LoadClassInfo() const
Try to load the ClassInfo if available.
Definition TClass.cxx:5810
void SetResetAfterMerge(ROOT::ResetAfterMergeFunc_t resetFunc)
Install a new wrapper around 'ResetAfterMerge'.
Definition TClass.cxx:6963
TVirtualStreamerInfo * GetStreamerInfoImpl(Int_t version, Bool_t silent) const
Definition TClass.cxx:4620
Bool_t MatchLegacyCheckSum(UInt_t checksum) const
Return true if the checksum passed as argument is one of the checksum value produced by the older che...
Definition TClass.cxx:6480
TViewPubFunctions * fAllPubMethod
Definition TClass.h:210
Bool_t HasInterpreterInfo() const
Definition TClass.h:407
static void AddClass(TClass *cl)
static: Add a class to the list and map of classes.
Definition TClass.cxx:494
void GetMissingDictionariesForBaseClasses(TCollection &result, TCollection &visited, bool recurse)
Verify the base classes always.
Definition TClass.cxx:3913
ROOT::Detail::TSchemaRuleSet * fSchemaRules
Pointer to reference proxy if this class represents a reference.
Definition TClass.h:278
std::atomic< Long_t > fProperty
Definition TClass.h:252
static void StreamerDefault(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Default streaming in cases where either we have no way to know what to do or if Property() has not ye...
Definition TClass.cxx:6859
void SetUnloaded()
Call this method to indicate that the shared library containing this class's code has been removed (u...
Definition TClass.cxx:6295
ROOT::DelArrFunc_t GetDeleteArray() const
Return the wrapper around delete [] ThiObject.
Definition TClass.cxx:7457
Bool_t HasInterpreterInfoInMemory() const
Definition TClass.h:406
TList * fClassMenuList
Definition TClass.h:211
ClassConvStreamerFunc_t fConvStreamerFunc
Definition TClass.h:242
void SetRuntimeProperties()
Internal routine to set calculate the class properties that can only be known at run-time,...
Definition TClass.cxx:6180
void BuildEmulatedRealData(const char *name, Longptr_t offset, TClass *cl, Bool_t isTransient=kFALSE)
Build the list of real data for an emulated class.
Definition TClass.cxx:2110
static TClass * LoadClass(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition TClass.cxx:5735
TString fSharedLibs
Definition TClass.h:227
const std::type_info * GetTypeInfo() const
Definition TClass.h:493
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition TClass.cxx:3756
ENewType
Definition TClass.h:107
@ kRealNew
Definition TClass.h:107
void Move(void *arenaFrom, void *arenaTo) const
Register the fact that an object was moved from the memory location 'arenaFrom' to the memory locatio...
Definition TClass.cxx:4313
static DeclIdMap_t * GetDeclIdMap()
Definition TClass.cxx:480
Short_t GetDeclFileLine() const
Definition TClass.h:426
void SetStreamerFunc(ClassStreamerFunc_t strm)
Set a wrapper/accessor function around this class custom streamer.
Definition TClass.cxx:6908
const char * GetImplFileName() const
Definition TClass.h:453
TList * GetListOfRealData() const
Definition TClass.h:450
Int_t Size() const
Return size of object of this class.
Definition TClass.cxx:5690
void SetCurrentStreamerInfo(TVirtualStreamerInfo *info)
Set pointer to current TVirtualStreamerInfo.
Definition TClass.cxx:5682
static DictFuncPtr_t GetDict(const char *cname)
Return a pointer to the dictionary loading function generated by rootcint.
Definition TClass.cxx:3408
Longptr_t fOffsetStreamer
Properties that can only be evaluated at run-time.
Definition TClass.h:272
Int_t fSizeof
Definition TClass.h:243
ROOT::NewArrFunc_t GetNewArray() const
Return the wrapper around new ThisClass[].
Definition TClass.cxx:7441
static void StreamerTObjectEmulated(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of TObjects when we do not have the library defining the class.
Definition TClass.cxx:6809
ROOT::NewFunc_t fNew
Definition TClass.h:235
@ kLoading
Definition TClass.h:330
@ kUnloading
Definition TClass.h:330
ROOT::ResetAfterMergeFunc_t GetResetAfterMerge() const
Return the wrapper around Merge.
Definition TClass.cxx:7425
TMethod * GetClassMethodWithPrototype(const char *name, const char *proto, Bool_t objectIsConst=kFALSE, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch)
Find the method with a given prototype.
Definition TClass.cxx:4513
Bool_t CanIgnoreTObjectStreamer()
Definition TClass.h:391
void SetGlobalIsA(IsAGlobalFunc_t)
This function installs a global IsA function for this class.
Definition TClass.cxx:6286
void GetMissingDictionariesForMembers(TCollection &result, TCollection &visited, bool recurse)
Verify the Data Members.
Definition TClass.cxx:3930
TObjArray * fStreamerInfo
Definition TClass.h:198
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition TClass.cxx:1930
TVirtualCollectionProxy * fCollectionProxy
Definition TClass.h:220
static ENewType IsCallingNew()
Static method returning the defConstructor flag passed to TClass::New().
Definition TClass.cxx:5888
void ls(Option_t *opt="") const
The ls function lists the contents of a class on stdout.
Definition TClass.cxx:4244
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition TClass.cxx:3622
void Store(TBuffer &b) const
Store class description on I/O buffer.
Definition TClass.cxx:5846
void InterpretedShowMembers(void *obj, TMemberInspector &insp, Bool_t isTransient)
Do a ShowMembers() traversal of all members and base classes' members using the reflection informatio...
Definition TClass.cxx:2240
static THashTable * fgClassTypedefHash
Definition TClass.h:336
void Init(const char *name, Version_t cversion, const std::type_info *info, TVirtualIsAProxy *isa, const char *dfil, const char *ifil, Int_t dl, Int_t il, ClassInfo_t *classInfo, Bool_t silent)
Initialize a TClass object.
Definition TClass.cxx:1367
std::atomic< TListOfDataMembers * > fData
Definition TClass.h:202
static void StreamerStreamerInfo(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of where we should directly use the StreamerInfo.
Definition TClass.cxx:6844
const TObjArray * GetStreamerInfos() const
Definition TClass.h:489
void SetClassVersion(Version_t version)
Private function.
Definition TClass.cxx:5661
char * EscapeChars(const char *text) const
Introduce an escape character (@) in front of a special chars.
Definition TClass.cxx:2567
const std::type_info * fTypeInfo
Definition TClass.h:224
std::atomic< TVirtualStreamerInfo * > fLastReadInfo
cached current streamer info.
Definition TClass.h:276
static void StreamerTObject(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of TObjects.
Definition TClass.cxx:6786
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition TClass.cxx:5898
@ kDefault
Definition TClass.h:332
@ kEmulatedStreamer
Definition TClass.h:332
@ kExternal
Definition TClass.h:332
@ kForeign
Definition TClass.h:332
@ kInstrumented
Definition TClass.h:332
@ kTObject
Definition TClass.h:332
static Bool_t AddRule(const char *rule)
Add a schema evolution customization rule.
Definition TClass.cxx:1888
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition TClass.cxx:5924
static void RemoveClass(TClass *cl)
static: Remove a class from the list and map of classes
Definition TClass.cxx:520
Bool_t HasLocalHashMember() const
Returns true if this class has an definition and/or overload of the member function Hash.
Definition TClass.cxx:7407
void DeleteArray(void *ary, Bool_t dtorOnly=kFALSE)
Explicitly call operator delete[] for an array.
Definition TClass.cxx:5515
ClassConvStreamerFunc_t GetConvStreamerFunc() const
Get a wrapper/accessor function around this class custom conversion streamer (member function).
Definition TClass.cxx:2945
Bool_t IsForeign() const
Return kTRUE is the class is Foreign (the class does not have a Streamer method).
Definition TClass.cxx:5933
ClassInfo_t * GetClassInfo() const
Definition TClass.h:430
ROOT::DelFunc_t fDelete
Definition TClass.h:237
TViewPubDataMembers * fAllPubData
Definition TClass.h:209
Int_t GetBaseClassOffset(const TClass *toBase, void *address=0, bool isDerivedObject=true)
Definition TClass.cxx:2789
void Dump() const
Dump contents of object on stdout.
Definition TClass.h:396
ClassInfo_t * fClassInfo
Definition TClass.h:222
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0, Bool_t isTransient=kFALSE) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition TClass.cxx:4585
Bool_t HasConsistentHashMember()
Return 'true' if we can guarantee that if this class (or any class in this class inheritance hierarch...
Definition TClass.h:498
void AdoptStreamer(TClassStreamer *strm)
Adopt a TClassStreamer object.
Definition TClass.cxx:6880
TClass * GetBaseDataMember(const char *datamember)
Return pointer to (base) class that contains datamember.
Definition TClass.cxx:2825
Long_t Property() const
Returns the properties of the TClass as a bit field stored as a Long_t value.
Definition TClass.cxx:6072
ECheckSum
Definition TClass.h:108
@ kLatestCheckSum
Definition TClass.h:117
@ kNoRange
Definition TClass.h:112
@ kCurrentCheckSum
Definition TClass.h:109
@ kNoBaseCheckSum
Definition TClass.h:116
@ kReflex
Definition TClass.h:114
@ kReflexNoComment
Definition TClass.h:111
@ kWithTypeDef
Definition TClass.h:113
@ kNoRangeCheck
Definition TClass.h:115
@ kNoEnum
Definition TClass.h:110
ObjectPtr NewObjectArray(Long_t nElements, ENewType defConstructor=kClassNew) const
Return a pointer to a newly allocated array of objects of this class.
Definition TClass.cxx:5195
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2895
void ResetCaches()
To clean out all caches.
Definition TClass.cxx:4201
std::atomic< Bool_t > fVersionUsed
saved remember if fOffsetStreamer has been set.
Definition TClass.h:259
Long_t ClassProperty() const
Return the C++ property of this class, eg.
Definition TClass.cxx:2395
void SetStreamerImpl()
Internal routine to set fStreamerImpl based on the value of fStreamerType.
Definition TClass.cxx:6201
const char * GetSharedLibs()
Get the list of shared libraries containing the code for class cls.
Definition TClass.cxx:3609
void CalculateStreamerOffset() const
Calculate the offset between an object of this class to its base class TObject.
Definition TClass.cxx:2181
void GetMissingDictionariesForPairElements(TCollection &result, TCollection &visited, bool recurse)
Definition TClass.cxx:3959
void ReplaceWith(TClass *newcl) const
Definition TClass.cxx:4128
void RegisterAddressInRepository(const char *where, void *location, const TClass *what) const
Definition TClass.cxx:290
Bool_t HasDefaultConstructor(Bool_t testio=kFALSE) const
Return true if we have access to a constructor usable for I/O.
Definition TClass.cxx:7379
void GetMenuItems(TList *listitems)
Returns list of methods accessible by context menu.
Definition TClass.cxx:3860
void SetNew(ROOT::NewFunc_t newFunc)
Install a new wrapper around 'new'.
Definition TClass.cxx:6971
void Draw(Option_t *option="")
Draw detailed class inheritance structure.
Definition TClass.cxx:2485
std::atomic< TMethodCall * > fIsAMethod
Definition TClass.h:231
static Int_t ReadRules()
Read the class.rules files from the default location:.
Definition TClass.cxx:1818
Bool_t CanSplitBaseAllow()
Pointer to the function implementing streaming for this class.
Definition TClass.cxx:2245
void MoveAddressInRepository(const char *where, void *oldadd, void *newadd, const TClass *what) const
Definition TClass.cxx:337
std::atomic< StreamerImpl_t > fStreamerImpl
Definition TClass.h:284
void SetContextMenuTitle(const char *title)
Change (i.e. set) the title of the TNamed.
Definition TClass.cxx:6255
void SetMemberStreamer(const char *name, MemberStreamerFunc_t strm)
Install a new member streamer (p will be copied).
Definition TClass.cxx:6730
std::atomic< TClass ** > fPersistentRef
Definition TClass.h:194
IsAGlobalFunc_t fGlobalIsA
pointer to the class's IsA proxy.
Definition TClass.h:230
TVirtualStreamerInfo * GetConversionStreamerInfo(const char *onfile_classname, Int_t version) const
Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this clas...
Definition TClass.cxx:7072
Short_t GetImplFileLine() const
Definition TClass.h:454
TMethod * GetMethodAllAny(const char *method)
Return pointer to method without looking at parameters.
Definition TClass.cxx:4370
std::atomic< UChar_t > fRuntimeProperties
Definition TClass.h:270
@ kInterpreted
Definition TClass.h:126
@ kHasTClassInit
Definition TClass.h:127
@ kEmulated
Definition TClass.h:125
@ kNoInfo
Definition TClass.h:122
@ kLoaded
Definition TClass.h:130
@ kForwardDeclared
Definition TClass.h:124
@ kNamespaceForMeta
Definition TClass.h:131
TVirtualStreamerInfo * FindConversionStreamerInfo(const char *onfile_classname, UInt_t checksum) const
Return a Conversion StreamerInfo from the class 'classname' for the layout represented by 'checksum' ...
Definition TClass.cxx:7179
Int_t GetBaseClassOffsetRecurse(const TClass *toBase)
Return data member offset to the base class "cl".
Definition TClass.cxx:2703
ROOT::DelFunc_t GetDelete() const
Return the wrapper around delete ThiObject.
Definition TClass.cxx:7449
static TClass * LoadClassDefault(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition TClass.cxx:5757
void SetClassSize(Int_t sizof)
Definition TClass.h:305
TMethod * FindClassOrBaseMethodWithId(DeclId_t faddr)
Find a method with decl id in this class or its bases.
Definition TClass.cxx:4426
static void StreamerExternal(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
There is special streamer for the class.
Definition TClass.cxx:6774
Long_t fClassProperty
Property See TClass::Property() for details.
Definition TClass.h:253
TString fContextMenuTitle
Definition TClass.h:223
static void StreamerTObjectInitialized(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of TObjects when fIsOffsetStreamerSet is known to have been set.
Definition TClass.cxx:6800
static void ConvStreamerInstrumented(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of instrumented class with a library.
Definition TClass.cxx:6831
std::atomic< Bool_t > fCanLoadClassInfo
Whether info was loaded from a root pcm.
Definition TClass.h:257
void SetConvStreamerFunc(ClassConvStreamerFunc_t strm)
Set a wrapper/accessor function around this class custom conversion streamer.
Definition TClass.cxx:6931
TVirtualStreamerInfo * FindStreamerInfo(TObjArray *arr, UInt_t checksum) const
Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum.
Definition TClass.cxx:7052
void GetMissingDictionaries(THashTable &result, bool recurse=false)
Get the classes that have a missing dictionary starting from this one.
Definition TClass.cxx:4073
void MakeCustomMenuList()
Makes a customizable version of the popup menu list, i.e.
Definition TClass.cxx:4269
TVirtualStreamerInfo * FindStreamerInfoAbstractEmulated(UInt_t checksum) const
For the case where the requestor class is emulated and this class is abstract, returns a pointer to t...
Definition TClass.cxx:4758
TMethod * GetMethodAny(const char *method)
Return pointer to method without looking at parameters.
Definition TClass.cxx:4360
TVirtualIsAProxy * GetIsAProxy() const
Return the proxy implementing the IsA functionality.
Definition TClass.cxx:2953
ROOT::MergeFunc_t GetMerge() const
Return the wrapper around Merge.
Definition TClass.cxx:7417
ROOT::ResetAfterMergeFunc_t fResetAfterMerge
Definition TClass.h:234
UInt_t fInstanceCount
Definition TClass.h:217
std::atomic< Bool_t > fHasRootPcmInfo
C++ Property of the class (is abstract, has virtual table, etc.)
Definition TClass.h:256
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4860
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition TClass.cxx:2606
ROOT::DesFunc_t fDestructor
Definition TClass.h:239
const char * GetDeclFileName() const
Return name of the file containing the declaration of this class.
Definition TClass.cxx:3449
ObjectPtr NewObject(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Definition TClass.cxx:4978
TRealData * GetRealData(const char *name) const
Return pointer to TRealData element with name "name".
Definition TClass.cxx:3489
void SetDeleteArray(ROOT::DelArrFunc_t deleteArrayFunc)
Install a new wrapper around 'delete []'.
Definition TClass.cxx:6995
TFunctionTemplate * GetFunctionTemplate(const char *name)
Definition TClass.cxx:3593
void ResetClassInfo()
Make sure that the current ClassInfo is up to date.
Definition TClass.cxx:4166
ROOT::NewArrFunc_t fNewArray
Definition TClass.h:236
Int_t ReadBuffer(TBuffer &b, void *pointer, Int_t version, UInt_t start, UInt_t count)
Function called by the Streamer functions to deserialize information from buffer b into object at p.
Definition TClass.cxx:6744
void GetMissingDictionariesWithRecursionCheck(TCollection &result, TCollection &visited, bool recurse)
From the second level of recursion onwards it is different state check.
Definition TClass.cxx:3976
bool IsClassStructOrUnion() const
Definition TClass.h:352
@ kHasLocalHashMember
Definition TClass.h:95
@ kHasNameMapNode
Definition TClass.h:104
@ kIgnoreTObjectStreamer
Definition TClass.h:96
@ kUnloaded
Definition TClass.h:97
@ kHasCustomStreamerMember
Definition TClass.h:105
@ kWarned
Definition TClass.h:103
@ kStartWithTObject
Definition TClass.h:102
@ kIsTObject
Definition TClass.h:99
@ kIsForeign
Definition TClass.h:100
std::atomic< TListOfDataMembers * > fUsingData
Definition TClass.h:203
TListOfFunctions * GetMethodList()
Return (create an empty one if needed) the list of functions.
Definition TClass.cxx:4341
void ResetMenuList()
Resets the menu list to it's standard value.
Definition TClass.cxx:4229
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2966
Int_t WriteBuffer(TBuffer &b, void *pointer, const char *info="")
Function called by the Streamer functions to serialize object at p to buffer b.
Definition TClass.cxx:6765
static TClass * LoadClassCustom(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition TClass.cxx:5787
Short_t fImplFileLine
Definition TClass.h:216
Collection abstract base class.
Definition TCollection.h:65
virtual void ls(Option_t *option="") const
List (ls) all objects in this collection.
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual void Add(TObject *obj)=0
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
All ROOT classes may have RTTI (run time type identification) support added.
Definition TDataMember.h:31
Int_t GetMaxIndex(Int_t dim) const
Return maximum index for array dimension "dim".
const char * GetTrueTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
Bool_t IsPersistent() const
Definition TDataMember.h:91
Int_t GetArrayDim() const
Return number of array dimensions.
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
Bool_t IsaPointer() const
Return true if data member is a pointer.
TDataType * GetDataType() const
Definition TDataMember.h:76
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
Basic data type descriptor (datatype information is obtained from CINT).
Definition TDataType.h:44
Int_t GetType() const
Definition TDataType.h:68
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
const char * AsString(void *buf) const
Return string containing value in buffer formatted according to the basic data type.
TString GetTypeName()
Get basic type of typedef, e,g.: "class TDirectory*" -> "TDirectory".
static TDataType * GetDataType(EDataType type)
Given a EDataType type, get the TDataType* that represents it.
static void GetDateTime(UInt_t datetime, Int_t &date, Int_t &time)
Static function that returns the date and time.
Definition TDatime.cxx:435
This class defines an abstract interface that must be implemented by all classes that contain diction...
EMemberSelection
Kinds of members to include in lists.
const void * DeclId_t
TDumpMembers(bool noAddr)
Definition TClass.cxx:557
void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient)
Print value of member mname.
Definition TClass.cxx:574
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
Definition TEnum.cxx:132
@ kNone
Definition TEnum.h:48
This class stores a (key,value) pair using an external hash.
Definition TExMap.h:33
Long64_t GetValue(ULong64_t hash, Long64_t key)
Return the value belonging to specified key and hash value.
Definition TExMap.cxx:173
void AddAt(UInt_t slot, ULong64_t hash, Long64_t key, Long64_t value)
Add an (key,value) pair to the table.
Definition TExMap.cxx:116
Dictionary for function template This class describes one single function template.
Global functions class (global functions are obtained from CINT).
Definition TFunction.h:30
Int_t GetNargs() const
Number of function arguments.
THashTable implements a hash table to store TObject's.
Definition THashTable.h:35
TObject * Remove(TObject *obj)
Remove object from the hashtable.
const TList * GetListForObject(const char *name) const
Return the TList corresponding to object's name based hash value.
void Add(TObject *obj)
Add object to the hash table.
TObject * FindObject(const char *name) const
Find object using its name.
virtual Bool_t ClassInfo_HasMethod(ClassInfo_t *, const char *) const
virtual const char * DataMemberInfo_Name(DataMemberInfo_t *) const
virtual const char * DataMemberInfo_TypeName(DataMemberInfo_t *) const
virtual int DataMemberInfo_TypeSize(DataMemberInfo_t *) const
virtual void * ClassInfo_New(ClassInfo_t *) const
virtual Bool_t ClassInfo_IsValid(ClassInfo_t *) const
virtual Int_t AutoParse(const char *cls)=0
virtual void ClassInfo_Delete(ClassInfo_t *) const
virtual void ClassInfo_DeleteArray(ClassInfo_t *, void *, bool) const
virtual Long_t ClassInfo_Property(ClassInfo_t *) const
virtual int ClassInfo_Size(ClassInfo_t *) const
virtual const char * ClassInfo_FullName(ClassInfo_t *) const
virtual int SetClassAutoLoading(int) const
virtual const char * ClassInfo_Title(ClassInfo_t *) const
virtual Long_t DataMemberInfo_TypeProperty(DataMemberInfo_t *) const
virtual int DataMemberInfo_Next(DataMemberInfo_t *) const
virtual DataMemberInfo_t * DataMemberInfo_Factory(ClassInfo_t *, TDictionary::EMemberSelection) const
virtual Long_t DataMemberInfo_Property(DataMemberInfo_t *) const
virtual int DataMemberInfo_ArrayDim(DataMemberInfo_t *) const
virtual void DataMemberInfo_Delete(DataMemberInfo_t *) const
virtual int DataMemberInfo_MaxIndex(DataMemberInfo_t *, Int_t) const
TDictionary::DeclId_t DeclId_t
virtual Bool_t ClassInfo_HasDefaultConstructor(ClassInfo_t *, Bool_t=kFALSE) const
virtual Long_t ClassInfo_ClassProperty(ClassInfo_t *) const
virtual Longptr_t ClassInfo_GetBaseOffset(ClassInfo_t *, ClassInfo_t *, void *=0, bool=true) const
virtual void ClassInfo_Destruct(ClassInfo_t *, void *) const
TIsAProxy implementation class.
Definition TIsAProxy.h:27
void Reset()
A collection of TDataMember objects designed for fast access given a DeclId_t and for keep track of T...
A collection of TEnum objects designed for fast access given a DeclId_t and for keep track of TEnum t...
A collection of TEnum objects designed for fast access given a DeclId_t and for keep track of TEnum t...
A collection of TFunction objects designed for fast access given a DeclId_t and for keep track of TFu...
virtual TObject * FindObject(const char *name) const
Specialize FindObject to do search for the a function just by name or create it if its not already in...
void Load()
Load all the functions known to the interpreter for the scope 'fClass' into this collection.
virtual void Delete(Option_t *option="")
Delete all TFunction object files.
A collection of TFunction objects designed for fast access given a DeclId_t and for keep track of TFu...
TFunction * Get(DeclId_t id)
Return (after creating it if necessary) the TMethod or TFunction describing the function correspondin...
virtual TObject * FindObject(const TObject *obj) const
Find object using its hash value (returned by its Hash() member).
virtual TList * GetListForObject(const char *name) const
Return the set of overloads for this name, collecting all available ones.
A doubly linked list.
Definition TList.h:38
virtual void Add(TObject *obj)
Definition TList.h:81
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition TList.cxx:822
virtual void AddFirst(TObject *obj)
Add object at the beginning of the list.
Definition TList.cxx:100
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition TList.cxx:578
virtual TObjLink * FirstLink() const
Definition TList.h:102
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:470
virtual void AddLast(TObject *obj)
Add object at the end of the list.
Definition TList.cxx:152
TMap implements an associative array of (key,value) pairs using a THashTable for efficient retrieval ...
Definition TMap.h:40
Abstract base class for accessing the data-members of a class.
virtual void Inspect(TClass *cl, const char *parent, const char *name, const void *addr)
Each ROOT method (see TMethod) has a linked list of its arguments.
Definition TMethodArg.h:36
const char * GetFullTypeName() const
Get full type description of method argument, e.g.: "class TDirectory*".
Each ROOT class (see TClass) has a linked list of methods.
Definition TMethod.h:38
TClass * GetClass() const
Definition TMethod.h:55
EMenuItemKind IsMenuItem() const
Definition TMethod.h:56
virtual TList * GetListOfMethodArgs()
Returns methodarg list and additionally updates fDataMember in TMethod by calling FindDataMember();.
Definition TMethod.cxx:307
virtual void ls(Option_t *option="") const
List TNamed name and title.
Definition TNamed.cxx:113
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
TString fName
Definition TNamed.h:32
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:140
virtual const char * GetTitle() const
Returns title of object.
Definition TNamed.h:48
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition TNamed.cxx:74
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
An array of TObjects.
Definition TObjArray.h:31
Int_t GetEntriesFast() const
Definition TObjArray.h:58
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
void Add(TObject *obj)
Definition TObjArray.h:68
Int_t GetEntries() const
Return the number of objects in array (i.e.
virtual void Clear(Option_t *option="")
Remove all objects from the array.
TObject * UncheckedAt(Int_t i) const
Definition TObjArray.h:84
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Int_t GetLast() const
Return index of last object in array.
Int_t LowerBound() const
Definition TObjArray.h:91
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
TObject * At(Int_t idx) const
Definition TObjArray.h:164
Collectable string class.
Definition TObjString.h:28
Mother of all ROOT objects.
Definition TObject.h:41
static void SetObjectStat(Bool_t stat)
Turn on/off tracking of objects in the TObjectTable.
Definition TObject.cxx:1044
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:429
virtual void Browse(TBrowser *b)
Browse object. May be overridden for another default action.
Definition TObject.cxx:191
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:201
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:949
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:393
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition TObject.h:153
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:766
static Bool_t GetObjectStat()
Get status of object stat flag.
Definition TObject.cxx:1037
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:963
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:991
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:777
void MakeZombie()
Definition TObject.h:53
void ResetBit(UInt_t f)
Definition TObject.h:200
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:937
Class used by TMap to store (key,value) pairs.
Definition TMap.h:102
Persistent version of a TClass.
Definition TProtoClass.h:38
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
Definition TROOT.cxx:2969
The TRealData class manages the effective list of all data members for a given class.
Definition TRealData.h:30
void AdoptStreamer(TMemberStreamer *p)
Definition TRealData.cxx:67
virtual const char * GetName() const
Returns name of object.
Definition TRealData.h:52
Long_t GetThisOffset() const
Definition TRealData.h:55
void SetIsObject(Bool_t isObject)
Definition TRealData.h:57
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
Int_t GetType() const
virtual const char * GetFullName() const
Return element name including dimensions, if any Note that this function stores the name into a stati...
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
Int_t GetArrayDim() const
virtual Bool_t IsaPointer() const
const char * GetTypeName() const
Int_t GetOffset() const
virtual Bool_t IsBase() const
Return kTRUE if the element represent a base class.
Basic string class.
Definition TString.h:136
Ssiz_t Length() const
Definition TString.h:410
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition TString.h:682
const char * Data() const
Definition TString.h:369
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:692
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:615
Bool_t IsNull() const
Definition TString.h:407
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.
Definition TString.cxx:662
TString & Remove(Ssiz_t pos)
Definition TString.h:673
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2336
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2314
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:624
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:639
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition TSystem.cxx:1081
View implementing the TList interface and giving access all the TDictionary describing public data me...
void Load()
Load all the DataMembers known to the interpreter for the scope 'fClass' and all its bases classes.
void Delete(Option_t *option="")
Delete is not allowed in this class.
View implementing the TList interface and giving access all the TFunction describing public methods i...
void Delete(Option_t *option="")
Delete is not allowed in this class.
void Load()
Load all the functions known to the interpreter for the scope 'fClass' and all its bases classes.
virtual Int_t GetProperties() const
virtual UInt_t Sizeof() const =0
virtual TClass::ObjectPtr NewObjectArray(Int_t nElements) const
virtual void Destructor(void *p, Bool_t dtorOnly=kFALSE) const
virtual void DeleteArray(void *p, Bool_t dtorOnly=kFALSE) const
virtual TClass * GetValueClass() const =0
virtual TClass::ObjectPtr NewObject() const
virtual void * At(UInt_t idx)=0
virtual UInt_t Size() const =0
virtual TVirtualCollectionProxy * Generate() const =0
virtual Bool_t HasPointers() const =0
virtual void SetClass(TClass *cl)=0
This class implements a mutex interface.
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
virtual TVirtualPad * cd(Int_t subpadnumber=0)=0
virtual void DrawClassObject(const TObject *obj, Option_t *option="")=0
virtual void Release()=0
virtual void SetClass(TClass *classptr)=0
virtual TVirtualRefProxy * Clone() const =0
Abstract Interface class describing Streamer information for one class.
virtual TVirtualStreamerInfo * GenerateInfoForPair(const std::string &pairclassname, bool silent, size_t hint_pair_offset, size_t hint_pair_size)=0
Generate the TClass and TStreamerInfo for the requested pair.
virtual void DeleteArray(void *p, Bool_t dtorOnly=kFALSE)=0
virtual void SetClassVersion(Int_t vers)=0
virtual TClassStreamer * GenEmulatedClassStreamer(const char *class_name, Bool_t silent)=0
virtual TVirtualStreamerInfo * NewInfo(TClass *cl)=0
virtual void BuildCheck(TFile *file=0, Bool_t load=kTRUE)=0
virtual TClass * GetActualClass(const void *obj) const =0
virtual UInt_t GetCheckSum() const =0
virtual Int_t GetOffset(const char *) const =0
static const char * GetElementCounterStart(const char *dmTitle)
Given a comment/title declaring an array counter, for example:
virtual void Build(Bool_t isTransient=kFALSE)=0
virtual Bool_t BuildFor(const TClass *cl)=0
virtual TVirtualCollectionProxy * GenExplicitProxy(const ::ROOT::Detail::TCollectionProxyInfo &info, TClass *cl)=0
virtual void Clear(Option_t *)=0
Set name and title to empty strings ("").
virtual TVirtualCollectionProxy * GenEmulatedProxy(const char *class_name, Bool_t silent)=0
virtual void SetClass(TClass *cl)=0
virtual void * NewArray(Long_t nElements, void *ary=0)=0
virtual TObjArray * GetElements() const =0
virtual Int_t GetSize() const =0
virtual void BuildOld()=0
static TVirtualStreamerInfo * Factory()
Static function returning a pointer to a new TVirtualStreamerInfo object.
virtual Version_t GetOldVersion() const =0
virtual void * New(void *obj=0)=0
virtual Int_t GetOnFileClassVersion() const =0
virtual void Destructor(void *p, Bool_t dtorOnly=kFALSE)=0
virtual Bool_t CompareContent(TClass *cl, TVirtualStreamerInfo *info, Bool_t warn, Bool_t complete, TFile *file)=0
virtual Int_t GetClassVersion() const =0
virtual void Update(const TClass *oldClass, TClass *newClass)=0
virtual TClass * GetClass() const =0
TText * text
TLine * line
return c1
Definition legend1.C:41
R__EXTERN void * gMmallocDesc
Definition TStorage.h:149
Bool_t HasConsistentHashMember(TClass &clRef)
Return true is the Hash/RecursiveRemove setup is consistent, i.e.
Definition TClass.cxx:7357
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
void(* DirAutoAdd_t)(void *, TDirectory *)
Definition Rtypes.h:113
R__EXTERN TVirtualRWMutex * gCoreMutex
void(* ResetAfterMergeFunc_t)(void *, TFileMergeInfo *)
Definition Rtypes.h:115
@ kClassThreadSlot
void(* DesFunc_t)(void *)
Definition Rtypes.h:112
TClass * CreateClass(const char *cname, Version_t id, const std::type_info &info, TVirtualIsAProxy *isa, const char *dfil, const char *ifil, Int_t dl, Int_t il)
Global function called by a class' static Dictionary() method (see the ClassDef macro).
Definition TClass.cxx:5855
void(* DelFunc_t)(void *)
Definition Rtypes.h:110
ESTLType
Definition ESTLType.h:28
@ kNotSTL
Definition ESTLType.h:29
void *(* NewArrFunc_t)(Long_t size, void *arena)
Definition Rtypes.h:109
void Class_ShowMembers(TClass *cl, const void *obj, TMemberInspector &)
Indirect call to the implementation of ShowMember allowing [forward] declaration with out a full defi...
Definition TClass.cxx:546
EFunctionMatchMode
@ kExactMatch
void(* DelArrFunc_t)(void *)
Definition Rtypes.h:111
void *(* NewFunc_t)(void *)
Definition Rtypes.h:108
Long64_t(* MergeFunc_t)(void *, TCollection *, TFileMergeInfo *)
Definition Rtypes.h:114
bool IsStdPairBase(std::string_view name)
Definition TClassEdit.h:196
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
bool IsStdArray(std::string_view name)
Definition TClassEdit.h:189
bool IsStdClass(const char *type)
return true if the class belongs to the std namespace
bool IsStdPair(std::string_view name)
Definition TClassEdit.h:191
bool IsInterpreterDetail(const char *type)
Return true if the type is one the interpreter details which are only forward declared (ClassInfo_t e...
char * DemangleTypeIdName(const std::type_info &ti, int &errorCode)
Demangle in a portable way the type id name.
ROOT::ESTLType IsSTLCont(std::string_view type)
type : type name: vector<list<classA,allocator>,allocator> result: 0 : not stl container code of cont...
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.
bool IsArtificial(std::string_view name)
Definition TClassEdit.h:159
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.
@ kDropStlDefault
Definition TClassEdit.h:82
bool IsSTLBitset(const char *type)
Return true is the name is std::bitset<number> or bitset<number>
UInt_t Find(std::list< std::pair< const Node< T > *, Float_t > > &nlist, const Node< T > *node, const T &event, UInt_t nfind)
Short_t Min(Short_t a, Short_t b)
Definition TMathBase.h:176
TMatrixT< Element > & Add(TMatrixT< Element > &target, Element scalar, const TMatrixT< Element > &source)
Modify addition: target += scalar * source.
Definition first.py:1
static const char * what
Definition stlLoader.cc:6
bool IsTemplate()
Check if the type is a template.
std::vector< std::string > fElements
Definition TClassEdit.h:141
TVirtualStreamerInfo * GetAllocator() const
Definition TClass.h:149
void * GetPtr() const
Definition TClass.h:147
TClass::ENewType & fCurrentValue
Definition TClass.cxx:274
TClass__GetCallingNewRAII(TClass::ENewType newvalue)
Definition TClass.cxx:277
TClass::ENewType fOldValue
Definition TClass.cxx:275
auto * m
Definition textangle.C:8
auto * l
Definition textangle.C:4