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