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 std::multimap, std::make_pair, std::string;
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) :
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) :
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 = name ? strlen(name) : 0;
200 if (strLen == 0) return;
201 // find <. If none, put end of string
202 const char* endCharPtr = strchr(name, '<');
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 }
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);
218 fClassNamesSet.insert(s);
219}
220
221////////////////////////////////////////////////////////////////////////////////
222
224{
225 Bool_t found = false;
226 {
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
251
252////////////////////////////////////////////////////////////////////////////////
253
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]
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:
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
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
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) override;
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
590 const char *memberName;
591 const char *memberFullTypeName;
592 const char *memberTitle;
596
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;
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;
630
631 isbasic = membertype !=nullptr;
632 isarray = element->GetArrayDim();
633 } else {
634 return;
635 }
636
637
639 if (strcmp(memberName,"fDatime") == 0 && memberDataType == kUInt_t) {
640 isdate = kTRUE;
641 }
643 if (strcmp(memberName,"fBits") == 0 && memberDataType == kUInt_t) {
644 isbits = kTRUE;
645 }
648 static TClassRef stdClass("std::string");
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)
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;
674 for (Int_t j = 0; j < i; j++) {
675 if (!std::isprint((*ppointer)[j])) {
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 {
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;
694 for (Int_t j = 0; j < i; j++) {
695 if (!std::isprint((*ppointer)[j])) {
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;
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) override;
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{
774 if (!dm) {
775 return;
776 }
777
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.
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
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 //
851 if (!dmclass) {
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) {
869 if (valcl->Property() & kIsAbstract) wantBuild = kFALSE;
870 if ( (isTransient)
871 && (dmclass->GetCollectionProxy()->GetProperties() & TVirtualCollectionProxy::kIsEmulated)
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 :(]
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 {
908 // main constructor.
909 fBrowser = b; fCount = 0;
910 }
911 virtual ~TAutoInspector() {}
913 void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient) override;
915};
916
917////////////////////////////////////////////////////////////////////////////////
918/// This method is called from ShowMembers() via AutoBrowse().
919
920void TAutoInspector::Inspect(TClass *cl, const char *tit, const char *name,
921 const void *addr, Bool_t /* isTransient */)
922{
923 if(tit && strchr(tit,'.')) return ;
924 if (fCount && !fBrowser) return;
925
926 TString ts;
927
928 if (!cl) return;
929 //if (*(cl->GetName()) == 'T') return;
930 if (*name == '*') name++;
931 int ln = strcspn(name,"[ ");
933
935 if (!classInfo) return;
936
937 // Browse data members
940
941 int found=0;
942 while (gCling->DataMemberInfo_Next(m)) { // MemberLoop
944 mname.ReplaceAll("*","");
945 if ((found = (iname==mname))) break;
946 }
947 assert(found);
948
949 // we skip: non static members and non objects
950 // - the member G__virtualinfo inserted by the CINT RTTI system
951
952 //Long_t prop = m.Property() | m.Type()->Property();
954 if (prop & kIsStatic) return;
955 if (prop & kIsFundamental) return;
956 if (prop & kIsEnum) return;
957 if (mname == "G__virtualinfo") return;
958
959 int size = sizeof(void*);
960
961 int nmax = 1;
962 if (prop & kIsArray) {
963 for (int dim = 0; dim < gCling->DataMemberInfo_ArrayDim(m); dim++) nmax *= gCling->DataMemberInfo_MaxIndex(m,dim);
964 }
965
968 TClass * clm = TClass::GetClass(clmName.c_str());
969 R__ASSERT(clm);
970 if (!(prop & kIsPointer)) {
971 size = clm->Size();
973 }
974
975
977 TVirtualCollectionProxy *proxy = clm->GetCollectionProxy();
978
979 for(int i=0; i<nmax; i++) {
980
981 char *ptr = (char*)addr + i*size;
982
983 void *obj = (prop & kIsPointer) ? *((void**)ptr) : (TObject*)ptr;
984
985 if (!obj) continue;
986
987 fCount++;
988 if (!fBrowser) return;
989
991 TClass *actualClass = clm->GetActualClass(obj);
992 if (clm->IsTObject()) {
993 TObject *tobj = (TObject*)clm->DynamicCast(TObject::Class(),obj);
994 bwname = tobj->GetName();
995 } else {
996 bwname = actualClass->GetName();
997 bwname += "::";
998 bwname += mname;
999 }
1000
1001 if (!clm->IsTObject() ||
1002 bwname.Length()==0 ||
1003 strcmp(bwname.Data(),actualClass->GetName())==0) {
1004 bwname = name;
1005 int l = strcspn(bwname.Data(),"[ ");
1006 if (l<bwname.Length() && bwname[l]=='[') {
1007 char cbuf[13]; snprintf(cbuf,13,"[%02d]",i);
1008 ts.Replace(0,999,bwname,l);
1009 ts += cbuf;
1010 bwname = (const char*)ts;
1011 }
1012 }
1013
1014 if (proxy==nullptr) {
1015
1016 fBrowser->Add(obj,clm,bwname);
1017
1018 } else {
1019 TClass *valueCl = proxy->GetValueClass();
1020
1021 if (valueCl==nullptr) {
1022
1023 fBrowser->Add( obj, clm, bwname );
1024
1025 } else {
1027 TClass *actualCl = nullptr;
1028
1029 int sz = proxy->Size();
1030
1031 char fmt[] = {"#%09d"};
1032 fmt[3] = '0'+(int)log10(double(sz))+1;
1033 char buf[20];
1034 for (int ii=0;ii<sz;ii++) {
1035 void *p = proxy->At(ii);
1036
1037 if (proxy->HasPointers()) {
1038 p = *((void**)p);
1039 if(!p) continue;
1040 actualCl = valueCl->GetActualClass(p);
1041 p = actualCl->DynamicCast(valueCl,p,0);
1042 }
1043 fCount++;
1044 snprintf(buf,20,fmt,ii);
1045 ts = bwname;
1046 ts += buf;
1047 fBrowser->Add( p, actualCl, ts );
1048 }
1049 }
1050 }
1051 }
1052}
1053
1054//______________________________________________________________________________
1055//______________________________________________________________________________
1056//______________________________________________________________________________
1057
1059
1060////////////////////////////////////////////////////////////////////////////////
1061/// Internal, default constructor.
1062///
1063/// \note Use `TClass::GetClass("ClassName")` to get access to a TClass object for a certain class!
1064
1066 TDictionary(),
1067 fPersistentRef(nullptr),
1068 fStreamerInfo(nullptr), fConversionStreamerInfo(nullptr), fRealData(nullptr),
1069 fBase(nullptr), fData(nullptr), fUsingData(nullptr), fEnums(nullptr), fFuncTemplate(nullptr), fMethod(nullptr), fAllPubData(nullptr),
1070 fAllPubMethod(nullptr), fClassMenuList(nullptr),
1072 fInstanceCount(0), fOnHeap(0),
1073 fCheckSum(0), fCollectionProxy(nullptr), fClassVersion(0), fClassInfo(nullptr),
1074 fTypeInfo(nullptr), fShowMembers(nullptr),
1075 fStreamer(nullptr), fIsA(nullptr), fGlobalIsA(nullptr), fIsAMethod(nullptr),
1076 fMerge(nullptr), fResetAfterMerge(nullptr), fNew(nullptr), fNewArray(nullptr), fDelete(nullptr), fDeleteArray(nullptr),
1077 fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fSizeof(-1),
1080 fState(kNoInfo),
1081 fCurrentInfo(nullptr), fLastReadInfo(nullptr), fRefProxy(nullptr),
1083
1084{
1085 // Default ctor.
1086
1088 {
1089 TMmallocDescTemp setreset;
1090 fStreamerInfo = new TObjArray(1, -2);
1091 }
1092 fDeclFileLine = -2; // -2 for standalone TClass (checked in dtor)
1093}
1094
1095////////////////////////////////////////////////////////////////////////////////
1096/// Create a TClass object. This object contains the full dictionary
1097/// of a class. It has list to baseclasses, datamembers and methods.
1098/// Use this ctor to create a standalone TClass object. Only useful
1099/// to get a temporary TClass interface to an interpreted class. Used by TTabCom.
1100///
1101/// \note Use `TClass::GetClass("ClassName")` to get access to a TClass object for a certain class!
1102
1105 fPersistentRef(nullptr),
1106 fStreamerInfo(nullptr), fConversionStreamerInfo(nullptr), fRealData(nullptr),
1107 fBase(nullptr), fData(nullptr), fUsingData(nullptr), fEnums(nullptr), fFuncTemplate(nullptr), fMethod(nullptr), fAllPubData(nullptr),
1108 fAllPubMethod(nullptr), fClassMenuList(nullptr),
1109 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1110 fInstanceCount(0), fOnHeap(0),
1111 fCheckSum(0), fCollectionProxy(nullptr), fClassVersion(0), fClassInfo(nullptr),
1112 fTypeInfo(nullptr), fShowMembers(nullptr),
1113 fStreamer(nullptr), fIsA(nullptr), fGlobalIsA(nullptr), fIsAMethod(nullptr),
1114 fMerge(nullptr), fResetAfterMerge(nullptr), fNew(nullptr), fNewArray(nullptr), fDelete(nullptr), fDeleteArray(nullptr),
1115 fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fSizeof(-1),
1116 fCanSplit(-1), fIsSyntheticPair(kFALSE), fHasCustomStreamerMember(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1117 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1118 fState(kNoInfo),
1119 fCurrentInfo(nullptr), fLastReadInfo(nullptr), fRefProxy(nullptr),
1120 fSchemaRules(nullptr), fStreamerImpl(&TClass::StreamerDefault)
1121{
1123
1124 if (!gROOT)
1125 ::Fatal("TClass::TClass", "ROOT system not initialized");
1126
1127 {
1128 TMmallocDescTemp setreset;
1129 fStreamerInfo = new TObjArray(1, -2);
1130 }
1131 fDeclFileLine = -2; // -2 for standalone TClass (checked in dtor)
1132
1134 if (!gInterpreter)
1135 ::Fatal("TClass::TClass", "gInterpreter not initialized");
1136
1137 gInterpreter->SetClassInfo(this); // sets fClassInfo pointer
1139 ::Warning("TClass::TClass", "no dictionary for class %s is available", name);
1141
1143 fConversionStreamerInfo = nullptr;
1144}
1145
1146////////////////////////////////////////////////////////////////////////////////
1147/// Internal constructor.
1148///
1149/// \note Use `TClass::GetClass("ClassName")` to get access to a TClass object for a certain class!
1150
1153 fPersistentRef(nullptr),
1154 fStreamerInfo(nullptr), fConversionStreamerInfo(nullptr), fRealData(nullptr),
1155 fBase(nullptr), fData(nullptr), fUsingData(nullptr), fEnums(nullptr), fFuncTemplate(nullptr), fMethod(nullptr), fAllPubData(nullptr),
1156 fAllPubMethod(nullptr), fClassMenuList(nullptr),
1157 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1158 fInstanceCount(0), fOnHeap(0),
1159 fCheckSum(0), fCollectionProxy(nullptr), fClassVersion(0), fClassInfo(nullptr),
1160 fTypeInfo(nullptr), fShowMembers(nullptr),
1161 fStreamer(nullptr), fIsA(nullptr), fGlobalIsA(nullptr), fIsAMethod(nullptr),
1162 fMerge(nullptr), fResetAfterMerge(nullptr), fNew(nullptr), fNewArray(nullptr), fDelete(nullptr), fDeleteArray(nullptr),
1163 fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fSizeof(-1),
1164 fCanSplit(-1), fIsSyntheticPair(kFALSE), fHasCustomStreamerMember(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1165 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1166 fState(kNoInfo),
1167 fCurrentInfo(nullptr), fLastReadInfo(nullptr), fRefProxy(nullptr),
1168 fSchemaRules(nullptr), fStreamerImpl(&TClass::StreamerDefault)
1169{
1171 Init(name, cversion, nullptr, nullptr, nullptr, nullptr, -1, -1, nullptr, silent);
1172}
1173
1174////////////////////////////////////////////////////////////////////////////////
1175/// Internal constructor, mimicing the case of a class fwd declared in the interpreter.
1176///
1177/// \note Use `TClass::GetClass("ClassName")` to get access to a TClass object for a certain class!
1178
1181 fPersistentRef(nullptr),
1182 fStreamerInfo(nullptr), fConversionStreamerInfo(nullptr), fRealData(nullptr),
1183 fBase(nullptr), fData(nullptr), fUsingData(nullptr), fEnums(nullptr), fFuncTemplate(nullptr), fMethod(nullptr), fAllPubData(nullptr),
1184 fAllPubMethod(nullptr), fClassMenuList(nullptr),
1185 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1186 fInstanceCount(0), fOnHeap(0),
1187 fCheckSum(0), fCollectionProxy(nullptr), fClassVersion(0), fClassInfo(nullptr),
1188 fTypeInfo(nullptr), fShowMembers(nullptr),
1189 fStreamer(nullptr), fIsA(nullptr), fGlobalIsA(nullptr), fIsAMethod(nullptr),
1190 fMerge(nullptr), fResetAfterMerge(nullptr), fNew(nullptr), fNewArray(nullptr), fDelete(nullptr), fDeleteArray(nullptr),
1191 fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fSizeof(-1),
1192 fCanSplit(-1), fIsSyntheticPair(kFALSE), fHasCustomStreamerMember(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1193 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1194 fState(theState),
1195 fCurrentInfo(nullptr), fLastReadInfo(nullptr), fRefProxy(nullptr),
1196 fSchemaRules(nullptr), fStreamerImpl(&TClass::StreamerDefault)
1197{
1199
1200 // Treat the case in which a TClass instance is created for a namespace
1203 theState = kForwardDeclared; // it immediately decays in kForwardDeclared
1204 }
1205
1207 ::Fatal("TClass::TClass",
1208 "A TClass entry cannot be initialized in a state different from kForwardDeclared or kEmulated.");
1209 Init(name, cversion, nullptr, nullptr, nullptr, nullptr, -1, -1, nullptr, silent);
1210}
1211
1212////////////////////////////////////////////////////////////////////////////////
1213/// Internal constructor.
1214///
1215/// Create a TClass object. This object contains the full dictionary
1216/// of a class. It has list to baseclasses, datamembers and methods.
1217/// Use this ctor to create a standalone TClass object. Most useful
1218/// to get a TClass interface to an interpreted class. Used by TTabCom.
1219///
1220/// This copies the ClassInfo (i.e. does *not* take ownership of it).
1221///
1222/// \note Use `TClass::GetClass("class")` to get access to a TClass object for a certain class!
1223
1225 const char *dfil, const char *ifil, Int_t dl, Int_t il, Bool_t silent) :
1226 TDictionary(""),
1227 fPersistentRef(nullptr),
1228 fStreamerInfo(nullptr), fConversionStreamerInfo(nullptr), fRealData(nullptr),
1229 fBase(nullptr), fData(nullptr), fUsingData(nullptr), fEnums(nullptr), fFuncTemplate(nullptr), fMethod(nullptr), fAllPubData(nullptr),
1230 fAllPubMethod(nullptr), fClassMenuList(nullptr),
1231 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1232 fInstanceCount(0), fOnHeap(0),
1233 fCheckSum(0), fCollectionProxy(nullptr), fClassVersion(0), fClassInfo(nullptr),
1234 fTypeInfo(nullptr), fShowMembers(nullptr),
1235 fStreamer(nullptr), fIsA(nullptr), fGlobalIsA(nullptr), fIsAMethod(nullptr),
1236 fMerge(nullptr), fResetAfterMerge(nullptr), fNew(nullptr), fNewArray(nullptr), fDelete(nullptr), fDeleteArray(nullptr),
1237 fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fSizeof(-1),
1238 fCanSplit(-1), fIsSyntheticPair(kFALSE), fHasCustomStreamerMember(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1239 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1240 fState(kNoInfo),
1241 fCurrentInfo(nullptr), fLastReadInfo(nullptr), fRefProxy(nullptr),
1242 fSchemaRules(nullptr), fStreamerImpl(&TClass::StreamerDefault)
1243{
1245
1246 if (!gROOT)
1247 ::Fatal("TClass::TClass", "ROOT system not initialized");
1248
1249 fDeclFileLine = -2; // -2 for standalone TClass (checked in dtor)
1250
1252 if (!gInterpreter)
1253 ::Fatal("TClass::TClass", "gInterpreter not initialized");
1254
1255 if (!classInfo || !gInterpreter->ClassInfo_IsValid(classInfo)) {
1256 MakeZombie();
1257 fState = kNoInfo;
1258 } else {
1259 fName = gInterpreter->ClassInfo_FullName(classInfo);
1260
1262 Init(fName, cversion, nullptr, nullptr, dfil, ifil, dl, il, classInfo, silent);
1263 }
1265
1266 fConversionStreamerInfo = nullptr;
1267}
1268
1269
1270////////////////////////////////////////////////////////////////////////////////
1271/// Internal constructor.
1272///
1273/// \note Use `TClass::GetClass("class")` to get access to a TClass object for a certain class!
1274
1276 const char *dfil, const char *ifil, Int_t dl, Int_t il, Bool_t silent) :
1278 fPersistentRef(nullptr),
1279 fStreamerInfo(nullptr), fConversionStreamerInfo(nullptr), fRealData(nullptr),
1280 fBase(nullptr), fData(nullptr), fUsingData(nullptr), fEnums(nullptr), fFuncTemplate(nullptr), fMethod(nullptr), fAllPubData(nullptr),
1281 fAllPubMethod(nullptr), fClassMenuList(nullptr),
1282 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1283 fInstanceCount(0), fOnHeap(0),
1284 fCheckSum(0), fCollectionProxy(nullptr), fClassVersion(0), fClassInfo(nullptr),
1285 fTypeInfo(nullptr), fShowMembers(nullptr),
1286 fStreamer(nullptr), fIsA(nullptr), fGlobalIsA(nullptr), fIsAMethod(nullptr),
1287 fMerge(nullptr), fResetAfterMerge(nullptr), fNew(nullptr), fNewArray(nullptr), fDelete(nullptr), fDeleteArray(nullptr),
1288 fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fSizeof(-1),
1289 fCanSplit(-1), fIsSyntheticPair(kFALSE), fHasCustomStreamerMember(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1290 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1291 fState(kNoInfo),
1292 fCurrentInfo(nullptr), fLastReadInfo(nullptr), fRefProxy(nullptr),
1293 fSchemaRules(nullptr), fStreamerImpl(&TClass::StreamerDefault)
1294{
1296 Init(name,cversion, nullptr, nullptr, dfil, ifil, dl, il, nullptr, silent);
1297}
1298
1299////////////////////////////////////////////////////////////////////////////////
1300/// Internal constructor.
1301///
1302/// \note Use `TClass::GetClass("class")` to get access to a TClass object for a certain class!
1303
1305 const std::type_info &info, TVirtualIsAProxy *isa,
1306 const char *dfil, const char *ifil, Int_t dl, Int_t il,
1307 Bool_t silent) :
1309 fPersistentRef(nullptr),
1310 fStreamerInfo(nullptr), fConversionStreamerInfo(nullptr), fRealData(nullptr),
1311 fBase(nullptr), fData(nullptr), fUsingData(nullptr), fEnums(nullptr), fFuncTemplate(nullptr), fMethod(nullptr), fAllPubData(nullptr),
1312 fAllPubMethod(nullptr),
1313 fClassMenuList(nullptr),
1314 fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
1315 fInstanceCount(0), fOnHeap(0),
1316 fCheckSum(0), fCollectionProxy(nullptr), fClassVersion(0), fClassInfo(nullptr),
1317 fTypeInfo(nullptr), fShowMembers(nullptr),
1318 fStreamer(nullptr), fIsA(nullptr), fGlobalIsA(nullptr), fIsAMethod(nullptr),
1319 fMerge(nullptr), fResetAfterMerge(nullptr), fNew(nullptr), fNewArray(nullptr), fDelete(nullptr), fDeleteArray(nullptr),
1320 fDestructor(nullptr), fDirAutoAdd(nullptr), fStreamerFunc(nullptr), fConvStreamerFunc(nullptr), fSizeof(-1),
1321 fCanSplit(-1), fIsSyntheticPair(kFALSE), fHasCustomStreamerMember(kFALSE), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
1322 fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fRuntimeProperties(0), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
1323 fState(kHasTClassInit),
1324 fCurrentInfo(nullptr), fLastReadInfo(nullptr), fRefProxy(nullptr),
1325 fSchemaRules(nullptr), fStreamerImpl(&TClass::StreamerDefault)
1326{
1328 // use info
1329 Init(name, cversion, &info, isa, dfil, ifil, dl, il, nullptr, silent);
1330}
1331
1332////////////////////////////////////////////////////////////////////////////////
1333/// we found at least one equivalent.
1334/// let's force a reload
1335
1337{
1339
1340 if (oldcl->CanIgnoreTObjectStreamer()) {
1342 }
1343
1345 TIter next(oldcl->GetStreamerInfos());
1346 while ((info = (TVirtualStreamerInfo*)next())) {
1347 info->Clear("build");
1348 info->SetClass(this);
1349 if (IsSyntheticPair()) {
1350 // Some pair's StreamerInfo were inappropriately marked as versioned
1351 info->SetClassVersion(1);
1352 // There is already a TStreamerInfo put there by the synthetic
1353 // creation.
1355 } else {
1356 fStreamerInfo->AddAtAndExpand(info,info->GetClassVersion());
1357 }
1358 }
1359 oldcl->fStreamerInfo->Clear();
1360
1361 oldcl->ReplaceWith(this);
1362 delete oldcl;
1363}
1364
1365////////////////////////////////////////////////////////////////////////////////
1366/// Initialize a TClass object. This object contains the full dictionary
1367/// of a class. It has list to baseclasses, datamembers and methods.
1368/// The caller of this function should be holding the ROOT Write lock.
1369
1371 const std::type_info *typeinfo, TVirtualIsAProxy *isa,
1372 const char *dfil, const char *ifil, Int_t dl, Int_t il,
1374 Bool_t silent)
1375{
1376 if (!gROOT)
1377 ::Fatal("TClass::TClass", "ROOT system not initialized");
1378 if (!name || !name[0]) {
1379 ::Error("TClass::Init", "The name parameter is invalid (null or empty)");
1380 MakeZombie();
1381 return;
1382 }
1383 // Always strip the default STL template arguments (from any template argument or the class name)
1385 fName = name; // We can assume that the artificial class name is already normalized.
1386 else
1388
1390 fDeclFileName = dfil ? dfil : "";
1391 fImplFileName = ifil ? ifil : "";
1392 fDeclFileLine = dl;
1393 fImplFileLine = il;
1395 fIsA = isa;
1396 if ( fIsA ) fIsA->SetClass(this);
1397 // See also TCling::GenerateTClass() which will update fClassVersion after creation!
1398 fStreamerInfo = new TObjArray(fClassVersion+2+10,-1); // +10 to read new data by old
1399 fProperty = -1;
1400 fClassProperty = 0;
1401 const bool ispair = TClassEdit::IsStdPair(fName);
1402 if (ispair)
1404
1406
1407 TClass *oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(fName.Data());
1408
1410
1411 if (oldcl && oldcl->TestBit(kLoading)) {
1412 // Do not recreate a class while it is already being created!
1413
1414 // We can no longer reproduce this case, to check whether we are, we use
1415 // this code:
1416 // Fatal("Init","A bad replacement for %s was requested\n",name);
1417 return;
1418 }
1419
1420 TClass **persistentRef = nullptr;
1421 if (oldcl) {
1422
1423 persistentRef = oldcl->fPersistentRef.exchange(nullptr);
1424
1425 // The code from here is also in ForceReload.
1427 // move the StreamerInfo immediately so that there are
1428 // properly updated!
1429
1430 if (oldcl->CanIgnoreTObjectStreamer()) {
1432 }
1434
1435 TIter next(oldcl->GetStreamerInfos());
1436 while ((info = (TVirtualStreamerInfo*)next())) {
1437 // We need to force a call to BuildOld
1438 info->Clear("build");
1439 info->SetClass(this);
1440 fStreamerInfo->AddAtAndExpand(info,info->GetClassVersion());
1441 }
1442 oldcl->fStreamerInfo->Clear();
1443 // The code diverges here from ForceReload.
1444
1445 // Move the Schema Rules too.
1446 fSchemaRules = oldcl->fSchemaRules;
1447 oldcl->fSchemaRules = nullptr;
1448
1449 // Move the TFunctions.
1450 fFuncTemplate = oldcl->fFuncTemplate;
1451 if (fFuncTemplate)
1452 fFuncTemplate->fClass = this;
1453 oldcl->fFuncTemplate = nullptr;
1454 fMethod.store( oldcl->fMethod );
1455 if (fMethod)
1456 (*fMethod).fClass = this;
1457 oldcl->fMethod = nullptr;
1458
1459 }
1460
1462 // Advertise ourself as the loading class for this class name
1463 TClass::AddClass(this);
1464
1466
1467 if (!gInterpreter)
1468 ::Fatal("TClass::Init", "gInterpreter not initialized");
1469
1470 if (givenInfo) {
1471 bool invalid = !gInterpreter->ClassInfo_IsValid(givenInfo);
1472 bool notloaded = !gInterpreter->ClassInfo_IsLoaded(givenInfo);
1473 auto property = gInterpreter->ClassInfo_Property(givenInfo);
1474
1475 if (invalid || (notloaded && (property & kIsNamespace)) ||
1478 MakeZombie();
1479 fState = kNoInfo;
1480 TClass::RemoveClass(this);
1481 return;
1482 }
1483 }
1484
1485 if (!invalid) {
1486 fClassInfo = gInterpreter->ClassInfo_Factory(givenInfo);
1487 fCanLoadClassInfo = false; // avoids calls to LoadClassInfo() if info is already loaded
1488 if (fState <= kEmulated)
1490 }
1491 }
1492
1493 // We need to check if the class it is not fwd declared for the cases where we
1494 // created a TClass directly in the kForwardDeclared state. Indeed in those cases
1495 // fClassInfo will always be nullptr.
1497
1498 if (fState == kHasTClassInit) {
1499 // If the TClass is being generated from a ROOT dictionary,
1500 // even though we do not seem to have a CINT dictionary for
1501 // the class, we will will try to load it anyway UNLESS
1502 // the class is an STL container (or string).
1503 // This is because we do not expect the CINT dictionary
1504 // to be present for all STL classes (and we can handle
1505 // the lack of CINT dictionary in that cases).
1506 // However, the cling the dictionary no longer carries
1507 // an instantiation with it, unless we request the loading
1508 // here *or* the user explicitly instantiate the template
1509 // we would not have a ClassInfo for the template
1510 // instantiation.
1512 // Here we check and grab the info from the rootpcm.
1514 if (proto)
1515 proto->FillTClass(this);
1516 }
1517 if (!fHasRootPcmInfo && gInterpreter->CheckClassInfo(fName, /* autoload = */ kTRUE)) {
1518 gInterpreter->SetClassInfo(this, kFALSE, silent); // sets fClassInfo pointer
1519 if (fClassInfo) {
1520 // This should be moved out of GetCheckSum itself however the last time
1521 // we tried this cause problem, in particular in the end-of-process operation.
1522 // fCheckSum = GetCheckSum(kLatestCheckSum);
1523 } else {
1524 if (!fClassInfo) {
1525 if (IsZombie()) {
1526 TClass::RemoveClass(this);
1527 return;
1528 }
1529 }
1530 }
1531 }
1532 }
1535 if (fState == kHasTClassInit) {
1536 if (fImplFileLine == -1 && fClassVersion == 0) {
1537 // We have a 'transient' class with a ClassDefInline and apparently no interpreter
1538 // information. Since it is transient, it is more than likely that the lack
1539 // will be harmles.
1540 } else {
1541 ::Error("TClass::Init", "no interpreter information for class %s is available even though it has a TClass "
1542 "initialization routine.",
1543 fName.Data());
1544 }
1545 } else {
1547 if (!ispairbase)
1548 ::Warning("TClass::Init", "no dictionary for class %s is available", fName.Data());
1549 }
1550 }
1551
1552 fgClassCount++;
1554
1555 // Make the typedef-expanded -> original hash table entries.
1556 // There may be several entries for any given key.
1557 // We only make entries if the typedef-expanded name
1558 // is different from the original name.
1560 if (!givenInfo && strchr (name, '<')) {
1561 if ( fName != name) {
1562 if (!fgClassTypedefHash) {
1563 fgClassTypedefHash = new THashTable (100, 5);
1564 fgClassTypedefHash->SetOwner (kTRUE);
1565 }
1566
1567 fgClassTypedefHash->Add (new TNameMapNode (name, fName));
1569
1570 }
1572 if (resolvedThis != name) {
1573 if (!fgClassTypedefHash) {
1574 fgClassTypedefHash = new THashTable (100, 5);
1575 fgClassTypedefHash->SetOwner (kTRUE);
1576 }
1577
1578 fgClassTypedefHash->Add (new TNameMapNode (resolvedThis, fName));
1580 }
1581
1582 }
1583
1584 //In case a class with the same name had been created by TVirtualStreamerInfo
1585 //we must delete the old class, importing only the StreamerInfo structure
1586 //from the old dummy class.
1587 if (oldcl) {
1588
1589 oldcl->ReplaceWith(this);
1590 delete oldcl;
1591
1592 } else if (!givenInfo && resolvedThis.Length() > 0 && fgClassTypedefHash) {
1593
1594 // Check for existing equivalent.
1595
1596 if (resolvedThis != fName) {
1597 oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(resolvedThis);
1598 if (oldcl && oldcl != this) {
1599 persistentRef = oldcl->fPersistentRef.exchange(nullptr);
1601 }
1602 }
1603 TIter next( fgClassTypedefHash->GetListForObject(resolvedThis) );
1604 while ( TNameMapNode* htmp = static_cast<TNameMapNode*> (next()) ) {
1605 if (resolvedThis != htmp->String()) continue;
1606 oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(htmp->fOrigName); // gROOT->GetClass (htmp->fOrigName, kFALSE);
1607 if (oldcl && oldcl != this) {
1608 persistentRef = oldcl->fPersistentRef.exchange(nullptr);
1610 }
1611 }
1612 }
1613 if (fClassInfo) {
1615 if ( fDeclFileName == nullptr || fDeclFileName[0] == '\0' ) {
1617 // Missing interface:
1618 // fDeclFileLine = gInterpreter->ClassInfo_FileLine( fClassInfo );
1619
1620 // But really do not want to set ImplFileLine as it is currently the
1621 // marker of being 'loaded' or not (reminder loaded == has a TClass bootstrap).
1622 }
1623 }
1624
1625 if (persistentRef) {
1627 } else {
1628 fPersistentRef = new TClass*;
1629 }
1630 *fPersistentRef = this;
1631
1632 if ( isStl || !strncmp(GetName(),"stdext::hash_",13) || !strncmp(GetName(),"__gnu_cxx::hash_",16) ) {
1633 if (fState != kHasTClassInit) {
1634 // If we have a TClass compiled initialization, we can safely assume that
1635 // there will also be a collection proxy.
1637 if (fCollectionProxy) {
1639
1640 // Numeric Collections have implicit conversions:
1642
1643 } else if (!silent) {
1644 Warning("Init","Collection proxy for %s was not properly initialized!",GetName());
1645 }
1646 if (fStreamer==nullptr) {
1647 fStreamer = TVirtualStreamerInfo::Factory()->GenEmulatedClassStreamer( GetName(), silent );
1648 }
1649 }
1650 } else if (TClassEdit::IsStdPair(GetName())) {
1651 // std::pairs have implicit conversions
1653 }
1654
1656}
1657
1658////////////////////////////////////////////////////////////////////////////////
1659/// TClass dtor. Deletes all list that might have been created.
1660
1662{
1664
1665 // Remove from the typedef hashtables.
1668 TIter next (fgClassTypedefHash->GetListForObject (resolvedThis));
1669 while ( TNameMapNode* htmp = static_cast<TNameMapNode*> (next()) ) {
1670 if (resolvedThis == htmp->String() && htmp->fOrigName == GetName()) {
1671 fgClassTypedefHash->Remove (htmp);
1672 delete htmp;
1673 break;
1674 }
1675 }
1676 }
1677
1678 // Not owning lists, don't call Delete()
1679 // But this still need to be done first because the TList destructor
1680 // does access the object contained (via GetObject()->TestBit(kCanDelete))
1681 delete fStreamer; fStreamer =nullptr;
1682 delete fAllPubData; fAllPubData =nullptr;
1683 delete fAllPubMethod; fAllPubMethod=nullptr;
1684
1685 delete fPersistentRef.load();
1686
1687 if (fBase.load())
1688 (*fBase).Delete();
1689 delete fBase.load(); fBase = nullptr;
1690
1691 if (fData.load())
1692 (*fData).Delete();
1693 delete fData.load(); fData = nullptr;
1694
1695 if (fUsingData.load())
1696 (*fUsingData).Delete();
1697 delete fUsingData.load(); fUsingData = nullptr;
1698
1699 if (fEnums.load())
1700 (*fEnums).Delete();
1701 delete fEnums.load(); fEnums = nullptr;
1702
1703 if (fFuncTemplate)
1705 delete fFuncTemplate; fFuncTemplate = nullptr;
1706
1707 if (fMethod.load())
1708 (*fMethod).Delete();
1709 delete fMethod.load(); fMethod=nullptr;
1710
1711 if (fRealData)
1712 fRealData->Delete();
1713 delete fRealData; fRealData=nullptr;
1714
1715 if (fStreamerInfo)
1717 delete fStreamerInfo; fStreamerInfo = nullptr;
1718
1719 if (fDeclFileLine >= -1)
1720 TClass::RemoveClass(this);
1721
1723 fClassInfo=nullptr;
1724
1725 if (fClassMenuList)
1727 delete fClassMenuList; fClassMenuList=nullptr;
1728
1730
1731 if ( fIsA ) delete fIsA;
1732
1733 if ( fRefProxy ) fRefProxy->Release();
1734 fRefProxy = nullptr;
1735
1736 delete fStreamer;
1737 delete fCollectionProxy;
1738 delete fIsAMethod.load();
1739 delete fSchemaRules;
1740 if (fConversionStreamerInfo.load()) {
1741 std::map<std::string, TObjArray*>::iterator it;
1742 std::map<std::string, TObjArray*>::iterator end = (*fConversionStreamerInfo).end();
1743 for( it = (*fConversionStreamerInfo).begin(); it != end; ++it ) {
1744 delete it->second;
1745 }
1746 delete fConversionStreamerInfo.load();
1747 }
1748}
1749
1750////////////////////////////////////////////////////////////////////////////////
1751
1752namespace {
1754 {
1755 // Read a class.rules file which contains one rule per line with comment
1756 // starting with a #
1757 // Returns the number of rules loaded.
1758 // Returns -1 in case of error.
1759
1760 R__ASSERT(f!=nullptr);
1761 TString rule(1024);
1762 int c, state = 0;
1763 Int_t count = 0;
1764
1765 while ((c = fgetc(f)) != EOF) {
1766 if (c == 13) // ignore CR
1767 continue;
1768 if (c == '\n') {
1769 if (state != 3) {
1770 state = 0;
1771 if (rule.Length() > 0) {
1772 if (TClass::AddRule(rule)) {
1773 ++count;
1774 }
1775 rule.Clear();
1776 }
1777 }
1778 continue;
1779 }
1780 switch (state) {
1781 case 0: // start of line
1782 switch (c) {
1783 case ' ':
1784 case '\t':
1785 break;
1786 case '#':
1787 state = 1;
1788 break;
1789 default:
1790 state = 2;
1791 break;
1792 }
1793 break;
1794
1795 case 1: // comment
1796 break;
1797
1798 case 2: // rule
1799 switch (c) {
1800 case '\\':
1801 state = 3; // Continuation request
1802 default:
1803 break;
1804 }
1805 break;
1806 }
1807 switch (state) {
1808 case 2:
1809 rule.Append(c);
1810 break;
1811 }
1812 }
1813 return count;
1814 }
1815}
1816
1817////////////////////////////////////////////////////////////////////////////////
1818/// Read the class.rules files from the default location:.
1819/// $ROOTSYS/etc/class.rules (or ROOTETCDIR/class.rules)
1820
1822{
1823 static const char *suffix = "class.rules";
1826
1827 Int_t res = -1;
1828
1829 FILE * f = fopen(sname,"r");
1830 if (f != nullptr) {
1831 res = ReadRulesContent(f);
1832 fclose(f);
1833 } else {
1834 ::Error("TClass::ReadRules()", "Cannot find rules file %s", sname.Data());
1835 }
1836 return res;
1837}
1838
1839////////////////////////////////////////////////////////////////////////////////
1840/// Read a class.rules file which contains one rule per line with comment
1841/// starting with a #
1842/// - Returns the number of rules loaded.
1843/// - Returns -1 in case of error.
1844
1846{
1847 if (!filename || !filename[0]) {
1848 ::Error("TClass::ReadRules", "no file name specified");
1849 return -1;
1850 }
1851
1852 FILE * f = fopen(filename,"r");
1853 if (f == nullptr) {
1854 ::Error("TClass::ReadRules","Failed to open %s\n",filename);
1855 return -1;
1856 }
1857 Int_t count = ReadRulesContent(f);
1858
1859 fclose(f);
1860 return count;
1861
1862}
1863
1864////////////////////////////////////////////////////////////////////////////////
1865/// Add a schema evolution customization rule.
1866/// The syntax of the rule can be either the short form:
1867/// ~~~ {.cpp}
1868/// [type=Read] classname membername [attributes=... ] [version=[...] ] [checksum=[...] ] [oldtype=...] [code={...}]
1869/// ~~~
1870/// or the long form
1871/// ~~~ {.cpp}
1872/// [type=Read] sourceClass=classname [targetclass=newClassname] [ source="type membername; [type2 membername2]" ]
1873/// [target="membername3;membername4"] [attributes=... ] [version=...] [checksum=...] [code={...}|functionname]
1874/// ~~~
1875///
1876/// For example to set HepMC::GenVertex::m_event to _not_ owned the object it is pointing to:
1877/// HepMC::GenVertex m_event attributes=NotOwner
1878///
1879/// Semantic of the tags:
1880/// - type : the type of the rule, valid values: Read, ReadRaw, Write, WriteRaw, the default is 'Read'.
1881/// - sourceClass : the name of the class as it is on the rule file
1882/// - targetClass : the name of the class as it is in the current code ; defaults to the value of sourceClass
1883/// - source : the types and names of the data members from the class on file that are needed, the list is separated by semi-colons ';'
1884/// - oldtype: in the short form only, indicates the type on disk of the data member.
1885/// - target : the names of the data members updated by this rule, the list is separated by semi-colons ';'
1886/// - attributes : list of possible qualifiers among: Owner, NotOwner
1887/// - 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]
1888/// - checksum : comma delimited list of the checksums of the class layout that this rule applies to.
1889/// - code={...} : code to be executed for the rule or name of the function implementing it.
1890
1892{
1894 if (! ruleobj->SetFromRule( rule ) ) {
1895 delete ruleobj;
1896 return kFALSE;
1897 }
1898
1900
1901 TClass *cl = TClass::GetClass( ruleobj->GetTargetClass() );
1902 if (!cl) {
1903 // Create an empty emulated class for now.
1904 cl = gInterpreter->GenerateTClass(ruleobj->GetTargetClass(), /* emulation = */ kTRUE, /*silent = */ kTRUE);
1905 }
1907
1910 ::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).",
1911 ruleobj->GetTargetClass(), ruleobj->GetVersion(), ruleobj->GetTargetString(), errmsg.Data() );
1912 delete ruleobj;
1913 return kFALSE;
1914 }
1915 return kTRUE;
1916}
1917
1918////////////////////////////////////////////////////////////////////////////////
1919/// Adopt a new set of Data Model Evolution rules.
1920
1929
1930////////////////////////////////////////////////////////////////////////////////
1931/// Return the set of the schema rules if any.
1932
1937
1938////////////////////////////////////////////////////////////////////////////////
1939/// Return the set of the schema rules if any.
1940/// If create is true, create an empty set
1941
1950
1951////////////////////////////////////////////////////////////////////////////////
1952
1953void TClass::AddImplFile(const char* filename, int line) {
1954 // Currently reset the implementation file and line.
1955 // In the close future, it will actually add this file and line
1956 // to a "list" of implementation files.
1957
1960}
1961
1962////////////////////////////////////////////////////////////////////////////////
1963/// Browse external object inherited from TObject.
1964/// It passes through inheritance tree and calls TBrowser::Add
1965/// in appropriate cases. Static function.
1966
1968{
1969 if (!obj) return 0;
1970
1972 obj->ShowMembers(insp);
1973 return insp.fCount;
1974}
1975
1976////////////////////////////////////////////////////////////////////////////////
1977/// Browse objects of of the class described by this TClass object.
1978
1979Int_t TClass::Browse(void *obj, TBrowser *b) const
1980{
1981 if (!obj) return 0;
1982
1984 if (IsTObject()) {
1985 // Call TObject::Browse.
1986
1987 if (!fIsOffsetStreamerSet) {
1989 }
1990 TObject* realTObject = (TObject*)((size_t)obj + fOffsetStreamer);
1991 realTObject->Browse(b);
1992 return 1;
1993 } else if (actual != this) {
1994 return actual->Browse(obj, b);
1995 } else if (GetCollectionProxy()) {
1996
1997 // do something useful.
1998
1999 } else {
2002 return insp.fCount;
2003 }
2004
2005 return 0;
2006}
2007
2008////////////////////////////////////////////////////////////////////////////////
2009/// This method is called by a browser to get the class information.
2010
2012{
2013 if (!HasInterpreterInfo()) return;
2014
2015 if (b) {
2016 if (!fRealData) BuildRealData();
2017
2018 b->Add(GetListOfDataMembers(), "Data Members");
2019 b->Add(GetListOfRealData(), "Real Data Members");
2020 b->Add(GetListOfMethods(), "Methods");
2021 b->Add(GetListOfBases(), "Base Classes");
2022 }
2023}
2024
2025////////////////////////////////////////////////////////////////////////////////
2026/// Build a full list of persistent data members.
2027/// Scans the list of all data members in the class itself and also
2028/// in all base classes. For each persistent data member, inserts a
2029/// TRealData object in the list fRealData.
2030///
2031
2033{
2034
2036
2037 // Only do this once.
2038 if (fRealData) {
2039 return;
2040 }
2041
2042 if (fClassVersion == 0) {
2044 }
2045
2046 // When called via TMapFile (e.g. Update()) make sure that the dictionary
2047 // gets allocated on the heap and not in the mapped file.
2048 TMmallocDescTemp setreset;
2049
2050 // Handle emulated classes and STL containers specially.
2052 // We are an emulated class or an STL container.
2053 fRealData = new TList;
2054 BuildEmulatedRealData("", 0, this, isTransient);
2055 return;
2056 }
2057
2058 // return early on string
2059 static TClassRef clRefString("std::string");
2060 if (clRefString == this) {
2061 return;
2062 }
2063
2064 // Complain about stl classes ending up here (unique_ptr etc) - except for
2065 // pair where we will build .first, .second just fine
2066 // and those for which the user explicitly requested a dictionary.
2070 Error("BuildRealData", "Inspection for %s not supported!", GetName());
2071 }
2072
2073 // The following statement will recursively call
2074 // all the subclasses of this class.
2075 fRealData = new TList;
2076 TBuildRealData brd(pointer, this);
2077
2078 // CallShowMember will force a call to InheritsFrom, which indirectly
2079 // calls TClass::GetClass. It forces the loading of new typedefs in
2080 // case some of them were not yet loaded.
2081 if ( ! CallShowMembers(pointer, brd, isTransient) ) {
2082 if ( isTransient ) {
2083 // This is a transient data member, so it is probably fine to not have
2084 // access to its content. However let's no mark it as definitively setup,
2085 // since another class might use this class for a persistent data member and
2086 // in this case we really want the error message.
2087 delete fRealData;
2088 fRealData = nullptr;
2089 } else {
2090 Error("BuildRealData", "Cannot find any ShowMembers function for %s!", GetName());
2091 }
2092 }
2093
2094 // Take this opportunity to build the real data for base classes.
2095 // In case one base class is abstract, it would not be possible later
2096 // to create the list of real data for this abstract class.
2097 TBaseClass* base = nullptr;
2098 TIter next(GetListOfBases());
2099 while ((base = (TBaseClass*) next())) {
2100 if (base->IsSTLContainer()) {
2101 continue;
2102 }
2103 TClass* c = base->GetClassPointer();
2104 if (c) {
2105 c->BuildRealData(nullptr, isTransient);
2106 }
2107 }
2108}
2109
2110////////////////////////////////////////////////////////////////////////////////
2111/// Build the list of real data for an emulated class
2112
2114{
2116
2118 if (Property() & kIsAbstract) {
2120 } else {
2122 }
2123 if (!info) {
2124 // This class is abstract, but we don't yet have a SteamerInfo for it ...
2125 Error("BuildEmulatedRealData","Missing StreamerInfo for %s",GetName());
2126 // Humm .. no information ... let's bail out
2127 return;
2128 }
2129
2130 TIter next(info->GetElements());
2132 while ((element = (TStreamerElement*)next())) {
2133 Int_t etype = element->GetType();
2134 Longptr_t eoffset = element->GetOffset();
2135 TClass *cle = element->GetClassPointer();
2136 if (element->IsBase() || etype == TVirtualStreamerInfo::kBase) {
2137 //base class are skipped in this loop, they will be added at the end.
2138 continue;
2139 } else if (etype == TVirtualStreamerInfo::kTObject ||
2142 etype == TVirtualStreamerInfo::kAny) {
2143 //member class
2144 TString rdname; rdname.Form("%s%s",name,element->GetFullName());
2145 TRealData *rd = new TRealData(rdname,offset+eoffset,nullptr);
2146 if (gDebug > 0) printf(" Class: %s, adding TRealData=%s, offset=%ld\n",cl->GetName(),rd->GetName(),rd->GetThisOffset());
2147 cl->GetListOfRealData()->Add(rd);
2148 // Now we a dot
2149 rdname.Form("%s%s.",name,element->GetFullName());
2150 if (cle) cle->BuildEmulatedRealData(rdname,offset+eoffset,cl, isTransient);
2151 } else {
2152 //others
2153 TString rdname; rdname.Form("%s%s",name,element->GetFullName());
2154 TRealData *rd = new TRealData(rdname,offset+eoffset,nullptr);
2155 if (gDebug > 0) printf(" Class: %s, adding TRealData=%s, offset=%ld\n",cl->GetName(),rd->GetName(),rd->GetThisOffset());
2156 cl->GetListOfRealData()->Add(rd);
2157 }
2158 //if (fClassInfo==0 && element->IsBase()) {
2159 // if (fBase==0) fBase = new TList;
2160 // TClass *base = element->GetClassPointer();
2161 // fBase->Add(new TBaseClass(this, cl, eoffset));
2162 //}
2163 }
2164 // The base classes must added last on the list of real data (to help with ambiguous data member names)
2165 next.Reset();
2166 while ((element = (TStreamerElement*)next())) {
2167 Int_t etype = element->GetType();
2168 if (element->IsBase() || etype == TVirtualStreamerInfo::kBase) {
2169 //base class
2170 Longptr_t eoffset = element->GetOffset();
2171 TClass *cle = element->GetClassPointer();
2172 if (cle) cle->BuildEmulatedRealData(name,offset+eoffset,cl, isTransient);
2173 }
2174 }
2175}
2176
2177
2178////////////////////////////////////////////////////////////////////////////////
2179/// Calculate the offset between an object of this class to
2180/// its base class TObject. The pointer can be adjusted by
2181/// that offset to access any virtual method of TObject like
2182/// Streamer() and ShowMembers().
2183
2185{
2188 // When called via TMapFile (e.g. Update()) make sure that the dictionary
2189 // gets allocated on the heap and not in the mapped file.
2190
2191 TMmallocDescTemp setreset;
2193 if (fStreamerType == kTObject) {
2195 }
2197 }
2198}
2199
2200
2201////////////////////////////////////////////////////////////////////////////////
2202/// Call ShowMembers() on the obj of this class type, passing insp and parent.
2203/// isATObject is -1 if unknown, 0 if it is not a TObject, and 1 if it is a TObject.
2204/// The function returns whether it was able to call ShowMembers().
2205
2207{
2208 if (fShowMembers) {
2209 // This should always works since 'pointer' should be pointing
2210 // to an object of the actual type of this TClass object.
2212 return kTRUE;
2213 } else {
2214
2216 if (fClassInfo) {
2217
2218 if (strcmp(GetName(), "string") == 0) {
2219 // For std::string we know that we do not have a ShowMembers
2220 // function and that it's okay.
2221 return kTRUE;
2222 }
2223 // Since we do have some dictionary information, let's
2224 // call the interpreter's ShowMember.
2225 // This works with Cling to support interpreted classes.
2226 gInterpreter->InspectMembers(insp, obj, this, isTransient);
2227 return kTRUE;
2228
2229 } else if (TVirtualStreamerInfo* sinfo = GetStreamerInfo()) {
2230 sinfo->CallShowMembers(obj, insp, isTransient);
2231 return kTRUE;
2232 } // isATObject
2233 } // fShowMembers is set
2234
2235 return kFALSE;
2236}
2237
2238////////////////////////////////////////////////////////////////////////////////
2239/// Do a ShowMembers() traversal of all members and base classes' members
2240/// using the reflection information from the interpreter. Works also for
2241/// interpreted objects.
2242
2244{
2245 return gInterpreter->InspectMembers(insp, obj, this, isTransient);
2246}
2247
2249{
2250 if (fCanSplit >= 0) {
2251 return ! ( fCanSplit & 0x2 );
2252 }
2253
2255
2256 if (GetCollectionProxy() != nullptr) {
2257 // A collection can never affect its derived class 'splittability'
2258 return kTRUE;
2259 }
2260
2261 if (this == TRef::Class()) { fCanSplit = 2; return kFALSE; }
2262 if (this == TRefArray::Class()) { fCanSplit = 2; return kFALSE; }
2263 if (this == TArray::Class()) { fCanSplit = 2; return kFALSE; }
2264 if (this == TClonesArray::Class()) { fCanSplit = 1; return kTRUE; }
2265 if (this == TCollection::Class()) { fCanSplit = 2; return kFALSE; }
2266
2267 // TTree is not always available (for example in rootcling), so we need
2268 // to grab it silently.
2269 auto refTreeClass( TClass::GetClass("TTree",kTRUE,kTRUE) );
2270 if (this == refTreeClass) { fCanSplit = 2; return kFALSE; }
2271
2272 if (!HasDataMemberInfo()) {
2273 TVirtualStreamerInfo *sinfo = ((TClass *)this)->GetCurrentStreamerInfo();
2274 if (sinfo==nullptr) sinfo = GetStreamerInfo();
2275 TIter next(sinfo->GetElements());
2277 while ((element = (TStreamerElement*)next())) {
2278 if (element->IsA() == TStreamerBase::Class()) {
2279 TClass *clbase = element->GetClassPointer();
2280 if (!clbase) {
2281 // If there is a missing base class, we can't split the immediate
2282 // derived class.
2283 fCanSplit = 0;
2284 return kFALSE;
2285 } else if (!clbase->CanSplitBaseAllow()) {
2286 fCanSplit = 2;
2287 return kFALSE;
2288 }
2289 }
2290 }
2291 }
2292
2293 // If we don't have data member info there is no more information
2294 // we can find out.
2295 if (!HasDataMemberInfo()) return kTRUE;
2296
2297 TObjLink *lnk = GetListOfBases() ? fBase.load()->FirstLink() : nullptr;
2298
2299 // Look at inheritance tree
2300 while (lnk) {
2301 TBaseClass *base = (TBaseClass*) lnk->GetObject();
2302 TClass *c = base->GetClassPointer();
2303 if(!c) {
2304 // If there is a missing base class, we can't split the immediate
2305 // derived class.
2306 fCanSplit = 0;
2307 return kFALSE;
2308 } else if (!c->CanSplitBaseAllow()) {
2309 fCanSplit = 2;
2310 return kFALSE;
2311 }
2312 lnk = lnk->Next();
2313 }
2314 return kTRUE;
2315}
2316
2317////////////////////////////////////////////////////////////////////////////////
2318/// Return true if the data member of this TClass can be saved separately.
2319
2321{
2322 // Note: add the possibility to set it for the class and the derived class.
2323 // save the info in TVirtualStreamerInfo
2324 // deal with the info in MakeProject
2325 if (fCanSplit >= 0) {
2326 // The user explicitly set the value
2327 return (fCanSplit & 0x1) == 1;
2328 }
2329
2331 TClass *This = const_cast<TClass*>(this);
2332
2333 if (this == TObject::Class()) { This->fCanSplit = 1; return kTRUE; }
2334 if (fName == "TClonesArray") { This->fCanSplit = 1; return kTRUE; }
2335 if (fRefProxy) { This->fCanSplit = 0; return kFALSE; }
2336 if (fName.BeginsWith("TVectorT<")) { This->fCanSplit = 0; return kFALSE; }
2337 if (fName.BeginsWith("TMatrixT<")) { This->fCanSplit = 0; return kFALSE; }
2338 if (fName == "string") { This->fCanSplit = 0; return kFALSE; }
2339 if (fName == "std::string") { This->fCanSplit = 0; return kFALSE; }
2340
2341 if (GetCollectionProxy()!=nullptr) {
2342 // For STL collection we need to look inside.
2343
2344 // However we do not split collections of collections
2345 // nor collections of strings
2346 // nor collections of pointers (unless explicit request (see TBranchSTL)).
2347
2348 if (GetCollectionProxy()->HasPointers()) { This->fCanSplit = 0; return kFALSE; }
2349
2351 if (valueClass == nullptr) { This->fCanSplit = 0; return kFALSE; }
2352 static TClassRef stdStringClass("std::string");
2354 { This->fCanSplit = 0; return kFALSE; }
2355 if (!valueClass->CanSplit()) { This->fCanSplit = 0; return kFALSE; }
2356 if (valueClass->GetCollectionProxy() != nullptr) { This->fCanSplit = 0; return kFALSE; }
2357
2358 This->fCanSplit = 1;
2359 return kTRUE;
2360
2361 }
2362
2363 if (GetStreamer() != nullptr || fStreamerFunc != nullptr) {
2364
2365 // We have an external custom streamer provided by the user, we must not
2366 // split it.
2367 This->fCanSplit = 0;
2368 return kFALSE;
2369
2370 } else if ( fHasCustomStreamerMember ) {
2371
2372 // We have a custom member function streamer or
2373 // an older (not StreamerInfo based) automatic streamer.
2374 This->fCanSplit = 0;
2375 return kFALSE;
2376 }
2377
2378 if (Size()==1) {
2379 // 'Empty' class there is nothing to split!.
2380 This->fCanSplit = 0;
2381 return kFALSE;
2382 }
2383
2384
2385 if ( !This->CanSplitBaseAllow() ) {
2386 return kFALSE;
2387 }
2388
2389 This->fCanSplit = 1;
2390 return kTRUE;
2391}
2392
2393////////////////////////////////////////////////////////////////////////////////
2394/// Return the C++ property of this class, eg. is abstract, has virtual base
2395/// class, see EClassProperty in TDictionary.h
2396
2398{
2399 if (fProperty == -1) Property();
2400 return fClassProperty;
2401}
2402
2403////////////////////////////////////////////////////////////////////////////////
2404/// Create a Clone of this TClass object using a different name but using the same 'dictionary'.
2405/// This effectively creates a hard alias for the class name.
2406
2407TObject *TClass::Clone(const char *new_name) const
2408{
2409 if (new_name == nullptr || new_name[0]=='\0' || fName == new_name) {
2410 Error("Clone","The name of the class must be changed when cloning a TClass object.");
2411 return nullptr;
2412 }
2413
2414 // Need to lock access to TROOT::GetListOfClasses so the cloning happens atomically
2416 // Temporarily remove the original from the list of classes.
2417 TClass::RemoveClass(const_cast<TClass*>(this));
2418
2419 TClass *copy;
2420 if (fTypeInfo) {
2421 copy = new TClass(GetName(),
2423 *fTypeInfo,
2424 new TIsAProxy(*fTypeInfo),
2428 GetImplFileLine());
2429 } else {
2430 copy = new TClass(GetName(),
2435 GetImplFileLine());
2436 }
2437 copy->fShowMembers = fShowMembers;
2438 // Remove the copy before renaming it
2439 TClass::RemoveClass(copy);
2440 copy->fName = new_name;
2441 TClass::AddClass(copy);
2442
2443 copy->SetNew(fNew);
2444 copy->SetNewArray(fNewArray);
2445 copy->SetDelete(fDelete);
2451 if (fStreamer) {
2453 }
2454 // If IsZombie is true, something went wrong and we will not be
2455 // able to properly copy the collection proxy
2456 if (fCollectionProxy && !copy->IsZombie()) {
2458 }
2459 copy->SetClassSize(fSizeof);
2460 if (fRefProxy) {
2462 }
2463 TClass::AddClass(const_cast<TClass*>(this));
2464 return copy;
2465}
2466
2467////////////////////////////////////////////////////////////////////////////////
2468/// Replaces the collection proxy for this class. The provided object is cloned
2469/// and the copy is then owned by `TClass`.
2470
2472{
2473// // This code was used too quickly test the STL Emulation layer
2474// Int_t k = TClassEdit::IsSTLCont(GetName());
2475// if (k==1||k==-1) return;
2476
2477 delete fCollectionProxy;
2478 fCollectionProxy = orig.Generate();
2479}
2480
2481////////////////////////////////////////////////////////////////////////////////
2482/// Draw detailed class inheritance structure.
2483/// If a class B inherits from a class A, the description of B is drawn
2484/// on the right side of the description of A.
2485/// Member functions overridden by B are shown in class A with a blue line
2486/// erasing the corresponding member function
2487
2489{
2490 if (!HasInterpreterInfo()) return;
2491
2493
2494 // Should we create a new canvas?
2495 TString opt = option;
2496 if (!ctxt.GetSaved() || !opt.Contains("same")) {
2497 TVirtualPad *padclass = (TVirtualPad*)(gROOT->GetListOfCanvases())->FindObject("R__class");
2498 if (!padclass) {
2499 gROOT->ProcessLine("new TCanvas(\"R__class\",\"class\",20,20,1000,750);");
2500 } else {
2501 padclass->cd();
2502 }
2503 }
2504
2505 if (gPad)
2506 gPad->DrawClassObject(this,option);
2507}
2508
2509////////////////////////////////////////////////////////////////////////////////
2510/// Dump contents of object on stdout.
2511/// Using the information in the object dictionary
2512/// each data member is interpreted.
2513/// If a data member is a pointer, the pointer value is printed
2514/// 'obj' is assume to point to an object of the class describe by this TClass
2515///
2516/// The following output is the Dump of a TArrow object:
2517/// ~~~ {.cpp}
2518/// fAngle 0 Arrow opening angle (degrees)
2519/// fArrowSize 0.2 Arrow Size
2520/// fOption.*fData
2521/// fX1 0.1 X of 1st point
2522/// fY1 0.15 Y of 1st point
2523/// fX2 0.67 X of 2nd point
2524/// fY2 0.83 Y of 2nd point
2525/// fUniqueID 0 object unique identifier
2526/// fBits 50331648 bit field status word
2527/// fLineColor 1 line color
2528/// fLineStyle 1 line style
2529/// fLineWidth 1 line width
2530/// fFillColor 19 fill area color
2531/// fFillStyle 1001 fill area style
2532/// ~~~
2533///
2534/// If noAddr is true, printout of all pointer values is skipped.
2535
2536void TClass::Dump(const void *obj, Bool_t noAddr /*=kFALSE*/) const
2537{
2538
2539 Longptr_t prObj = noAddr ? 0 : (Longptr_t)obj;
2540 if (IsTObject()) {
2541 if (!fIsOffsetStreamerSet) {
2543 }
2545
2546
2547 if (sizeof(this) == 4)
2548 Printf("==> Dumping object at: 0x%08lx, name=%s, class=%s\n",prObj,tobj->GetName(),GetName());
2549 else
2550 Printf("==> Dumping object at: 0x%016lx, name=%s, class=%s\n",prObj,tobj->GetName(),GetName());
2551 } else {
2552
2553 if (sizeof(this) == 4)
2554 Printf("==> Dumping object at: 0x%08lx, class=%s\n",prObj,GetName());
2555 else
2556 Printf("==> Dumping object at: 0x%016lx, class=%s\n",prObj,GetName());
2557 }
2558
2559 TDumpMembers dm(noAddr);
2560 if (!CallShowMembers(obj, dm, kFALSE)) {
2561 Info("Dump", "No ShowMembers function, dumping disabled");
2562 }
2563}
2564
2565////////////////////////////////////////////////////////////////////////////////
2566/// Introduce an escape character (@) in front of a special chars.
2567/// You need to use the result immediately before it is being overwritten.
2568
2569char *TClass::EscapeChars(const char *text) const
2570{
2571 static const UInt_t maxsize = 255;
2572 static char name[maxsize+2]; //One extra if last char needs to be escaped
2573
2574 UInt_t nch = text ? strlen(text) : 0;
2575 UInt_t icur = 0;
2576 for (UInt_t i = 0; i < nch && icur < maxsize; ++i, ++icur) {
2577 if (text[i] == '\"' || text[i] == '[' || text[i] == '~' ||
2578 text[i] == ']' || text[i] == '&' || text[i] == '#' ||
2579 text[i] == '!' || text[i] == '^' || text[i] == '<' ||
2580 text[i] == '?' || text[i] == '>') {
2581 name[icur] = '@';
2582 ++icur;
2583 }
2584 name[icur] = text[i];
2585 }
2586 name[icur] = 0;
2587 return name;
2588}
2589
2590////////////////////////////////////////////////////////////////////////////////
2591/// Return a pointer to the real class of the object.
2592/// This is equivalent to object->IsA() when the class has a ClassDef.
2593/// It is REQUIRED that object is coming from a proper pointer to the
2594/// class represented by 'this'.
2595/// Example: Special case:
2596/// ~~~ {.cpp}
2597/// class MyClass : public AnotherClass, public TObject
2598/// ~~~
2599/// then on return, one must do:
2600/// ~~~ {.cpp}
2601/// TObject *obj = (TObject*)((void*)myobject)directory->Get("some object of MyClass");
2602/// MyClass::Class()->GetActualClass(obj); // this would be wrong!!!
2603/// ~~~
2604/// Also if the class represented by 'this' and NONE of its parents classes
2605/// have a virtual ptr table, the result will be 'this' and NOT the actual
2606/// class.
2607
2608TClass *TClass::GetActualClass(const void *object) const
2609{
2610 if (!object)
2611 return (TClass*)this;
2612 if (fIsA) {
2613 return (*fIsA)(object); // ROOT::IsA((ThisClass*)object);
2614 } else if (fGlobalIsA) {
2615 return fGlobalIsA(this,object);
2616 } else {
2617 if (IsTObject()) {
2618
2619 if (!fIsOffsetStreamerSet) {
2621 }
2622 TObject* realTObject = (TObject*)((size_t)object + fOffsetStreamer);
2623
2624 return realTObject->IsA();
2625 }
2626
2627 if (HasInterpreterInfo()) {
2628
2629 TVirtualIsAProxy *isa = nullptr;
2631 isa = (TVirtualIsAProxy*)gROOT->ProcessLineFast(TString::Format("new ::TInstrumentedIsAProxy<%s>(0);",GetName()));
2632 }
2633 else {
2634 isa = (TVirtualIsAProxy*)gROOT->ProcessLineFast(TString::Format("new ::TIsAProxy(typeid(%s));",GetName()));
2635 }
2636 if (isa) {
2638 const_cast<TClass*>(this)->fIsA = isa;
2639 }
2640 if (fIsA) {
2641 return (*fIsA)(object); // ROOT::IsA((ThisClass*)object);
2642 }
2643 }
2645 if (sinfo) {
2646 return sinfo->GetActualClass(object);
2647 }
2648 return (TClass*)this;
2649 }
2650}
2651
2652////////////////////////////////////////////////////////////////////////////////
2653/// Return pointer to the base class "classname". Returns 0 in case
2654/// "classname" is not a base class. Takes care of multiple inheritance.
2655
2656TClass *TClass::GetBaseClass(const char *classname)
2657{
2658 // check if class name itself is equal to classname
2659 if (strcmp(GetName(), classname) == 0) return this;
2660
2661 if (!HasDataMemberInfo()) return nullptr;
2662
2663 // Make sure we deal with possible aliases, we could also have normalized
2664 // the name.
2666
2667 if (search) return GetBaseClass(search);
2668 else return nullptr;
2669}
2670
2671////////////////////////////////////////////////////////////////////////////////
2672/// Return pointer to the base class "cl". Returns 0 in case "cl"
2673/// is not a base class. Takes care of multiple inheritance.
2674
2676{
2677 // check if class name itself is equal to classname
2678 if (cl == this) return this;
2679
2680 if (!HasDataMemberInfo()) return nullptr;
2681
2682 TObjLink *lnk = GetListOfBases() ? fBase.load()->FirstLink() : nullptr;
2683
2684 // otherwise look at inheritance tree
2685 while (lnk) {
2686 TClass *c, *c1;
2687 TBaseClass *base = (TBaseClass*) lnk->GetObject();
2688 c = base->GetClassPointer();
2689 if (c) {
2690 if (cl == c) return c;
2691 c1 = c->GetBaseClass(cl);
2692 if (c1) return c1;
2693 }
2694 lnk = lnk->Next();
2695 }
2696 return nullptr;
2697}
2698
2699////////////////////////////////////////////////////////////////////////////////
2700/// Return data member offset to the base class "cl".
2701/// - Returns -1 in case "cl" is not a base class.
2702/// - Returns -2 if cl is a base class, but we can't find the offset
2703/// because it's virtual.
2704/// Takes care of multiple inheritance.
2705
2707{
2708 // check if class name itself is equal to classname
2709 if (cl == this) return 0;
2710
2711 if (!fBase.load()) {
2713 // If the information was not provided by the root pcm files and
2714 // if we can not find the ClassInfo, we have to fall back to the
2715 // StreamerInfo
2716 if (!fClassInfo) {
2718 if (!sinfo) return -1;
2720 Int_t offset = 0;
2721
2722 TObjArray &elems = *(sinfo->GetElements());
2723 Int_t size = elems.GetLast()+1;
2724 for(Int_t i=0; i<size; i++) {
2726 if (element->IsBase()) {
2727 if (element->IsA() == TStreamerBase::Class()) {
2729 TClass *baseclass = base->GetClassPointer();
2730 if (!baseclass) return -1;
2731 Int_t subOffset = baseclass->GetBaseClassOffsetRecurse(cl);
2732 if (subOffset == -2) return -2;
2733 if (subOffset != -1) return offset+subOffset;
2734 offset += baseclass->Size();
2735 } else if (element->IsA() == TStreamerSTL::Class()) {
2737 TClass *baseclass = base->GetClassPointer();
2738 if (!baseclass) return -1;
2739 Int_t subOffset = baseclass->GetBaseClassOffsetRecurse(cl);
2740 if (subOffset == -2) return -2;
2741 if (subOffset != -1) return offset+subOffset;
2742 offset += baseclass->Size();
2743
2744 } else {
2745 Error("GetBaseClassOffsetRecurse","Unexpected element type for base class: %s\n",element->IsA()->GetName());
2746 }
2747 }
2748 }
2749 return -1;
2750 }
2751 }
2752
2753 TClass *c;
2754 Int_t off;
2755 TBaseClass *inh;
2756 TObjLink *lnk = nullptr;
2757 if (fBase.load() == nullptr)
2759 else
2760 lnk = fBase.load()->FirstLink();
2761
2762 // otherwise look at inheritance tree
2763 while (lnk) {
2764 inh = (TBaseClass *)lnk->GetObject();
2765 //use option load=kFALSE to avoid a warning like:
2766 //"Warning in <TClass::TClass>: no dictionary for class TRefCnt is available"
2767 //We can not afford to not have the class if it exist, so we
2768 //use kTRUE.
2769 c = inh->GetClassPointer(kTRUE); // kFALSE);
2770 if (c) {
2771 if (cl == c) {
2772 if ((inh->Property() & kIsVirtualBase) != 0)
2773 return -2;
2774 return inh->GetDelta();
2775 }
2776 off = c->GetBaseClassOffsetRecurse(cl);
2777 if (off == -2) return -2;
2778 if (off != -1) {
2779 return off + inh->GetDelta();
2780 }
2781 }
2782 lnk = lnk->Next();
2783 }
2784 return -1;
2785}
2786
2787////////////////////////////////////////////////////////////////////////////////
2788/// - Return data member offset to the base class "cl".
2789/// - Returns -1 in case "cl" is not a base class.
2790/// Takes care of multiple inheritance.
2791
2793{
2794 // Warning("GetBaseClassOffset","Requires the use of fClassInfo for %s to %s",GetName(),toBase->GetName());
2795
2796 if (this == toBase) return 0;
2797
2798 if ((!address /* || !has_virtual_base */) &&
2799 (!HasInterpreterInfoInMemory() || !toBase->HasInterpreterInfoInMemory())) {
2800 // At least of the ClassInfo have not been loaded in memory yet and
2801 // since there is no virtual base class (or we don't have enough so it
2802 // would not make a difference) we can use the 'static' information
2804 if (offset != -2) {
2805 return offset;
2806 }
2807 return offset;
2808 }
2809
2811 ClassInfo_t* base = toBase->GetClassInfo();
2812 if(derived && base) {
2813 // TClingClassInfo::GetBaseOffset takes the lock.
2814 return gCling->ClassInfo_GetBaseOffset(derived, base, address, isDerivedObject);
2815 }
2816 else {
2818 if (offset != -2) {
2819 return offset;
2820 }
2821 }
2822 return -1;
2823}
2824
2825////////////////////////////////////////////////////////////////////////////////
2826/// Return pointer to (base) class that contains datamember.
2827
2829{
2830 if (!HasDataMemberInfo()) return nullptr;
2831
2832 // Check if data member exists in class itself
2834 if (dm) return this;
2835
2836 // if datamember not found in class, search in next base classes
2837 TBaseClass *inh;
2838 TIter next(GetListOfBases());
2839 while ((inh = (TBaseClass *) next())) {
2840 TClass *c = inh->GetClassPointer();
2841 if (c) {
2842 TClass *cdm = c->GetBaseDataMember(datamember);
2843 if (cdm) return cdm;
2844 }
2845 }
2846
2847 return nullptr;
2848}
2849
2850namespace {
2851 // A local Helper class used to keep 2 pointer (the collection proxy
2852 // and the class streamer) in the thread local storage.
2853
2854 struct TClassLocalStorage {
2855 TClassLocalStorage() : fCollectionProxy(nullptr), fStreamer(nullptr) {};
2856
2857 TVirtualCollectionProxy *fCollectionProxy;
2858 TClassStreamer *fStreamer;
2859
2860 static TClassLocalStorage *GetStorage(const TClass *cl)
2861 {
2862 // Return the thread storage for the TClass.
2863
2864 void **thread_ptr = (*gThreadTsd)(nullptr,ROOT::kClassThreadSlot);
2865 if (thread_ptr) {
2866 if (*thread_ptr==nullptr) *thread_ptr = new TExMap();
2867 TExMap *lmap = (TExMap*)(*thread_ptr);
2868 ULong_t hash = TString::Hash(&cl, sizeof(void*));
2869 ULongptr_t local = 0;
2870 UInt_t slot;
2871 if ((local = (ULongptr_t)lmap->GetValue(hash, (Longptr_t)cl, slot)) != 0) {
2872 } else {
2873 local = (ULongptr_t) new TClassLocalStorage();
2874 lmap->AddAt(slot, hash, (Longptr_t)cl, local);
2875 }
2876 return (TClassLocalStorage*)local;
2877 }
2878 return nullptr;
2879 }
2880 };
2881}
2882
2883////////////////////////////////////////////////////////////////////////////////
2884/// Return the 'type' of the STL the TClass is representing.
2885/// and return ROOT::kNotSTL if it is not representing an STL collection.
2886
2888{
2889 auto proxy = GetCollectionProxy();
2890 if (proxy) return (ROOT::ESTLType)proxy->GetCollectionType();
2891 return ROOT::kNotSTL;
2892}
2893
2894
2895////////////////////////////////////////////////////////////////////////////////
2896/// Return the proxy describing the collection (if any).
2897
2899{
2900 // Use assert, so that this line (slow because of the TClassEdit) is completely
2901 // removed in optimized code.
2902 //assert(TestBit(kLoading) || !TClassEdit::IsSTLCont(fName) || fCollectionProxy || 0 == "The TClass for the STL collection has no collection proxy!");
2904 TClassLocalStorage *local = TClassLocalStorage::GetStorage(this);
2905 if (local == nullptr) return fCollectionProxy;
2906 if (local->fCollectionProxy==nullptr) local->fCollectionProxy = fCollectionProxy->Generate();
2907 return local->fCollectionProxy;
2908 }
2909 return fCollectionProxy;
2910}
2911
2912////////////////////////////////////////////////////////////////////////////////
2913/// Return the Streamer Class allowing streaming (if any).
2914
2916{
2917 if (gThreadTsd && fStreamer) {
2918 TClassLocalStorage *local = TClassLocalStorage::GetStorage(this);
2919 if (local==nullptr) return fStreamer;
2920 if (local->fStreamer==nullptr) {
2921 local->fStreamer = fStreamer->Generate();
2922 const std::type_info &orig = ( typeid(*fStreamer) );
2923 if (!local->fStreamer) {
2924 Warning("GetStreamer","For %s, the TClassStreamer (%s) passed's call to Generate failed!",GetName(),orig.name());
2925 } else {
2926 const std::type_info &copy = ( typeid(*local->fStreamer) );
2927 if (strcmp(orig.name(),copy.name())!=0) {
2928 Warning("GetStreamer","For %s, the TClassStreamer passed does not properly implement the Generate method (%s vs %s)\n",GetName(),orig.name(),copy.name());
2929 }
2930 }
2931 }
2932 return local->fStreamer;
2933 }
2934 return fStreamer;
2935}
2936
2937////////////////////////////////////////////////////////////////////////////////
2938/// Get a wrapper/accessor function around this class custom streamer (member function).
2939
2944
2945////////////////////////////////////////////////////////////////////////////////
2946/// Get a wrapper/accessor function around this class custom conversion streamer (member function).
2947
2952
2953////////////////////////////////////////////////////////////////////////////////
2954/// Return the proxy implementing the IsA functionality.
2955
2957{
2958 return fIsA;
2959}
2960
2961////////////////////////////////////////////////////////////////////////////////
2962/// Static method returning pointer to TClass of the specified class name.
2963/// If load is true, an attempt is made to obtain the class by loading
2964/// the appropriate shared library (directed by the rootmap file).
2965/// If silent is 'true', do not warn about missing dictionary for the class.
2966/// (typically used for classes that are used only for transient members)
2967/// Returns `nullptr` in case class is not found.
2968
2970{
2971 return TClass::GetClass(name, load, silent, 0, 0);
2972}
2973
2975{
2976 if (!name || !name[0]) return nullptr;
2977
2978 if (strstr(name, "(anonymous)")) return nullptr;
2979 if (strstr(name, "(unnamed)")) return nullptr;
2980 if (strncmp(name,"class ",6)==0) name += 6;
2981 if (strncmp(name,"struct ",7)==0) name += 7;
2982
2983 if (!gROOT->GetListOfClasses()) return nullptr;
2984
2985 // FindObject will take the read lock before actually getting the
2986 // TClass pointer so we will need not get a partially initialized
2987 // object.
2988 TClass *cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
2989
2990 // Early return to release the lock without having to execute the
2991 // long-ish normalization.
2992 if (cl && (cl->IsLoaded() || cl->TestBit(kUnloading)))
2993 return cl;
2994
2996
2997 // Now that we got the write lock, another thread may have constructed the
2998 // TClass while we were waiting, so we need to do the checks again.
2999
3000 cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
3001 if (cl) {
3002 if (cl->IsLoaded() || cl->TestBit(kUnloading))
3003 return cl;
3004
3005 // We could speed-up some of the search by adding (the equivalent of)
3006 //
3007 // if (cl->GetState() == kInterpreter) return cl
3008 //
3009 // In this case, if a ROOT dictionary was available when the TClass
3010 // was first requested it would have been used and if a ROOT dictionary is
3011 // loaded later on TClassTable::Add will take care of updating the TClass.
3012 // So as far as ROOT dictionary are concerned, if the current TClass is
3013 // in interpreted state, we are sure there is nothing to load.
3014 //
3015 // However (see TROOT::LoadClass), the TClass can also be loaded/provided
3016 // by a user provided TClassGenerator. We have no way of knowing whether
3017 // those do (or even can) behave the same way as the ROOT dictionary and
3018 // have the 'dictionary is now available for use' step informs the existing
3019 // TClass that their dictionary is now available.
3020
3021 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
3022 load = kTRUE;
3023 }
3024
3026 // If there is a @ symbol (followed by a version number) then this is a synthetic class name created
3027 // from an already normalized name for the purpose of supporting schema evolution.
3028 // There is no dictionary or interpreter information about this kind of class, the only
3029 // (undesirable) side-effect of doing the search would be a waste of CPU time and potential
3030 // auto-loading or auto-parsing based on the scope of the name.
3031 return cl;
3032 }
3033
3034 // To avoid spurious auto parsing, let's check if the name as-is is
3035 // known in the TClassTable.
3037 // The name is normalized, so the result of the first search is
3038 // authoritative.
3039 if (!cl && !load)
3040 return nullptr;
3041
3042 TClass *loadedcl = (dict)();
3043 if (loadedcl) {
3044 loadedcl->PostLoadCheck();
3045 return loadedcl;
3046 }
3047
3048 // We should really not fall through to here, but if we do, let's just
3049 // continue as before ...
3050 }
3051
3052 // Note: this variable does not always holds the fully normalized name
3053 // as there is information from a not yet loaded library or from header
3054 // not yet parsed that may be needed to fully normalize the name.
3055 std::string normalizedName;
3057
3058 if (!cl) {
3059 // First look at known types but without triggering any loads
3060 {
3061 THashTable *typeTable = dynamic_cast<THashTable *>(gROOT->GetListOfTypes());
3062 TDataType *type = (TDataType *)typeTable->THashTable::FindObject(name);
3063 if (type) {
3064 if (type->GetType() > 0)
3065 // This is a numerical type
3066 return nullptr;
3067 // This is a typedef
3068 normalizedName = type->GetTypeName();
3070 }
3071 }
3072 {
3075 }
3076 // Try the normalized name.
3077 if (normalizedName != name) {
3078 cl = (TClass*)gROOT->GetListOfClasses()->FindObject(normalizedName.c_str());
3079
3080 if (cl) {
3081 if (cl->IsLoaded() || cl->TestBit(kUnloading))
3082 return cl;
3083
3084 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
3085 load = kTRUE;
3086 }
3088 }
3089 } else {
3090 normalizedName = cl->GetName(); // Use the fact that all TClass names are normalized.
3091 }
3092
3093 if (!load)
3094 return nullptr;
3095
3096 // We want to avoid auto-parsing due to intentionally missing dictionary for std::pair.
3097 // However, we don't need this special treatement in rootcling (there is no auto-parsing)
3098 // and we want to make that the TClass for the pair goes through the regular creation
3099 // mechanism (i.e. in rootcling they should be in kInterpreted state and never in
3100 // kEmulated state) so that they have proper interpreter (ClassInfo) information which
3101 // will be used to create the TProtoClass (if one is requested for the pair).
3104
3105 auto loadClass = [](const char *requestedname) -> TClass* {
3107 if (dict) {
3108 TClass *loadedcl = (dict)();
3109 if (loadedcl) {
3110 loadedcl->PostLoadCheck();
3111 return loadedcl;
3112 }
3113 }
3114 return nullptr;
3115 };
3116
3117 // Check with the changed name first.
3118 if (nameChanged) {
3119 if(TClass *loadedcl = loadClass(normalizedName.c_str()))
3120 return loadedcl;
3121 }
3122 if (gInterpreter->AutoLoad(normalizedName.c_str(),kTRUE)) {
3123 // Check if we just loaded the necessary dictionary.
3124 if (TClass *loadedcl = loadClass(normalizedName.c_str()))
3125 return loadedcl;
3126
3127 // At this point more information has been loaded. This
3128 // information might be pertinent to the normalization of the name.
3129 // For example it might contain or be a typedef for which we don't
3130 // have a forward declaration (eg. typedef to instance of class
3131 // template with default parameters). So let's redo the normalization
3132 // as the new information (eg. typedef in TROOT::GetListOfTypes) might
3133 // lead to a different value.
3134 {
3136 std::string normalizedNameAfterAutoLoad;
3140 }
3141 if (nameChanged) {
3142 // Try to load with an attempt to autoload with the new name
3144 return loadedcl;
3145 }
3146 }
3147
3148 // If name is known to be an enum, we don't need to try to load it.
3150 return nullptr;
3151
3152 // Maybe this was a typedef: let's try to see if this is the case
3153 if (!ispair && !ispairbase) {
3154 if (TDataType* theDataType = gROOT->GetType(normalizedName.c_str())){
3155 // We have a typedef: we get the name of the underlying type
3156 auto underlyingTypeName = theDataType->GetTypeName();
3157 // We see if we can bootstrap a class with it
3159 return loadedcl;
3160 }
3161 }
3162
3163 // See if the TClassGenerator can produce the TClass we need.
3165 return loadedcl;
3166
3167 // We have not been able to find a loaded TClass, return the Emulated
3168 // TClass if we have one.
3169 if (cl)
3170 return cl;
3171
3172 if (ispair) {
3175 // Fall-through to allow TClass to be created when known by the interpreter
3176 // This is used in the case where TStreamerInfo can not handle them.
3177 if (pairinfo)
3178 return pairinfo->GetClass();
3179 } else {
3180 // Check if we have an STL container that might provide it.
3181 static const size_t slen = strlen("pair");
3182 static const char *associativeContainer[] = { "map", "unordered_map", "multimap",
3183 "unordered_multimap", "set", "unordered_set", "multiset", "unordered_multiset" };
3184 for(auto contname : associativeContainer) {
3185 std::string collname = contname;
3186 collname.append( normalizedName.c_str() + slen );
3187 TClass *collcl = TClass::GetClass(collname.c_str(), false, silent);
3188 if (!collcl)
3190 if (collcl) {
3191 auto p = collcl->GetCollectionProxy();
3192 if (p)
3193 cl = p->GetValueClass();
3194 if (cl)
3195 return cl;
3196 }
3197 }
3198 }
3199 } else if (TClassEdit::IsSTLCont( normalizedName.c_str() ))
3200 {
3201 return gInterpreter->GenerateTClass(normalizedName.c_str(), kTRUE, silent);
3202 }
3203
3204 // Check the interpreter only after autoparsing the template if any.
3205 if (!ispairbase) {
3206 std::string::size_type posLess = normalizedName.find('<');
3207 if (posLess != std::string::npos) {
3208 gCling->AutoParse(normalizedName.substr(0, posLess).c_str());
3209 }
3210 }
3211
3212 //last attempt. Look in CINT list of all (compiled+interpreted) classes
3213 if (gDebug>0){
3214 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());
3215 }
3216 if (normalizedName.length()) {
3217 auto cci = gInterpreter->CheckClassInfo(normalizedName.c_str(), kTRUE /* autoload */,
3218 kTRUE /*Only class, structs and ns*/);
3219
3220 // We could have an interpreted class with an inline ClassDef, in this case we do not
3221 // want to create an 'interpreted' TClass but we want the one triggered via the call to
3222 // the Dictionary member. If we go ahead and generate the 'interpreted' version it will
3223 // replace if/when there is a call to IsA on an object of this type.
3224
3226 auto ci = gInterpreter->ClassInfo_Factory(normalizedName.c_str());
3227 auto funcDecl = gInterpreter->GetFunctionWithPrototype(ci, "Dictionary", "", false, ROOT::kExactMatch);
3228 auto method = gInterpreter->MethodInfo_Factory(funcDecl);
3229 typedef void (*tcling_callfunc_Wrapper_t)(void *, int, void **, void *);
3230 auto funcPtr = (tcling_callfunc_Wrapper_t)gInterpreter->MethodInfo_InterfaceMethod(method);
3231
3232 TClass *res = nullptr;
3233 if (funcPtr)
3234 funcPtr(nullptr, 0, nullptr, &res);
3235 // else
3236 // We could fallback to the interpreted case ...
3237 // For now just 'fail' (return nullptr)
3238
3239 gInterpreter->MethodInfo_Delete(method);
3240 gInterpreter->ClassInfo_Delete(ci);
3241
3242 return res;
3243 } else if (cci) {
3244 // Get the normalized name based on the decl (currently the only way
3245 // to get the part to add or drop the default arguments as requested by the user)
3246 std::string alternative;
3247 gInterpreter->GetInterpreterTypeName(normalizedName.c_str(), alternative, kTRUE);
3248 if (alternative.empty())
3249 return nullptr;
3250 const char *altname = alternative.c_str();
3251 if (strncmp(altname, "std::", 5) == 0) {
3252 // For namespace (for example std::__1), GetInterpreterTypeName does
3253 // not strip std::, so we must do it explicitly here.
3254 altname += 5;
3255 }
3256 if (altname != normalizedName && strcmp(altname, name) != 0) {
3257 // altname now contains the full name of the class including a possible
3258 // namespace if there has been a using namespace statement.
3259
3260 // At least in the case C<string [2]> (normalized) vs C<string[2]> (altname)
3261 // the TClassEdit normalization and the TMetaUtils normalization leads to
3262 // two different space layout. To avoid an infinite recursion, we also
3263 // add the test on (altname != name)
3264
3265 return GetClass(altname, load);
3266 }
3267
3268 TClass *ncl = gInterpreter->GenerateTClass(normalizedName.c_str(), /* emulation = */ kFALSE, silent);
3269 if (!ncl->IsZombie()) {
3270 return ncl;
3271 }
3272 delete ncl;
3273 }
3274 }
3275 return nullptr;
3276}
3277
3278////////////////////////////////////////////////////////////////////////////////
3279/// Return pointer to class with name.
3280
3281TClass *TClass::GetClass(const std::type_info& typeinfo, Bool_t load, Bool_t /* silent */, size_t hint_pair_offset, size_t hint_pair_size)
3282{
3283 if (!gROOT->GetListOfClasses())
3284 return nullptr;
3285
3286 //protect access to TROOT::GetIdMap
3288
3289 TClass* cl = GetIdMap()->Find(typeinfo.name());
3290
3291 if (cl && cl->IsLoaded()) return cl;
3292
3294
3295 // Now that we got the write lock, another thread may have constructed the
3296 // TClass while we were waiting, so we need to do the checks again.
3297
3298 cl = GetIdMap()->Find(typeinfo.name());
3299
3300 if (cl) {
3301 if (cl->IsLoaded()) return cl;
3302 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
3303 load = kTRUE;
3304 } else {
3305 // Note we might need support for typedefs and simple types!
3306
3307 // TDataType *objType = GetType(name, load);
3308 //if (objType) {
3309 // const char *typdfName = objType->GetTypeName();
3310 // if (typdfName && strcmp(typdfName, name)) {
3311 // cl = GetClass(typdfName, load);
3312 // return cl;
3313 // }
3314 // }
3315 }
3316
3317 if (!load) return nullptr;
3318
3320 if (dict) {
3321 cl = (dict)();
3322 if (cl) cl->PostLoadCheck();
3323 return cl;
3324 }
3325 if (cl) return cl;
3326
3327 TIter next(gROOT->GetListOfClassGenerators());
3328 TClassGenerator *gen;
3329 while( (gen = (TClassGenerator*) next()) ) {
3330 cl = gen->GetClass(typeinfo,load);
3331 if (cl) {
3332 cl->PostLoadCheck();
3333 return cl;
3334 }
3335 }
3336
3337 // try AutoLoading the typeinfo
3339 if (!autoload_old) {
3340 // Re-disable, we just meant to test
3342 }
3343 if (autoload_old && gInterpreter->AutoLoad(typeinfo,kTRUE)) {
3344 // Disable autoload to avoid potential infinite recursion
3347 if (cl) {
3348 return cl;
3349 }
3350 }
3351
3352 if (hint_pair_offset) {
3353 int err = 0;
3355 if (!err) {
3358 if (cl)
3359 return cl;
3360 }
3361 }
3362
3363 // last attempt. Look in the interpreter list of all (compiled+interpreted)
3364 // classes
3365 cl = gInterpreter->GetClass(typeinfo, load);
3366
3367 return cl; // Can be zero.
3368}
3369
3370////////////////////////////////////////////////////////////////////////////////
3371/// Static method returning pointer to TClass of the specified ClassInfo.
3372/// If load is true an attempt is made to obtain the class by loading
3373/// the appropriate shared library (directed by the rootmap file).
3374/// If silent is 'true', do not warn about missing dictionary for the class.
3375/// (typically used for class that are used only for transient members)
3376/// Returns 0 in case class is not found.
3377
3379{
3380 if (!info || !gCling->ClassInfo_IsValid(info)) return nullptr;
3381 if (!gROOT->GetListOfClasses()) return nullptr;
3382
3383 // Technically we need the write lock only for the call to ClassInfo_FullName
3384 // and GenerateTClass but FindObject will take the read lock (and LoadClass will
3385 // take the write lock). Since taking/releasing the lock is expensive, let just
3386 // take the write guard and keep it.
3388
3389 // Get the normalized name.
3391
3392 TClass *cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
3393
3394 if (cl) {
3395 if (cl->IsLoaded()) return cl;
3396
3397 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
3398 load = kTRUE;
3399
3400 }
3401
3402 if (!load) return nullptr;
3403
3404 TClass *loadedcl = nullptr;
3405 if (cl) loadedcl = gROOT->LoadClass(cl->GetName(),silent);
3406 else loadedcl = gROOT->LoadClass(name,silent);
3407
3408 if (loadedcl) return loadedcl;
3409
3410 if (cl) return cl; // If we found the class but we already have a dummy class use it.
3411
3412 // We did not find a proper TClass but we do know (we have a valid
3413 // ClassInfo) that the class is known to the interpreter.
3414 TClass *ncl = gInterpreter->GenerateTClass(info, silent);
3415 if (!ncl->IsZombie()) {
3416 return ncl;
3417 } else {
3418 delete ncl;
3419 return nullptr;
3420 }
3421}
3422
3423////////////////////////////////////////////////////////////////////////////////
3424
3428
3429////////////////////////////////////////////////////////////////////////////////
3430
3431Bool_t TClass::GetClass(DeclId_t id, std::vector<TClass*> &classes)
3432{
3433 if (!gROOT->GetListOfClasses()) return 0;
3434
3435 DeclIdMap_t* map = GetDeclIdMap();
3436 // Get all the TClass pointer that have the same DeclId.
3437 DeclIdMap_t::equal_range iter = map->Find(id);
3438 if (iter.first == iter.second) return false;
3439 std::vector<TClass*>::iterator vectIt = classes.begin();
3440 for (DeclIdMap_t::const_iterator it = iter.first; it != iter.second; ++it)
3441 vectIt = classes.insert(vectIt, it->second);
3442 return true;
3443}
3444
3445////////////////////////////////////////////////////////////////////////////////
3446/// Return a pointer to the dictionary loading function generated by
3447/// rootcint
3448
3450{
3452}
3453
3454////////////////////////////////////////////////////////////////////////////////
3455/// Return a pointer to the dictionary loading function generated by
3456/// rootcint
3457
3458DictFuncPtr_t TClass::GetDict (const std::type_info& info)
3459{
3460 return TClassTable::GetDict(info);
3461}
3462
3463////////////////////////////////////////////////////////////////////////////////
3464/// Return pointer to datamember object with name "datamember".
3465
3467{
3468 if ((!(fData.load() && (*fData).IsLoaded()) && !HasInterpreterInfo())
3469 || datamember == nullptr) return nullptr;
3470
3471 // Strip off leading *'s and trailing [
3472 const char *start_name = datamember;
3473 while (*start_name == '*') ++start_name;
3474
3475 // Empty name are 'legal', they represent anonymous unions.
3476 // if (*start_name == 0) return 0;
3477
3478 if (const char *s = strchr(start_name, '[')){
3479 UInt_t len = s-start_name;
3481 return (TDataMember *)((TClass*)this)->GetListOfDataMembers(kFALSE)->FindObject(name.Data());
3482 } else {
3483 return (TDataMember *)((TClass*)this)->GetListOfDataMembers(kFALSE)->FindObject(start_name);
3484 }
3485}
3486
3487////////////////////////////////////////////////////////////////////////////////
3488/// Return name of the file containing the declaration of this class.
3489
3490const char *TClass::GetDeclFileName() const
3491{
3493 return gInterpreter->ClassInfo_FileName( fClassInfo );
3494 return fDeclFileName;
3495}
3496
3497////////////////////////////////////////////////////////////////////////////////
3498/// return offset for member name. name can be a data member in
3499/// the class itself, one of its base classes, or one member in
3500/// one of the aggregated classes.
3501///
3502/// In case of an emulated class, the list of emulated TRealData is built
3503
3505{
3507 if (rd) return rd->GetThisOffset();
3508 if (strchr(name,'[')==nullptr) {
3509 // If this is a simple name there is a chance to find it in the
3510 // StreamerInfo even if we did not find it in the RealData.
3511 // For example an array name would be fArray[3] in RealData but
3512 // just fArray in the streamerInfo.
3513 TVirtualStreamerInfo *info = const_cast<TClass*>(this)->GetCurrentStreamerInfo();
3514 if (info) {
3515 return info->GetOffset(name);
3516 }
3517 }
3518 return 0;
3519}
3520
3521////////////////////////////////////////////////////////////////////////////////
3522/// Return pointer to TRealData element with name "name".
3523///
3524/// Name can be a data member in the class itself,
3525/// one of its base classes, or a member in
3526/// one of the aggregated classes.
3527///
3528/// In case of an emulated class, the list of emulated TRealData is built.
3529
3531{
3532 if (!fRealData) {
3533 const_cast<TClass*>(this)->BuildRealData();
3534 }
3535
3536 if (!fRealData) {
3537 return nullptr;
3538 }
3539
3540 if (!name) {
3541 return nullptr;
3542 }
3543
3544 // First try just the whole name.
3546 if (rd) {
3547 return rd;
3548 }
3549
3550 std::string givenName(name);
3551
3552 // Try ignoring the array dimensions.
3553 std::string::size_type firstBracket = givenName.find_first_of("[");
3554 if (firstBracket != std::string::npos) {
3555 // -- We are looking for an array data member.
3556 std::string nameNoDim(givenName.substr(0, firstBracket));
3558 while (lnk) {
3559 TObject* obj = lnk->GetObject();
3560 std::string objName(obj->GetName());
3561 std::string::size_type pos = objName.find_first_of("[");
3562 // Only match arrays to arrays for now.
3563 if (pos != std::string::npos) {
3564 objName.erase(pos);
3565 if (objName == nameNoDim) {
3566 return static_cast<TRealData*>(obj);
3567 }
3568 }
3569 lnk = lnk->Next();
3570 }
3571 }
3572
3573 // Now try it as a pointer.
3574 std::ostringstream ptrname;
3575 ptrname << "*" << givenName;
3576 rd = (TRealData*) fRealData->FindObject(ptrname.str().c_str());
3577 if (rd) {
3578 return rd;
3579 }
3580
3581 // Check for a dot in the name.
3582 std::string::size_type firstDot = givenName.find_first_of(".");
3583 if (firstDot == std::string::npos) {
3584 // -- Not found, a simple name, all done.
3585 return nullptr;
3586 }
3587
3588 //
3589 // At this point the name has a dot in it, so it is the name
3590 // of some contained sub-object.
3591 //
3592
3593 // May be a pointer like in TH1: fXaxis.fLabels (in TRealdata is named fXaxis.*fLabels)
3594 std::string::size_type lastDot = givenName.find_last_of(".");
3595 std::ostringstream starname;
3596 starname << givenName.substr(0, lastDot) << ".*" << givenName.substr(lastDot + 1);
3597 rd = (TRealData*) fRealData->FindObject(starname.str().c_str());
3598 if (rd) {
3599 return rd;
3600 }
3601
3602 // Last attempt in case a member has been changed from
3603 // a static array to a pointer, for example the member
3604 // was arr[20] and is now *arr.
3605 //
3606 // Note: In principle, one could also take into account
3607 // the opposite situation where a member like *arr has
3608 // been converted to arr[20].
3609 //
3610 // FIXME: What about checking after the first dot as well?
3611 //
3612 std::string::size_type bracket = starname.str().find_first_of("[");
3613 if (bracket != std::string::npos) {
3614 rd = (TRealData*) fRealData->FindObject(starname.str().substr(0, bracket).c_str());
3615 if (rd) {
3616 return rd;
3617 }
3618 }
3619
3620 // Strip the first component, it may be the name of
3621 // the branch (old TBranchElement code), and try again.
3622 std::string firstDotName(givenName.substr(firstDot + 1));
3623
3624 rd = GetRealData(firstDotName.c_str());
3625 if (rd)
3626 return rd;
3627
3628 // Not found;
3629 return nullptr;
3630}
3631
3632////////////////////////////////////////////////////////////////////////////////
3633
3635{
3636 if (!gInterpreter || !HasInterpreterInfo()) return nullptr;
3637
3638 // The following
3640
3642}
3643
3644////////////////////////////////////////////////////////////////////////////////
3645/// Get the list of shared libraries containing the code for class cls.
3646/// The first library in the list is the one containing the class, the
3647/// others are the libraries the first one depends on. Returns 0
3648/// in case the library is not found.
3649
3651{
3652 if (!gInterpreter) return nullptr;
3653
3654 if (fSharedLibs.IsNull())
3655 fSharedLibs = gInterpreter->GetClassSharedLibs(fName);
3656
3657 return !fSharedLibs.IsNull() ? fSharedLibs.Data() : nullptr;
3658}
3659
3660////////////////////////////////////////////////////////////////////////////////
3661/// Return list containing the TBaseClass(es) of a class.
3662
3664{
3665 if (!fBase.load()) {
3666 if (fCanLoadClassInfo) {
3667 if (fState == kHasTClassInit) {
3668
3670 if (!fHasRootPcmInfo) {
3671 // The bases are in our ProtoClass; we don't need the class info.
3673 if (proto && proto->FillTClass(this))
3674 return fBase;
3675 }
3676 }
3677 // We test again on fCanLoadClassInfo has another thread may have executed it.
3679 LoadClassInfo();
3680 }
3681 }
3682 if (!fClassInfo)
3683 return nullptr;
3684
3685 if (!gInterpreter)
3686 Fatal("GetListOfBases", "gInterpreter not initialized");
3687
3689 if (!fBase.load()) {
3690 gInterpreter->CreateListOfBaseClasses(this);
3691 }
3692 }
3693 return fBase;
3694}
3695
3696////////////////////////////////////////////////////////////////////////////////
3697/// Return a list containing the TEnums of a class.
3698///
3699/// The list returned is safe to use from multiple thread without explicitly
3700/// taking the ROOT global lock.
3701///
3702/// In the case the TClass represents a namespace, the returned list will
3703/// implicit take the ROOT global lock upon any access (see TListOfEnumsWithLock)
3704///
3705/// In the case the TClass represents a class or struct and requestListLoading
3706/// is true, the list is immutable (and thus safe to access from multiple thread
3707/// without taking the global lock at all).
3708///
3709/// In the case the TClass represents a class or struct and requestListLoading
3710/// is false, the list is mutable and thus we return a TListOfEnumsWithLock
3711/// which will implicit take the ROOT global lock upon any access.
3712
3714{
3715 auto temp = fEnums.load();
3716 if (temp) {
3717 if (requestListLoading) {
3718 if (fProperty == -1) Property();
3719 if (! ((kIsClass | kIsStruct | kIsUnion) & fProperty) ) {
3721 temp->Load();
3722 } else if ( temp->IsA() == TListOfEnumsWithLock::Class() ) {
3723 // We have a class for which the list was not loaded fully at
3724 // first use.
3726 temp->Load();
3727 }
3728 }
3729 return temp;
3730 }
3731
3732 if (!requestListLoading) {
3733 if (fProperty == -1) Property();
3735 if (fEnums.load()) {
3736 return fEnums.load();
3737 }
3738
3739 if (IsFromRootCling()) // rootcling is single thread (this save some space in the rootpcm).
3740 fEnums = new TListOfEnums(this);
3741 else
3742 fEnums = new TListOfEnumsWithLock(this);
3743 return fEnums;
3744 }
3745
3747 if (fEnums.load()) {
3748 (*fEnums).Load();
3749 return fEnums.load();
3750 }
3751 if (fProperty == -1) Property();
3752 if ( (kIsClass | kIsStruct | kIsUnion) & fProperty) {
3753 // For this case, the list will be immutable
3754 temp = new TListOfEnums(this);
3755 } else {
3756 //namespaces can have enums added to them
3757 temp = new TListOfEnumsWithLock(this);
3758 }
3759 temp->Load();
3760 fEnums = temp;
3761 return temp;
3762}
3763
3764////////////////////////////////////////////////////////////////////////////////
3765/// Create the list containing the TDataMembers (of actual data members or members
3766/// pulled in through using declarations) of a class.
3767
3769{
3771
3772 if (!data) {
3774 // The members are in our ProtoClass; we don't need the class info.
3776 if (proto && proto->FillTClass(this))
3777 return data;
3778 }
3779
3780 data = new TListOfDataMembers(this, selection);
3781 }
3782 if (IsClassStructOrUnion()) {
3783 // If the we have a class or struct or union, the order
3784 // of data members is the list is essential since it determines their
3785 // order on file. So we must always load. Also, the list is fixed
3786 // since the language does not allow to add members.
3787 if (!(*data).IsLoaded())
3788 (*data).Load();
3789
3790 } else if (load) (*data).Load();
3791 return data;
3792}
3793
3794////////////////////////////////////////////////////////////////////////////////
3795/// Return list containing the TDataMembers of a class.
3796
3798{
3799 // Fast path, no lock? Classes load at creation time.
3800 if (IsClassStructOrUnion()) {
3801 auto data = fData.load();
3802 if (data && data->IsLoaded())
3803 return data;
3804 } else if (!load && fData)
3805 return fData;
3806
3808}
3809
3810////////////////////////////////////////////////////////////////////////////////
3811/// Return list containing the TDataMembers of using declarations of a class.
3812
3814{
3815 // Fast path, no lock? Classes load at creation time.
3816 if ((!load || IsClassStructOrUnion()) && fUsingData)
3817 return fUsingData;
3818
3820}
3821
3822////////////////////////////////////////////////////////////////////////////////
3823/// Return TListOfFunctionTemplates for a class.
3824
3826{
3828
3830 if (load) fFuncTemplate->Load();
3831 return fFuncTemplate;
3832}
3833
3834////////////////////////////////////////////////////////////////////////////////
3835/// Return list containing the TMethods of a class.
3836/// If load is true, the list is populated with all the defined function
3837/// and currently instantiated function template.
3838
3840{
3842
3843 if (!fMethod.load()) GetMethodList();
3844 if (load) {
3845 if (gDebug>0) Info("GetListOfMethods","Header Parsing - Asking for all the methods of class %s: this can involve parsing.",GetName());
3846 (*fMethod).Load();
3847 }
3848 return fMethod;
3849}
3850
3851////////////////////////////////////////////////////////////////////////////////
3852/// Return the collection of functions named "name".
3853
3855{
3856 return const_cast<TClass*>(this)->GetMethodList()->GetListForObject(name);
3857}
3858
3859
3860////////////////////////////////////////////////////////////////////////////////
3861/// Returns a list of all public methods of this class and its base classes.
3862/// Refers to a subset of the methods in GetListOfMethods() so don't do
3863/// GetListOfAllPublicMethods()->Delete().
3864/// Algorithm used to get the list is:
3865/// - put all methods of the class in the list (also protected and private
3866/// ones).
3867/// - loop over all base classes and add only those methods not already in the
3868/// list (also protected and private ones).
3869/// - once finished, loop over resulting list and remove all private and
3870/// protected methods.
3871
3873{
3875
3877 if (load) {
3878 if (gDebug>0) Info("GetListOfAllPublicMethods","Header Parsing - Asking for all the methods of class %s: this can involve parsing.",GetName());
3880 }
3881 return fAllPubMethod;
3882}
3883
3884////////////////////////////////////////////////////////////////////////////////
3885/// Returns a list of all public data members of this class and its base
3886/// classes. Refers to a subset of the data members in GetListOfDatamembers()
3887/// so don't do GetListOfAllPublicDataMembers()->Delete().
3888
3890{
3892
3894 if (load) fAllPubData->Load();
3895 return fAllPubData;
3896}
3897
3898////////////////////////////////////////////////////////////////////////////////
3899/// Returns list of methods accessible by context menu.
3900
3902{
3903 if (!HasInterpreterInfo()) return;
3904
3905 // get the base class
3908 while ((baseClass = (TBaseClass *) nextBase())) {
3909 TClass *base = baseClass->GetClassPointer();
3910 if (base) base->GetMenuItems(list);
3911 }
3912
3913 // remove methods redefined in this class with no menu
3914 TMethod *method, *m;
3916 while ((method = (TMethod*)next())) {
3917 m = (TMethod*)list->FindObject(method->GetName());
3918 if (method->IsMenuItem() != kMenuNoMenu) {
3919 if (!m)
3920 list->AddFirst(method);
3921 } else {
3922 if (m && m->GetNargs() == method->GetNargs())
3923 list->Remove(m);
3924 }
3925 }
3926}
3927
3928////////////////////////////////////////////////////////////////////////////////
3929/// Check whether a class has a dictionary or not.
3930/// This is equivalent to ask if a class is coming from a bootstrapping
3931/// procedure initiated during the loading of a library.
3932
3934{
3935 return IsLoaded();
3936}
3937
3938////////////////////////////////////////////////////////////////////////////////
3939/// Check whether a class has a dictionary or ROOT can load one.
3940/// This is equivalent to ask HasDictionary() or whether a library is known
3941/// where it can be loaded from, or whether a Dictionary function is
3942/// available because the class's dictionary library was already loaded.
3943
3945{
3946 if (TClass* cl = (TClass*)gROOT->GetListOfClasses()->FindObject(clname))
3947 return cl->IsLoaded();
3948 return gClassTable->GetDict(clname) || gInterpreter->GetClassSharedLibs(clname);
3949}
3950
3951////////////////////////////////////////////////////////////////////////////////
3952/// Verify the base classes always.
3953
3955{
3956 TList* lb = GetListOfBases();
3957 if (!lb) return;
3958 TIter nextBase(lb);
3959 TBaseClass* base = nullptr;
3960 while ((base = (TBaseClass*)nextBase())) {
3961 TClass* baseCl = base->GetClassPointer();
3962 if (baseCl) {
3963 baseCl->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3964 }
3965 }
3966}
3967
3968////////////////////////////////////////////////////////////////////////////////
3969/// Verify the Data Members.
3970
3972{
3974 if (!ldm) return ;
3976 TDataMember * dm = nullptr;
3977 while ((dm = (TDataMember*)nextMemb())) {
3978 // If it is a transient
3979 if(!dm->IsPersistent()) {
3980 continue;
3981 }
3982 if (dm->Property() & kIsStatic) {
3983 continue;
3984 }
3985 // If it is a built-in data type.
3986 TClass* dmTClass = nullptr;
3987 if (dm->GetDataType()) {
3988 // We have a basic datatype.
3989 dmTClass = nullptr;
3990 // Otherwise get the string representing the type.
3991 } else if (dm->GetTypeName()) {
3993 }
3994 if (dmTClass) {
3995 dmTClass->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3996 }
3997 }
3998}
3999
4001{
4002 // Pair is a special case and we have to check its elements for missing dictionaries
4003 // Pair is a transparent container so we should always look at its.
4004
4006 for (int i = 0; i < 2; i++) {
4007 TClass* pairElement = ((TStreamerElement*)SI->GetElements()->At(i))->GetClass();
4008 if (pairElement) {
4009 pairElement->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
4010 }
4011 }
4012}
4013
4014////////////////////////////////////////////////////////////////////////////////
4015/// From the second level of recursion onwards it is different state check.
4016
4018{
4019 if (result.FindObject(this) || visited.FindObject(this)) return;
4020
4021 static TClassRef sCIString("string");
4022 if (this == sCIString) return;
4023
4025 if (splitType.IsTemplate()) {
4026 // We now treat special cases:
4027 // - pair
4028 // - unique_ptr
4029 // - array
4030 // - tuple
4031
4032 // Small helper to get the TClass instance from a classname and recursively
4033 // investigate it
4034 auto checkDicts = [&](const string &clName){
4035 auto cl = TClass::GetClass(clName.c_str());
4036 if (!cl) {
4037 // We try to remove * and const from the type name if any
4038 const auto clNameShortType = TClassEdit::ShortType(clName.c_str(), 1);
4039 cl = TClass::GetClass(clNameShortType.c_str());
4040 }
4041 if (cl && !cl->HasDictionary()) {
4042 cl->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
4043 }
4044 };
4045
4046 const auto &elements = splitType.fElements;
4047 const auto &templName = elements[0];
4048
4049 // Special treatment for pair.
4050 if (templName == "pair") {
4052 return;
4053 }
4054
4055 // Special treatment of unique_ptr or array
4056 // They are treated together since they have 1 single template argument
4057 // which is interesting when checking for missing dictionaries.
4058 if (templName == "unique_ptr" || templName == "array") {
4059 checkDicts(elements[1]);
4060 return;
4061 }
4062
4063 // Special treatment of tuple
4064 // This type must be treated separately since it can have N template
4065 // arguments which are interesting, unlike unique_ptr or array.
4066 if (templName == "tuple") {
4067 // -1 because the elements end with a list of the "stars", i.e. number of
4068 // * after the type name
4069 const auto nTemplArgs = elements.size() - 1;
4070 // loop starts at 1 because the first element is the template name
4071 for (auto iTemplArg = 1U; iTemplArg < nTemplArgs; ++iTemplArg) {
4072 checkDicts(elements[iTemplArg]);
4073 }
4074 return;
4075 }
4076 } // this is not a template
4077
4078 if (!HasDictionary()) {
4079 result.Add(this);
4080 }
4081
4082 visited.Add(this);
4083 //Check whether a custom streamer
4085 if (GetCollectionProxy()) {
4086 // We need to look at the collection's content
4087 // The collection has different kind of elements the check would be required.
4088 TClass* t = nullptr;
4089 if ((t = GetCollectionProxy()->GetValueClass())) {
4090 if (!t->HasDictionary()) {
4092 }
4093 }
4094 } else {
4095 if (recurse) {
4097 }
4099 }
4100 }
4101}
4102
4103////////////////////////////////////////////////////////////////////////////////
4104/// Get the classes that have a missing dictionary starting from this one.
4105/// - With recurse = false the classes checked for missing dictionaries are:
4106/// the class itself, all base classes, direct data members,
4107/// and for collection proxies the container's
4108/// elements without iterating over the element's data members;
4109/// - With recurse = true the classes checked for missing dictionaries are:
4110/// the class itself, all base classes, recursing on the data members,
4111/// and for the collection proxies recursion on the elements of the
4112/// collection and iterating over the element's data members.
4113
4115{
4116 // Top level recursion it different from the following levels of recursion.
4117
4118 if (result.FindObject(this)) return;
4119
4120 static TClassRef sCIString("string");
4121 if (this == sCIString) return;
4122
4124
4127 return;
4128 }
4129
4130 if (strncmp(fName, "unique_ptr<", 11) == 0 || strncmp(fName, "array<", 6) == 0 || strncmp(fName, "tuple<", 6) == 0) {
4132 return;
4133 }
4134
4135 if (!HasDictionary()) {
4136 result.Add(this);
4137 }
4138
4139 visited.Add(this);
4140
4141 //Check whether a custom streamer
4143 if (GetCollectionProxy()) {
4144 // We need to look at the collection's content
4145 // The collection has different kind of elements the check would be required.
4146 TClass* t = nullptr;
4147 if ((t = GetCollectionProxy()->GetValueClass())) {
4148 if (!t->HasDictionary()) {
4150 }
4151 }
4152 } else {
4155 }
4156 }
4157}
4158
4159////////////////////////////////////////////////////////////////////////////////
4160/// Return kTRUE if the class has elements.
4161
4162Bool_t TClass::IsFolder(void *obj) const
4163{
4164 return Browse(obj,(TBrowser*)nullptr);
4165}
4166
4167//______________________________________________________________________________
4168//______________________________________________________________________________
4170{
4171 // Inform the other objects to replace this object by the new TClass (newcl)
4172
4174 //we must update the class pointers pointing to 'this' in all TStreamerElements
4175 TIter nextClass(gROOT->GetListOfClasses());
4176 TClass *acl;
4178
4179 // Since we are in the process of replacing a TClass by a TClass
4180 // coming from a dictionary, there is no point in loading any
4181 // libraries during this search.
4183 while ((acl = (TClass*)nextClass())) {
4184 if (acl == newcl) continue;
4185
4186 TIter nextInfo(acl->GetStreamerInfos());
4187 while ((info = (TVirtualStreamerInfo*)nextInfo())) {
4188
4189 info->Update(this, newcl);
4190 }
4191 }
4192
4193 gInterpreter->UnRegisterTClassUpdate(this);
4194}
4195
4196////////////////////////////////////////////////////////////////////////////////
4197/// Make sure that the current ClassInfo is up to date.
4198
4200{
4201 Warning("ResetClassInfo(Long_t tagnum)","Call to deprecated interface (does nothing)");
4202}
4203
4204////////////////////////////////////////////////////////////////////////////////
4205/// Make sure that the current ClassInfo is up to date.
4206
4208{
4210
4212
4213 if (fClassInfo) {
4215 gInterpreter->ClassInfo_Delete(fClassInfo);
4216 fClassInfo = nullptr;
4217 }
4218 // We can not check at this point whether after the unload there will
4219 // still be interpreter information about this class (as v5 was doing),
4220 // instead this function must only be called if the definition is (about)
4221 // to be unloaded.
4222
4223 ResetCaches();
4224
4225 // We got here because the definition Decl is about to be unloaded.
4227 if (fStreamerInfo->GetEntries() != 0) {
4229 } else {
4231 }
4232 } else {
4233 // if the ClassInfo was loaded for a class with a TClass Init and it
4234 // gets unloaded, should we guess it can be reloaded?
4236 }
4237}
4238
4239////////////////////////////////////////////////////////////////////////////////
4240/// To clean out all caches.
4241
4243{
4244 R__ASSERT(!TestBit(kLoading) && "Resetting the caches does not make sense during loading!" );
4245
4246 // Not owning lists, don't call Delete(), but unload
4247 if (fData.load())
4248 (*fData).Unload();
4249 if (fUsingData.load())
4250 (*fUsingData).Unload();
4251 if (fEnums.load())
4252 (*fEnums).Unload();
4253 if (fMethod.load())
4254 (*fMethod).Unload();
4255
4256 delete fAllPubData; fAllPubData = nullptr;
4257
4258 if (fBase.load())
4259 (*fBase).Delete();
4260 delete fBase.load(); fBase = nullptr;
4261
4262 if (fRealData)
4263 fRealData->Delete();
4264 delete fRealData; fRealData=nullptr;
4265}
4266
4267////////////////////////////////////////////////////////////////////////////////
4268/// Resets the menu list to it's standard value.
4269
4278
4279////////////////////////////////////////////////////////////////////////////////
4280/// The ls function lists the contents of a class on stdout. Ls output
4281/// is typically much less verbose then Dump().
4282/// If options contains 'streamerinfo', run ls on the list of streamerInfos
4283/// and the list of conversion streamerInfos.
4284
4285void TClass::ls(Option_t *options) const
4286{
4287 TNamed::ls(options);
4288 if (options==nullptr || options[0]==0) return;
4289
4290 if (strstr(options,"streamerinfo")!=nullptr) {
4291 GetStreamerInfos()->ls(options);
4292
4293 if (fConversionStreamerInfo.load()) {
4294 std::map<std::string, TObjArray*>::iterator it;
4295 std::map<std::string, TObjArray*>::iterator end = (*fConversionStreamerInfo).end();
4296 for( it = (*fConversionStreamerInfo).begin(); it != end; ++it ) {
4297 it->second->ls(options);
4298 }
4299 }
4300 }
4301}
4302
4303////////////////////////////////////////////////////////////////////////////////
4304/// Makes a customizable version of the popup menu list, i.e. makes a list
4305/// of TClassMenuItem objects of methods accessible by context menu.
4306/// The standard (and different) way consists in having just one element
4307/// in this list, corresponding to the whole standard list.
4308/// Once the customizable version is done, one can remove or add elements.
4309
4311{
4314
4315 // Make sure fClassMenuList is initialized and empty.
4316 GetMenuList()->Delete();
4317
4318 TList* methodList = new TList;
4320
4321 TMethod *method;
4323 TClass *classPtr = nullptr;
4324 TIter next(methodList);
4325
4326 while ((method = (TMethod*) next())) {
4327 // if go to a mother class method, add separator
4328 if (classPtr != method->GetClass()) {
4331 classPtr = method->GetClass();
4332 }
4333 // Build the signature of the method
4334 TString sig;
4335 TList* margsList = method->GetListOfMethodArgs();
4337 while ((methodArg = (TMethodArg*)nextarg())) {
4338 sig = sig+","+methodArg->GetFullTypeName();
4339 }
4340 if (sig.Length()!=0) sig.Remove(0,1); // remove first comma
4342 method->GetName(), method->GetName(),nullptr,
4343 sig.Data(),-1,TClassMenuItem::kIsSelf);
4344 if (method->IsMenuItem() == kMenuToggle) menuItem->SetToggle();
4346 }
4347 delete methodList;
4348}
4349
4350////////////////////////////////////////////////////////////////////////////////
4351/// Register the fact that an object was moved from the memory location
4352/// 'arenaFrom' to the memory location 'arenaTo'.
4353
4354void TClass::Move(void *arenaFrom, void *arenaTo) const
4355{
4356 // If/when we have access to a copy constructor (or better to a move
4357 // constructor), this function should also perform the data move.
4358 // For now we just information the repository.
4359
4360 if ((GetState() <= kEmulated) && !fCollectionProxy) {
4361 MoveAddressInRepository("TClass::Move",arenaFrom,arenaTo,this);
4362 }
4363}
4364
4365////////////////////////////////////////////////////////////////////////////////
4366/// Return the list of menu items associated with the class.
4367
4369 if (!fClassMenuList) {
4370 fClassMenuList = new TList();
4372 }
4373 return fClassMenuList;
4374}
4375
4376////////////////////////////////////////////////////////////////////////////////
4377/// Return (create an empty one if needed) the list of functions.
4378/// The major difference with GetListOfMethod is that this returns
4379/// the internal type of fMethod and thus can not be made public.
4380/// It also never 'loads' the content of the list.
4381
4383{
4384 if (!fMethod.load()) {
4385 std::unique_ptr<TListOfFunctions> temp{ new TListOfFunctions(this) };
4386 TListOfFunctions* expected = nullptr;
4387 if(fMethod.compare_exchange_strong(expected, temp.get()) ) {
4388 temp.release();
4389 }
4390 }
4391 return fMethod;
4392}
4393
4394
4395////////////////////////////////////////////////////////////////////////////////
4396/// Return pointer to method without looking at parameters.
4397/// Does not look in (possible) base classes.
4398/// Has the side effect of loading all the TMethod object in the list
4399/// of the class.
4400
4402{
4403 if (!HasInterpreterInfo()) return nullptr;
4404 return (TMethod*) GetMethodList()->FindObject(method);
4405}
4406
4407////////////////////////////////////////////////////////////////////////////////
4408/// Return pointer to method without looking at parameters.
4409/// Does look in all base classes.
4410
4412{
4413 if (!HasInterpreterInfo()) return nullptr;
4414
4416 if (m) return m;
4417
4418 TBaseClass *base;
4420 while ((base = (TBaseClass *) nextb())) {
4421 TClass *c = base->GetClassPointer();
4422 if (c) {
4423 m = c->GetMethodAllAny(method);
4424 if (m) return m;
4425 }
4426 }
4427
4428 return nullptr;
4429}
4430
4431////////////////////////////////////////////////////////////////////////////////
4432/// Find the best method (if there is one) matching the parameters.
4433/// The params string must contain argument values, like "3189, \"aap\", 1.3".
4434/// The function invokes GetClassMethod to search for a possible method
4435/// in the class itself or in its base classes. Returns 0 in case method
4436/// is not found.
4437
4438TMethod *TClass::GetMethod(const char *method, const char *params,
4439 Bool_t objectIsConst /* = kFALSE */)
4440{
4442 if (!fClassInfo) return nullptr;
4443
4444 if (!gInterpreter)
4445 Fatal("GetMethod", "gInterpreter not initialized");
4446
4447 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithValues(fClassInfo,
4448 method, params,
4450
4451 if (!decl) return nullptr;
4452
4453 // search recursively in this class or its base classes
4455 if (f) return f;
4456
4457 Error("GetMethod",
4458 "\nDid not find matching TMethod <%s> with \"%s\" %sfor %s",
4459 method,params,objectIsConst ? "const " : "", GetName());
4460 return nullptr;
4461}
4462
4463
4464////////////////////////////////////////////////////////////////////////////////
4465/// Find a method with decl id in this class or its bases.
4466
4468 if (TFunction* method = GetMethodList()->Get(declId))
4469 return static_cast<TMethod *>(method);
4470
4471 for (auto item : *GetListOfBases())
4472 if (auto base = static_cast<TBaseClass *>(item)->GetClassPointer())
4473 if (TFunction* method = base->FindClassOrBaseMethodWithId(declId))
4474 return static_cast<TMethod *>(method);
4475
4476 return nullptr;
4477}
4478
4479////////////////////////////////////////////////////////////////////////////////
4480/// Find the method with a given prototype. The proto string must be of the
4481/// form: "char*,int,double". Returns 0 in case method is not found.
4482
4484 Bool_t objectIsConst /* = kFALSE */,
4485 ROOT::EFunctionMatchMode mode /* = ROOT::kConversionMatch */)
4486{
4488 if (!fClassInfo) return nullptr;
4489
4490 if (!gInterpreter)
4491 Fatal("GetMethodWithPrototype", "gInterpreter not initialized");
4492
4493 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithPrototype(fClassInfo,
4494 method, proto,
4496
4497 if (!decl) return nullptr;
4499 if (f) return f;
4500 Error("GetMethodWithPrototype",
4501 "\nDid not find matching TMethod <%s> with \"%s\" %sfor %s",
4502 method,proto,objectIsConst ? "const " : "", GetName());
4503 return nullptr;
4504}
4505
4506////////////////////////////////////////////////////////////////////////////////
4507/// Look for a method in this class that has the interface function
4508/// address faddr.
4509
4511{
4512 if (!HasInterpreterInfo()) return nullptr;
4513
4514 TMethod *m;
4515 TIter next(GetListOfMethods());
4516 while ((m = (TMethod *) next())) {
4517 if (faddr == (Longptr_t)m->InterfaceMethod())
4518 return m;
4519 }
4520 return nullptr;
4521}
4522
4523////////////////////////////////////////////////////////////////////////////////
4524/// Look for a method in this class that has the name and matches the parameters.
4525/// The params string must contain argument values, like "3189, \"aap\", 1.3".
4526/// Returns 0 in case method is not found.
4527/// See TClass::GetMethod to also search the base classes.
4528
4529TMethod *TClass::GetClassMethod(const char *name, const char* params,
4530 Bool_t objectIsConst /* = kFALSE */)
4531{
4533 if (!fClassInfo) return nullptr;
4534
4535 if (!gInterpreter)
4536 Fatal("GetClassMethod", "gInterpreter not initialized");
4537
4538 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithValues(fClassInfo,
4539 name, params,
4541
4542 if (!decl) return nullptr;
4543
4545
4546 return (TMethod*)f; // Could be zero if the decl is actually in a base class.
4547}
4548
4549////////////////////////////////////////////////////////////////////////////////
4550/// Find the method with a given prototype. The proto string must be of the
4551/// form: "char*,int,double". Returns 0 in case method is not found.
4552/// See TClass::GetMethodWithPrototype to also search the base classes.
4553
4555 Bool_t objectIsConst /* = kFALSE */,
4556 ROOT::EFunctionMatchMode mode /* = ROOT::kConversionMatch */)
4557{
4559 if (!fClassInfo) return nullptr;
4560
4561 if (!gInterpreter)
4562 Fatal("GetClassMethodWithPrototype", "gInterpreter not initialized");
4563
4564 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithPrototype(fClassInfo,
4565 name, proto,
4567 mode);
4568
4569 if (!decl) return nullptr;
4570
4572
4573 return (TMethod*)f; // Could be zero if the decl is actually in a base class.
4574}
4575
4576////////////////////////////////////////////////////////////////////////////////
4577/// Return the number of data members of this class
4578/// Note that in case the list of data members is not yet created, it will be done
4579/// by GetListOfDataMembers().
4580
4582{
4583 if (!HasDataMemberInfo()) return 0;
4584
4586 if (lm)
4587 return lm->GetSize();
4588 else
4589 return 0;
4590}
4591
4592////////////////////////////////////////////////////////////////////////////////
4593/// Return the number of methods of this class
4594/// Note that in case the list of methods is not yet created, it will be done
4595/// by GetListOfMethods().
4596/// This will also load/populate the list of methods, to get 'just' the
4597/// number of currently loaded methods use:
4598/// cl->GetListOfMethods(false)->GetSize();
4599
4601{
4602 if (!HasInterpreterInfo()) return 0;
4603
4605 if (lm)
4606 return lm->GetSize();
4607 else
4608 return 0;
4609}
4610
4611////////////////////////////////////////////////////////////////////////////////
4612/// returns a pointer to the TVirtualStreamerInfo object for version
4613/// If the object does not exist, it is created
4614///
4615/// Note: There are two special version numbers:
4616///
4617/// - 0: Use the class version from the currently loaded class library.
4618/// - -1: Assume no class library loaded (emulated class).
4619///
4620/// Warning: If we create a new streamer info, whether or not the build
4621/// optimizes is controlled externally to us by a global variable!
4622/// Don't call us unless you have set that variable properly
4623/// with TStreamer::Optimize()!
4624///
4625
4627{
4629
4630 // Version 0 is special, it means the currently loaded version.
4631 // We need to set it at the beginning to be able to guess it correctly.
4632
4633 if (version == 0)
4635
4636 // If the StreamerInfo is assigned to the fLastReadInfo, we are
4637 // guaranteed it was built and compiled.
4638 if (sinfo && sinfo->GetClassVersion() == version)
4639 return sinfo;
4640
4641 // Note that the access to fClassVersion above is technically not thread-safe with a low probably of problems.
4642 // fClassVersion is not an atomic and is modified TClass::SetClassVersion (called from RootClassVersion via
4643 // ROOT::ResetClassVersion) and is 'somewhat' protected by the atomic fVersionUsed.
4644 // However, direct access to fClassVersion should be replaced by calls to GetClassVersion to set fVersionUsed.
4645 // Even with such a change the code here and in these functions need to be reviewed as a cursory look seem
4646 // to indicates they are not yet properly protection against mutli-thread access.
4647 //
4648 // However, the use of these functions is rare and mostly done at library loading time which should
4649 // in almost all cases preceeds the possibility of GetStreamerInfo being called from multiple thread
4650 // on that same TClass object.
4651 //
4652 // Summary: need careful review but risk of problem is extremely low.
4653
4655
4657};
4658
4659// Implementation of/for TStreamerInfo::GetStreamerInfo.
4660// This routine assumes the global lock has been taken.
4662{
4663 // Warning: version may be -1 for an emulated class, or -2 if the
4664 // user requested the emulated streamerInfo for an abstract
4665 // base class, even though we have a dictionary for it.
4666
4667 if ((version < -1) || (version >= (fStreamerInfo->GetSize()-1))) {
4668 Error("GetStreamerInfo", "class: %s, attempting to access a wrong version: %d", GetName(), version);
4669 // FIXME: Shouldn't we go to -1 here, or better just abort?
4671 }
4672
4674
4675 if (!sinfo && (version != fClassVersion)) {
4676 // When the requested version does not exist we return
4677 // the TVirtualStreamerInfo for the currently loaded class version.
4678 // FIXME: This arguably makes no sense, we should warn and return nothing instead.
4679 // Note: This is done for STL collections
4680 // Note: fClassVersion could be -1 here (for an emulated class).
4681 // This is also the code path take for unversioned classes.
4683 }
4684
4685 if (!sinfo) {
4686 // We just were not able to find a streamer info, we have to make a new one.
4687 TMmallocDescTemp setreset;
4688 sinfo = TVirtualStreamerInfo::Factory()->NewInfo(const_cast<TClass*>(this));
4690 if (gDebug > 0) {
4691 printf("Creating StreamerInfo for class: %s, version: %d\n", GetName(), fClassVersion);
4692 }
4694 // If we do not have a StreamerInfo for this version and we do not
4695 // have dictionary information nor a proxy, there is nothing to build!
4696 sinfo->Build(silent);
4697 }
4698 } else {
4699 if (!sinfo->IsCompiled()) {
4700 // Streamer info has not been compiled, but exists.
4701 // Therefore it was read in from a file and we have to do schema evolution?
4702 // Or it didn't have a dictionary before, but does now?
4703 sinfo->BuildOld();
4704 }
4705 }
4706
4707 // Cache the current info if we now have it.
4708 if (version == fClassVersion)
4710
4711 // If the compilation succeeded, remember this StreamerInfo.
4712 if (sinfo->IsCompiled())
4714
4715 return sinfo;
4716}
4717
4718////////////////////////////////////////////////////////////////////////////////
4719/// For the case where the requestor class is emulated and this class is abstract,
4720/// returns a pointer to the TVirtualStreamerInfo object for version with an emulated
4721/// representation whether or not the class is loaded.
4722///
4723/// If the object does not exist, it is created
4724///
4725/// Note: There are two special version numbers:
4726///
4727/// - 0: Use the class version from the currently loaded class library.
4728/// - -1: Assume no class library loaded (emulated class).
4729///
4730/// Warning: If we create a new streamer info, whether or not the build
4731/// optimizes is controlled externally to us by a global variable!
4732/// Don't call us unless you have set that variable properly
4733/// with TStreamer::Optimize()!
4734///
4735
4737{
4738 TVirtualStreamerInfo *sinfo = nullptr;
4739
4741 newname += "@@emulated";
4742
4744
4746
4747 if (emulated)
4748 sinfo = emulated->GetStreamerInfo(version);
4749
4750 if (!sinfo) {
4751 // The emulated version of the streamerInfo is explicitly requested and has
4752 // not been built yet.
4753
4755
4756 if (!sinfo && (version != fClassVersion)) {
4757 // When the requested version does not exist we return
4758 // the TVirtualStreamerInfo for the currently loaded class version.
4759 // FIXME: This arguably makes no sense, we should warn and return nothing instead.
4761 }
4762
4763 if (!sinfo) {
4764 // Let's take the first available StreamerInfo as a start
4766 for (Int_t i = -1; sinfo == nullptr && i < ninfos; ++i)
4768 }
4769
4770 if (sinfo) {
4771 sinfo = dynamic_cast<TVirtualStreamerInfo *>(sinfo->Clone());
4772 if (sinfo) {
4773 sinfo->SetClass(nullptr);
4774 sinfo->SetName(newname);
4775 sinfo->BuildCheck();
4776 sinfo->BuildOld();
4777 sinfo->GetClass()->AddRule(TString::Format("sourceClass=%s targetClass=%s",GetName(),newname.Data()));
4778 } else {
4779 Error("GetStreamerInfoAbstractEmulated", "could not create TVirtualStreamerInfo");
4780 }
4781 }
4782 }
4783 return sinfo;
4784}
4785
4786////////////////////////////////////////////////////////////////////////////////
4787/// For the case where the requestor class is emulated and this class is abstract,
4788/// returns a pointer to the TVirtualStreamerInfo object for version with an emulated
4789/// representation whether or not the class is loaded.
4790///
4791/// If the object does not exist, it is created
4792///
4793/// Warning: If we create a new streamer info, whether or not the build
4794/// optimizes is controlled externally to us by a global variable!
4795/// Don't call us unless you have set that variable properly
4796/// with TStreamer::Optimize()!
4797///
4798
4800{
4801 TVirtualStreamerInfo *sinfo = nullptr;
4802
4804 newname += "@@emulated";
4805
4807
4809
4810 if (emulated)
4811 sinfo = emulated->FindStreamerInfo(checksum);
4812
4813 if (!sinfo) {
4814 // The emulated version of the streamerInfo is explicitly requested and has
4815 // not been built yet.
4816
4818
4819 if (!sinfo && (checksum != fCheckSum)) {
4820 // When the requested version does not exist we return
4821 // the TVirtualStreamerInfo for the currently loaded class version.
4822 // FIXME: This arguably makes no sense, we should warn and return nothing instead.
4824 }
4825
4826 if (!sinfo) {
4827 // Let's take the first available StreamerInfo as a start
4829 for (Int_t i = -1; sinfo == nullptr && i < ninfos; ++i)
4831 }
4832
4833 if (sinfo) {
4834 sinfo = dynamic_cast<TVirtualStreamerInfo*>( sinfo->Clone() );
4835 if (sinfo) {
4836 sinfo->SetClass(nullptr);
4837 sinfo->SetName( newname );
4838 sinfo->BuildCheck();
4839 sinfo->BuildOld();
4840 sinfo->GetClass()->AddRule(TString::Format("sourceClass=%s targetClass=%s",GetName(),newname.Data()));
4841 } else {
4842 Error("GetStreamerInfoAbstractEmulated", "could not create TVirtualStreamerInfo");
4843 }
4844 }
4845 }
4846 return sinfo;
4847}
4848
4849////////////////////////////////////////////////////////////////////////////////
4850/// When the class kIgnoreTObjectStreamer bit is set, the automatically
4851/// generated Streamer will not call TObject::Streamer.
4852/// This option saves the TObject space overhead on the file.
4853/// However, the information (fBits, fUniqueID) of TObject is lost.
4854///
4855/// Note that to be effective for objects streamed object-wise this function
4856/// must be called for the class deriving directly from TObject, eg, assuming
4857/// that BigTrack derives from Track and Track derives from TObject, one must do:
4858/// ~~~ {.cpp}
4859/// Track::Class()->IgnoreTObjectStreamer();
4860/// ~~~
4861/// and not:
4862/// ~~~ {.cpp}
4863/// BigTrack::Class()->IgnoreTObjectStreamer();
4864/// ~~~
4865/// To be effective for object streamed member-wise or split in a TTree,
4866/// this function must be called for the most derived class (i.e. BigTrack).
4867
4869{
4870 // We need to tak the lock since we are test and then setting fBits
4871 // and TStreamerInfo::fBits (and the StreamerInfo state in general)
4872 // which can also be modified by another thread.
4874
4875 if ( doIgnore && TestBit(kIgnoreTObjectStreamer)) return;
4876 if (!doIgnore && !TestBit(kIgnoreTObjectStreamer)) return;
4878 if (sinfo) {
4879 if (sinfo->IsCompiled()) {
4880 // -- Warn the user that what they are doing cannot work.
4881 // Note: The reason is that TVirtualStreamerInfo::Build() examines
4882 // the kIgnoreTObjectStreamer bit and sets the TStreamerElement
4883 // type for the TObject base class streamer element it creates
4884 // to -1 as a flag. Later on the TStreamerInfo::Compile()
4885 // member function sees the flag and does not insert the base
4886 // class element into the compiled streamer info. None of this
4887 // machinery works correctly if we are called after the streamer
4888 // info has already been built and compiled.
4889 Error("IgnoreTObjectStreamer","Must be called before the creation of StreamerInfo");
4890 return;
4891 }
4892 }
4895}
4896
4897////////////////////////////////////////////////////////////////////////////////
4898/// Return kTRUE if this class inherits from a class with name "classname".
4899/// note that the function returns kTRUE in case classname is the class itself
4900
4901Bool_t TClass::InheritsFrom(const char *classname) const
4902{
4903 if (strcmp(GetName(), classname) == 0) return kTRUE;
4904
4905 return InheritsFrom(TClass::GetClass(classname,kTRUE,kTRUE));
4906}
4907
4908////////////////////////////////////////////////////////////////////////////////
4909/// Return kTRUE if this class inherits from class cl.
4910/// note that the function returns KTRUE in case cl is the class itself
4911
4913{
4914 if (!cl) return kFALSE;
4915 if (cl == this) return kTRUE;
4916
4917 if (!HasDataMemberInfo()) {
4918 TVirtualStreamerInfo *sinfo = ((TClass *)this)->GetCurrentStreamerInfo();
4919 if (sinfo==nullptr) sinfo = GetStreamerInfo();
4920 TIter next(sinfo->GetElements());
4922 while ((element = (TStreamerElement*)next())) {
4923 if (element->IsA() == TStreamerBase::Class()) {
4924 TClass *clbase = element->GetClassPointer();
4925 if (!clbase) return kFALSE; //missing class
4926 if (clbase->InheritsFrom(cl)) return kTRUE;
4927 }
4928 }
4929 return kFALSE;
4930 }
4931 // cast const away (only for member fBase which can be set in GetListOfBases())
4932 if (((TClass *)this)->GetBaseClass(cl)) return kTRUE;
4933 return kFALSE;
4934}
4935
4936////////////////////////////////////////////////////////////////////////////////
4937/// Cast obj of this class type up to baseclass cl if up is true.
4938/// Cast obj of this class type down from baseclass cl if up is false.
4939/// If this class is not a baseclass of cl return 0, else the pointer
4940/// to the cl part of this (up) or to this (down).
4941
4942void *TClass::DynamicCast(const TClass *cl, void *obj, Bool_t up)
4943{
4944 if (cl == this) return obj;
4945
4946 if (!HasDataMemberInfo()) return nullptr;
4947
4948 Int_t off;
4949 if ((off = GetBaseClassOffset(cl, obj)) != -1) {
4950 if (up)
4951 return (void*)((Longptr_t)obj+off);
4952 else
4953 return (void*)((Longptr_t)obj-off);
4954 }
4955 return nullptr;
4956}
4957
4958////////////////////////////////////////////////////////////////////////////////
4959/// Cast obj of this class type up to baseclass cl if up is true.
4960/// Cast obj of this class type down from baseclass cl if up is false.
4961/// If this class is not a baseclass of cl return 0, else the pointer
4962/// to the cl part of this (up) or to this (down).
4963
4964const void *TClass::DynamicCast(const TClass *cl, const void *obj, Bool_t up)
4965{
4966 return DynamicCast(cl,const_cast<void*>(obj),up);
4967}
4968
4969////////////////////////////////////////////////////////////////////////////////
4970/// Return a pointer to a newly allocated object of this class.
4971/// The class must have a default constructor. For meaning of
4972/// defConstructor, see TClass::IsCallingNew().
4973///
4974/// If quiet is true, do no issue a message via Error on case
4975/// of problems, just return 0.
4976///
4977/// The constructor actually called here can be customized by
4978/// using the rootcint pragma:
4979/// ~~~ {.cpp}
4980/// #pragma link C++ ioctortype UserClass;
4981/// ~~~
4982/// For example, with this pragma and a class named MyClass,
4983/// this method will called the first of the following 3
4984/// constructors which exists and is public:
4985/// ~~~ {.cpp}
4986/// MyClass(UserClass*);
4987/// MyClass(TRootIOCtor*);
4988/// MyClass(); // Or a constructor with all its arguments defaulted.
4989/// ~~~
4990///
4991/// When more than one pragma ioctortype is used, the first seen as priority
4992/// For example with:
4993/// ~~~ {.cpp}
4994/// #pragma link C++ ioctortype UserClass1;
4995/// #pragma link C++ ioctortype UserClass2;
4996/// ~~~
4997/// We look in the following order:
4998/// ~~~ {.cpp}
4999/// MyClass(UserClass1*);
5000/// MyClass(UserClass2*);
5001/// MyClass(TRootIOCtor*);
5002/// MyClass(); // Or a constructor with all its arguments defaulted.
5003/// ~~~
5004
5006{
5007 auto obj = NewObject(defConstructor, quiet);
5008 if (obj.GetPtr() && obj.GetAllocator()) {
5009 // Register the object for special handling in the destructor.
5010 RegisterAddressInRepository("TClass::New", obj.GetPtr(), this);
5011 }
5012 return obj.GetPtr();
5013}
5014
5015// See TClass:New
5016// returns a TClass::ObjectPtr which remembers if the object was allocated
5017// via a TStreamerInfo.
5018
5020{
5021 ObjectPtr p;
5022
5023 if (fNew) {
5024 // We have the new operator wrapper function,
5025 // so there is a dictionary and it was generated
5026 // by rootcint, so there should be a default
5027 // constructor we can call through the wrapper.
5028 {
5030 p = fNew(nullptr);
5031 }
5032 if (!p && !quiet) {
5033 //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
5034 Error("New", "cannot create object of class %s", GetName());
5035 }
5036 } else if (HasInterpreterInfo()) {
5037 // We have the dictionary but do not have the
5038 // constructor wrapper, so the dictionary was
5039 // not generated by rootcint. Let's try to
5040 // create the object by having the interpreter
5041 // call the new operator, hopefully the class
5042 // library is loaded and there will be a default
5043 // constructor we can call.
5044 // [This is very unlikely to work, but who knows!]
5045 {
5048 }
5049 if (!p && !quiet) {
5050 //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
5051 Error("New", "cannot create object of class %s", GetName());
5052 }
5053 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5054 // There is no dictionary at all, so this is an emulated
5055 // class; however we do have the services of a collection proxy,
5056 // so this is an emulated STL class.
5057 {
5060 }
5061 if (!p && !quiet) {
5062 //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
5063 Error("New", "cannot create object of class %s", GetName());
5064 }
5065 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5066 // There is no dictionary at all and we do not have
5067 // the services of a collection proxy available, so
5068 // use the streamer info to approximate calling a
5069 // constructor (basically we just make sure that the
5070 // pointer data members are null, unless they are marked
5071 // as preallocated with the "->" comment, in which case
5072 // we default-construct an object to point at).
5073
5074 // Do not register any TObject's that we create
5075 // as a result of creating this object.
5076 // FIXME: Why do we do this?
5077 // FIXME: Partial Answer: Is this because we may never actually deregister them???
5078
5080 if(statsave) {
5082 }
5084 if (!sinfo) {
5085 if (!quiet)
5086 Error("New", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
5087 return nullptr;
5088 }
5089
5090 {
5092 p = { sinfo->New(), sinfo};
5093 }
5094
5095 // FIXME: Mistake? See note above at the GetObjectStat() call.
5096 // Allow TObject's to be registered again.
5097 if(statsave) {
5099 }
5100
5101 if (!p) {
5102 Error("New", "Failed to construct class '%s' using streamer info", GetName());
5103 }
5104
5105 return p;
5106 } else {
5107 Fatal("New", "This cannot happen!");
5108 }
5109
5110 return p;
5111}
5112
5113////////////////////////////////////////////////////////////////////////////////
5114/// Return a pointer to a newly allocated object of this class.
5115/// The class must have a default constructor. For meaning of
5116/// defConstructor, see TClass::IsCallingNew().
5117
5119{
5120 auto obj = NewObject(arena, defConstructor);
5121 if (obj.GetPtr() && obj.GetAllocator()) {
5122 // Register the object for special handling in the destructor.
5123 RegisterAddressInRepository("TClass::New with placement", obj.GetPtr(), this);
5124 }
5125 return obj.GetPtr();
5126}
5127
5128////////////////////////////////////////////////////////////////////////////////
5129/// Return a pointer to a newly allocated object of this class.
5130/// The class must have a default constructor. For meaning of
5131/// defConstructor, see TClass::IsCallingNew().
5132
5134{
5135 ObjectPtr p;
5136
5137 if (fNew) {
5138 // We have the new operator wrapper function,
5139 // so there is a dictionary and it was generated
5140 // by rootcint, so there should be a default
5141 // constructor we can call through the wrapper.
5142 {
5144 p = fNew(arena);
5145 }
5146 if (!p) {
5147 Error("New with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
5148 }
5149 } else if (HasInterpreterInfo()) {
5150 // We have the dictionary but do not have the
5151 // constructor wrapper, so the dictionary was
5152 // not generated by rootcint. Let's try to
5153 // create the object by having the interpreter
5154 // call the new operator, hopefully the class
5155 // library is loaded and there will be a default
5156 // constructor we can call.
5157 // [This is very unlikely to work, but who knows!]
5158 {
5161 }
5162 if (!p) {
5163 Error("New with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
5164 }
5165 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5166 // There is no dictionary at all, so this is an emulated
5167 // class; however we do have the services of a collection proxy,
5168 // so this is an emulated STL class.
5169 {
5172 }
5173 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5174 // There is no dictionary at all and we do not have
5175 // the services of a collection proxy available, so
5176 // use the streamer info to approximate calling a
5177 // constructor (basically we just make sure that the
5178 // pointer data members are null, unless they are marked
5179 // as preallocated with the "->" comment, in which case
5180 // we default-construct an object to point at).
5181
5182 // ???BUG??? ???WHY???
5183 // Do not register any TObject's that we create
5184 // as a result of creating this object.
5186 if(statsave) {
5188 }
5189
5191 if (!sinfo) {
5192 Error("New with placement", "Cannot construct class '%s' version %d at address %p, no streamer info available!", GetName(), fClassVersion, arena);
5193 return nullptr;
5194 }
5195
5196 {
5198 p = { sinfo->New(arena), sinfo };
5199 }
5200
5201 // ???BUG???
5202 // Allow TObject's to be registered again.
5203 if(statsave) {
5205 }
5206
5207 } else {
5208 Error("New with placement", "This cannot happen!");
5209 }
5210
5211 return p;
5212}
5213
5214////////////////////////////////////////////////////////////////////////////////
5215/// Return a pointer to a newly allocated array of objects
5216/// of this class.
5217/// The class must have a default constructor. For meaning of
5218/// defConstructor, see TClass::IsCallingNew().
5219
5221{
5223 if (obj.GetPtr() && obj.GetAllocator()) {
5224 // Register the object for special handling in the destructor.
5225 RegisterAddressInRepository("TClass::NewArray", obj.GetPtr(), this);
5226 }
5227 return obj.GetPtr();
5228}
5229
5230////////////////////////////////////////////////////////////////////////////////
5231/// Return a pointer to a newly allocated array of objects
5232/// of this class.
5233/// The class must have a default constructor. For meaning of
5234/// defConstructor, see TClass::IsCallingNew().
5235
5237{
5238 ObjectPtr p;
5239
5240 if (fNewArray) {
5241 // We have the new operator wrapper function,
5242 // so there is a dictionary and it was generated
5243 // by rootcint, so there should be a default
5244 // constructor we can call through the wrapper.
5245 {
5247 p = fNewArray(nElements, nullptr);
5248 }
5249 if (!p) {
5250 Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
5251 }
5252 } else if (HasInterpreterInfo()) {
5253 // We have the dictionary but do not have the
5254 // constructor wrapper, so the dictionary was
5255 // not generated by rootcint. Let's try to
5256 // create the object by having the interpreter
5257 // call the new operator, hopefully the class
5258 // library is loaded and there will be a default
5259 // constructor we can call.
5260 // [This is very unlikely to work, but who knows!]
5261 {
5264 }
5265 if (!p) {
5266 Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
5267 }
5268 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5269 // There is no dictionary at all, so this is an emulated
5270 // class; however we do have the services of a collection proxy,
5271 // so this is an emulated STL class.
5272 {
5275 }
5276 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5277 // There is no dictionary at all and we do not have
5278 // the services of a collection proxy available, so
5279 // use the streamer info to approximate calling a
5280 // constructor (basically we just make sure that the
5281 // pointer data members are null, unless they are marked
5282 // as preallocated with the "->" comment, in which case
5283 // we default-construct an object to point at).
5284
5285 // ???BUG??? ???WHY???
5286 // Do not register any TObject's that we create
5287 // as a result of creating this object.
5289 if(statsave) {
5291 }
5292
5294 if (!sinfo) {
5295 Error("NewArray", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
5296 return nullptr;
5297 }
5298
5299 {
5301 p = { sinfo->NewArray(nElements), sinfo };
5302 }
5303
5304 // ???BUG???
5305 // Allow TObject's to be registered again.
5306 if(statsave) {
5308 }
5309
5310 } else {
5311 Error("NewArray", "This cannot happen!");
5312 }
5313
5314 return p;
5315}
5316
5317////////////////////////////////////////////////////////////////////////////////
5318/// Return a pointer to a newly allocated object of this class.
5319/// The class must have a default constructor. For meaning of
5320/// defConstructor, see TClass::IsCallingNew().
5321
5323{
5325 if (obj.GetPtr() && obj.GetAllocator()) {
5326 // Register the object for special handling in the destructor.
5327 RegisterAddressInRepository("TClass::NewArray with placement", obj.GetPtr(), this);
5328 }
5329 return obj.GetPtr();
5330}
5331
5332////////////////////////////////////////////////////////////////////////////////
5333/// Return a pointer to a newly allocated object of this class.
5334/// The class must have a default constructor. For meaning of
5335/// defConstructor, see TClass::IsCallingNew().
5336
5338{
5339 ObjectPtr p;
5340
5341 if (fNewArray) {
5342 // We have the new operator wrapper function,
5343 // so there is a dictionary and it was generated
5344 // by rootcint, so there should be a default
5345 // constructor we can call through the wrapper.
5346 {
5349 }
5350 if (!p) {
5351 Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
5352 }
5353 } else if (HasInterpreterInfo()) {
5354 // We have the dictionary but do not have the constructor wrapper,
5355 // so the dictionary was not generated by rootcint (it was made either
5356 // by cint or by some external mechanism). Let's try to create the
5357 // object by having the interpreter call the new operator, either the
5358 // class library is loaded and there is a default constructor we can
5359 // call, or the class is interpreted and we will call the default
5360 // constructor that way, or no default constructor is available and
5361 // we fail.
5362 {
5365 }
5366 if (!p) {
5367 Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
5368 }
5369 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5370 // There is no dictionary at all, so this is an emulated
5371 // class; however we do have the services of a collection proxy,
5372 // so this is an emulated STL class.
5373 {
5376 }
5377 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5378 // There is no dictionary at all and we do not have
5379 // the services of a collection proxy available, so
5380 // use the streamer info to approximate calling a
5381 // constructor (basically we just make sure that the
5382 // pointer data members are null, unless they are marked
5383 // as preallocated with the "->" comment, in which case
5384 // we default-construct an object to point at).
5385
5386 // ???BUG??? ???WHY???
5387 // Do not register any TObject's that we create
5388 // as a result of creating this object.
5390 if(statsave) {
5392 }
5393
5395 if (!sinfo) {
5396 Error("NewArray with placement", "Cannot construct class '%s' version %d at address %p, no streamer info available!", GetName(), fClassVersion, arena);
5397 return nullptr;
5398 }
5399
5400 {
5402 p = { sinfo->NewArray(nElements, arena), sinfo };
5403 }
5404
5405 // ???BUG???
5406 // Allow TObject's to be registered again.
5407 if(statsave) {
5409 }
5410
5412 // We always register emulated objects, we need to always
5413 // use the streamer info to destroy them.
5414 }
5415
5416 return p;
5417 } else {
5418 Error("NewArray with placement", "This cannot happen!");
5419 }
5420
5421 return p;
5422}
5423
5424////////////////////////////////////////////////////////////////////////////////
5425/// Explicitly call destructor for object.
5426
5428{
5429 // Do nothing if passed a null pointer.
5430 if (obj == nullptr) return;
5431
5432 void* p = obj;
5433
5434 if (dtorOnly && fDestructor) {
5435 // We have the destructor wrapper, use it.
5436 fDestructor(p);
5437 } else if ((!dtorOnly) && fDelete) {
5438 // We have the delete wrapper, use it.
5439 fDelete(p);
5440 } else if (HasInterpreterInfo()) {
5441 // We have the dictionary but do not have the
5442 // destruct/delete wrapper, so the dictionary was
5443 // not generated by rootcint (it could have been
5444 // created by cint or by some external mechanism).
5445 // Let's have the interpreter call the destructor,
5446 // either the code will be in a loaded library,
5447 // or it will be interpreted, otherwise we fail
5448 // because there is no destructor code at all.
5449 if (dtorOnly) {
5451 } else {
5453 }
5454 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5455 // There is no dictionary at all, so this is an emulated
5456 // class; however we do have the services of a collection proxy,
5457 // so this is an emulated STL class.
5459 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5460 // There is no dictionary at all and we do not have
5461 // the services of a collection proxy available, so
5462 // use the streamer info to approximate calling a
5463 // destructor.
5464
5467
5468 // Was this object allocated through TClass?
5469 Version_t objVer = -1;
5470 {
5472 RepoCont_t::iterator iter = fObjectVersionRepository.find(p);
5473 if (iter == fObjectVersionRepository.end()) {
5474 // No, it wasn't, skip special version handling.
5475 //Error("Destructor2", "Attempt to delete unregistered object of class '%s' at address %p!", GetName(), p);
5476 inRepo = kFALSE;
5477 } else {
5478 //objVer = iter->second;
5479 for (; (iter != fObjectVersionRepository.end()) && (iter->first == p); ++iter) {
5480 objVer = iter->second;
5481 if (objVer == fClassVersion) {
5483 break;
5484 }
5485 }
5486 }
5487 }
5488
5489 if (!inRepo || currentVersion) {
5490 // The object was allocated using code for the same class version
5491 // as is loaded now. We may proceed without worry.
5493 if (si) {
5494 si->Destructor(p, dtorOnly);
5495 } else {
5496 Error("Destructor", "No streamer info available for class '%s' version %d at address %p, cannot destruct emulated object!", GetName(), fClassVersion, p);
5497 Error("Destructor", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5499 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5500 Error("Destructor", "fStreamerInfo->At(%d): %p", i, fStreamerInfo->At(i));
5501 if (fStreamerInfo->At(i) != nullptr) {
5502 Error("Destructor", "Doing Dump() ...");
5504 }
5505 }
5506 }
5507 } else {
5508 // The loaded class version is not the same as the version of the code
5509 // which was used to allocate this object. The best we can do is use
5510 // the TVirtualStreamerInfo to try to free up some of the allocated memory.
5512 if (si) {
5513 si->Destructor(p, dtorOnly);
5514 } else {
5515 Error("Destructor", "No streamer info available for class '%s' version %d, cannot destruct object at addr: %p", GetName(), objVer, p);
5516 Error("Destructor", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5518 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5519 Error("Destructor2", "fStreamerInfo->At(%d): %p", i, fStreamerInfo->At(i));
5520 if (fStreamerInfo->At(i) != nullptr) {
5521 // Do some debugging output.
5522 Error("Destructor2", "Doing Dump() ...");
5524 }
5525 }
5526 }
5527 }
5528
5529 if (inRepo && p) {
5530 UnregisterAddressInRepository("TClass::Destructor",p,this);
5531 }
5532 } else {
5533 Error("Destructor", "This cannot happen! (class %s)", GetName());
5534 }
5535}
5536
5537////////////////////////////////////////////////////////////////////////////////
5538/// Explicitly call destructor for object.
5539
5541{
5542 // Do nothing if passed a null pointer.
5543 if (obj.GetPtr() == nullptr)
5544 return;
5545
5546 if (obj.GetAllocator()) {
5547 obj.GetAllocator()->Destructor(obj.GetPtr(), dtorOnly);
5548 } else {
5549 Destructor(obj.GetPtr(), dtorOnly);
5550 }
5551}
5552
5553////////////////////////////////////////////////////////////////////////////////
5554/// Explicitly call operator delete[] for an array.
5555
5557{
5558 // Do nothing if passed a null pointer.
5559 if (ary == nullptr) return;
5560
5561 // Make a copy of the address.
5562 void* p = ary;
5563
5564 if (fDeleteArray) {
5565 if (dtorOnly) {
5566 Error("DeleteArray", "Destructor only is not supported!");
5567 } else {
5568 // We have the array delete wrapper, use it.
5570 }
5571 } else if (HasInterpreterInfo()) {
5572 // We have the dictionary but do not have the
5573 // array delete wrapper, so the dictionary was
5574 // not generated by rootcint. Let's try to
5575 // delete the array by having the interpreter
5576 // call the array delete operator, hopefully
5577 // the class library is loaded and there will be
5578 // a destructor we can call.
5580 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5581 // There is no dictionary at all, so this is an emulated
5582 // class; however we do have the services of a collection proxy,
5583 // so this is an emulated STL class.
5585 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5586 // There is no dictionary at all and we do not have
5587 // the services of a collection proxy available, so
5588 // use the streamer info to approximate calling the
5589 // array destructor.
5590
5593
5594 // Was this array object allocated through TClass?
5595 Version_t objVer = -1;
5596 {
5598 RepoCont_t::iterator iter = fObjectVersionRepository.find(p);
5599 if (iter == fObjectVersionRepository.end()) {
5600 // No, it wasn't, we cannot know what to do.
5601 //Error("DeleteArray", "Attempt to delete unregistered array object, element type '%s', at address %p!", GetName(), p);
5602 inRepo = kFALSE;
5603 } else {
5604 for (; (iter != fObjectVersionRepository.end()) && (iter->first == p); ++iter) {
5605 objVer = iter->second;
5606 if (objVer == fClassVersion) {
5608 break;
5609 }
5610 }
5611 }
5612 }
5613
5614 if (!inRepo || currentVersion) {
5615 // The object was allocated using code for the same class version
5616 // as is loaded now. We may proceed without worry.
5618 if (si) {
5619 si->DeleteArray(ary, dtorOnly);
5620 } else {
5621 Error("DeleteArray", "No streamer info available for class '%s' version %d at address %p, cannot destruct object!", GetName(), fClassVersion, ary);
5622 Error("DeleteArray", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5624 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5625 Error("DeleteArray", "fStreamerInfo->At(%d): %p", v, fStreamerInfo->At(i));
5626 if (fStreamerInfo->At(i)) {
5627 Error("DeleteArray", "Doing Dump() ...");
5629 }
5630 }
5631 }
5632 } else {
5633 // The loaded class version is not the same as the version of the code
5634 // which was used to allocate this array. The best we can do is use
5635 // the TVirtualStreamerInfo to try to free up some of the allocated memory.
5637 if (si) {
5638 si->DeleteArray(ary, dtorOnly);
5639 } else {
5640 Error("DeleteArray", "No streamer info available for class '%s' version %d at address %p, cannot destruct object!", GetName(), objVer, ary);
5641 Error("DeleteArray", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5643 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5644 Error("DeleteArray", "fStreamerInfo->At(%d): %p", v, fStreamerInfo->At(i));
5645 if (fStreamerInfo->At(i)) {
5646 // Print some debugging info.
5647 Error("DeleteArray", "Doing Dump() ...");
5649 }
5650 }
5651 }
5652 }
5653
5654 // Deregister the object for special handling in the destructor.
5655 if (inRepo && p) {
5656 UnregisterAddressInRepository("TClass::DeleteArray",p,this);
5657 }
5658 } else {
5659 Error("DeleteArray", "This cannot happen! (class '%s')", GetName());
5660 }
5661}
5662
5663////////////////////////////////////////////////////////////////////////////////
5664/// Explicitly call operator delete[] for an array.
5665
5667{
5668 // Do nothing if passed a null pointer.
5669 if (obj.GetPtr() == nullptr) return;
5670
5671 if (obj.GetAllocator()) {
5672 obj.GetAllocator()->DeleteArray(obj.GetPtr(), dtorOnly);
5673 } else {
5674 DeleteArray(obj.GetPtr(), dtorOnly);
5675 }
5676}
5677
5678////////////////////////////////////////////////////////////////////////////////
5679/// Set the splitability of this class:
5680/// - -1: Use the default calculation
5681/// - 0: Disallow splitting
5682/// - 1: Always allow splitting.
5683/// - 2: Disallow splitting of the class and splitting of any it's derived classes.
5684
5689
5690////////////////////////////////////////////////////////////////////////////////
5691/// Private function. Set the class version for the 'class' represented by
5692/// this TClass object. See the public interface:
5693/// ROOT::ResetClassVersion
5694/// defined in TClassTable.cxx
5695///
5696/// Note on class version numbers:
5697/// - If no class number has been specified, TClass::GetVersion will return -1
5698/// - The Class Version 0 request the whole object to be transient
5699/// - The Class Version 1, unless specified via ClassDef indicates that the
5700/// I/O should use the TClass checksum to distinguish the layout of the class
5701
5707
5708////////////////////////////////////////////////////////////////////////////////
5709/// Determine and set pointer to current TVirtualStreamerInfo
5710
5719
5720////////////////////////////////////////////////////////////////////////////////
5721/// Set pointer to current TVirtualStreamerInfo
5722
5727
5728////////////////////////////////////////////////////////////////////////////////
5729/// Return size of object of this class.
5730
5732{
5733 if (fSizeof!=-1) return fSizeof;
5736 return GetStreamerInfo()->GetSize();
5737}
5738
5739////////////////////////////////////////////////////////////////////////////////
5740/// Load class description from I/O buffer and return class object.
5741
5743{
5744 UInt_t maxsize = 256;
5745 char *s = new char[maxsize];
5746
5747 Int_t pos = b.Length();
5748
5749 b.ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end.
5750 while (strlen(s) == (maxsize - 1)) {
5751 // The classname is too large, try again with a large buffer.
5752 b.SetBufferOffset(pos);
5753 maxsize = 2*maxsize;
5754 delete [] s;
5755 s = new char[maxsize];
5756 b.ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end.
5757 }
5758
5759 TClass *cl = TClass::GetClass(s, kTRUE);
5760 if (!cl)
5761 ::Error("TClass::Load", "dictionary of class %s not found", s);
5762
5763 delete [] s;
5764 return cl;
5765}
5766
5767////////////////////////////////////////////////////////////////////////////////
5768/// Helper function used by TClass::GetClass().
5769/// This function attempts to load the dictionary for 'classname'
5770/// either from the TClassTable or from the list of generator.
5771/// If silent is 'true', do not warn about missing dictionary for the class.
5772/// (typically used for class that are used only for transient members)
5773///
5774/// The 'requestedname' is expected to be already normalized.
5775
5777{
5778 // This function does not (and should not) attempt to check in the
5779 // list of loaded classes or in the typedef.
5780
5782
5784
5785 if (result) return result;
5787}
5788
5789////////////////////////////////////////////////////////////////////////////////
5790/// Helper function used by TClass::GetClass().
5791/// This function attempts to load the dictionary for 'classname' from
5792/// the TClassTable or the autoloader.
5793/// If silent is 'true', do not warn about missing dictionary for the class.
5794/// (typically used for class that are used only for transient members)
5795///
5796/// The 'requestedname' is expected to be already normalized.
5797
5799{
5800 // This function does not (and should not) attempt to check in the
5801 // list of loaded classes or in the typedef.
5802
5804
5805 if (!dict) {
5806 if (gInterpreter->AutoLoad(requestedname, kTRUE)) {
5808 }
5809 }
5810
5811 if (dict) {
5812 TClass *ncl = (dict)();
5813 if (ncl) ncl->PostLoadCheck();
5814 return ncl;
5815 }
5816 return nullptr;
5817}
5818
5819////////////////////////////////////////////////////////////////////////////////
5820/// Helper function used by TClass::GetClass().
5821/// This function attempts to load the dictionary for 'classname'
5822/// from the list of generator.
5823/// If silent is 'true', do not warn about missing dictionary for the class.
5824/// (typically used for class that are used only for transient members)
5825///
5826/// The 'requestedname' is expected to be already normalized.
5827
5829{
5830 // This function does not (and should not) attempt to check in the
5831 // list of loaded classes or in the typedef.
5832
5833 TIter next(gROOT->GetListOfClassGenerators());
5834 TClassGenerator *gen;
5835 while ((gen = (TClassGenerator*) next())) {
5837 if (cl) {
5838 cl->PostLoadCheck();
5839 return cl;
5840 }
5841 }
5842 return nullptr;
5843}
5844
5845////////////////////////////////////////////////////////////////////////////////
5846/// Try to load the ClassInfo if available. This function may require parsing
5847/// the header file and/or loading data from the clang pcm. If further calls to
5848/// this function cannot affect the value of fClassInfo, fCanLoadClassInfo is set
5849/// to false.
5850
5852{
5854
5855 // Return if another thread already loaded the info
5856 // while we were waiting for the lock
5858 return;
5859
5860 bool autoParse = !gInterpreter->IsAutoParsingSuspended();
5861
5862 if (autoParse && !fClassInfo)
5863 gInterpreter->AutoParse(GetName());
5864
5865 if (!fClassInfo) // Could be indirectly set by the parsing
5866 gInterpreter->SetClassInfo(const_cast<TClass *>(this));
5867
5868 if (autoParse && !fClassInfo) {
5869 if (fImplFileLine == -1 && fClassVersion == 0) {
5870 // We have a 'transient' class with a ClassDefInline and apparently no interpreter
5871 // information. Since it is transient, it is more than likely that the lack
5872 // will be harmles.
5873 } else {
5874 ::Error("TClass::LoadClassInfo", "no interpreter information for class %s is available"
5875 " even though it has a TClass initialization routine.",
5876 fName.Data());
5877 }
5878 }
5879
5880 // Keep trying to load the ClassInfo, since we have no ClassInfo yet,
5881 // we will get an update even when there is an explicit load. So whether
5882 // or not the autoparsing is on, we will need to keep trying to load
5883 // the ClassInfo.
5885}
5886
5887////////////////////////////////////////////////////////////////////////////////
5888/// Store class description on I/O buffer.
5889
5891{
5892 b.WriteString(GetName());
5893}
5894
5895////////////////////////////////////////////////////////////////////////////////
5896/// Global function called by a class' static Dictionary() method
5897/// (see the ClassDef macro).
5898
5900 const std::type_info &info, TVirtualIsAProxy *isa,
5901 const char *dfil, const char *ifil,
5902 Int_t dl, Int_t il)
5903{
5904 // When called via TMapFile (e.g. Update()) make sure that the dictionary
5905 // gets allocated on the heap and not in the mapped file.
5906 TMmallocDescTemp setreset;
5907 return new TClass(cname, id, info, isa, dfil, ifil, dl, il);
5908}
5909
5910////////////////////////////////////////////////////////////////////////////////
5911/// Global function called by a class' static Dictionary() method
5912/// (see the ClassDef macro).
5913
5915 const char *dfil, const char *ifil,
5916 Int_t dl, Int_t il)
5917{
5918 // When called via TMapFile (e.g. Update()) make sure that the dictionary
5919 // gets allocated on the heap and not in the mapped file.
5920 TMmallocDescTemp setreset;
5921 return new TClass(cname, id, dfil, ifil, dl, il);
5922}
5923
5924////////////////////////////////////////////////////////////////////////////////
5925/// Static method returning the defConstructor flag passed to TClass::New().
5926/// New type is either:
5927/// - TClass::kRealNew - when called via plain new
5928/// - TClass::kClassNew - when called via TClass::New()
5929/// - TClass::kDummyNew - when called via TClass::New() but object is a dummy,
5930/// in which case the object ctor might take short cuts
5931
5936
5937////////////////////////////////////////////////////////////////////////////////
5938/// Return true if the shared library of this class is currently in the a
5939/// process's memory. Return false, after the shared library has been
5940/// unloaded or if this is an 'emulated' class created from a file's StreamerInfo.
5941
5943{
5944 return fState == kHasTClassInit;
5945}
5946
5947////////////////////////////////////////////////////////////////////////////////
5948/// Returns true if this class inherits from TObject and if the start of
5949/// the TObject parts is at the very beginning of the objects.
5950/// Concretely this means that the following code is proper for this class:
5951/// ~~~ {.cpp}
5952/// ThisClass *ptr;
5953/// void *void_ptr = (void)ptr;
5954/// TObject *obj = (TObject*)void_ptr;
5955/// ~~~
5956/// This code would be wrong if 'ThisClass' did not inherit 'first' from
5957/// TObject.
5958
5960{
5961 if (fProperty==(-1)) Property();
5962 return TestBit(kStartWithTObject);
5963}
5964
5965////////////////////////////////////////////////////////////////////////////////
5966/// Return kTRUE is the class inherits from TObject.
5967
5969{
5970 if (fProperty==(-1)) Property();
5971 return TestBit(kIsTObject);
5972}
5973
5974////////////////////////////////////////////////////////////////////////////////
5975/// Return kTRUE is the class is Foreign (the class does not have a Streamer method).
5976
5978{
5979 if (fProperty==(-1)) Property();
5980 // If the property are not set and the class is a pair, hard code that
5981 // it is a unversioned/Foreign class.
5982 return TestBit(kIsForeign);
5983}
5984
5985////////////////////////////////////////////////////////////////////////////////
5986/// Do the initialization that can only be done after the CINT dictionary has
5987/// been fully populated and can not be delayed efficiently.
5988
5990{
5991 // In the case of a Foreign class (loaded class without a Streamer function)
5992 // we reset fClassVersion to be -1 so that the current TVirtualStreamerInfo will not
5993 // be confused with a previously loaded streamerInfo.
5994
5995 if (IsLoaded() && HasInterpreterInfo() && fClassVersion==1 /*&& fStreamerInfo
5996 && fStreamerInfo->At(1)*/ && IsForeign() )
5997 {
5998 SetClassVersion(-1);
5999 }
6000 // Note: We are careful to check the class version first because checking
6001 // for foreign can trigger an AutoParse.
6002 else if (IsLoaded() && HasDataMemberInfo() && fStreamerInfo && ((fClassVersion > 1) || !IsForeign()))
6003 {
6005
6007 // Here we need to check whether this TVirtualStreamerInfo (which presumably has been
6008 // loaded from a file) is consistent with the definition in the library we just loaded.
6009 // BuildCheck is not appropriate here since it check a streamerinfo against the
6010 // 'current streamerinfo' which, at time point, would be the same as 'info'!
6012 && (info->GetCheckSum()!=GetCheckSum() && !info->CompareContent(this,nullptr,kFALSE,kFALSE, nullptr) && !(MatchLegacyCheckSum(info->GetCheckSum()))))
6013 {
6014 Bool_t warn = ! TestBit(kWarned);
6015 if (warn && info->GetOldVersion()<=2) {
6016 // Names of STL base classes was modified in vers==3. Allocators removed
6017 //
6019 TBaseClass *bc;
6020 while ((bc=(TBaseClass*)nextBC()))
6021 {if (TClassEdit::IsSTLCont(bc->GetName())) warn = kFALSE;}
6022 }
6023
6024 if (warn) {
6025 if (info->GetOnFileClassVersion()==1 && fClassVersion>1) {
6026 Warning("PostLoadCheck","\n\
6027 The class %s transitioned from not having a specified class version\n\
6028 to having a specified class version (the current class version is %d).\n\
6029 However too many different non-versioned layouts of the class have\n\
6030 already been loaded so far. To work around this problem you can\n\
6031 load fewer 'old' file in the same ROOT session or load the C++ library\n\
6032 describing the class %s before opening the files or increase the version\n\
6033 number of the class for example ClassDef(%s,%d).\n\
6034 Do not try to write objects with the current class definition,\n\
6035 the files might not be readable.\n",
6037 } else {
6038 Warning("PostLoadCheck","\n\
6039 The StreamerInfo version %d for the class %s which was read\n\
6040 from a file previously opened has the same version as the active class\n\
6041 but a different checksum. You should update the version to ClassDef(%s,%d).\n\
6042 Do not try to write objects with the current class definition,\n\
6043 the files will not be readable.\n"
6045 }
6046 info->CompareContent(this,nullptr,kTRUE,kTRUE,nullptr);
6047 SetBit(kWarned);
6048 }
6049 }
6050 }
6051 if (fCollectionProxy) {
6052 // Update the related pair's TClass if it has already been created.
6053 size_t noffset = 0;
6054 if (strncmp(GetName(), "map<", 4) == 0)
6055 noffset = 3;
6056 else if (strncmp(GetName(), "multimap<", 9) == 0)
6057 noffset = 8;
6058 else if (strncmp(GetName(), "unordered_map<", 14) == 0)
6059 noffset = 13;
6060 else if (strncmp(GetName(), "unordered_multimap<", 19) == 0)
6061 noffset = 18;
6062 if (noffset) {
6063 std::string pairname("pair");
6064 pairname.append(GetName() + noffset);
6065 auto pcl = TClass::GetClass(pairname.c_str(), false, false);
6066 if ( pcl && !pcl->IsLoaded() && !pcl->IsSyntheticPair() )
6067 {
6069
6071 TIter nextClass(gROOT->GetListOfClasses());
6072 while (auto acl = (TClass*)nextClass()) {
6073 if (acl == this) continue;
6074 if (acl->fCollectionProxy && acl->fCollectionProxy->GetValueClass() == pcl) {
6075 acl->fCollectionProxy->Reset();
6076 }
6077 }
6078
6079 TIter next(pcl->GetStreamerInfos());
6080 while (auto info = (TVirtualStreamerInfo*)next()) {
6081 if (info->IsBuilt()) {
6082 info->Clear("build");
6083 info->BuildOld();
6084 }
6085 }
6087 }
6088 }
6089 }
6090}
6091
6092////////////////////////////////////////////////////////////////////////////////
6093/// Returns the properties of the TClass as a bit field stored as a `Long_t` value.
6094///
6095/// The bit values used for the return value are defined in the enum EProperty (in TDictionary.h)
6096///
6097/// Also sets `TObject::fBits` and `fStreamerType` to cache information about the
6098/// class. The bits stored in `TObject::fBits` are
6099/// ~~~ {.cpp}
6100/// kIsTObject : the class inherits from TObject
6101/// kStartWithTObject: TObject is the left-most class in the inheritance tree
6102/// kIsForeign : the class doe not have a Streamer method
6103/// ~~~
6104/// The value of `fStreamerType` are
6105/// ~~~ {.cpp}
6106/// kTObject : the class inherits from TObject
6107/// kForeign : the class does not have a Streamer method
6108/// kInstrumented: the class does have a Streamer method
6109/// kExternal: the class has a free standing way of streaming itself
6110/// kEmulatedStreamer: the class is missing its shared library.
6111/// ~~~
6112///
6113/// Implementation note: the data member fProperty has the value -1
6114/// until it is initialized.
6115
6117{
6118 // Check if we can return without taking the lock,
6119 // this is valid since fProperty is atomic and set as
6120 // the last operation before return.
6121 if (fProperty!=(-1)) return fProperty;
6122
6124
6125 // Check if another thread set fProperty while we
6126 // were waiting.
6127 if (fProperty!=(-1)) return fProperty;
6128
6129 // Avoid asking about the class when it is still building
6130 if (TestBit(kLoading)) return fProperty;
6131
6133 // We have no interpreter information but we already set the streamer type
6134 // so we have already been here and have no new information, then let's
6135 // give up. See the code at this end of this routine (else branch of the
6136 // `if (HasInterpreterInfo()` for the path we took before.
6137 return 0;
6138 }
6139
6140 // When called via TMapFile (e.g. Update()) make sure that the dictionary
6141 // gets allocated on the heap and not in the mapped file.
6142 TMmallocDescTemp setreset;
6143
6144 TClass *kl = const_cast<TClass*>(this);
6145
6147
6149 kl->SetBit(kIsTObject);
6150
6151 // Is it DIRECT inheritance from TObject?
6152 Int_t delta = kl->GetBaseClassOffsetRecurse(TObject::Class());
6153 if (delta==0) kl->SetBit(kStartWithTObject);
6154
6156 }
6157
6158 if (HasInterpreterInfo()) {
6159
6160 // This code used to use ClassInfo_Has|IsValidMethod but since v6
6161 // they return true if the routine is defined in the class or any of
6162 // its parent. We explicitly want to know whether the function is
6163 // defined locally.
6164 if (!const_cast<TClass*>(this)->GetClassMethodWithPrototype("Streamer","TBuffer&",kFALSE)) {
6165
6166 kl->SetBit(kIsForeign);
6168
6169 } else if (streamerType == TClass::kDefault) {
6170 if (kl->fConvStreamerFunc) {
6172 } else if (kl->fStreamerFunc) {
6174 } else {
6175 // We have an automatic streamer using the StreamerInfo .. no need to go through the
6176 // Streamer method function itself.
6178 }
6179 }
6180
6181 if (fStreamer) {
6183 }
6184
6185 if (const_cast<TClass *>(this)->GetClassMethodWithPrototype("Hash", "", kTRUE)) {
6186 kl->SetBit(kHasLocalHashMember);
6187 }
6188
6189 kl->SetStreamerImpl(streamerType);
6190
6191 if (GetClassInfo()) {
6192 // In the case where the TClass for one of ROOT's core class
6193 // (eg TClonesArray for map<int,TClonesArray*>) is requested
6194 // during the execution of rootcling, we could end up in a situation
6195 // where we should have the information (since TClonesArray has
6196 // a dictionary as part of libCore) but do not because the user
6197 // only include a forward declaration of TClonesArray and we do not
6198 // forcefully load the header file either (because the autoparsing
6199 // is intentionally disabled).
6200 kl->fClassProperty = gCling->ClassInfo_ClassProperty(fClassInfo);
6201 // Must set this last since other threads may read fProperty
6202 // and think all test bits have been properly set.
6203 kl->fProperty = gCling->ClassInfo_Property(fClassInfo);
6204 }
6205
6206 } else {
6207
6208 if (fStreamer) {
6210 }
6211
6213
6214 kl->SetStreamerImpl(streamerType);
6215 // fProperty was *not* set so that it can be forced to be recalculated
6216 // next time.
6217 return 0;
6218 }
6219
6220 return fProperty;
6221}
6222
6223////////////////////////////////////////////////////////////////////////////////
6224/// Internal routine to set calculate the class properties that can only be
6225/// known at run-time, for example whether the Hash member function and the
6226/// destructor are consistent.
6227
6229{
6230 // For now, no need to lock this routines as fRuntimeProperties is
6231 // the only atomic set here and this is done at the end
6232 // and there is no downside if the execution is done twice.
6233
6234 // Note SetRuntimeProperties is set to const as it is technically
6235 // thread-safe.
6236
6238
6241
6242 const_cast<TClass *>(this)->fRuntimeProperties = properties;
6243}
6244
6245////////////////////////////////////////////////////////////////////////////////
6246/// Internal routine to set fStreamerImpl based on the value of
6247/// fStreamerType.
6248
6250{
6252 switch (fStreamerType) {
6256 case kInstrumented: {
6260 break;
6261 }
6262
6263 case kEmulatedStreamer: // intentional fall through
6264 case kForeign|kEmulatedStreamer: // intentional fall through
6269 default:
6270 Error("SetStreamerImpl","Unexpected value of fStreamerType: %d",fStreamerType);
6271 }
6272}
6273
6274
6275////////////////////////////////////////////////////////////////////////////////
6276/// Create the collection proxy object (and the streamer object) from
6277/// using the information in the TCollectionProxyInfo.
6278
6280{
6282
6283 delete fCollectionProxy;
6284
6285 // We can not use GetStreamerInfo() instead of TVirtualStreamerInfo::Factory()
6286 // because GetStreamerInfo call TStreamerInfo::Build which need to have fCollectionProxy
6287 // set correctly.
6288
6289 TVirtualCollectionProxy *p = TVirtualStreamerInfo::Factory()->GenExplicitProxy(info,this);
6291
6292 AdoptStreamer(TVirtualStreamerInfo::Factory()->GenExplicitClassStreamer(info,this));
6293
6295 // Numeric Collections have implicit conversions:
6297 }
6298 fCanSplit = -1;
6299}
6300
6301////////////////////////////////////////////////////////////////////////////////
6302/// Change (i.e. set) the title of the TNamed.
6303
6304void TClass::SetContextMenuTitle(const char *title)
6305{
6306 fContextMenuTitle = title;
6307}
6308
6309////////////////////////////////////////////////////////////////////////////////
6310/// This function installs a global IsA function for this class.
6311/// The global IsA function will be used if there is no local IsA function (fIsA)
6312///
6313/// A global IsA function has the signature:
6314///
6315/// ~~~ {.cpp}
6316/// TClass *func( TClass *cl, const void *obj);
6317/// ~~~
6318///
6319/// 'cl' is a pointer to the TClass object that corresponds to the
6320/// 'pointer type' used to retrieve the value 'obj'
6321///
6322/// For example with:
6323/// ~~~ {.cpp}
6324/// TNamed * m = new TNamed("example","test");
6325/// TObject* o = m
6326/// ~~~
6327/// and
6328/// the global IsA function would be called with TObject::Class() as
6329/// the first parameter and the exact numerical value in the pointer
6330/// 'o'.
6331///
6332/// In other word, inside the global IsA function. it is safe to C-style
6333/// cast the value of 'obj' into a pointer to the class described by 'cl'.
6334
6336{
6337 fGlobalIsA = func;
6338}
6339
6340////////////////////////////////////////////////////////////////////////////////
6341/// Call this method to indicate that the shared library containing this
6342/// class's code has been removed (unloaded) from the process's memory
6343/// The caller of this calss should be holding the ROOT Write lock.
6344
6346{
6347 if (TestBit(kUnloaded) && !TestBit(kUnloading)) {
6348 // Don't redo the work.
6349 return;
6350 }
6352
6353 //R__ASSERT(fState == kLoaded);
6354 if (fState != kLoaded) {
6355 Fatal("SetUnloaded","The TClass for %s is being unloaded when in state %d\n",
6356 GetName(),(int)fState);
6357 }
6358
6360
6361 // Make sure SetClassInfo, re-calculated the state.
6363
6364 delete fIsA; fIsA = nullptr;
6365 // Disable the autoloader while calling SetClassInfo, to prevent
6366 // the library from being reloaded!
6367 {
6370 gInterpreter->SetClassInfo(this,kTRUE);
6371 }
6372 fDeclFileName = nullptr;
6373 fDeclFileLine = 0;
6374 fImplFileName = nullptr;
6375 fImplFileLine = 0;
6376 fTypeInfo = nullptr;
6377
6378 if (fMethod.load()) {
6379 (*fMethod).Unload();
6380 }
6381 if (fData.load()) {
6382 (*fData).Unload();
6383 }
6384 if (fUsingData.load()) {
6385 (*fUsingData).Unload();
6386 }
6387 if (fEnums.load()) {
6388 (*fEnums).Unload();
6389 }
6390
6392 fState = kEmulated;
6393 }
6394
6397}
6398
6399////////////////////////////////////////////////////////////////////////////////
6400/// Info is a string describing the names and types of attributes
6401/// written by the class Streamer function.
6402/// If info is an empty string (when called by TObject::StreamerInfo)
6403/// the default Streamer info string is build. This corresponds to
6404/// the case of an automatically generated Streamer.
6405/// In case of user defined Streamer function, it is the user responsibility
6406/// to implement a StreamerInfo function (override TObject::StreamerInfo).
6407/// The user must call IsA()->SetStreamerInfo(info) from this function.
6408
6409TVirtualStreamerInfo *TClass::SetStreamerInfo(Int_t /*version*/, const char * /*info*/)
6410{
6411 // info is specified, nothing to do, except that we should verify
6412 // that it contains a valid descriptor.
6413
6414/*
6415 TDataMember *dm;
6416 Int_t nch = info ? strlen(info) : 0;
6417 Bool_t update = kTRUE;
6418 if (nch != 0) {
6419 //decode strings like "TObject;TAttLine;fA;fB;Int_t i,j,k;"
6420 char *save, *temp, *blank, *colon, *comma;
6421 save = new char[10000];
6422 temp = save;
6423 strlcpy(temp,info,10000);
6424 //remove heading and trailing blanks
6425 while (*temp == ' ') temp++;
6426 while (save[nch-1] == ' ') {nch--; save[nch] = 0;}
6427 if (nch == 0) {delete [] save; return;}
6428 if (save[nch-1] != ';') {save[nch] = ';'; save[nch+1] = 0;}
6429 //remove blanks around , or ;
6430 while ((blank = strstr(temp,"; "))) strcpy(blank+1,blank+2);
6431 while ((blank = strstr(temp," ;"))) strcpy(blank, blank+1);
6432 while ((blank = strstr(temp,", "))) strcpy(blank+1,blank+2);
6433 while ((blank = strstr(temp," ,"))) strcpy(blank, blank+1);
6434 while ((blank = strstr(temp," "))) strcpy(blank, blank+1);
6435 //loop on tokens separated by ;
6436 char *final = new char[1000];
6437 char token[100];
6438 while ((colon=strchr(temp,';'))) {
6439 *colon = 0;
6440 strlcpy(token,temp,100);
6441 blank = strchr(token,' ');
6442 if (blank) {
6443 *blank = 0;
6444 if (!gROOT->GetType(token)) {
6445 Error("SetStreamerInfo","Illegal type: %s in %s",token,info);
6446 return;
6447 }
6448 while (blank) {
6449 strlcat(final,token,1000);
6450 strlcat(final," ",1000);
6451 comma = strchr(blank+1,','); if (comma) *comma=0;
6452 strlcat(final,blank+1,1000);
6453 strlcat(final,";",1000);
6454 blank = comma;
6455 }
6456
6457 } else {
6458 if (TClass::GetClass(token,update)) {
6459 //a class name
6460 strlcat(final,token,1000); strlcat(final,";",1000);
6461 } else {
6462 //a data member name
6463 dm = (TDataMember*)GetListOfDataMembers()->FindObject(token);
6464 if (dm) {
6465 strlcat(final,dm->GetFullTypeName(),1000);
6466 strlcat(final," ",1000);
6467 strlcat(final,token,1000); strlcat(final,";",1000);
6468 } else {
6469 Error("SetStreamerInfo","Illegal name: %s in %s",token,info);
6470 return;
6471 }
6472 }
6473 update = kFALSE;
6474 }
6475 temp = colon+1;
6476 if (*temp == 0) break;
6477 }
6478 //// fStreamerInfo = final;
6479 delete [] final;
6480 delete [] save;
6481 return;
6482 }
6483
6484 //info is empty. Let's build the default Streamer descriptor
6485
6486 char *temp = new char[10000];
6487 temp[0] = 0;
6488 char local[100];
6489
6490 //add list of base classes
6491 TIter nextb(GetListOfBases());
6492 TBaseClass *base;
6493 while ((base = (TBaseClass*) nextb())) {
6494 snprintf(local,100,"%s;",base->GetName());
6495 strlcat(temp,local,10000);
6496 }
6497
6498 //add list of data members and types
6499 TIter nextd(GetListOfDataMembers());
6500 while ((dm = (TDataMember *) nextd())) {
6501 if (dm->IsEnum()) continue;
6502 if (!dm->IsPersistent()) continue;
6503 Long_t property = dm->Property();
6504 if (property & kIsStatic) continue;
6505 TClass *acl = TClass::GetClass(dm->GetTypeName(),update);
6506 update = kFALSE;
6507 if (acl) {
6508 if (acl->GetClassVersion() == 0) continue;
6509 }
6510
6511 // dm->GetArrayIndex() returns an empty string if it does not
6512 // applies
6513 const char * index = dm->GetArrayIndex();
6514 if (strlen(index)==0)
6515 snprintf(local,100,"%s %s;",dm->GetFullTypeName(),dm->GetName());
6516 else
6517 snprintf(local,100,"%s %s[%s];",dm->GetFullTypeName(),dm->GetName(),index);
6518 strlcat(temp,local,10000);
6519 }
6520 //fStreamerInfo = temp;
6521 delete [] temp;
6522*/
6523 return nullptr;
6524}
6525
6526////////////////////////////////////////////////////////////////////////////////
6527/// Return true if the checksum passed as argument is one of the checksum
6528/// value produced by the older checksum calculation algorithm.
6529
6531{
6532 for(UInt_t i = 1; i < kLatestCheckSum; ++i) {
6533 if ( checksum == GetCheckSum( (ECheckSum) i ) ) return kTRUE;
6534 }
6535 return kFALSE;
6536}
6537
6538////////////////////////////////////////////////////////////////////////////////
6539/// Call GetCheckSum with validity check.
6540
6542{
6543 bool isvalid;
6544 return GetCheckSum(code,isvalid);
6545}
6546
6547////////////////////////////////////////////////////////////////////////////////
6548/// Return GetCheckSum(kCurrentCheckSum,isvalid);
6549
6554
6555////////////////////////////////////////////////////////////////////////////////
6556/// Compute and/or return the class check sum.
6557///
6558/// isvalid is set to false, if the function is unable to calculate the
6559/// checksum.
6560///
6561/// The class ckecksum is used by the automatic schema evolution algorithm
6562/// to uniquely identify a class version.
6563/// The check sum is built from the names/types of base classes and
6564/// data members.
6565/// Original algorithm from Victor Perevovchikov (perev@bnl.gov).
6566///
6567/// The valid range of code is determined by ECheckSum.
6568///
6569/// - kNoEnum: data members of type enum are not counted in the checksum
6570/// - kNoRange: return the checksum of data members and base classes, not including the ranges and array size found in comments.
6571/// - kWithTypeDef: use the sugared type name in the calculation.
6572///
6573/// This is needed for backward compatibility.
6574///
6575/// WARNING: this function must be kept in sync with TStreamerInfo::GetCheckSum.
6576/// They are both used to handle backward compatibility and should both return the same values.
6577/// TStreamerInfo uses the information in TStreamerElement while TClass uses the information
6578/// from TClass::GetListOfBases and TClass::GetListOfDataMembers.
6579
6581{
6582 // fCheckSum is an atomic variable. Also once it has
6583 // transition from a zero Value it never changes. If two
6584 // thread reach past this if statement and calculated the
6585 // 'kLastestCheckSum', they will by definition obtain the
6586 // same value, so technically we could simply have:
6587 // if (fCheckSum && code == kCurrentCheckSum) return fCheckSum;
6588 // However save a little bit of barrier time by calling load()
6589 // only once.
6590
6591 isvalid = kTRUE;
6592
6594 if (currentChecksum && code == kCurrentCheckSum) return currentChecksum;
6595
6597
6598 // kCurrentCheckSum (0) is the default parameter value and should be kept
6599 // for backward compatibility, too be able to use the inequality checks,
6600 // we need to set the code to the largest value.
6601 if (code == kCurrentCheckSum) code = kLatestCheckSum;
6602
6603 UInt_t id = 0;
6604
6605 int il;
6606 TString name = GetName();
6607 TString type;
6608 il = name.Length();
6609 for (int i=0; i<il; i++) id = id*3+name[i];
6610
6611 // Here we skip he base classes in case this is a pair or STL collection,
6612 // otherwise, on some STL implementations, it can happen that pair has
6613 // base classes which are an internal implementation detail.
6614 TList *tlb = ((TClass*)this)->GetListOfBases();
6616 // Loop over bases if not a proxied collection or a pair
6617
6619
6620 TBaseClass *tbc=nullptr;
6621 while((tbc=(TBaseClass*)nextBase())) {
6622 name = tbc->GetName();
6624 if (isSTL)
6626 il = name.Length();
6627 for (int i=0; i<il; i++) id = id*3+name[i];
6628 if (code > kNoBaseCheckSum && !isSTL) {
6629 if (tbc->GetClassPointer() == nullptr) {
6630 Error("GetCheckSum","Calculating the checksum for (%s) requires the base class (%s) meta information to be available!",
6631 GetName(),tbc->GetName());
6632 isvalid = kFALSE;
6633 return 0;
6634 } else
6635 id = id*3 + tbc->GetClassPointer()->GetCheckSum();
6636 }
6637 }/*EndBaseLoop*/
6638 }
6639 TList *tlm = ((TClass*)this)->GetListOfDataMembers();
6640 if (tlm) { // Loop over members
6642 TDataMember *tdm=nullptr;
6643 Long_t prop = 0;
6644 while((tdm=(TDataMember*)nextMemb())) {
6645 if (!tdm->IsPersistent()) continue;
6646 // combine properties
6647 prop = (tdm->Property());
6648 TDataType* tdt = tdm->GetDataType();
6649 if (tdt) prop |= tdt->Property();
6650
6651 if ( prop&kIsStatic) continue;
6652 name = tdm->GetName(); il = name.Length();
6653 if ( (code > kNoEnum) && code != kReflex && code != kReflexNoComment && prop&kIsEnum)
6654 id = id*3 + 1;
6655
6656 int i;
6657 for (i=0; i<il; i++) id = id*3+name[i];
6658
6659 if (code > kWithTypeDef || code == kReflexNoComment) {
6660 type = tdm->GetTrueTypeName();
6661 // GetTrueTypeName uses GetFullyQualifiedName which already drops
6662 // the default template parameter, so we no longer need to do this.
6663 //if (TClassEdit::IsSTLCont(type))
6664 // type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
6665 if (code == kReflex || code == kReflexNoComment) {
6666 if (prop&kIsEnum) {
6667 type = "int";
6668 } else {
6669 type.ReplaceAll("ULong64_t","unsigned long long");
6670 type.ReplaceAll("Long64_t","long long");
6671 type.ReplaceAll("<signed char","<char");
6672 type.ReplaceAll(",signed char",",char");
6673 if (type=="signed char") type = "char";
6674 }
6675 }
6676 } else {
6677 type = tdm->GetFullTypeName();
6678 // GetFullTypeName uses GetFullyQualifiedName which already drops
6679 // the default template parameter, so we no longer need to do this.
6680 //if (TClassEdit::IsSTLCont(type))
6681 // type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
6682 }
6683
6684 il = type.Length();
6685 for (i=0; i<il; i++) id = id*3+type[i];
6686
6687 int dim = tdm->GetArrayDim();
6688 if (prop&kIsArray) {
6689 for (int ii=0;ii<dim;ii++) id = id*3+tdm->GetMaxIndex(ii);
6690 }
6691 if (code > kNoRange) {
6692 const char *left;
6693 if (code > TClass::kNoRangeCheck)
6695 else
6696 left = strstr(tdm->GetTitle(),"[");
6697 if (left) {
6698 const char *right = strstr(left,"]");
6699 if (right) {
6700 ++left;
6701 while (left != right) {
6702 id = id*3 + *left;
6703 ++left;
6704 }
6705 }
6706 }
6707 }
6708 }/*EndMembLoop*/
6709 }
6710 // This should be moved to Initialization time however the last time
6711 // we tried this cause problem, in particular in the end-of-process operation.
6712 if (code==kLatestCheckSum) fCheckSum = id;
6713 return id;
6714}
6715
6716////////////////////////////////////////////////////////////////////////////////
6717/// Adopt the Reference proxy pointer to indicate that this class
6718/// represents a reference.
6719/// When a new proxy is adopted, the old one is deleted.
6720
6722{
6724
6725 if ( fRefProxy ) {
6726 fRefProxy->Release();
6727 }
6728 fRefProxy = proxy;
6729 if ( fRefProxy ) {
6730 fRefProxy->SetClass(this);
6731 }
6732 fCanSplit = -1;
6733}
6734
6735////////////////////////////////////////////////////////////////////////////////
6736/// Adopt the TMemberStreamer pointer to by p and use it to Stream non basic
6737/// member name.
6738
6740{
6741 if (fRealData) {
6742
6744
6745 TIter next(fRealData);
6746 TRealData *rd;
6747 while ((rd = (TRealData*)next())) {
6748 if (strcmp(rd->GetName(),name) == 0) {
6749 // If there is a TStreamerElement that took a pointer to the
6750 // streamer we should inform it!
6751 rd->AdoptStreamer(p);
6752 return;
6753 }
6754 }
6755 }
6756
6757 Error("AdoptMemberStreamer","Cannot adope member streamer for %s::%s",GetName(), name);
6758 delete p;
6759
6760// NOTE: This alternative was proposed but not is not used for now,
6761// One of the major difference with the code above is that the code below
6762// did not require the RealData to have been built
6763// if (!fData) return;
6764// const char *n = name;
6765// while (*n=='*') n++;
6766// TString ts(n);
6767// int i = ts.Index("[");
6768// if (i>=0) ts.Remove(i,999);
6769// TDataMember *dm = (TDataMember*)fData->FindObject(ts.Data());
6770// if (!dm) {
6771// Warning("SetStreamer","Can not find member %s::%s",GetName(),name);
6772// return;
6773// }
6774// dm->SetStreamer(p);
6775}
6776
6777////////////////////////////////////////////////////////////////////////////////
6778/// Install a new member streamer (p will be copied).
6779
6784
6785////////////////////////////////////////////////////////////////////////////////
6786/// Function called by the Streamer functions to deserialize information
6787/// from buffer b into object at p.
6788/// This function assumes that the class version and the byte count information
6789/// have been read.
6790/// - version is the version number of the class
6791/// - start is the starting position in the buffer b
6792/// - count is the number of bytes for this object in the buffer
6793
6795{
6796 return b.ReadClassBuffer(this,pointer,version,start,count);
6797}
6798
6799////////////////////////////////////////////////////////////////////////////////
6800/// Function called by the Streamer functions to deserialize information
6801/// from buffer b into object at p.
6802
6804{
6805 return b.ReadClassBuffer(this,pointer);
6806}
6807
6808////////////////////////////////////////////////////////////////////////////////
6809/// Function called by the Streamer functions to serialize object at p
6810/// to buffer b. The optional argument info may be specified to give an
6811/// alternative StreamerInfo instead of using the default StreamerInfo
6812/// automatically built from the class definition.
6813/// For more information, see class TVirtualStreamerInfo.
6814
6815Int_t TClass::WriteBuffer(TBuffer &b, void *pointer, const char * /*info*/)
6816{
6817 b.WriteClassBuffer(this,pointer);
6818 return 0;
6819}
6820
6821////////////////////////////////////////////////////////////////////////////////
6822///There is special streamer for the class
6823
6825{
6826 // case kExternal:
6827 // case kExternal|kEmulatedStreamer:
6828
6829 TClassStreamer *streamer = gThreadTsd ? pThis->GetStreamer() : pThis->fStreamer;
6830 streamer->Stream(b,object,onfile_class);
6831}
6832
6833////////////////////////////////////////////////////////////////////////////////
6834/// Case of TObjects
6835
6836void TClass::StreamerTObject(const TClass* pThis, void *object, TBuffer &b, const TClass * /* onfile_class */)
6837{
6838 // case kTObject:
6839
6840 if (!pThis->fIsOffsetStreamerSet) {
6841 pThis->CalculateStreamerOffset();
6842 }
6843 TObject *tobj = (TObject*)((Longptr_t)object + pThis->fOffsetStreamer);
6844 tobj->Streamer(b);
6845}
6846
6847////////////////////////////////////////////////////////////////////////////////
6848/// Case of TObjects when fIsOffsetStreamerSet is known to have been set.
6849
6850void TClass::StreamerTObjectInitialized(const TClass* pThis, void *object, TBuffer &b, const TClass * /* onfile_class */)
6851{
6852 TObject *tobj = (TObject*)((Longptr_t)object + pThis->fOffsetStreamer);
6853 tobj->Streamer(b);
6854}
6855
6856////////////////////////////////////////////////////////////////////////////////
6857/// Case of TObjects when we do not have the library defining the class.
6858
6860{
6861 // case kTObject|kEmulatedStreamer :
6862 if (b.IsReading()) {
6863 b.ReadClassEmulated(pThis, object, onfile_class);
6864 } else {
6865 b.WriteClassBuffer(pThis, object);
6866 }
6867}
6868
6869////////////////////////////////////////////////////////////////////////////////
6870/// Case of instrumented class with a library
6871
6872void TClass::StreamerInstrumented(const TClass* pThis, void *object, TBuffer &b, const TClass * /* onfile_class */)
6873{
6874 // case kInstrumented:
6875 pThis->fStreamerFunc(b,object);
6876}
6877
6878////////////////////////////////////////////////////////////////////////////////
6879/// Case of instrumented class with a library
6880
6882{
6883 // case kInstrumented:
6884 pThis->fConvStreamerFunc(b,object,onfile_class);
6885}
6886
6887////////////////////////////////////////////////////////////////////////////////
6888/// Case of where we should directly use the StreamerInfo.
6889/// - case kForeign:
6890/// - case kForeign|kEmulatedStreamer:
6891/// - case kInstrumented|kEmulatedStreamer:
6892/// - case kEmulatedStreamer:
6893
6895{
6896 if (b.IsReading()) {
6897 b.ReadClassBuffer(pThis, object, onfile_class);
6898 //ReadBuffer (b, object);
6899 } else {
6900 //WriteBuffer(b, object);
6901 b.WriteClassBuffer(pThis, object);
6902 }
6903}
6904
6905////////////////////////////////////////////////////////////////////////////////
6906/// Default streaming in cases where either we have no way to know what to do
6907/// or if Property() has not yet been called.
6908
6910{
6911 if (pThis->fProperty==(-1)) {
6912 pThis->Property();
6913 }
6914
6915 // We could get here because after this thread started StreamerDefault
6916 // *and* before check fProperty, another thread might have call Property
6917 // and this fProperty when we read it, is not -1 and fStreamerImpl is
6918 // supposed to be set properly (no longer pointing to the default).
6919 if (pThis->fStreamerImpl.load() == &TClass::StreamerDefault) {
6920 pThis->Fatal("StreamerDefault", "fStreamerImpl not properly initialized (%d)", pThis->fStreamerType);
6921 } else {
6922 (*pThis->fStreamerImpl)(pThis,object,b,onfile_class);
6923 }
6924}
6925
6926////////////////////////////////////////////////////////////////////////////////
6927/// Adopt a TClassStreamer object. Ownership is transfered to this TClass
6928/// object.
6929
6931{
6932// // This code can be used to quickly test the STL Emulation layer
6933// Int_t k = TClassEdit::IsSTLCont(GetName());
6934// if (k==1||k==-1) { delete str; return; }
6935
6937
6938 if (fStreamer) delete fStreamer;
6939 if (str) {
6941 fStreamer = str;
6943 } else if (fStreamer) {
6944 // Case where there was a custom streamer and it is hereby removed,
6945 // we need to reset fStreamerType
6946 fStreamer = str;
6948 if (fProperty != -1) {
6949 fProperty = -1;
6950 Property();
6951 }
6952 }
6953}
6954
6955////////////////////////////////////////////////////////////////////////////////
6956/// Set a wrapper/accessor function around this class custom streamer.
6957
6959{
6961 if (fProperty != -1 && !fConvStreamerFunc &&
6962 ( (fStreamerFunc == nullptr && strm != nullptr) || (fStreamerFunc != nullptr && strm == nullptr) ) )
6963 {
6965
6966 // Since initialization has already been done, make sure to tweak it
6967 // for the new state.
6971 }
6972 } else {
6974 }
6975 fCanSplit = -1;
6976}
6977
6978////////////////////////////////////////////////////////////////////////////////
6979/// Set a wrapper/accessor function around this class custom conversion streamer.
6980
6982{
6984 if (fProperty != -1 &&
6985 ( (fConvStreamerFunc == nullptr && strm != nullptr) || (fConvStreamerFunc != nullptr && strm == nullptr) ) )
6986 {
6988
6989 // Since initialization has already been done, make sure to tweak it
6990 // for the new state.
6994 }
6995 } else {
6997 }
6998 fCanSplit = -1;
6999}
7000
7001
7002////////////////////////////////////////////////////////////////////////////////
7003/// Install a new wrapper around 'Merge'.
7004
7009
7010////////////////////////////////////////////////////////////////////////////////
7011/// Install a new wrapper around 'ResetAfterMerge'.
7012
7017
7018////////////////////////////////////////////////////////////////////////////////
7019/// Install a new wrapper around 'new'.
7020
7025
7026////////////////////////////////////////////////////////////////////////////////
7027/// Install a new wrapper around 'new []'.
7028
7033
7034////////////////////////////////////////////////////////////////////////////////
7035/// Install a new wrapper around 'delete'.
7036
7041
7042////////////////////////////////////////////////////////////////////////////////
7043/// Install a new wrapper around 'delete []'.
7044
7049
7050////////////////////////////////////////////////////////////////////////////////
7051/// Install a new wrapper around the destructor.
7052
7057
7058////////////////////////////////////////////////////////////////////////////////
7059/// Install a new wrapper around the directory auto add function.
7060/// The function autoAddFunc has the signature void (*)(void *obj, TDirectory dir)
7061/// and should register 'obj' to the directory if dir is not null
7062/// and unregister 'obj' from its current directory if dir is null
7063
7068
7069////////////////////////////////////////////////////////////////////////////////
7070/// Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum
7071
7073{
7075 if (guess && guess->GetCheckSum() == checksum) {
7076 return guess;
7077 } else {
7078 if (fCheckSum == checksum)
7079 return GetStreamerInfo(0, isTransient);
7080
7082
7084 for (Int_t i=-1;i<ninfos;++i) {
7085 // TClass::fStreamerInfos has a lower bound not equal to 0,
7086 // so we have to use At and should not use UncheckedAt
7088 if (info && info->GetCheckSum() == checksum) {
7089 // R__ASSERT(i==info->GetClassVersion() || (i==-1&&info->GetClassVersion()==1));
7090 info->BuildOld();
7091 if (info->IsCompiled()) fLastReadInfo = info;
7092 return info;
7093 }
7094 }
7095 return nullptr;
7096 }
7097}
7098
7099////////////////////////////////////////////////////////////////////////////////
7100/// Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum
7101
7103{
7105 Int_t ninfos = arr->GetEntriesFast()-1;
7106 for (Int_t i=-1;i<ninfos;i++) {
7107 // TClass::fStreamerInfos has a lower bound not equal to 0,
7108 // so we have to use At and should not use UncheckedAt
7110 if (!info) continue;
7111 if (info->GetCheckSum() == checksum) {
7112 R__ASSERT(i==info->GetClassVersion() || (i==-1&&info->GetClassVersion()==1));
7113 return info;
7114 }
7115 }
7116 return nullptr;
7117}
7118
7119////////////////////////////////////////////////////////////////////////////////
7120/// Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this class, if any.
7121
7123{
7124 TClass *cl = TClass::GetClass( classname );
7125 if( !cl )
7126 return nullptr;
7127 return GetConversionStreamerInfo( cl, version );
7128}
7129
7130////////////////////////////////////////////////////////////////////////////////
7131/// Return a Conversion StreamerInfo from the class represented by cl for version number 'version' to this class, if any.
7132
7134{
7135 //----------------------------------------------------------------------------
7136 // Check if the classname was specified correctly
7137 /////////////////////////////////////////////////////////////////////////////
7138
7139 if( !cl )
7140 return nullptr;
7141
7142 if( cl == this )
7143 return GetStreamerInfo( version );
7144
7145 //----------------------------------------------------------------------------
7146 // Check if we already have it
7147 /////////////////////////////////////////////////////////////////////////////
7148
7149 TObjArray* arr = nullptr;
7150 if (fConversionStreamerInfo.load()) {
7151 std::map<std::string, TObjArray*>::iterator it;
7153
7154 it = (*fConversionStreamerInfo).find( cl->GetName() );
7155
7156 if( it != (*fConversionStreamerInfo).end() ) {
7157 arr = it->second;
7158 }
7159
7160 if( arr && version >= -1 && version < arr->GetSize() && arr->At( version ) )
7161 return (TVirtualStreamerInfo*) arr->At( version );
7162 }
7163
7165
7166 //----------------------------------------------------------------------------
7167 // We don't have the streamer info so find it in other class
7168 /////////////////////////////////////////////////////////////////////////////
7169
7170 const TObjArray *clSI = cl->GetStreamerInfos();
7171 TVirtualStreamerInfo* info = nullptr;
7172 if( version >= -1 && version < clSI->GetSize() )
7174
7175 if (!info && cl->GetCollectionProxy()) {
7176 info = cl->GetStreamerInfo(); // instantiate the StreamerInfo for STL collections.
7177 }
7178
7179 if( !info )
7180 return nullptr;
7181
7182 //----------------------------------------------------------------------------
7183 // We have the right info so we need to clone it to create new object with
7184 // non artificial streamer elements and we should build it for current class
7185 /////////////////////////////////////////////////////////////////////////////
7186
7187 info = (TVirtualStreamerInfo*)info->Clone();
7188
7189 // When cloning the StreamerInfo we record (and thus restore)
7190 // the absolute value of the version, let's restore the sign.
7191 if (version == -1)
7192 info->SetClassVersion(-1);
7193
7194 if( !info->BuildFor( this ) ) {
7195 delete info;
7196 return nullptr;
7197 }
7198
7199 if (!info->IsCompiled()) {
7200 // Streamer info has not been compiled, but exists.
7201 // Therefore it was read in from a file and we have to do schema evolution?
7202 // Or it didn't have a dictionary before, but does now?
7203 info->BuildOld();
7204 }
7205
7206 //----------------------------------------------------------------------------
7207 // Cache this streamer info
7208 /////////////////////////////////////////////////////////////////////////////
7209
7210 if (!arr) {
7211 arr = new TObjArray(version+10, -1);
7212 if (!fConversionStreamerInfo.load()) {
7213 fConversionStreamerInfo = new std::map<std::string, TObjArray*>();
7214 }
7215 (*fConversionStreamerInfo)[cl->GetName()] = arr;
7216 }
7217 if (arr->At(info->GetClassVersion())) {
7218 Error("GetConversionStreamerInfo", "Conversion StreamerInfo from %s to %s version %d has already been created",
7219 this->GetName(), info->GetName(), info->GetClassVersion());
7220 delete arr->At(info->GetClassVersion());
7221 }
7222 arr->AddAtAndExpand( info, info->GetClassVersion() );
7223 return info;
7224}
7225
7226////////////////////////////////////////////////////////////////////////////////
7227/// Return a Conversion StreamerInfo from the class 'classname' for the layout represented by 'checksum' to this class, if any.
7228
7230{
7231 TClass *cl = TClass::GetClass( classname );
7232 if( !cl )
7233 return nullptr;
7235}
7236
7237////////////////////////////////////////////////////////////////////////////////
7238/// Return a Conversion StreamerInfo from the class represented by cl for the layout represented by 'checksum' to this class, if any.
7239
7241{
7242 //---------------------------------------------------------------------------
7243 // Check if the classname was specified correctly
7244 /////////////////////////////////////////////////////////////////////////////
7245
7246 if( !cl )
7247 return nullptr;
7248
7249 if( cl == this )
7250 return FindStreamerInfo( checksum );
7251
7252 //----------------------------------------------------------------------------
7253 // Check if we already have it
7254 /////////////////////////////////////////////////////////////////////////////
7255
7256 TObjArray* arr = nullptr;
7257 TVirtualStreamerInfo* info = nullptr;
7258 if (fConversionStreamerInfo.load()) {
7259 std::map<std::string, TObjArray*>::iterator it;
7260
7262
7263 it = (*fConversionStreamerInfo).find( cl->GetName() );
7264
7265 if( it != (*fConversionStreamerInfo).end() ) {
7266 arr = it->second;
7267 }
7268 if (arr) {
7270 }
7271 }
7272
7273 if( info )
7274 return info;
7275
7277
7278 //----------------------------------------------------------------------------
7279 // Get it from the foreign class
7280 /////////////////////////////////////////////////////////////////////////////
7281
7283
7284 if( !info )
7285 return nullptr;
7286
7287 //----------------------------------------------------------------------------
7288 // We have the right info so we need to clone it to create new object with
7289 // non artificial streamer elements and we should build it for current class
7290 /////////////////////////////////////////////////////////////////////////////
7291
7292 int version = info->GetClassVersion();
7293 info = (TVirtualStreamerInfo*)info->Clone();
7294
7295 // When cloning the StreamerInfo we record (and thus restore)
7296 // the absolute value of the version, let's restore the sign.
7297 if (version == -1)
7298 info->SetClassVersion(-1);
7299
7300 if( !info->BuildFor( this ) ) {
7301 delete info;
7302 return nullptr;
7303 }
7304
7305 if (!info->IsCompiled()) {
7306 // Streamer info has not been compiled, but exists.
7307 // Therefore it was read in from a file and we have to do schema evolution?
7308 // Or it didn't have a dictionary before, but does now?
7309 info->BuildOld();
7310 }
7311
7312 //----------------------------------------------------------------------------
7313 // Cache this streamer info
7314 /////////////////////////////////////////////////////////////////////////////
7315
7316 if (!arr) {
7317 arr = new TObjArray(16, -2);
7318 if (!fConversionStreamerInfo.load()) {
7319 fConversionStreamerInfo = new std::map<std::string, TObjArray*>();
7320 }
7321 (*fConversionStreamerInfo)[cl->GetName()] = arr;
7322 }
7323 arr->AddAtAndExpand( info, info->GetClassVersion() );
7324
7325 return info;
7326}
7327
7328////////////////////////////////////////////////////////////////////////////////
7329/// Register the StreamerInfo in the given slot, change the State of the
7330/// TClass as appropriate.
7331
7333{
7334 if (info) {
7336 Int_t slot = info->GetClassVersion();
7338 && fStreamerInfo->At(slot) != nullptr
7339 && fStreamerInfo->At(slot) != info) {
7340 Error("RegisterStreamerInfo",
7341 "Register StreamerInfo for %s on non-empty slot (%d).",
7342 GetName(),slot);
7343 }
7345 if (fState <= kForwardDeclared) {
7346 fState = kEmulated;
7347 if (fCheckSum==0 && slot==fClassVersion) fCheckSum = info->GetCheckSum();
7348 }
7349 }
7350}
7351
7352////////////////////////////////////////////////////////////////////////////////
7353/// Remove and delete the StreamerInfo in the given slot.
7354/// Update the slot accordingly.
7355
7357{
7358 if (fStreamerInfo->GetSize() >= slot) {
7362 if (fLastReadInfo.load() == info)
7363 fLastReadInfo = nullptr;
7364 if (fCurrentInfo.load() == info)
7365 fCurrentInfo = nullptr;
7366 delete info;
7367 if (fState == kEmulated && fStreamerInfo->GetEntries() == 0) {
7369 }
7370 }
7371}
7372
7373////////////////////////////////////////////////////////////////////////////////
7374/// Return true is the Hash/RecursiveRemove setup is consistent, i.e. when all
7375/// classes in the class hierarchy that overload TObject::Hash do call
7376/// ROOT::CallRecursiveRemoveIfNeeded in their destructor.
7377/// i.e. it is safe to call the Hash virtual function during the RecursiveRemove operation.
7378/// This routines is used for a small subset of the class for which we need
7379/// the answer before gROOT is properly initialized.
7380
7382{
7383 // Hand selection of correct classes, those classes should be
7384 // cross-checked in testHashRecursiveRemove.cxx
7385 static const char *handVerified[] = {
7386 "TEnvRec", "TDataType", "TObjArray", "TList", "THashList",
7387 "TClass", "TCling", "TInterpreter", "TMethod", "ROOT::Internal::TCheckHashRecursiveRemoveConsistency",
7388 "TCheckHashRecursiveRemoveConsistency", "TGWindow",
7389 "TDirectory", "TDirectoryFile", "TObject", "TH1",
7390 "TQClass", "TGlobal" };
7391
7392 if (cname && cname[0]) {
7393 for (auto cursor : handVerified) {
7394 if (strcmp(cname, cursor) == 0)
7395 return true;
7396 }
7397 }
7398 return false;
7399}
7400
7401////////////////////////////////////////////////////////////////////////////////
7402/// Return true is the Hash/RecursiveRemove setup is consistent, i.e. when all
7403/// classes in the class hierarchy that overload TObject::Hash do call
7404/// ROOT::CallRecursiveRemoveIfNeeded in their destructor.
7405/// i.e. it is safe to call the Hash virtual function during the RecursiveRemove operation.
7406
7408{
7409 return clRef.HasConsistentHashMember();
7410}
7411
7412////////////////////////////////////////////////////////////////////////////////
7413/// Return true if we have access to a constructor usable for I/O. This is
7414/// typically the default constructor but can also be a constructor specifically
7415/// marked for I/O (for example a constructor taking a TRootIOCtor* as an
7416/// argument). In other words, if this routine returns true, TClass::New is
7417/// guarantee to succeed.
7418/// To know if the class described by this TClass has a default constructor
7419/// (public or not), use
7420/// \code{.cpp}
7421/// cl->GetProperty() & kClassHasDefaultCtor
7422/// \endcode
7423/// To know if the class described by this TClass has a public default
7424/// constructor use:
7425/// \code{.cpp}
7426/// gInterpreter->ClassInfo_HasDefaultConstructor(aClass->GetClassInfo());
7427/// \endcode
7428
7430{
7431
7432 if (fNew) return kTRUE;
7433
7434 if (HasInterpreterInfo()) {
7437 }
7438 if (fCollectionProxy) {
7439 return kTRUE;
7440 }
7441 if (fCurrentInfo.load()) {
7442 // Emulated class, we know how to construct them via the TStreamerInfo
7443 return kTRUE;
7444 }
7445 return kFALSE;
7446}
7447
7448////////////////////////////////////////////////////////////////////////////////
7449/// Returns true if this class has an definition and/or overload of the
7450/// member function Hash.
7451///
7452/// For example to test if the class overload TObject::Hash use
7453/// ~~~ {.cpp}
7454/// if (cl->IsTObject() && cl->HasLocalHashMember())
7455/// ~~~
7456
7458{
7459 if (fProperty == (-1))
7460 Property();
7462}
7463
7464////////////////////////////////////////////////////////////////////////////////
7465/// Return the wrapper around Merge.
7466
7468{
7469 return fMerge;
7470}
7471
7472////////////////////////////////////////////////////////////////////////////////
7473/// Return the wrapper around Merge.
7474
7479
7480////////////////////////////////////////////////////////////////////////////////
7481/// Return the wrapper around new ThisClass().
7482
7484{
7485 return fNew;
7486}
7487
7488////////////////////////////////////////////////////////////////////////////////
7489/// Return the wrapper around new ThisClass[].
7490
7492{
7493 return fNewArray;
7494}
7495
7496////////////////////////////////////////////////////////////////////////////////
7497/// Return the wrapper around delete ThiObject.
7498
7500{
7501 return fDelete;
7502}
7503
7504////////////////////////////////////////////////////////////////////////////////
7505/// Return the wrapper around delete [] ThiObject.
7506
7511
7512////////////////////////////////////////////////////////////////////////////////
7513/// Return the wrapper around the destructor
7514
7516{
7517 return fDestructor;
7518}
7519
7520////////////////////////////////////////////////////////////////////////////////
7521/// Return the wrapper around the directory auto add function.
7522
#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
virtual RooAbsTestStatistic * create(const char *name, const char *title, RooAbsReal &real, RooAbsData &data, const RooArgSet &projDeps, Configuration const &cfg)=0
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Definition RtypesCore.h:63
int Int_t
Definition RtypesCore.h:45
long Longptr_t
Definition RtypesCore.h:82
short Version_t
Definition RtypesCore.h:65
unsigned long ULong_t
Definition RtypesCore.h:55
long Long_t
Definition RtypesCore.h:54
unsigned int UInt_t
Definition RtypesCore.h:46
unsigned long ULongptr_t
Definition RtypesCore.h:83
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
constexpr Ssiz_t kNPOS
Definition RtypesCore.h:124
constexpr 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:377
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:79
ROOT::TMapTypeToTClass IdMap_t
Definition TClass.h:78
void(* tcling_callfunc_Wrapper_t)(void *, int, void **, void *)
const Bool_t kIterBackward
Definition TCollection.h:43
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t cursor
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h prop
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char cname
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t property
Option_t Option_t TPoint TPoint const char text
char name[80]
Definition TGX11.cxx:110
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:622
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:414
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2503
@ kDefault
Definition TSystem.h:237
R__EXTERN TSystem * gSystem
Definition TSystem.h:566
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:17536
#define free
Definition civetweb.c:1539
#define snprintf
Definition civetweb.c:1540
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
static TClass * Class()
TBrowser * fBrowser
Definition TClass.cxx:904
Bool_t IsTreatingNonAccessibleTypes() override
Definition TClass.cxx:914
TAutoInspector(TBrowser *b)
Definition TClass.cxx:906
virtual ~TAutoInspector()
Definition TClass.cxx:911
void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient) override
This method is called from ShowMembers() via AutoBrowse().
Definition TClass.cxx:920
Each class (see TClass) has a linked list of its base class(es).
Definition TBaseClass.h:33
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.
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) override
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.
TClassRef is used to implement a permanent reference to a TClass object.
Definition TClassRef.h:28
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:81
UInt_t GetCheckSum(ECheckSum code=kCurrentCheckSum) const
Call GetCheckSum with validity check.
Definition TClass.cxx:6541
Bool_t IsSyntheticPair() const
Definition TClass.h:521
RepoCont_t fObjectVersionRepository
Definition TClass.h:344
ShowMembersFunc_t fShowMembers
Definition TClass.h:225
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition TClass.cxx:3466
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:3813
void ForceReload(TClass *oldcl)
we found at least one equivalent.
Definition TClass.cxx:1336
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:2320
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:7064
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:5220
static TDeclNameRegistry fNoInfoOrEmuOrFwdDeclNameRegistry
Definition TClass.h:328
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:6721
TMethod * GetClassMethod(Longptr_t faddr)
Look for a method in this class that has the interface function address faddr.
Definition TClass.cxx:4510
TVirtualStreamerInfo * DetermineCurrentStreamerInfo()
Determine and set pointer to current TVirtualStreamerInfo.
Definition TClass.cxx:5711
void Browse(TBrowser *b) override
This method is called by a browser to get the class information.
Definition TClass.cxx:2011
EState GetState() const
Definition TClass.h:488
ROOT::ESTLType GetCollectionType() const
Return the 'type' of the STL the TClass is representing.
Definition TClass.cxx:2887
void Draw(Option_t *option="") override
Draw detailed class inheritance structure.
Definition TClass.cxx:2488
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:6739
void ResetInstanceCount()
Definition TClass.h:547
ClassStreamerFunc_t GetStreamerFunc() const
Get a wrapper/accessor function around this class custom streamer (member function).
Definition TClass.cxx:2940
void RemoveStreamerInfo(Int_t slot)
Remove and delete the StreamerInfo in the given slot.
Definition TClass.cxx:7356
void SetCanSplit(Int_t splitmode)
Set the splitability of this class:
Definition TClass.cxx:5685
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:3768
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:4736
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5005
void SetMerge(ROOT::MergeFunc_t mergeFunc)
Install a new wrapper around 'Merge'.
Definition TClass.cxx:7005
ConvSIMap_t fConversionStreamerInfo
Definition TClass.h:199
ROOT::DirAutoAdd_t fDirAutoAdd
Definition TClass.h:240
Bool_t HasDataMemberInfo() const
Definition TClass.h:407
TVirtualRefProxy * fRefProxy
cached streamer info used in the last read.
Definition TClass.h:280
TList * GetMenuList() const
Return the list of menu items associated with the class.
Definition TClass.cxx:4368
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:4438
static TClass * Load(TBuffer &b)
Load class description from I/O buffer and return class object.
Definition TClass.cxx:5742
EState fState
cached of the streaming method to use
Definition TClass.h:277
ROOT::DesFunc_t GetDestructor() const
Return the wrapper around the destructor.
Definition TClass.cxx:7515
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:4483
void CopyCollectionProxy(const TVirtualCollectionProxy &)
Replaces the collection proxy for this class.
Definition TClass.cxx:2471
Int_t fStreamerType
saved info to call Streamer
Definition TClass.h:276
TList * fRealData
Definition TClass.h:200
UInt_t fOnHeap
Definition TClass.h:218
void ls(Option_t *opt="") const override
The ls function lists the contents of a class on stdout.
Definition TClass.cxx:4285
std::atomic< TList * > fBase
Definition TClass.h:201
std::atomic< Char_t > fCanSplit
Definition TClass.h:245
Bool_t HasDictionary() const
Check whether a class has a dictionary or not.
Definition TClass.cxx:3933
const TList * GetListOfAllPublicMethods(Bool_t load=kTRUE)
Returns a list of all public methods of this class and its base classes.
Definition TClass.cxx:3872
TList * GetListOfAllPublicDataMembers(Bool_t load=kTRUE)
Returns a list of all public data members of this class and its base classes.
Definition TClass.cxx:3889
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:1661
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:5427
Version_t fClassVersion
Definition TClass.h:221
std::atomic< TVirtualStreamerInfo * > fCurrentInfo
Current 'state' of the class (Emulated,Interpreted,Loaded)
Definition TClass.h:278
TList * GetListOfFunctionTemplates(Bool_t load=kTRUE)
Return TListOfFunctionTemplates for a class.
Definition TClass.cxx:3825
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:4942
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:7332
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:7029
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:2206
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:6279
static Bool_t HasDictionarySelection(const char *clname)
Check whether a class has a dictionary or ROOT can load one.
Definition TClass.cxx:3944
void AdoptSchemaRules(ROOT::Detail::TSchemaRuleSet *rules)
Adopt a new set of Data Model Evolution rules.
Definition TClass.cxx:1921
static void StreamerInstrumented(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of instrumented class with a library.
Definition TClass.cxx:6872
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:6409
static std::atomic< Int_t > fgClassCount
Definition TClass.h:326
TVirtualStreamerInfo * GetCurrentStreamerInfo()
Definition TClass.h:439
ROOT::DirAutoAdd_t GetDirectoryAutoAdd() const
Return the wrapper around the directory auto add function.
Definition TClass.cxx:7523
void AddImplFile(const char *filename, int line)
Definition TClass.cxx:1953
TCollection * GetListOfMethodOverloads(const char *name) const
Return the collection of functions named "name".
Definition TClass.cxx:3854
std::atomic< TListOfEnums * > fEnums
Definition TClass.h:205
static Bool_t HasNoInfoOrEmuOrFwdDeclaredDecl(const char *)
Definition TClass.cxx:3425
TVirtualMutex * fOVRMutex
Definition TClass.h:342
TList * GetListOfEnums(Bool_t load=kTRUE)
Return a list containing the TEnums of a class.
Definition TClass.cxx:3713
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:5959
TList * GetListOfMethods(Bool_t load=kTRUE)
Return list containing the TMethods of a class.
Definition TClass.cxx:3839
TClass()
Internal, default constructor.
Definition TClass.cxx:1065
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:4600
std::atomic< Bool_t > fIsOffsetStreamerSet
Indicates whether the ClassInfo is supposed to be available.
Definition TClass.h:261
void IgnoreTObjectStreamer(Bool_t ignore=kTRUE)
When the class kIgnoreTObjectStreamer bit is set, the automatically generated Streamer will not call ...
Definition TClass.cxx:4868
TClassStreamer * GetStreamer() const
Return the Streamer Class allowing streaming (if any).
Definition TClass.cxx:2915
static IdMap_t * GetIdMap()
Definition TClass.cxx:469
void SetDelete(ROOT::DelFunc_t deleteFunc)
Install a new wrapper around 'delete'.
Definition TClass.cxx:7037
static Int_t AutoBrowse(TObject *obj, TBrowser *browser)
Browse external object inherited from TObject.
Definition TClass.cxx:1967
ROOT::NewFunc_t GetNew() const
Return the wrapper around new ThisClass().
Definition TClass.cxx:7483
TClass * GetBaseClass(const char *classname)
Return pointer to the base class "classname".
Definition TClass.cxx:2656
Longptr_t GetDataMemberOffset(const char *membername) const
return offset for member name.
Definition TClass.cxx:3504
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:4581
void SetDestructor(ROOT::DesFunc_t destructorFunc)
Install a new wrapper around the destructor.
Definition TClass.cxx:7053
virtual void PostLoadCheck()
Do the initialization that can only be done after the CINT dictionary has been fully populated and ca...
Definition TClass.cxx:5989
void LoadClassInfo() const
Try to load the ClassInfo if available.
Definition TClass.cxx:5851
void SetResetAfterMerge(ROOT::ResetAfterMergeFunc_t resetFunc)
Install a new wrapper around 'ResetAfterMerge'.
Definition TClass.cxx:7013
TVirtualStreamerInfo * GetStreamerInfoImpl(Int_t version, Bool_t silent) const
Definition TClass.cxx:4661
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:6530
TViewPubFunctions * fAllPubMethod
Definition TClass.h:210
Bool_t HasInterpreterInfo() const
Definition TClass.h:410
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:3954
ROOT::Detail::TSchemaRuleSet * fSchemaRules
Pointer to reference proxy if this class represents a reference.
Definition TClass.h:281
std::atomic< Long_t > fProperty
Definition TClass.h:255
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:6909
void SetUnloaded()
Call this method to indicate that the shared library containing this class's code has been removed (u...
Definition TClass.cxx:6345
ROOT::DelArrFunc_t GetDeleteArray() const
Return the wrapper around delete [] ThiObject.
Definition TClass.cxx:7507
Bool_t HasInterpreterInfoInMemory() const
Definition TClass.h:409
TList * fClassMenuList
Definition TClass.h:211
ClassConvStreamerFunc_t fConvStreamerFunc
Definition TClass.h:242
void BuildRealData(void *pointer=nullptr, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition TClass.cxx:2032
void SetRuntimeProperties()
Internal routine to set calculate the class properties that can only be known at run-time,...
Definition TClass.cxx:6228
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:2113
static TClass * LoadClass(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition TClass.cxx:5776
TString fSharedLibs
Definition TClass.h:227
const std::type_info * GetTypeInfo() const
Definition TClass.h:496
void SetStreamerImpl(Int_t streamerType)
Internal routine to set fStreamerImpl based on the value of fStreamerType.
Definition TClass.cxx:6249
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition TClass.cxx:3797
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:4354
static DeclIdMap_t * GetDeclIdMap()
Definition TClass.cxx:480
Short_t GetDeclFileLine() const
Definition TClass.h:429
void SetStreamerFunc(ClassStreamerFunc_t strm)
Set a wrapper/accessor function around this class custom streamer.
Definition TClass.cxx:6958
const char * GetImplFileName() const
Definition TClass.h:456
TList * GetListOfRealData() const
Definition TClass.h:453
Int_t Size() const
Return size of object of this class.
Definition TClass.cxx:5731
void SetCurrentStreamerInfo(TVirtualStreamerInfo *info)
Set pointer to current TVirtualStreamerInfo.
Definition TClass.cxx:5723
static DictFuncPtr_t GetDict(const char *cname)
Return a pointer to the dictionary loading function generated by rootcint.
Definition TClass.cxx:3449
Longptr_t fOffsetStreamer
Properties that can only be evaluated at run-time.
Definition TClass.h:275
Int_t fSizeof
Definition TClass.h:243
ROOT::NewArrFunc_t GetNewArray() const
Return the wrapper around new ThisClass[].
Definition TClass.cxx:7491
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:6859
ROOT::NewFunc_t fNew
Definition TClass.h:235
@ kLoading
Definition TClass.h:332
@ kUnloading
Definition TClass.h:332
ROOT::ResetAfterMergeFunc_t GetResetAfterMerge() const
Return the wrapper around Merge.
Definition TClass.cxx:7475
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:4554
void SetGlobalIsA(IsAGlobalFunc_t)
This function installs a global IsA function for this class.
Definition TClass.cxx:6335
void GetMissingDictionariesForMembers(TCollection &result, TCollection &visited, bool recurse)
Verify the Data Members.
Definition TClass.cxx:3971
TObjArray * fStreamerInfo
Definition TClass.h:198
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition TClass.cxx:1933
TObject * Clone(const char *newname="") const override
Create a Clone of this TClass object using a different name but using the same 'dictionary'.
Definition TClass.cxx:2407
TVirtualCollectionProxy * fCollectionProxy
Definition TClass.h:220
static ENewType IsCallingNew()
Static method returning the defConstructor flag passed to TClass::New().
Definition TClass.cxx:5932
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition TClass.cxx:3663
void Store(TBuffer &b) const
Store class description on I/O buffer.
Definition TClass.cxx:5890
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:2243
static THashTable * fgClassTypedefHash
Definition TClass.h:338
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:1370
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:6894
const TObjArray * GetStreamerInfos() const
Definition TClass.h:492
void SetClassVersion(Version_t version)
Private function.
Definition TClass.cxx:5702
char * EscapeChars(const char *text) const
Introduce an escape character (@) in front of a special chars.
Definition TClass.cxx:2569
const std::type_info * fTypeInfo
Definition TClass.h:224
std::atomic< TVirtualStreamerInfo * > fLastReadInfo
cached current streamer info.
Definition TClass.h:279
static void StreamerTObject(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of TObjects.
Definition TClass.cxx:6836
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition TClass.cxx:5942
@ kDefault
Definition TClass.h:334
@ kEmulatedStreamer
Definition TClass.h:334
@ kExternal
Definition TClass.h:334
@ kForeign
Definition TClass.h:334
@ kInstrumented
Definition TClass.h:334
@ kTObject
Definition TClass.h:334
static Bool_t AddRule(const char *rule)
Add a schema evolution customization rule.
Definition TClass.cxx:1891
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition TClass.cxx:5968
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:7457
void DeleteArray(void *ary, Bool_t dtorOnly=kFALSE)
Explicitly call operator delete[] for an array.
Definition TClass.cxx:5556
ClassConvStreamerFunc_t GetConvStreamerFunc() const
Get a wrapper/accessor function around this class custom conversion streamer (member function).
Definition TClass.cxx:2948
Bool_t IsForeign() const
Return kTRUE is the class is Foreign (the class does not have a Streamer method).
Definition TClass.cxx:5977
ClassInfo_t * GetClassInfo() const
Definition TClass.h:433
ROOT::DelFunc_t fDelete
Definition TClass.h:237
TViewPubDataMembers * fAllPubData
Definition TClass.h:209
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:4626
void AdoptStreamer(TClassStreamer *strm)
Adopt a TClassStreamer object.
Definition TClass.cxx:6930
TClass * GetBaseDataMember(const char *datamember)
Return pointer to (base) class that contains datamember.
Definition TClass.cxx:2828
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
void Dump() const override
Dump contents of object on stdout.
Definition TClass.h:398
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4901
Int_t GetBaseClassOffset(const TClass *toBase, void *address=nullptr, bool isDerivedObject=true)
Definition TClass.cxx:2792
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:5236
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2898
void ResetCaches()
To clean out all caches.
Definition TClass.cxx:4242
std::atomic< Bool_t > fVersionUsed
saved remember if fOffsetStreamer has been set.
Definition TClass.h:262
Long_t ClassProperty() const
Return the C++ property of this class, eg.
Definition TClass.cxx:2397
const char * GetSharedLibs()
Get the list of shared libraries containing the code for class cls.
Definition TClass.cxx:3650
void CalculateStreamerOffset() const
Calculate the offset between an object of this class to its base class TObject.
Definition TClass.cxx:2184
void GetMissingDictionariesForPairElements(TCollection &result, TCollection &visited, bool recurse)
Definition TClass.cxx:4000
void ReplaceWith(TClass *newcl) const
Definition TClass.cxx:4169
void RegisterAddressInRepository(const char *where, void *location, const TClass *what) const
Definition TClass.cxx:290
Long_t Property() const override
Returns the properties of the TClass as a bit field stored as a Long_t value.
Definition TClass.cxx:6116
Bool_t HasDefaultConstructor(Bool_t testio=kFALSE) const
Return true if we have access to a constructor usable for I/O.
Definition TClass.cxx:7429
void GetMenuItems(TList *listitems)
Returns list of methods accessible by context menu.
Definition TClass.cxx:3901
void SetNew(ROOT::NewFunc_t newFunc)
Install a new wrapper around 'new'.
Definition TClass.cxx:7021
std::atomic< TMethodCall * > fIsAMethod
Definition TClass.h:231
static Int_t ReadRules()
Read the class.rules files from the default location:.
Definition TClass.cxx:1821
Bool_t CanSplitBaseAllow()
Pointer to the function implementing streaming for this class.
Definition TClass.cxx:2248
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:287
void SetContextMenuTitle(const char *title)
Change (i.e. set) the title of the TNamed.
Definition TClass.cxx:6304
void SetMemberStreamer(const char *name, MemberStreamerFunc_t strm)
Install a new member streamer (p will be copied).
Definition TClass.cxx:6780
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:7122
Short_t GetImplFileLine() const
Definition TClass.h:457
TMethod * GetMethodAllAny(const char *method)
Return pointer to method without looking at parameters.
Definition TClass.cxx:4411
std::atomic< UChar_t > fRuntimeProperties
Definition TClass.h:273
@ 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:7229
Int_t GetBaseClassOffsetRecurse(const TClass *toBase)
Return data member offset to the base class "cl".
Definition TClass.cxx:2706
ROOT::DelFunc_t GetDelete() const
Return the wrapper around delete ThiObject.
Definition TClass.cxx:7499
static TClass * LoadClassDefault(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition TClass.cxx:5798
void SetClassSize(Int_t sizof)
Definition TClass.h:307
TMethod * FindClassOrBaseMethodWithId(DeclId_t faddr)
Find a method with decl id in this class or its bases.
Definition TClass.cxx:4467
static void StreamerExternal(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
There is special streamer for the class.
Definition TClass.cxx:6824
Long_t fClassProperty
Property See TClass::Property() for details.
Definition TClass.h:256
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:6850
static void ConvStreamerInstrumented(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of instrumented class with a library.
Definition TClass.cxx:6881
std::atomic< Bool_t > fCanLoadClassInfo
Whether info was loaded from a root pcm.
Definition TClass.h:260
void SetConvStreamerFunc(ClassConvStreamerFunc_t strm)
Set a wrapper/accessor function around this class custom conversion streamer.
Definition TClass.cxx:6981
TVirtualStreamerInfo * FindStreamerInfo(TObjArray *arr, UInt_t checksum) const
Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum.
Definition TClass.cxx:7102
void GetMissingDictionaries(THashTable &result, bool recurse=false)
Get the classes that have a missing dictionary starting from this one.
Definition TClass.cxx:4114
void MakeCustomMenuList()
Makes a customizable version of the popup menu list, i.e.
Definition TClass.cxx:4310
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:4799
TMethod * GetMethodAny(const char *method)
Return pointer to method without looking at parameters.
Definition TClass.cxx:4401
TVirtualIsAProxy * GetIsAProxy() const
Return the proxy implementing the IsA functionality.
Definition TClass.cxx:2956
ROOT::MergeFunc_t GetMerge() const
Return the wrapper around Merge.
Definition TClass.cxx:7467
ROOT::ResetAfterMergeFunc_t fResetAfterMerge
Definition TClass.h:234
Bool_t IsFolder() const override
Returns kTRUE in case object contains browsable objects (like containers or lists of other objects).
Definition TClass.h:517
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:259
TClass * GetActualClass(const void *object) const
Return a pointer to the real class of the object.
Definition TClass.cxx:2608
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:3490
ObjectPtr NewObject(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Definition TClass.cxx:5019
TRealData * GetRealData(const char *name) const
Return pointer to TRealData element with name "name".
Definition TClass.cxx:3530
void SetDeleteArray(ROOT::DelArrFunc_t deleteArrayFunc)
Install a new wrapper around 'delete []'.
Definition TClass.cxx:7045
Bool_t fHasCustomStreamerMember
The class has a Streamer method and it is implemented by the user or an older (not StreamerInfo based...
Definition TClass.h:253
TFunctionTemplate * GetFunctionTemplate(const char *name)
Definition TClass.cxx:3634
void ResetClassInfo()
Make sure that the current ClassInfo is up to date.
Definition TClass.cxx:4207
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:6794
void GetMissingDictionariesWithRecursionCheck(TCollection &result, TCollection &visited, bool recurse)
From the second level of recursion onwards it is different state check.
Definition TClass.cxx:4017
bool IsClassStructOrUnion() const
Definition TClass.h:354
@ kHasLocalHashMember
Definition TClass.h:96
@ kHasNameMapNode
Definition TClass.h:105
@ kIgnoreTObjectStreamer
Definition TClass.h:97
@ kUnloaded
Definition TClass.h:98
@ kWarned
Definition TClass.h:104
@ kStartWithTObject
Definition TClass.h:103
@ kIsTObject
Definition TClass.h:100
@ kIsForeign
Definition TClass.h:101
std::atomic< TListOfDataMembers * > fUsingData
Definition TClass.h:203
TListOfFunctions * GetMethodList()
Return (create an empty one if needed) the list of functions.
Definition TClass.cxx:4382
void ResetMenuList()
Resets the menu list to it's standard value.
Definition TClass.cxx:4270
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:2969
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:6815
static TClass * LoadClassCustom(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition TClass.cxx:5828
Short_t fImplFileLine
Definition TClass.h:216
static TClass * Class()
Collection abstract base class.
Definition TCollection.h:65
static TClass * Class()
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
const char * GetTrueTypeName() const
Get the desugared type name of this data member, including const and volatile qualifiers.
Bool_t IsPersistent() const
Definition TDataMember.h:91
Long_t Property() const override
Get property description word. For meaning of bits see EProperty.
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 the decayed type name of this data member, removing const and volatile qualifiers,...
Basic data type descriptor (datatype information is obtained from CINT).
Definition TDataType.h:44
static void GetDateTime(UInt_t datetime, Int_t &date, Int_t &time)
Static function that returns the date and time.
Definition TDatime.cxx:431
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
void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient) override
Print value of member mname.
Definition TClass.cxx:574
TDumpMembers(bool noAddr)
Definition TClass.cxx:557
static TEnum * GetEnum(const std::type_info &ti, ESearchAction sa=kALoadAndInterpLookup)
Definition TEnum.cxx:175
@ kNone
Definition TEnum.h:48
This class stores a (key,value) pair using an external hash.
Definition TExMap.h:33
Dictionary for function template This class describes one single function template.
Global functions class (global functions are obtained from CINT).
Definition TFunction.h:30
THashTable implements a hash table to store TObject's.
Definition THashTable.h:35
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 *=nullptr, 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...
static TClass * Class()
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...
TObject * FindObject(const char *name) const override
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.
void Delete(Option_t *option="") override
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 TList * GetListForObject(const char *name) const
Return the set of overloads for this name, collecting all available ones.
TObject * FindObject(const TObject *obj) const override
Find object using its hash value (returned by its Hash() member).
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:576
void Add(TObject *obj) override
Definition TList.h:83
void AddLast(TObject *obj) override
Add object at the end of the list.
Definition TList.cxx:150
virtual TObjLink * FirstLink() const
Definition TList.h:104
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:468
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
Each ROOT class (see TClass) has a linked list of methods.
Definition TMethod.h:38
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
TString fName
Definition TNamed.h:32
void ls(Option_t *option="") const override
List TNamed name and title.
Definition TNamed.cxx:113
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.
Int_t GetEntries() const override
Return the number of objects in array (i.e.
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
TObject * UncheckedAt(Int_t i) const
Definition TObjArray.h:84
TObject * RemoveAt(Int_t idx) override
Remove object at index idx.
Int_t GetLast() const override
Return index of last object in array.
Int_t LowerBound() const
Definition TObjArray.h:91
void Add(TObject *obj) override
Definition TObjArray.h:68
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:1068
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:439
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:196
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:973
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:403
static TClass * Class()
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:780
static Bool_t GetObjectStat()
Get status of object stat flag.
Definition TObject.cxx:1061
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:987
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1015
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:791
void MakeZombie()
Definition TObject.h:53
void ResetBit(UInt_t f)
Definition TObject.h:195
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:961
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:3080
The TRealData class manages the effective list of all data members for a given class.
Definition TRealData.h:30
const char * GetName() const override
Returns name of object.
Definition TRealData.h:52
static TClass * Class()
static TClass * Class()
TClass * GetClassPointer() const override
Returns a pointer to the TClass of this element.
static TClass * Class()
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
static TClass * Class()
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
const char * Data() const
Definition TString.h:376
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:623
Bool_t IsNull() const
Definition TString.h:414
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.
Definition TString.cxx:677
TString & Remove(Ssiz_t pos)
Definition TString.h:685
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:2378
static TClass * Class()
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
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="") override
Delete is not allowed in this class.
View implementing the TList interface and giving access all the TFunction describing public methods i...
void Load()
Load all the functions known to the interpreter for the scope 'fClass' and all its bases classes.
RAII helper class that ensures that PushProxy() / PopProxy() are called when entering / leaving a C++...
Defines a common interface to inspect/change the contents of an object that represents a collection.
virtual UInt_t Sizeof() const =0
Return the sizeof() of the collection object.
virtual TClass::ObjectPtr NewObjectArray(Int_t nElements) const
Construct an array of nElements container objects and return the base address of the array.
virtual void Destructor(void *p, Bool_t dtorOnly=kFALSE) const
Execute the container destructor.
virtual void DeleteArray(void *p, Bool_t dtorOnly=kFALSE) const
Execute the container array destructor.
virtual TClass * GetValueClass() const =0
If the value type is a user-defined class, return a pointer to the TClass representing the value type...
virtual TClass::ObjectPtr NewObject() const
Construct a new container object and return its address.
virtual TVirtualCollectionProxy * Generate() const =0
Returns a clean object of the actual class that derives from TVirtualCollectionProxy.
virtual Bool_t Reset()
Reset the information gathered from StreamerInfos and value's TClass.
virtual Bool_t HasPointers() const =0
Return true if the content is of type 'pointer to'.
virtual void SetClass(TClass *cl)=0
This class implements a mutex interface.
small helper class to store/restore gPad context in TPad methods
Definition TVirtualPad.h:61
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
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 void DeleteArray(void *p, Bool_t dtorOnly=kFALSE)=0
static const char * GetElementCounterStart(const char *dmTitle)
Given a comment/title declaring an array counter, for example:
virtual Int_t GetSize() const =0
static TVirtualStreamerInfo * Factory()
Static function returning a pointer to a new TVirtualStreamerInfo object.
virtual void Destructor(void *p, Bool_t dtorOnly=kFALSE)=0
TLine * line
return c1
Definition legend1.C:41
R__EXTERN void * gMmallocDesc
Definition TStorage.h:141
Bool_t HasConsistentHashMember(TClass &clRef)
Return true is the Hash/RecursiveRemove setup is consistent, i.e.
Definition TClass.cxx:7407
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:114
R__EXTERN TVirtualRWMutex * gCoreMutex
void(* ResetAfterMergeFunc_t)(void *, TFileMergeInfo *)
Definition Rtypes.h:116
@ kClassThreadSlot
void(* DesFunc_t)(void *)
Definition Rtypes.h:113
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:5899
void(* DelFunc_t)(void *)
Definition Rtypes.h:111
ESTLType
Definition ESTLType.h:28
@ kNotSTL
Definition ESTLType.h:29
void *(* NewArrFunc_t)(Long_t size, void *arena)
Definition Rtypes.h:110
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:112
void *(* NewFunc_t)(void *)
Definition Rtypes.h:109
Long64_t(* MergeFunc_t)(void *, TCollection *, TFileMergeInfo *)
Definition Rtypes.h:115
bool IsStdPairBase(std::string_view name)
Definition TClassEdit.h:188
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
bool IsStdArray(std::string_view name)
Definition TClassEdit.h:183
bool IsStdClass(const char *type)
return true if the class belongs to the std namespace
bool IsStdPair(std::string_view name)
Definition TClassEdit.h:184
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)
Returns the smallest of a and b.
Definition TMathBase.h:198
TMatrixT< Element > & Add(TMatrixT< Element > &target, Element scalar, const TMatrixT< Element > &source)
Modify addition: target += scalar * source.
static const char * what
Definition stlLoader.cc:5
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
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4