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