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