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