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