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