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