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