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