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