Logo ROOT   6.18/05
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```{.cpp}
29auto myClassTClass_0 = TClass::GetClass("myClass");
30auto myClassTClass_1 = TClass::GetClass<myClass>();
31auto myClassTClass_2 = TClass::GetClass(myClassTypeInfo);
32```
33
34The name of classes is crucial for ROOT. A careful procedure of *name normalization* is carried out for
35each and every class. A *normalized name* is a valid C++ class name.
36In order to access the name of a class within the ROOT type system, the method TClass::GetName() can be used.
37*/
38
39//*-*x7.5 macros/layout_class
40
41#include "TClass.h"
42
43#include "Riostream.h"
44#include "TBaseClass.h"
45#include "TBrowser.h"
46#include "TBuffer.h"
47#include "TClassGenerator.h"
48#include "TClassEdit.h"
49#include "TClassMenuItem.h"
50#include "TClassRef.h"
51#include "TClassTable.h"
52#include "TDataMember.h"
53#include "TDataType.h"
54#include "TEnum.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
1383 // Advertise ourself as the loading class for this class name
1384 TClass::AddClass(this);
1385
1387
1388 if (!gInterpreter)
1389 ::Fatal("TClass::Init", "gInterpreter not initialized");
1390
1391 if (givenInfo) {
1392 bool invalid = !gInterpreter->ClassInfo_IsValid(givenInfo);
1393 bool notloaded = !gInterpreter->ClassInfo_IsLoaded(givenInfo);
1394 auto property = gInterpreter->ClassInfo_Property(givenInfo);
1395
1396 if (invalid || (notloaded && (property & kIsNamespace)) ||
1397 !(property & (kIsClass | kIsStruct | kIsNamespace))) {
1399 MakeZombie();
1400 fState = kNoInfo;
1401 TClass::RemoveClass(this);
1402 return;
1403 }
1404 }
1405
1406 if (!invalid) {
1407 fClassInfo = gInterpreter->ClassInfo_Factory(givenInfo);
1408 fCanLoadClassInfo = false; // avoids calls to LoadClassInfo() if info is already loaded
1409 if (fState <= kEmulated)
1411 }
1412 }
1413
1414 // We need to check if the class it is not fwd declared for the cases where we
1415 // created a TClass directly in the kForwardDeclared state. Indeed in those cases
1416 // fClassInfo will always be nullptr.
1418
1419 if (fState == kHasTClassInit) {
1420 // If the TClass is being generated from a ROOT dictionary,
1421 // even though we do not seem to have a CINT dictionary for
1422 // the class, we will will try to load it anyway UNLESS
1423 // the class is an STL container (or string).
1424 // This is because we do not expect the CINT dictionary
1425 // to be present for all STL classes (and we can handle
1426 // the lack of CINT dictionary in that cases).
1427 // However, the cling the dictionary no longer carries
1428 // an instantiation with it, unless we request the loading
1429 // here *or* the user explicitly instantiate the template
1430 // we would not have a ClassInfo for the template
1431 // instantiation.
1433 // Here we check and grab the info from the rootpcm.
1435 if (proto && proto->FillTClass(this)) {
1437 }
1438 }
1439 if (!fHasRootPcmInfo && gInterpreter->CheckClassInfo(fName, /* autoload = */ kTRUE)) {
1440 gInterpreter->SetClassInfo(this); // sets fClassInfo pointer
1441 if (fClassInfo) {
1442 // This should be moved out of GetCheckSum itself however the last time
1443 // we tried this cause problem, in particular in the end-of-process operation.
1444 // fCheckSum = GetCheckSum(kLatestCheckSum);
1445 } else {
1446 if (!fClassInfo) {
1447 if (IsZombie()) {
1448 TClass::RemoveClass(this);
1449 return;
1450 }
1451 }
1452 }
1453 }
1454 }
1455 if (!silent && (!fClassInfo && !fCanLoadClassInfo) && !isStl && fName.First('@')==kNPOS &&
1457 if (fState == kHasTClassInit) {
1458 if (fImplFileLine == -1 && fClassVersion == 0) {
1459 // We have a 'transient' class with a ClassDefInline and apparently no interpreter
1460 // information. Since it is transient, it is more than likely that the lack
1461 // will be harmles.
1462 } else {
1463 ::Error("TClass::Init", "no interpreter information for class %s is available even though it has a TClass "
1464 "initialization routine.",
1465 fName.Data());
1466 }
1467 } else {
1468 // In this case we initialised this TClass instance starting from the fwd declared state
1469 // and we know we have no dictionary: no need to warn
1470 ::Warning("TClass::Init", "no dictionary for class %s is available", fName.Data());
1471 }
1472 }
1473
1474 fgClassCount++;
1476
1477 // Make the typedef-expanded -> original hash table entries.
1478 // There may be several entries for any given key.
1479 // We only make entries if the typedef-expanded name
1480 // is different from the original name.
1481 TString resolvedThis;
1482 if (!givenInfo && strchr (name, '<')) {
1483 if ( fName != name) {
1484 if (!fgClassTypedefHash) {
1485 fgClassTypedefHash = new THashTable (100, 5);
1487 }
1488
1491
1492 }
1493 resolvedThis = TClassEdit::ResolveTypedef (name, kTRUE);
1494 if (resolvedThis != name) {
1495 if (!fgClassTypedefHash) {
1496 fgClassTypedefHash = new THashTable (100, 5);
1498 }
1499
1500 fgClassTypedefHash->Add (new TNameMapNode (resolvedThis, fName));
1502 }
1503
1504 }
1505
1506 //In case a class with the same name had been created by TVirtualStreamerInfo
1507 //we must delete the old class, importing only the StreamerInfo structure
1508 //from the old dummy class.
1509 if (oldcl) {
1510
1511 oldcl->ReplaceWith(this);
1512 delete oldcl;
1513
1514 } else if (!givenInfo && resolvedThis.Length() > 0 && fgClassTypedefHash) {
1515
1516 // Check for existing equivalent.
1517
1518 if (resolvedThis != fName) {
1519 oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(resolvedThis);
1520 if (oldcl && oldcl != this) {
1521 persistentRef = oldcl->fPersistentRef.exchange(0);
1522 ForceReload (oldcl);
1523 }
1524 }
1525 TIter next( fgClassTypedefHash->GetListForObject(resolvedThis) );
1526 while ( TNameMapNode* htmp = static_cast<TNameMapNode*> (next()) ) {
1527 if (resolvedThis != htmp->String()) continue;
1528 oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(htmp->fOrigName); // gROOT->GetClass (htmp->fOrigName, kFALSE);
1529 if (oldcl && oldcl != this) {
1530 persistentRef = oldcl->fPersistentRef.exchange(0);
1531 ForceReload (oldcl);
1532 }
1533 }
1534 }
1535 if (fClassInfo) {
1537 if ( fDeclFileName == 0 || fDeclFileName[0] == '\0' ) {
1538 fDeclFileName = kUndeterminedClassInfoName;
1539 // Missing interface:
1540 // fDeclFileLine = gInterpreter->ClassInfo_FileLine( fClassInfo );
1541
1542 // But really do not want to set ImplFileLine as it is currently the
1543 // marker of being 'loaded' or not (reminder loaded == has a TClass bootstrap).
1544 }
1545 }
1546
1547 if (persistentRef) {
1548 fPersistentRef = persistentRef;
1549 } else {
1550 fPersistentRef = new TClass*;
1551 }
1552 *fPersistentRef = this;
1553
1554 if ( isStl || !strncmp(GetName(),"stdext::hash_",13) || !strncmp(GetName(),"__gnu_cxx::hash_",16) ) {
1555 if (fState != kHasTClassInit) {
1556 // If we have a TClass compiled initialization, we can safely assume that
1557 // there will also be a collection proxy.
1559 if (fCollectionProxy) {
1561
1562 // Numeric Collections have implicit conversions:
1564
1565 } else if (!silent) {
1566 Warning("Init","Collection proxy for %s was not properly initialized!",GetName());
1567 }
1568 if (fStreamer==0) {
1570 }
1571 }
1572 } else if (!strncmp(GetName(),"std::pair<",10) || !strncmp(GetName(),"pair<",5) ) {
1573 // std::pairs have implicit conversions
1575 }
1576
1578}
1579
1580////////////////////////////////////////////////////////////////////////////////
1581/// TClass dtor. Deletes all list that might have been created.
1582
1584{
1586
1587 // Remove from the typedef hashtables.
1589 TString resolvedThis = TClassEdit::ResolveTypedef (GetName(), kTRUE);
1590 TIter next (fgClassTypedefHash->GetListForObject (resolvedThis));
1591 while ( TNameMapNode* htmp = static_cast<TNameMapNode*> (next()) ) {
1592 if (resolvedThis == htmp->String() && htmp->fOrigName == GetName()) {
1593 fgClassTypedefHash->Remove (htmp);
1594 delete htmp;
1595 break;
1596 }
1597 }
1598 }
1599
1600 // Not owning lists, don't call Delete()
1601 // But this still need to be done first because the TList destructor
1602 // does access the object contained (via GetObject()->TestBit(kCanDelete))
1603 delete fStreamer; fStreamer =0;
1604 delete fAllPubData; fAllPubData =0;
1605 delete fAllPubMethod; fAllPubMethod=0;
1606
1607 delete fPersistentRef.load();
1608
1609 if (fBase.load())
1610 (*fBase).Delete();
1611 delete fBase.load(); fBase = 0;
1612
1613 if (fData)
1614 fData->Delete();
1615 delete fData; fData = 0;
1616
1617 if (fEnums.load())
1618 (*fEnums).Delete();
1619 delete fEnums.load(); fEnums = 0;
1620
1621 if (fFuncTemplate)
1623 delete fFuncTemplate; fFuncTemplate = 0;
1624
1625 if (fMethod.load())
1626 (*fMethod).Delete();
1627 delete fMethod.load(); fMethod=0;
1628
1629 if (fRealData)
1630 fRealData->Delete();
1631 delete fRealData; fRealData=0;
1632
1633 if (fStreamerInfo)
1635 delete fStreamerInfo; fStreamerInfo = nullptr;
1636
1637 if (fDeclFileLine >= -1)
1638 TClass::RemoveClass(this);
1639
1641 fClassInfo=0;
1642
1643 if (fClassMenuList)
1646
1648
1649 if ( fIsA ) delete fIsA;
1650
1651 if ( fRefProxy ) fRefProxy->Release();
1652 fRefProxy = 0;
1653
1654 delete fStreamer;
1655 delete fCollectionProxy;
1656 delete fIsAMethod.load();
1657 delete fSchemaRules;
1658 if (fConversionStreamerInfo.load()) {
1659 std::map<std::string, TObjArray*>::iterator it;
1660 std::map<std::string, TObjArray*>::iterator end = (*fConversionStreamerInfo).end();
1661 for( it = (*fConversionStreamerInfo).begin(); it != end; ++it ) {
1662 delete it->second;
1663 }
1664 delete fConversionStreamerInfo.load();
1665 }
1666}
1667
1668////////////////////////////////////////////////////////////////////////////////
1669
1670namespace {
1671 Int_t ReadRulesContent(FILE *f)
1672 {
1673 // Read a class.rules file which contains one rule per line with comment
1674 // starting with a #
1675 // Returns the number of rules loaded.
1676 // Returns -1 in case of error.
1677
1678 R__ASSERT(f!=0);
1679 TString rule(1024);
1680 int c, state = 0;
1681 Int_t count = 0;
1682
1683 while ((c = fgetc(f)) != EOF) {
1684 if (c == 13) // ignore CR
1685 continue;
1686 if (c == '\n') {
1687 if (state != 3) {
1688 state = 0;
1689 if (rule.Length() > 0) {
1690 if (TClass::AddRule(rule)) {
1691 ++count;
1692 }
1693 rule.Clear();
1694 }
1695 }
1696 continue;
1697 }
1698 switch (state) {
1699 case 0: // start of line
1700 switch (c) {
1701 case ' ':
1702 case '\t':
1703 break;
1704 case '#':
1705 state = 1;
1706 break;
1707 default:
1708 state = 2;
1709 break;
1710 }
1711 break;
1712
1713 case 1: // comment
1714 break;
1715
1716 case 2: // rule
1717 switch (c) {
1718 case '\\':
1719 state = 3; // Continuation request
1720 default:
1721 break;
1722 }
1723 break;
1724 }
1725 switch (state) {
1726 case 2:
1727 rule.Append(c);
1728 break;
1729 }
1730 }
1731 return count;
1732 }
1733}
1734
1735////////////////////////////////////////////////////////////////////////////////
1736/// Read the class.rules files from the default location:.
1737/// $ROOTSYS/etc/class.rules (or ROOTETCDIR/class.rules)
1738
1740{
1741 static const char *suffix = "class.rules";
1742 TString sname = suffix;
1744
1745 Int_t res = -1;
1746
1747 FILE * f = fopen(sname,"r");
1748 if (f != 0) {
1749 res = ReadRulesContent(f);
1750 fclose(f);
1751 } else {
1752 ::Error("TClass::ReadRules()", "Cannot find rules file %s", sname.Data());
1753 }
1754 return res;
1755}
1756
1757////////////////////////////////////////////////////////////////////////////////
1758/// Read a class.rules file which contains one rule per line with comment
1759/// starting with a #
1760/// - Returns the number of rules loaded.
1761/// - Returns -1 in case of error.
1762
1763Int_t TClass::ReadRules( const char *filename )
1764{
1765 if (!filename || !filename[0]) {
1766 ::Error("TClass::ReadRules", "no file name specified");
1767 return -1;
1768 }
1769
1770 FILE * f = fopen(filename,"r");
1771 if (f == 0) {
1772 ::Error("TClass::ReadRules","Failed to open %s\n",filename);
1773 return -1;
1774 }
1775 Int_t count = ReadRulesContent(f);
1776
1777 fclose(f);
1778 return count;
1779
1780}
1781
1782////////////////////////////////////////////////////////////////////////////////
1783/// Add a schema evolution customization rule.
1784/// The syntax of the rule can be either the short form:
1785/// ~~~ {.cpp}
1786/// [type=Read] classname membername [attributes=... ] [version=[...] ] [checksum=[...] ] [oldtype=...] [code={...}]
1787/// ~~~
1788/// or the long form
1789/// ~~~ {.cpp}
1790/// [type=Read] sourceClass=classname [targetclass=newClassname] [ source="type membername; [type2 membername2]" ]
1791/// [target="membername3;membername4"] [attributes=... ] [version=...] [checksum=...] [code={...}|functionname]
1792/// ~~~
1793///
1794/// For example to set HepMC::GenVertex::m_event to _not_ owned the object it is pointing to:
1795/// HepMC::GenVertex m_event attributes=NotOwner
1796///
1797/// Semantic of the tags:
1798/// - type : the type of the rule, valid values: Read, ReadRaw, Write, WriteRaw, the default is 'Read'.
1799/// - sourceClass : the name of the class as it is on the rule file
1800/// - targetClass : the name of the class as it is in the current code ; defaults to the value of sourceClass
1801/// - source : the types and names of the data members from the class on file that are needed, the list is separated by semi-colons ';'
1802/// - oldtype: in the short form only, indicates the type on disk of the data member.
1803/// - target : the names of the data members updated by this rule, the list is separated by semi-colons ';'
1804/// - attributes : list of possible qualifiers among: Owner, NotOwner
1805/// - 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]
1806/// - checksum : comma delimited list of the checksums of the class layout that this rule applies to.
1807/// - code={...} : code to be executed for the rule or name of the function implementing it.
1808
1809Bool_t TClass::AddRule( const char *rule )
1810{
1811 ROOT::TSchemaRule *ruleobj = new ROOT::TSchemaRule();
1812 if (! ruleobj->SetFromRule( rule ) ) {
1813 delete ruleobj;
1814 return kFALSE;
1815 }
1816
1818
1819 TClass *cl = TClass::GetClass( ruleobj->GetTargetClass() );
1820 if (!cl) {
1821 // Create an empty emulated class for now.
1822 cl = gInterpreter->GenerateTClass(ruleobj->GetTargetClass(), /* emulation = */ kTRUE, /*silent = */ kTRUE);
1823 }
1825
1826 TString errmsg;
1827 if( !rset->AddRule( ruleobj, ROOT::Detail::TSchemaRuleSet::kCheckConflict, &errmsg ) ) {
1828 ::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).",
1829 ruleobj->GetTargetClass(), ruleobj->GetVersion(), ruleobj->GetTargetString(), errmsg.Data() );
1830 delete ruleobj;
1831 return kFALSE;
1832 }
1833 return kTRUE;
1834}
1835
1836////////////////////////////////////////////////////////////////////////////////
1837/// Adopt a new set of Data Model Evolution rules.
1838
1840{
1842
1843 delete fSchemaRules;
1844 fSchemaRules = rules;
1845 fSchemaRules->SetClass( this );
1846}
1847
1848////////////////////////////////////////////////////////////////////////////////
1849/// Return the set of the schema rules if any.
1850
1852{
1853 return fSchemaRules;
1854}
1855
1856////////////////////////////////////////////////////////////////////////////////
1857/// Return the set of the schema rules if any.
1858/// If create is true, create an empty set
1859
1861{
1862 if (create && fSchemaRules == 0) {
1864 fSchemaRules->SetClass( this );
1865 }
1866 return fSchemaRules;
1867}
1868
1869////////////////////////////////////////////////////////////////////////////////
1870
1871void TClass::AddImplFile(const char* filename, int line) {
1872 // Currently reset the implementation file and line.
1873 // In the close future, it will actually add this file and line
1874 // to a "list" of implementation files.
1875
1876 fImplFileName = filename;
1878}
1879
1880////////////////////////////////////////////////////////////////////////////////
1881/// Browse external object inherited from TObject.
1882/// It passes through inheritance tree and calls TBrowser::Add
1883/// in appropriate cases. Static function.
1884
1886{
1887 if (!obj) return 0;
1888
1889 TAutoInspector insp(b);
1890 obj->ShowMembers(insp);
1891 return insp.fCount;
1892}
1893
1894////////////////////////////////////////////////////////////////////////////////
1895/// Browse objects of of the class described by this TClass object.
1896
1897Int_t TClass::Browse(void *obj, TBrowser *b) const
1898{
1899 if (!obj) return 0;
1900
1901 TClass *actual = GetActualClass(obj);
1902 if (IsTObject()) {
1903 // Call TObject::Browse.
1904
1905 if (!fIsOffsetStreamerSet) {
1907 }
1908 TObject* realTObject = (TObject*)((size_t)obj + fOffsetStreamer);
1909 realTObject->Browse(b);
1910 return 1;
1911 } else if (actual != this) {
1912 return actual->Browse(obj, b);
1913 } else if (GetCollectionProxy()) {
1914
1915 // do something useful.
1916
1917 } else {
1918 TAutoInspector insp(b);
1919 CallShowMembers(obj,insp,kFALSE);
1920 return insp.fCount;
1921 }
1922
1923 return 0;
1924}
1925
1926////////////////////////////////////////////////////////////////////////////////
1927/// This method is called by a browser to get the class information.
1928
1930{
1931 if (!HasInterpreterInfo()) return;
1932
1933 if (b) {
1934 if (!fRealData) BuildRealData();
1935
1936 b->Add(GetListOfDataMembers(), "Data Members");
1937 b->Add(GetListOfRealData(), "Real Data Members");
1938 b->Add(GetListOfMethods(), "Methods");
1939 b->Add(GetListOfBases(), "Base Classes");
1940 }
1941}
1942
1943////////////////////////////////////////////////////////////////////////////////
1944/// Build a full list of persistent data members.
1945/// Scans the list of all data members in the class itself and also
1946/// in all base classes. For each persistent data member, inserts a
1947/// TRealData object in the list fRealData.
1948///
1949
1950void TClass::BuildRealData(void* pointer, Bool_t isTransient)
1951{
1952
1954
1955 // Only do this once.
1956 if (fRealData) {
1957 return;
1958 }
1959
1960 if (fClassVersion == 0) {
1961 isTransient = kTRUE;
1962 }
1963
1964 // When called via TMapFile (e.g. Update()) make sure that the dictionary
1965 // gets allocated on the heap and not in the mapped file.
1966 TMmallocDescTemp setreset;
1967
1968 // Handle emulated classes and STL containers specially.
1970 // We are an emulated class or an STL container.
1971 fRealData = new TList;
1972 BuildEmulatedRealData("", 0, this);
1973 return;
1974 }
1975
1976 // return early on string
1977 static TClassRef clRefString("std::string");
1978 if (clRefString == this) {
1979 return;
1980 }
1981
1982 // Complain about stl classes ending up here (unique_ptr etc) - except for
1983 // pair where we will build .first, .second just fine
1984 // and those for which the user explicitly requested a dictionary.
1985 if (!isTransient && GetState() != kHasTClassInit
1987 && strncmp(GetName(), "pair<", 5) != 0) {
1988 Error("BuildRealData", "Inspection for %s not supported!", GetName());
1989 }
1990
1991 // The following statement will recursively call
1992 // all the subclasses of this class.
1993 fRealData = new TList;
1994 TBuildRealData brd(pointer, this);
1995
1996 // CallShowMember will force a call to InheritsFrom, which indirectly
1997 // calls TClass::GetClass. It forces the loading of new typedefs in
1998 // case some of them were not yet loaded.
1999 if ( ! CallShowMembers(pointer, brd, isTransient) ) {
2000 if ( isTransient ) {
2001 // This is a transient data member, so it is probably fine to not have
2002 // access to its content. However let's no mark it as definitively setup,
2003 // since another class might use this class for a persistent data member and
2004 // in this case we really want the error message.
2005 delete fRealData;
2006 fRealData = 0;
2007 } else {
2008 Error("BuildRealData", "Cannot find any ShowMembers function for %s!", GetName());
2009 }
2010 }
2011
2012 // Take this opportunity to build the real data for base classes.
2013 // In case one base class is abstract, it would not be possible later
2014 // to create the list of real data for this abstract class.
2015 TBaseClass* base = 0;
2016 TIter next(GetListOfBases());
2017 while ((base = (TBaseClass*) next())) {
2018 if (base->IsSTLContainer()) {
2019 continue;
2020 }
2021 TClass* c = base->GetClassPointer();
2022 if (c) {
2023 c->BuildRealData(0, isTransient);
2024 }
2025 }
2026}
2027
2028////////////////////////////////////////////////////////////////////////////////
2029/// Build the list of real data for an emulated class
2030
2031void TClass::BuildEmulatedRealData(const char *name, Long_t offset, TClass *cl)
2032{
2034
2036 if (Property() & kIsAbstract) {
2038 } else {
2039 info = GetStreamerInfo();
2040 }
2041 if (!info) {
2042 // This class is abstract, but we don't yet have a SteamerInfo for it ...
2043 Error("BuildEmulatedRealData","Missing StreamerInfo for %s",GetName());
2044 // Humm .. no information ... let's bail out
2045 return;
2046 }
2047
2048 TIter next(info->GetElements());
2049 TStreamerElement *element;
2050 while ((element = (TStreamerElement*)next())) {
2051 Int_t etype = element->GetType();
2052 Long_t eoffset = element->GetOffset();
2053 TClass *cle = element->GetClassPointer();
2054 if (element->IsBase() || etype == TVirtualStreamerInfo::kBase) {
2055 //base class are skipped in this loop, they will be added at the end.
2056 continue;
2057 } else if (etype == TVirtualStreamerInfo::kTObject ||
2060 etype == TVirtualStreamerInfo::kAny) {
2061 //member class
2062 TString rdname; rdname.Form("%s%s",name,element->GetFullName());
2063 TRealData *rd = new TRealData(rdname,offset+eoffset,0);
2064 if (gDebug > 0) printf(" Class: %s, adding TRealData=%s, offset=%ld\n",cl->GetName(),rd->GetName(),rd->GetThisOffset());
2065 cl->GetListOfRealData()->Add(rd);
2066 // Now we a dot
2067 rdname.Form("%s%s.",name,element->GetFullName());
2068 if (cle) cle->BuildEmulatedRealData(rdname,offset+eoffset,cl);
2069 } else {
2070 //others
2071 TString rdname; rdname.Form("%s%s",name,element->GetFullName());
2072 TRealData *rd = new TRealData(rdname,offset+eoffset,0);
2073 if (gDebug > 0) printf(" Class: %s, adding TRealData=%s, offset=%ld\n",cl->GetName(),rd->GetName(),rd->GetThisOffset());
2074 cl->GetListOfRealData()->Add(rd);
2075 }
2076 //if (fClassInfo==0 && element->IsBase()) {
2077 // if (fBase==0) fBase = new TList;
2078 // TClass *base = element->GetClassPointer();
2079 // fBase->Add(new TBaseClass(this, cl, eoffset));
2080 //}
2081 }
2082 // The base classes must added last on the list of real data (to help with ambiguous data member names)
2083 next.Reset();
2084 while ((element = (TStreamerElement*)next())) {
2085 Int_t etype = element->GetType();
2086 if (element->IsBase() || etype == TVirtualStreamerInfo::kBase) {
2087 //base class
2088 Long_t eoffset = element->GetOffset();
2089 TClass *cle = element->GetClassPointer();
2090 if (cle) cle->BuildEmulatedRealData(name,offset+eoffset,cl);
2091 }
2092 }
2093}
2094
2095
2096////////////////////////////////////////////////////////////////////////////////
2097/// Calculate the offset between an object of this class to
2098/// its base class TObject. The pointer can be adjusted by
2099/// that offset to access any virtual method of TObject like
2100/// Streamer() and ShowMembers().
2101
2103{
2106 // When called via TMapFile (e.g. Update()) make sure that the dictionary
2107 // gets allocated on the heap and not in the mapped file.
2108
2109 TMmallocDescTemp setreset;
2111 if (fStreamerType == kTObject) {
2113 }
2115 }
2116}
2117
2118
2119////////////////////////////////////////////////////////////////////////////////
2120/// Call ShowMembers() on the obj of this class type, passing insp and parent.
2121/// isATObject is -1 if unknown, 0 if it is not a TObject, and 1 if it is a TObject.
2122/// The function returns whether it was able to call ShowMembers().
2123
2124Bool_t TClass::CallShowMembers(const void* obj, TMemberInspector &insp, Bool_t isTransient) const
2125{
2126 if (fShowMembers) {
2127 // This should always works since 'pointer' should be pointing
2128 // to an object of the actual type of this TClass object.
2129 fShowMembers(obj, insp, isTransient);
2130 return kTRUE;
2131 } else {
2132
2134 if (fClassInfo) {
2135
2136 if (strcmp(GetName(), "string") == 0) {
2137 // For std::string we know that we do not have a ShowMembers
2138 // function and that it's okay.
2139 return kTRUE;
2140 }
2141 // Since we do have some dictionary information, let's
2142 // call the interpreter's ShowMember.
2143 // This works with Cling to support interpreted classes.
2144 gInterpreter->InspectMembers(insp, obj, this, isTransient);
2145 return kTRUE;
2146
2147 } else if (TVirtualStreamerInfo* sinfo = GetStreamerInfo()) {
2148 sinfo->CallShowMembers(obj, insp, isTransient);
2149 return kTRUE;
2150 } // isATObject
2151 } // fShowMembers is set
2152
2153 return kFALSE;
2154}
2155
2156////////////////////////////////////////////////////////////////////////////////
2157/// Do a ShowMembers() traversal of all members and base classes' members
2158/// using the reflection information from the interpreter. Works also for
2159/// interpreted objects.
2160
2161void TClass::InterpretedShowMembers(void* obj, TMemberInspector &insp, Bool_t isTransient)
2162{
2163 return gInterpreter->InspectMembers(insp, obj, this, isTransient);
2164}
2165
2167{
2168 if (fCanSplit >= 0) {
2169 return ! ( fCanSplit & 0x2 );
2170 }
2171
2173
2174 if (GetCollectionProxy() != nullptr) {
2175 // A collection can never affect its derived class 'splittability'
2176 return kTRUE;
2177 }
2178
2179 if (this == TRef::Class()) { fCanSplit = 2; return kFALSE; }
2180 if (this == TRefArray::Class()) { fCanSplit = 2; return kFALSE; }
2181 if (this == TArray::Class()) { fCanSplit = 2; return kFALSE; }
2182 if (this == TClonesArray::Class()) { fCanSplit = 1; return kTRUE; }
2183 if (this == TCollection::Class()) { fCanSplit = 2; return kFALSE; }
2184
2185 // TTree is not always available (for example in rootcling), so we need
2186 // to grab it silently.
2187 auto refTreeClass( TClass::GetClass("TTree",kTRUE,kTRUE) );
2188 if (this == refTreeClass) { fCanSplit = 2; return kFALSE; }
2189
2190 if (!HasDataMemberInfo()) {
2191 TVirtualStreamerInfo *sinfo = ((TClass *)this)->GetCurrentStreamerInfo();
2192 if (sinfo==0) sinfo = GetStreamerInfo();
2193 TIter next(sinfo->GetElements());
2194 TStreamerElement *element;
2195 while ((element = (TStreamerElement*)next())) {
2196 if (element->IsA() == TStreamerBase::Class()) {
2197 TClass *clbase = element->GetClassPointer();
2198 if (!clbase) {
2199 // If there is a missing base class, we can't split the immediate
2200 // derived class.
2201 fCanSplit = 0;
2202 return kFALSE;
2203 } else if (!clbase->CanSplitBaseAllow()) {
2204 fCanSplit = 2;
2205 return kFALSE;
2206 }
2207 }
2208 }
2209 }
2210
2211 // If we don't have data member info there is no more information
2212 // we can find out.
2213 if (!HasDataMemberInfo()) return kTRUE;
2214
2215 TObjLink *lnk = GetListOfBases() ? fBase.load()->FirstLink() : 0;
2216
2217 // Look at inheritance tree
2218 while (lnk) {
2219 TClass *c;
2220 TBaseClass *base = (TBaseClass*) lnk->GetObject();
2221 c = base->GetClassPointer();
2222 if(!c) {
2223 // If there is a missing base class, we can't split the immediate
2224 // derived class.
2225 fCanSplit = 0;
2226 return kFALSE;
2227 } else if (!c->CanSplitBaseAllow()) {
2228 fCanSplit = 2;
2229 return kFALSE;
2230 }
2231 lnk = lnk->Next();
2232 }
2233 return kTRUE;
2234}
2235
2236////////////////////////////////////////////////////////////////////////////////
2237/// Return true if the data member of this TClass can be saved separately.
2238
2240{
2241 // Note: add the possibility to set it for the class and the derived class.
2242 // save the info in TVirtualStreamerInfo
2243 // deal with the info in MakeProject
2244 if (fCanSplit >= 0) {
2245 // The user explicitly set the value
2246 return (fCanSplit & 0x1) == 1;
2247 }
2248
2250 TClass *This = const_cast<TClass*>(this);
2251
2252 if (this == TObject::Class()) { This->fCanSplit = 1; return kTRUE; }
2253 if (fName == "TClonesArray") { This->fCanSplit = 1; return kTRUE; }
2254 if (fRefProxy) { This->fCanSplit = 0; return kFALSE; }
2255 if (fName.BeginsWith("TVectorT<")) { This->fCanSplit = 0; return kFALSE; }
2256 if (fName.BeginsWith("TMatrixT<")) { This->fCanSplit = 0; return kFALSE; }
2257 if (fName == "string") { This->fCanSplit = 0; return kFALSE; }
2258 if (fName == "std::string") { This->fCanSplit = 0; return kFALSE; }
2259
2260 if (GetCollectionProxy()!=0) {
2261 // For STL collection we need to look inside.
2262
2263 // However we do not split collections of collections
2264 // nor collections of strings
2265 // nor collections of pointers (unless explicit request (see TBranchSTL)).
2266
2267 if (GetCollectionProxy()->HasPointers()) { This->fCanSplit = 0; return kFALSE; }
2268
2269 TClass *valueClass = GetCollectionProxy()->GetValueClass();
2270 if (valueClass == 0) { This->fCanSplit = 0; return kFALSE; }
2271 static TClassRef stdStringClass("std::string");
2272 if (valueClass==TString::Class() || valueClass==stdStringClass)
2273 { This->fCanSplit = 0; return kFALSE; }
2274 if (!valueClass->CanSplit()) { This->fCanSplit = 0; return kFALSE; }
2275 if (valueClass->GetCollectionProxy() != 0) { This->fCanSplit = 0; return kFALSE; }
2276
2277 Int_t stl = -TClassEdit::IsSTLCont(GetName(), 0);
2278 if ((stl==ROOT::kSTLmap || stl==ROOT::kSTLmultimap)
2279 && !valueClass->HasDataMemberInfo())
2280 {
2281 This->fCanSplit = 0;
2282 return kFALSE;
2283 }
2284
2285 This->fCanSplit = 1;
2286 return kTRUE;
2287
2288 }
2289
2290 if (GetStreamer() != nullptr || fStreamerFunc != nullptr) {
2291
2292 // We have an external custom streamer provided by the user, we must not
2293 // split it.
2294 This->fCanSplit = 0;
2295 return kFALSE;
2296
2298
2299 // We have a custom member function streamer or
2300 // an older (not StreamerInfo based) automatic streamer.
2301 This->fCanSplit = 0;
2302 return kFALSE;
2303 }
2304
2305 if (Size()==1) {
2306 // 'Empty' class there is nothing to split!.
2307 This->fCanSplit = 0;
2308 return kFALSE;
2309 }
2310
2311
2312 if ( !This->CanSplitBaseAllow() ) {
2313 return kFALSE;
2314 }
2315
2316 This->fCanSplit = 1;
2317 return kTRUE;
2318}
2319
2320////////////////////////////////////////////////////////////////////////////////
2321/// Return the C++ property of this class, eg. is abstract, has virtual base
2322/// class, see EClassProperty in TDictionary.h
2323
2325{
2326 if (fProperty == -1) Property();
2327 return fClassProperty;
2328}
2329
2330////////////////////////////////////////////////////////////////////////////////
2331/// Create a Clone of this TClass object using a different name but using the same 'dictionary'.
2332/// This effectively creates a hard alias for the class name.
2333
2334TObject *TClass::Clone(const char *new_name) const
2335{
2336 if (new_name == 0 || new_name[0]=='\0' || fName == new_name) {
2337 Error("Clone","The name of the class must be changed when cloning a TClass object.");
2338 return 0;
2339 }
2340
2341 // Need to lock access to TROOT::GetListOfClasses so the cloning happens atomically
2343 // Temporarily remove the original from the list of classes.
2344 TClass::RemoveClass(const_cast<TClass*>(this));
2345
2346 TClass *copy;
2347 if (fTypeInfo) {
2348 copy = new TClass(GetName(),
2350 *fTypeInfo,
2351 new TIsAProxy(*fTypeInfo),
2355 GetImplFileLine());
2356 } else {
2357 copy = new TClass(GetName(),
2362 GetImplFileLine());
2363 }
2364 copy->fShowMembers = fShowMembers;
2365 // Remove the copy before renaming it
2366 TClass::RemoveClass(copy);
2367 copy->fName = new_name;
2368 TClass::AddClass(copy);
2369
2370 copy->SetNew(fNew);
2371 copy->SetNewArray(fNewArray);
2372 copy->SetDelete(fDelete);
2378 if (fStreamer) {
2380 }
2381 // If IsZombie is true, something went wrong and we will not be
2382 // able to properly copy the collection proxy
2383 if (fCollectionProxy && !copy->IsZombie()) {
2385 }
2386 copy->SetClassSize(fSizeof);
2387 if (fRefProxy) {
2389 }
2390 TClass::AddClass(const_cast<TClass*>(this));
2391 return copy;
2392}
2393
2394////////////////////////////////////////////////////////////////////////////////
2395/// Copy the argument.
2396
2398{
2399// // This code was used too quickly test the STL Emulation layer
2400// Int_t k = TClassEdit::IsSTLCont(GetName());
2401// if (k==1||k==-1) return;
2402
2403 delete fCollectionProxy;
2404 fCollectionProxy = orig.Generate();
2405}
2406
2407////////////////////////////////////////////////////////////////////////////////
2408/// Draw detailed class inheritance structure.
2409/// If a class B inherits from a class A, the description of B is drawn
2410/// on the right side of the description of A.
2411/// Member functions overridden by B are shown in class A with a blue line
2412/// erasing the corresponding member function
2413
2415{
2416 if (!HasInterpreterInfo()) return;
2417
2418 TVirtualPad *padsav = gPad;
2419
2420 // Should we create a new canvas?
2421 TString opt=option;
2422 if (!padsav || !opt.Contains("same")) {
2423 TVirtualPad *padclass = (TVirtualPad*)(gROOT->GetListOfCanvases())->FindObject("R__class");
2424 if (!padclass) {
2425 gROOT->ProcessLine("new TCanvas(\"R__class\",\"class\",20,20,1000,750);");
2426 } else {
2427 padclass->cd();
2428 }
2429 }
2430
2431 if (gPad) gPad->DrawClassObject(this,option);
2432
2433 if (padsav) padsav->cd();
2434}
2435
2436////////////////////////////////////////////////////////////////////////////////
2437/// Dump contents of object on stdout.
2438/// Using the information in the object dictionary
2439/// each data member is interpreted.
2440/// If a data member is a pointer, the pointer value is printed
2441/// 'obj' is assume to point to an object of the class describe by this TClass
2442///
2443/// The following output is the Dump of a TArrow object:
2444/// ~~~ {.cpp}
2445/// fAngle 0 Arrow opening angle (degrees)
2446/// fArrowSize 0.2 Arrow Size
2447/// fOption.*fData
2448/// fX1 0.1 X of 1st point
2449/// fY1 0.15 Y of 1st point
2450/// fX2 0.67 X of 2nd point
2451/// fY2 0.83 Y of 2nd point
2452/// fUniqueID 0 object unique identifier
2453/// fBits 50331648 bit field status word
2454/// fLineColor 1 line color
2455/// fLineStyle 1 line style
2456/// fLineWidth 1 line width
2457/// fFillColor 19 fill area color
2458/// fFillStyle 1001 fill area style
2459/// ~~~
2460///
2461/// If noAddr is true, printout of all pointer values is skipped.
2462
2463void TClass::Dump(const void *obj, Bool_t noAddr /*=kFALSE*/) const
2464{
2465
2466 Long_t prObj = noAddr ? 0 : (Long_t)obj;
2467 if (IsTObject()) {
2468 if (!fIsOffsetStreamerSet) {
2470 }
2471 TObject *tobj = (TObject*)((Long_t)obj + fOffsetStreamer);
2472
2473
2474 if (sizeof(this) == 4)
2475 Printf("==> Dumping object at: 0x%08lx, name=%s, class=%s\n",prObj,tobj->GetName(),GetName());
2476 else
2477 Printf("==> Dumping object at: 0x%016lx, name=%s, class=%s\n",prObj,tobj->GetName(),GetName());
2478 } else {
2479
2480 if (sizeof(this) == 4)
2481 Printf("==> Dumping object at: 0x%08lx, class=%s\n",prObj,GetName());
2482 else
2483 Printf("==> Dumping object at: 0x%016lx, class=%s\n",prObj,GetName());
2484 }
2485
2486 TDumpMembers dm(noAddr);
2487 if (!CallShowMembers(obj, dm, kFALSE)) {
2488 Info("Dump", "No ShowMembers function, dumping disabled");
2489 }
2490}
2491
2492////////////////////////////////////////////////////////////////////////////////
2493/// Introduce an escape character (@) in front of a special chars.
2494/// You need to use the result immediately before it is being overwritten.
2495
2496char *TClass::EscapeChars(const char *text) const
2497{
2498 static const UInt_t maxsize = 255;
2499 static char name[maxsize+2]; //One extra if last char needs to be escaped
2500
2501 UInt_t nch = strlen(text);
2502 UInt_t icur = 0;
2503 for (UInt_t i = 0; i < nch && icur < maxsize; ++i, ++icur) {
2504 if (text[i] == '\"' || text[i] == '[' || text[i] == '~' ||
2505 text[i] == ']' || text[i] == '&' || text[i] == '#' ||
2506 text[i] == '!' || text[i] == '^' || text[i] == '<' ||
2507 text[i] == '?' || text[i] == '>') {
2508 name[icur] = '@';
2509 ++icur;
2510 }
2511 name[icur] = text[i];
2512 }
2513 name[icur] = 0;
2514 return name;
2515}
2516
2517////////////////////////////////////////////////////////////////////////////////
2518/// Return a pointer the the real class of the object.
2519/// This is equivalent to object->IsA() when the class has a ClassDef.
2520/// It is REQUIRED that object is coming from a proper pointer to the
2521/// class represented by 'this'.
2522/// Example: Special case:
2523/// ~~~ {.cpp}
2524/// class MyClass : public AnotherClass, public TObject
2525/// ~~~
2526/// then on return, one must do:
2527/// ~~~ {.cpp}
2528/// TObject *obj = (TObject*)((void*)myobject)directory->Get("some object of MyClass");
2529/// MyClass::Class()->GetActualClass(obj); // this would be wrong!!!
2530/// ~~~
2531/// Also if the class represented by 'this' and NONE of its parents classes
2532/// have a virtual ptr table, the result will be 'this' and NOT the actual
2533/// class.
2534
2535TClass *TClass::GetActualClass(const void *object) const
2536{
2537 if (object==0) return (TClass*)this;
2538 if (fIsA) {
2539 return (*fIsA)(object); // ROOT::IsA((ThisClass*)object);
2540 } else if (fGlobalIsA) {
2541 return fGlobalIsA(this,object);
2542 } else {
2543 if (IsTObject()) {
2544
2545 if (!fIsOffsetStreamerSet) {
2547 }
2548 TObject* realTObject = (TObject*)((size_t)object + fOffsetStreamer);
2549
2550 return realTObject->IsA();
2551 }
2552
2553 if (HasInterpreterInfo()) {
2554
2555 TVirtualIsAProxy *isa = 0;
2557 isa = (TVirtualIsAProxy*)gROOT->ProcessLineFast(TString::Format("new ::TInstrumentedIsAProxy<%s>(0);",GetName()));
2558 }
2559 else {
2560 isa = (TVirtualIsAProxy*)gROOT->ProcessLineFast(TString::Format("new ::TIsAProxy(typeid(%s));",GetName()));
2561 }
2562 if (isa) {
2564 const_cast<TClass*>(this)->fIsA = isa;
2565 }
2566 if (fIsA) {
2567 return (*fIsA)(object); // ROOT::IsA((ThisClass*)object);
2568 }
2569 }
2571 if (sinfo) {
2572 return sinfo->GetActualClass(object);
2573 }
2574 return (TClass*)this;
2575 }
2576}
2577
2578////////////////////////////////////////////////////////////////////////////////
2579/// Return pointer to the base class "classname". Returns 0 in case
2580/// "classname" is not a base class. Takes care of multiple inheritance.
2581
2582TClass *TClass::GetBaseClass(const char *classname)
2583{
2584 // check if class name itself is equal to classname
2585 if (strcmp(GetName(), classname) == 0) return this;
2586
2587 if (!HasDataMemberInfo()) return 0;
2588
2589 // Make sure we deal with possible aliases, we could also have normalized
2590 // the name.
2591 TClass *search = TClass::GetClass(classname,kTRUE,kTRUE);
2592
2593 if (search) return GetBaseClass(search);
2594 else return 0;
2595}
2596
2597////////////////////////////////////////////////////////////////////////////////
2598/// Return pointer to the base class "cl". Returns 0 in case "cl"
2599/// is not a base class. Takes care of multiple inheritance.
2600
2602{
2603 // check if class name itself is equal to classname
2604 if (cl == this) return this;
2605
2606 if (!HasDataMemberInfo()) return 0;
2607
2608 TObjLink *lnk = GetListOfBases() ? fBase.load()->FirstLink() : 0;
2609
2610 // otherwise look at inheritance tree
2611 while (lnk) {
2612 TClass *c, *c1;
2613 TBaseClass *base = (TBaseClass*) lnk->GetObject();
2614 c = base->GetClassPointer();
2615 if (c) {
2616 if (cl == c) return c;
2617 c1 = c->GetBaseClass(cl);
2618 if (c1) return c1;
2619 }
2620 lnk = lnk->Next();
2621 }
2622 return 0;
2623}
2624
2625////////////////////////////////////////////////////////////////////////////////
2626/// Return data member offset to the base class "cl".
2627/// - Returns -1 in case "cl" is not a base class.
2628/// - Returns -2 if cl is a base class, but we can't find the offset
2629/// because it's virtual.
2630/// Takes care of multiple inheritance.
2631
2633{
2634 // check if class name itself is equal to classname
2635 if (cl == this) return 0;
2636
2637 if (!fBase.load()) {
2639 // If the information was not provided by the root pcm files and
2640 // if we can not find the ClassInfo, we have to fall back to the
2641 // StreamerInfo
2642 if (!fClassInfo) {
2644 if (!sinfo) return -1;
2645 TStreamerElement *element;
2646 Int_t offset = 0;
2647
2648 TObjArray &elems = *(sinfo->GetElements());
2649 Int_t size = elems.GetLast()+1;
2650 for(Int_t i=0; i<size; i++) {
2651 element = (TStreamerElement*)elems[i];
2652 if (element->IsBase()) {
2653 if (element->IsA() == TStreamerBase::Class()) {
2654 TStreamerBase *base = (TStreamerBase*)element;
2655 TClass *baseclass = base->GetClassPointer();
2656 if (!baseclass) return -1;
2657 Int_t subOffset = baseclass->GetBaseClassOffsetRecurse(cl);
2658 if (subOffset == -2) return -2;
2659 if (subOffset != -1) return offset+subOffset;
2660 offset += baseclass->Size();
2661 } else if (element->IsA() == TStreamerSTL::Class()) {
2662 TStreamerSTL *base = (TStreamerSTL*)element;
2663 TClass *baseclass = base->GetClassPointer();
2664 if (!baseclass) return -1;
2665 Int_t subOffset = baseclass->GetBaseClassOffsetRecurse(cl);
2666 if (subOffset == -2) return -2;
2667 if (subOffset != -1) return offset+subOffset;
2668 offset += baseclass->Size();
2669
2670 } else {
2671 Error("GetBaseClassOffsetRecurse","Unexpected element type for base class: %s\n",element->IsA()->GetName());
2672 }
2673 }
2674 }
2675 return -1;
2676 }
2677 }
2678
2679 TClass *c;
2680 Int_t off;
2681 TBaseClass *inh;
2682 TObjLink *lnk = 0;
2683 if (fBase.load() == 0)
2684 lnk = GetListOfBases()->FirstLink();
2685 else
2686 lnk = fBase.load()->FirstLink();
2687
2688 // otherwise look at inheritance tree
2689 while (lnk) {
2690 inh = (TBaseClass *)lnk->GetObject();
2691 //use option load=kFALSE to avoid a warning like:
2692 //"Warning in <TClass::TClass>: no dictionary for class TRefCnt is available"
2693 //We can not afford to not have the class if it exist, so we
2694 //use kTRUE.
2695 c = inh->GetClassPointer(kTRUE); // kFALSE);
2696 if (c) {
2697 if (cl == c) {
2698 if ((inh->Property() & kIsVirtualBase) != 0)
2699 return -2;
2700 return inh->GetDelta();
2701 }
2702 off = c->GetBaseClassOffsetRecurse(cl);
2703 if (off == -2) return -2;
2704 if (off != -1) {
2705 return off + inh->GetDelta();
2706 }
2707 }
2708 lnk = lnk->Next();
2709 }
2710 return -1;
2711}
2712
2713////////////////////////////////////////////////////////////////////////////////
2714/// - Return data member offset to the base class "cl".
2715/// - Returns -1 in case "cl" is not a base class.
2716/// Takes care of multiple inheritance.
2717
2718Int_t TClass::GetBaseClassOffset(const TClass *toBase, void *address, bool isDerivedObject)
2719{
2720 // Warning("GetBaseClassOffset","Requires the use of fClassInfo for %s to %s",GetName(),toBase->GetName());
2721
2722 if (this == toBase) return 0;
2723
2724 if ((!address /* || !has_virtual_base */) &&
2726 // At least of the ClassInfo have not been loaded in memory yet and
2727 // since there is no virtual base class (or we don't have enough so it
2728 // would not make a difference) we can use the 'static' information
2729 Int_t offset = GetBaseClassOffsetRecurse (toBase);
2730 if (offset != -2) {
2731 return offset;
2732 }
2733 return offset;
2734 }
2735
2736 ClassInfo_t* derived = GetClassInfo();
2737 ClassInfo_t* base = toBase->GetClassInfo();
2738 if(derived && base) {
2739 // TClingClassInfo::GetBaseOffset takes the lock.
2740 return gCling->ClassInfo_GetBaseOffset(derived, base, address, isDerivedObject);
2741 }
2742 else {
2743 Int_t offset = GetBaseClassOffsetRecurse (toBase);
2744 if (offset != -2) {
2745 return offset;
2746 }
2747 }
2748 return -1;
2749}
2750
2751////////////////////////////////////////////////////////////////////////////////
2752/// Return pointer to (base) class that contains datamember.
2753
2754TClass *TClass::GetBaseDataMember(const char *datamember)
2755{
2756 if (!HasDataMemberInfo()) return 0;
2757
2758 // Check if data member exists in class itself
2759 TDataMember *dm = GetDataMember(datamember);
2760 if (dm) return this;
2761
2762 // if datamember not found in class, search in next base classes
2763 TBaseClass *inh;
2764 TIter next(GetListOfBases());
2765 while ((inh = (TBaseClass *) next())) {
2766 TClass *c = inh->GetClassPointer();
2767 if (c) {
2768 TClass *cdm = c->GetBaseDataMember(datamember);
2769 if (cdm) return cdm;
2770 }
2771 }
2772
2773 return 0;
2774}
2775
2776namespace {
2777 // A local Helper class used to keep 2 pointer (the collection proxy
2778 // and the class streamer) in the thread local storage.
2779
2780 struct TClassLocalStorage {
2781 TClassLocalStorage() : fCollectionProxy(0), fStreamer(0) {};
2782
2783 TVirtualCollectionProxy *fCollectionProxy;
2784 TClassStreamer *fStreamer;
2785
2786 static TClassLocalStorage *GetStorage(const TClass *cl)
2787 {
2788 // Return the thread storage for the TClass.
2789
2790 void **thread_ptr = (*gThreadTsd)(0,ROOT::kClassThreadSlot);
2791 if (thread_ptr) {
2792 if (*thread_ptr==0) *thread_ptr = new TExMap();
2793 TExMap *lmap = (TExMap*)(*thread_ptr);
2794 ULong_t hash = TString::Hash(&cl, sizeof(void*));
2795 ULong_t local = 0;
2796 UInt_t slot;
2797 if ((local = (ULong_t)lmap->GetValue(hash, (Long_t)cl, slot)) != 0) {
2798 } else {
2799 local = (ULong_t) new TClassLocalStorage();
2800 lmap->AddAt(slot, hash, (Long_t)cl, local);
2801 }
2802 return (TClassLocalStorage*)local;
2803 }
2804 return 0;
2805 }
2806 };
2807}
2808
2809////////////////////////////////////////////////////////////////////////////////
2810/// Return the 'type' of the STL the TClass is representing.
2811/// and return ROOT::kNotSTL if it is not representing an STL collection.
2812
2814{
2815 auto proxy = GetCollectionProxy();
2816 if (proxy) return (ROOT::ESTLType)proxy->GetCollectionType();
2817 return ROOT::kNotSTL;
2818}
2819
2820
2821////////////////////////////////////////////////////////////////////////////////
2822/// Return the proxy describing the collection (if any).
2823
2825{
2826 // Use assert, so that this line (slow because of the TClassEdit) is completely
2827 // removed in optimized code.
2828 //assert(TestBit(kLoading) || !TClassEdit::IsSTLCont(fName) || fCollectionProxy || 0 == "The TClass for the STL collection has no collection proxy!");
2830 TClassLocalStorage *local = TClassLocalStorage::GetStorage(this);
2831 if (local == 0) return fCollectionProxy;
2832 if (local->fCollectionProxy==0) local->fCollectionProxy = fCollectionProxy->Generate();
2833 return local->fCollectionProxy;
2834 }
2835 return fCollectionProxy;
2836}
2837
2838////////////////////////////////////////////////////////////////////////////////
2839/// Return the Streamer Class allowing streaming (if any).
2840
2842{
2843 if (gThreadTsd && fStreamer) {
2844 TClassLocalStorage *local = TClassLocalStorage::GetStorage(this);
2845 if (local==0) return fStreamer;
2846 if (local->fStreamer==0) {
2847 local->fStreamer = fStreamer->Generate();
2848 const std::type_info &orig = ( typeid(*fStreamer) );
2849 if (!local->fStreamer) {
2850 Warning("GetStreamer","For %s, the TClassStreamer (%s) passed's call to Generate failed!",GetName(),orig.name());
2851 } else {
2852 const std::type_info &copy = ( typeid(*local->fStreamer) );
2853 if (strcmp(orig.name(),copy.name())!=0) {
2854 Warning("GetStreamer","For %s, the TClassStreamer passed does not properly implement the Generate method (%s vs %s)\n",GetName(),orig.name(),copy.name());
2855 }
2856 }
2857 }
2858 return local->fStreamer;
2859 }
2860 return fStreamer;
2861}
2862
2863////////////////////////////////////////////////////////////////////////////////
2864/// Get a wrapper/accessor function around this class custom streamer (member function).
2865
2867{
2868 return fStreamerFunc;
2869}
2870
2871////////////////////////////////////////////////////////////////////////////////
2872/// Get a wrapper/accessor function around this class custom conversion streamer (member function).
2873
2875{
2876 return fConvStreamerFunc;
2877}
2878
2879////////////////////////////////////////////////////////////////////////////////
2880/// Return the proxy implementing the IsA functionality.
2881
2883{
2884 return fIsA;
2885}
2886
2887////////////////////////////////////////////////////////////////////////////////
2888/// Static method returning pointer to TClass of the specified class name.
2889/// If load is true an attempt is made to obtain the class by loading
2890/// the appropriate shared library (directed by the rootmap file).
2891/// If silent is 'true', do not warn about missing dictionary for the class.
2892/// (typically used for class that are used only for transient members)
2893/// Returns 0 in case class is not found.
2894
2895TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent)
2896{
2897 if (!name || !name[0]) return 0;
2898
2899 if (strstr(name, "(anonymous)")) return 0;
2900 if (strncmp(name,"class ",6)==0) name += 6;
2901 if (strncmp(name,"struct ",7)==0) name += 7;
2902
2903 if (!gROOT->GetListOfClasses()) return 0;
2904
2905 // FindObject will take the read lock before actually getting the
2906 // TClass pointer so we will need not get a partially initialized
2907 // object.
2908 TClass *cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
2909
2910 // Early return to release the lock without having to execute the
2911 // long-ish normalization.
2912 if (cl && (cl->IsLoaded() || cl->TestBit(kUnloading))) return cl;
2913
2915
2916 // Now that we got the write lock, another thread may have constructed the
2917 // TClass while we were waiting, so we need to do the checks again.
2918
2919 cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
2920 if (cl) {
2921 if (cl->IsLoaded() || cl->TestBit(kUnloading)) return cl;
2922
2923 // We could speed-up some of the search by adding (the equivalent of)
2924 //
2925 // if (cl->GetState() == kInterpreter) return cl
2926 //
2927 // In this case, if a ROOT dictionary was available when the TClass
2928 // was first requested it would have been used and if a ROOT dictionary is
2929 // loaded later on TClassTable::Add will take care of updating the TClass.
2930 // So as far as ROOT dictionary are concerned, if the current TClass is
2931 // in interpreted state, we are sure there is nothing to load.
2932 //
2933 // However (see TROOT::LoadClass), the TClass can also be loaded/provided
2934 // by a user provided TClassGenerator. We have no way of knowing whether
2935 // those do (or even can) behave the same way as the ROOT dictionary and
2936 // have the 'dictionary is now available for use' step informs the existing
2937 // TClass that their dictionary is now available.
2938
2939 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
2940 load = kTRUE;
2941 }
2942
2943 // To avoid spurious auto parsing, let's check if the name as-is is
2944 // known in the TClassTable.
2946 if (dict) {
2947 // The name is normalized, so the result of the first search is
2948 // authoritative.
2949 if (!cl && !load) return 0;
2950
2951 TClass *loadedcl = (dict)();
2952 if (loadedcl) {
2953 loadedcl->PostLoadCheck();
2954 return loadedcl;
2955 }
2956
2957 // We should really not fall through to here, but if we do, let's just
2958 // continue as before ...
2959 }
2960
2961 std::string normalizedName;
2962 Bool_t checkTable = kFALSE;
2963
2964 if (!cl) {
2965 {
2967 TClassEdit::GetNormalizedName(normalizedName, name);
2968 }
2969 // Try the normalized name.
2970 if (normalizedName != name) {
2971 cl = (TClass*)gROOT->GetListOfClasses()->FindObject(normalizedName.c_str());
2972
2973 if (cl) {
2974 if (cl->IsLoaded() || cl->TestBit(kUnloading)) return cl;
2975
2976 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
2977 load = kTRUE;
2978 }
2979 checkTable = kTRUE;
2980 }
2981 } else {
2982 normalizedName = cl->GetName(); // Use the fact that all TClass names are normalized.
2983 checkTable = load && (normalizedName != name);
2984 }
2985
2986 if (!load) return 0;
2987
2988// This assertion currently fails because of
2989// TClass *c1 = TClass::GetClass("basic_iostream<char,char_traits<char> >");
2990// TClass *c2 = TClass::GetClass("std::iostream");
2991// where the TClassEdit normalized name of iostream is basic_iostream<char>
2992// i.e missing the addition of the default parameter. This is because TClingLookupHelper
2993// uses only 'part' of TMetaUtils::GetNormalizedName.
2994
2995// if (!cl) {
2996// TDataType* dataType = (TDataType*)gROOT->GetListOfTypes()->FindObject(name);
2997// TClass *altcl = dataType ? (TClass*)gROOT->GetListOfClasses()->FindObject(dataType->GetFullTypeName()) : 0;
2998// if (altcl && normalizedName != altcl->GetName())
2999// ::Fatal("TClass::GetClass","The existing name (%s) for %s is different from the normalized name: %s\n",
3000// altcl->GetName(), name, normalizedName.c_str());
3001// }
3002
3003 TClass *loadedcl = 0;
3004 if (checkTable) {
3005 loadedcl = LoadClassDefault(normalizedName.c_str(),silent);
3006 } else {
3007 if (gInterpreter->AutoLoad(normalizedName.c_str(),kTRUE)) {
3008 loadedcl = LoadClassDefault(normalizedName.c_str(),silent);
3009 }
3010 // Maybe this was a typedef: let's try to see if this is the case
3011 if (!loadedcl){
3012 if (TDataType* theDataType = gROOT->GetType(normalizedName.c_str())){
3013 // We have a typedef: we get the name of the underlying type
3014 auto underlyingTypeName = theDataType->GetTypeName();
3015 // We see if we can bootstrap a class with it
3016 auto underlyingTypeDict = TClassTable::GetDictNorm(underlyingTypeName.Data());
3017 if (underlyingTypeDict){
3018 loadedcl = underlyingTypeDict();
3019 }
3020
3021 }
3022 }
3023 }
3024 if (loadedcl) return loadedcl;
3025
3026 // See if the TClassGenerator can produce the TClass we need.
3027 loadedcl = LoadClassCustom(normalizedName.c_str(),silent);
3028 if (loadedcl) return loadedcl;
3029
3030 // We have not been able to find a loaded TClass, return the Emulated
3031 // TClass if we have one.
3032 if (cl) return cl;
3033
3034 if (TClassEdit::IsSTLCont( normalizedName.c_str() )) {
3035
3036 return gInterpreter->GenerateTClass(normalizedName.c_str(), kTRUE, silent);
3037 }
3038
3039 // Check the interpreter only after autoparsing the template if any.
3040 {
3041 std::string::size_type posLess = normalizedName.find('<');
3042 if (posLess != std::string::npos) {
3043 gCling->AutoParse(normalizedName.substr(0, posLess).c_str());
3044 }
3045 }
3046
3047 //last attempt. Look in CINT list of all (compiled+interpreted) classes
3048 if (gDebug>0){
3049 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());
3050 }
3051 if (normalizedName.length()) {
3052 auto cci = gInterpreter->CheckClassInfo(normalizedName.c_str(), kTRUE /* autoload */,
3053 kTRUE /*Only class, structs and ns*/);
3054
3055 // We could have an interpreted class with an inline ClassDef, in this case we do not
3056 // want to create an 'interpreted' TClass but we want the one triggered via the call to
3057 // the Dictionary member. If we go ahead and generate the 'interpreted' version it will
3058 // replace if/when there is a call to IsA on an object of this type.
3059
3061 auto ci = gInterpreter->ClassInfo_Factory(normalizedName.c_str());
3062 auto funcDecl = gInterpreter->GetFunctionWithPrototype(ci, "Dictionary", "", false, ROOT::kExactMatch);
3063 auto method = gInterpreter->MethodInfo_Factory(funcDecl);
3064 typedef void (*tcling_callfunc_Wrapper_t)(void *, int, void **, void *);
3065 auto funcPtr = (tcling_callfunc_Wrapper_t)gInterpreter->MethodInfo_InterfaceMethod(method);
3066
3067 TClass *res = nullptr;
3068 if (funcPtr)
3069 funcPtr(0, 0, nullptr, &res);
3070 // else
3071 // We could fallback to the interpreted case ...
3072 // For now just 'fail' (return nullptr)
3073
3074 gInterpreter->MethodInfo_Delete(method);
3075 gInterpreter->ClassInfo_Delete(ci);
3076
3077 return res;
3078 } else if (cci) {
3079 // Get the normalized name based on the decl (currently the only way
3080 // to get the part to add or drop the default arguments as requested by the user)
3081 std::string alternative;
3082 gInterpreter->GetInterpreterTypeName(normalizedName.c_str(), alternative, kTRUE);
3083 const char *altname = alternative.c_str();
3084 if (strncmp(altname, "std::", 5) == 0) {
3085 // For namespace (for example std::__1), GetInterpreterTypeName does
3086 // not strip std::, so we must do it explicitly here.
3087 altname += 5;
3088 }
3089 if (altname != normalizedName && strcmp(altname, name) != 0) {
3090 // altname now contains the full name of the class including a possible
3091 // namespace if there has been a using namespace statement.
3092
3093 // At least in the case C<string [2]> (normalized) vs C<string[2]> (altname)
3094 // the TClassEdit normalization and the TMetaUtils normalization leads to
3095 // two different space layout. To avoid an infinite recursion, we also
3096 // add the test on (altname != name)
3097
3098 return GetClass(altname, load);
3099 }
3100
3101 TClass *ncl = gInterpreter->GenerateTClass(normalizedName.c_str(), /* emulation = */ kFALSE, silent);
3102 if (!ncl->IsZombie()) {
3103 return ncl;
3104 }
3105 delete ncl;
3106 }
3107 }
3108 return nullptr;
3109}
3110
3111////////////////////////////////////////////////////////////////////////////////
3112/// Return pointer to class with name.
3113
3114TClass *TClass::GetClass(const std::type_info& typeinfo, Bool_t load, Bool_t /* silent */)
3115{
3116 if (!gROOT->GetListOfClasses())
3117 return 0;
3118
3119 //protect access to TROOT::GetIdMap
3121
3122 TClass* cl = GetIdMap()->Find(typeinfo.name());
3123
3124 if (cl && cl->IsLoaded()) return cl;
3125
3127
3128 // Now that we got the write lock, another thread may have constructed the
3129 // TClass while we were waiting, so we need to do the checks again.
3130
3131 cl = GetIdMap()->Find(typeinfo.name());
3132
3133 if (cl) {
3134 if (cl->IsLoaded()) return cl;
3135 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
3136 load = kTRUE;
3137 } else {
3138 // Note we might need support for typedefs and simple types!
3139
3140 // TDataType *objType = GetType(name, load);
3141 //if (objType) {
3142 // const char *typdfName = objType->GetTypeName();
3143 // if (typdfName && strcmp(typdfName, name)) {
3144 // cl = GetClass(typdfName, load);
3145 // return cl;
3146 // }
3147 // }
3148 }
3149
3150 if (!load) return 0;
3151
3152 DictFuncPtr_t dict = TClassTable::GetDict(typeinfo);
3153 if (dict) {
3154 cl = (dict)();
3155 if (cl) cl->PostLoadCheck();
3156 return cl;
3157 }
3158 if (cl) return cl;
3159
3160 TIter next(gROOT->GetListOfClassGenerators());
3161 TClassGenerator *gen;
3162 while( (gen = (TClassGenerator*) next()) ) {
3163 cl = gen->GetClass(typeinfo,load);
3164 if (cl) {
3165 cl->PostLoadCheck();
3166 return cl;
3167 }
3168 }
3169
3170 // try autoloading the typeinfo
3171 int autoload_old = gCling->SetClassAutoloading(1);
3172 if (!autoload_old) {
3173 // Re-disable, we just meant to test
3175 }
3176 if (autoload_old && gInterpreter->AutoLoad(typeinfo,kTRUE)) {
3177 // Disable autoload to avoid potential infinite recursion
3179 cl = GetClass(typeinfo, load);
3180 if (cl) {
3181 return cl;
3182 }
3183 }
3184
3185 // last attempt. Look in the interpreter list of all (compiled+interpreted)
3186 // classes
3187 cl = gInterpreter->GetClass(typeinfo, load);
3188
3189 return cl; // Can be zero.
3190}
3191
3192////////////////////////////////////////////////////////////////////////////////
3193/// Static method returning pointer to TClass of the specified ClassInfo.
3194/// If load is true an attempt is made to obtain the class by loading
3195/// the appropriate shared library (directed by the rootmap file).
3196/// If silent is 'true', do not warn about missing dictionary for the class.
3197/// (typically used for class that are used only for transient members)
3198/// Returns 0 in case class is not found.
3199
3200TClass *TClass::GetClass(ClassInfo_t *info, Bool_t load, Bool_t silent)
3201{
3202 if (!info || !gCling->ClassInfo_IsValid(info)) return 0;
3203 if (!gROOT->GetListOfClasses()) return 0;
3204
3205 // Technically we need the write lock only for the call to ClassInfo_FullName
3206 // and GenerateTClass but FindObject will take the read lock (and LoadClass will
3207 // take the write lock). Since taking/releasing the lock is expensive, let just
3208 // take the write guard and keep it.
3210
3211 // Get the normalized name.
3213
3214 TClass *cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
3215
3216 if (cl) {
3217 if (cl->IsLoaded()) return cl;
3218
3219 //we may pass here in case of a dummy class created by TVirtualStreamerInfo
3220 load = kTRUE;
3221
3222 }
3223
3224 if (!load) return 0;
3225
3226 TClass *loadedcl = 0;
3227 if (cl) loadedcl = gROOT->LoadClass(cl->GetName(),silent);
3228 else loadedcl = gROOT->LoadClass(name,silent);
3229
3230 if (loadedcl) return loadedcl;
3231
3232 if (cl) return cl; // If we found the class but we already have a dummy class use it.
3233
3234 // We did not find a proper TClass but we do know (we have a valid
3235 // ClassInfo) that the class is known to the interpreter.
3236 TClass *ncl = gInterpreter->GenerateTClass(info, silent);
3237 if (!ncl->IsZombie()) {
3238 return ncl;
3239 } else {
3240 delete ncl;
3241 return 0;
3242 }
3243}
3244
3245////////////////////////////////////////////////////////////////////////////////
3246
3249}
3250
3251////////////////////////////////////////////////////////////////////////////////
3252
3253Bool_t TClass::GetClass(DeclId_t id, std::vector<TClass*> &classes)
3254{
3255 if (!gROOT->GetListOfClasses()) return 0;
3256
3257 DeclIdMap_t* map = GetDeclIdMap();
3258 // Get all the TClass pointer that have the same DeclId.
3259 DeclIdMap_t::equal_range iter = map->Find(id);
3260 if (iter.first == iter.second) return false;
3261 std::vector<TClass*>::iterator vectIt = classes.begin();
3262 for (DeclIdMap_t::const_iterator it = iter.first; it != iter.second; ++it)
3263 vectIt = classes.insert(vectIt, it->second);
3264 return true;
3265}
3266
3267////////////////////////////////////////////////////////////////////////////////
3268/// Return a pointer to the dictionary loading function generated by
3269/// rootcint
3270
3272{
3273 return TClassTable::GetDict(cname);
3274}
3275
3276////////////////////////////////////////////////////////////////////////////////
3277/// Return a pointer to the dictionary loading function generated by
3278/// rootcint
3279
3280DictFuncPtr_t TClass::GetDict (const std::type_info& info)
3281{
3282 return TClassTable::GetDict(info);
3283}
3284
3285////////////////////////////////////////////////////////////////////////////////
3286/// Return pointer to datamember object with name "datamember".
3287
3288TDataMember *TClass::GetDataMember(const char *datamember) const
3289{
3290 if ((!(fData && fData->IsLoaded()) && !HasInterpreterInfo())
3291 || datamember == 0) return 0;
3292
3293 // Strip off leading *'s and trailing [
3294 const char *start_name = datamember;
3295 while (*start_name == '*') ++start_name;
3296
3297 // Empty name are 'legal', they represent anonymous unions.
3298 // if (*start_name == 0) return 0;
3299
3300 if (const char *s = strchr(start_name, '[')){
3301 UInt_t len = s-start_name;
3302 TString name(start_name,len);
3303 return (TDataMember *)((TClass*)this)->GetListOfDataMembers(kFALSE)->FindObject(name.Data());
3304 } else {
3305 return (TDataMember *)((TClass*)this)->GetListOfDataMembers(kFALSE)->FindObject(start_name);
3306 }
3307}
3308
3309////////////////////////////////////////////////////////////////////////////////
3310/// Return name of the file containing the declaration of this class.
3311
3312const char *TClass::GetDeclFileName() const
3313{
3314 if (fDeclFileName == kUndeterminedClassInfoName)
3315 return gInterpreter->ClassInfo_FileName( fClassInfo );
3316 return fDeclFileName;
3317}
3318
3319////////////////////////////////////////////////////////////////////////////////
3320/// return offset for member name. name can be a data member in
3321/// the class itself, one of its base classes, or one member in
3322/// one of the aggregated classes.
3323///
3324/// In case of an emulated class, the list of emulated TRealData is built
3325
3327{
3328 TRealData *rd = GetRealData(name);
3329 if (rd) return rd->GetThisOffset();
3330 if (strchr(name,'[')==0) {
3331 // If this is a simple name there is a chance to find it in the
3332 // StreamerInfo even if we did not find it in the RealData.
3333 // For example an array name would be fArray[3] in RealData but
3334 // just fArray in the streamerInfo.
3335 TVirtualStreamerInfo *info = const_cast<TClass*>(this)->GetCurrentStreamerInfo();
3336 if (info) {
3337 return info->GetOffset(name);
3338 }
3339 }
3340 return 0;
3341}
3342
3343////////////////////////////////////////////////////////////////////////////////
3344/// Return pointer to TRealData element with name "name".
3345///
3346/// Name can be a data member in the class itself,
3347/// one of its base classes, or a member in
3348/// one of the aggregated classes.
3349///
3350/// In case of an emulated class, the list of emulated TRealData is built.
3351
3353{
3354 if (!fRealData) {
3355 const_cast<TClass*>(this)->BuildRealData();
3356 }
3357
3358 if (!fRealData) {
3359 return 0;
3360 }
3361
3362 if (!name) {
3363 return 0;
3364 }
3365
3366 // First try just the whole name.
3368 if (rd) {
3369 return rd;
3370 }
3371
3372 std::string givenName(name);
3373
3374 // Try ignoring the array dimensions.
3375 std::string::size_type firstBracket = givenName.find_first_of("[");
3376 if (firstBracket != std::string::npos) {
3377 // -- We are looking for an array data member.
3378 std::string nameNoDim(givenName.substr(0, firstBracket));
3379 TObjLink* lnk = fRealData->FirstLink();
3380 while (lnk) {
3381 TObject* obj = lnk->GetObject();
3382 std::string objName(obj->GetName());
3383 std::string::size_type pos = objName.find_first_of("[");
3384 // Only match arrays to arrays for now.
3385 if (pos != std::string::npos) {
3386 objName.erase(pos);
3387 if (objName == nameNoDim) {
3388 return static_cast<TRealData*>(obj);
3389 }
3390 }
3391 lnk = lnk->Next();
3392 }
3393 }
3394
3395 // Now try it as a pointer.
3396 std::ostringstream ptrname;
3397 ptrname << "*" << givenName;
3398 rd = (TRealData*) fRealData->FindObject(ptrname.str().c_str());
3399 if (rd) {
3400 return rd;
3401 }
3402
3403 // Check for a dot in the name.
3404 std::string::size_type firstDot = givenName.find_first_of(".");
3405 if (firstDot == std::string::npos) {
3406 // -- Not found, a simple name, all done.
3407 return 0;
3408 }
3409
3410 //
3411 // At this point the name has a dot in it, so it is the name
3412 // of some contained sub-object.
3413 //
3414
3415 // May be a pointer like in TH1: fXaxis.fLabels (in TRealdata is named fXaxis.*fLabels)
3416 std::string::size_type lastDot = givenName.find_last_of(".");
3417 std::ostringstream starname;
3418 starname << givenName.substr(0, lastDot) << ".*" << givenName.substr(lastDot + 1);
3419 rd = (TRealData*) fRealData->FindObject(starname.str().c_str());
3420 if (rd) {
3421 return rd;
3422 }
3423
3424 // Strip the first component, it may be the name of
3425 // the branch (old TBranchElement code), and try again.
3426 std::string firstDotName(givenName.substr(firstDot + 1));
3427
3428 // New attempt starting after the first "." if any,
3429 // this allows for the case that the first component
3430 // may have been a branch name (for TBranchElement).
3431 rd = (TRealData*) fRealData->FindObject(firstDotName.c_str());
3432 if (rd) {
3433 return rd;
3434 }
3435
3436 // New attempt starting after the first "." if any,
3437 // but this time try ignoring the array dimensions.
3438 // Again, we are allowing for the case that the first
3439 // component may have been a branch name (for TBranchElement).
3440 std::string::size_type firstDotBracket = firstDotName.find_first_of("[");
3441 if (firstDotBracket != std::string::npos) {
3442 // -- We are looking for an array data member.
3443 std::string nameNoDim(firstDotName.substr(0, firstDotBracket));
3444 TObjLink* lnk = fRealData->FirstLink();
3445 while (lnk) {
3446 TObject* obj = lnk->GetObject();
3447 std::string objName(obj->GetName());
3448 std::string::size_type pos = objName.find_first_of("[");
3449 // Only match arrays to arrays for now.
3450 if (pos != std::string::npos) {
3451 objName.erase(pos);
3452 if (objName == nameNoDim) {
3453 return static_cast<TRealData*>(obj);
3454 }
3455 }
3456 lnk = lnk->Next();
3457 }
3458 }
3459
3460 // New attempt starting after the first "." if any,
3461 // but this time check for a pointer type. Again, we
3462 // are allowing for the case that the first component
3463 // may have been a branch name (for TBranchElement).
3464 ptrname.str("");
3465 ptrname << "*" << firstDotName;
3466 rd = (TRealData*) fRealData->FindObject(ptrname.str().c_str());
3467 if (rd) {
3468 return rd;
3469 }
3470
3471 // Last attempt in case a member has been changed from
3472 // a static array to a pointer, for example the member
3473 // was arr[20] and is now *arr.
3474 //
3475 // Note: In principle, one could also take into account
3476 // the opposite situation where a member like *arr has
3477 // been converted to arr[20].
3478 //
3479 // FIXME: What about checking after the first dot as well?
3480 //
3481 std::string::size_type bracket = starname.str().find_first_of("[");
3482 if (bracket == std::string::npos) {
3483 return 0;
3484 }
3485 rd = (TRealData*) fRealData->FindObject(starname.str().substr(0, bracket).c_str());
3486 if (rd) {
3487 return rd;
3488 }
3489
3490 // Not found;
3491 return 0;
3492}
3493
3494////////////////////////////////////////////////////////////////////////////////
3495
3497{
3498 if (!gInterpreter || !HasInterpreterInfo()) return 0;
3499
3500 // The following
3502
3504}
3505
3506////////////////////////////////////////////////////////////////////////////////
3507/// Get the list of shared libraries containing the code for class cls.
3508/// The first library in the list is the one containing the class, the
3509/// others are the libraries the first one depends on. Returns 0
3510/// in case the library is not found.
3511
3513{
3514 if (!gInterpreter) return 0;
3515
3516 if (fSharedLibs.IsNull())
3517 fSharedLibs = gInterpreter->GetClassSharedLibs(fName);
3518
3519 return !fSharedLibs.IsNull() ? fSharedLibs.Data() : 0;
3520}
3521
3522////////////////////////////////////////////////////////////////////////////////
3523/// Return list containing the TBaseClass(es) of a class.
3524
3526{
3527 if (!fBase.load()) {
3528 if (fCanLoadClassInfo) {
3529 if (fState == kHasTClassInit) {
3530
3532 // NOTE: Add test to prevent redo if another thread has already done the work.
3533 // if (!fHasRootPcmInfo) {
3534
3535 // The bases are in our ProtoClass; we don't need the class info.
3537 if (proto && proto->FillTClass(this)) {
3538 // Not sure this code is still needed
3539 // R__ASSERT(kFALSE);
3540
3542 }
3543 }
3544 // We test again on fCanLoadClassInfo has another thread may have executed it.
3546 LoadClassInfo();
3547 }
3548 }
3549 if (!fClassInfo) return 0;
3550
3551 if (!gInterpreter)
3552 Fatal("GetListOfBases", "gInterpreter not initialized");
3553
3555 if (!fBase.load()) {
3556 gInterpreter->CreateListOfBaseClasses(this);
3557 }
3558 }
3559 return fBase;
3560}
3561
3562////////////////////////////////////////////////////////////////////////////////
3563/// Return a list containing the TEnums of a class.
3564///
3565/// The list returned is safe to use from multiple thread without explicitly
3566/// taking the ROOT global lock.
3567///
3568/// In the case the TClass represents a namespace, the returned list will
3569/// implicit take the ROOT global lock upon any access (see TListOfEnumsWithLock)
3570///
3571/// In the case the TClass represents a class or struct and requestListLoading
3572/// is true, the list is immutable (and thus safe to access from multiple thread
3573/// without taking the global lock at all).
3574///
3575/// In the case the TClass represents a class or struct and requestListLoading
3576/// is false, the list is mutable and thus we return a TListOfEnumsWithLock
3577/// which will implicit take the ROOT global lock upon any access.
3578
3579TList *TClass::GetListOfEnums(Bool_t requestListLoading /* = kTRUE */)
3580{
3581 auto temp = fEnums.load();
3582 if (temp) {
3583 if (requestListLoading) {
3584 if (fProperty == -1) Property();
3585 if (! ((kIsClass | kIsStruct | kIsUnion) & fProperty) ) {
3587 temp->Load();
3588 } else if ( temp->IsA() == TListOfEnumsWithLock::Class() ) {
3589 // We have a class for which the list was not loaded fully at
3590 // first use.
3592 temp->Load();
3593 }
3594 }
3595 return temp;
3596 }
3597
3598 if (!requestListLoading) {
3599 if (fProperty == -1) Property();
3601 if (fEnums.load()) {
3602 return fEnums.load();
3603 }
3604
3605 static bool fromRootCling = dlsym(RTLD_DEFAULT, "usedToIdentifyRootClingByDlSym");
3606
3607 if (fromRootCling) // rootcling is single thread (this save some space in the rootpcm).
3608 fEnums = new TListOfEnums(this);
3609 else
3610 fEnums = new TListOfEnumsWithLock(this);
3611 return fEnums;
3612 }
3613
3615 if (fEnums.load()) {
3616 (*fEnums).Load();
3617 return fEnums.load();
3618 }
3619 if (fProperty == -1) Property();
3620 if ( (kIsClass | kIsStruct | kIsUnion) & fProperty) {
3621 // For this case, the list will be immutable
3622 temp = new TListOfEnums(this);
3623 } else {
3624 //namespaces can have enums added to them
3625 temp = new TListOfEnumsWithLock(this);
3626 }
3627 temp->Load();
3628 fEnums = temp;
3629 return temp;
3630}
3631
3632////////////////////////////////////////////////////////////////////////////////
3633/// Return list containing the TDataMembers of a class.
3634
3636{
3638
3639 if (!fData) {
3641 // NOTE: Add test to prevent redo if another thread has already done the work.
3642 // if (!fHasRootPcmInfo) {
3643
3644 // The members are in our ProtoClass; we don't need the class info.
3646 if (proto && proto->FillTClass(this)) {
3647 // Not sure this code is still needed
3648 // R__ASSERT(kFALSE);
3649
3651 return fData;
3652 }
3653 }
3654 fData = new TListOfDataMembers(this);
3655 }
3656 if (Property() & (kIsClass|kIsStruct|kIsUnion)) {
3657 // If the we have a class or struct or union, the order
3658 // of data members is the list is essential since it determines their
3659 // order on file. So we must always load. Also, the list is fixed
3660 // since the language does not allow to add members.
3661 if (!fData->IsLoaded()) fData->Load();
3662
3663 } else if (load) fData->Load();
3664 return fData;
3665}
3666
3667////////////////////////////////////////////////////////////////////////////////
3668/// Return list containing the TEnums of a class.
3669
3671{
3673
3675 if (load) fFuncTemplate->Load();
3676 return fFuncTemplate;
3677}
3678
3679////////////////////////////////////////////////////////////////////////////////
3680/// Return list containing the TMethods of a class.
3681/// If load is true, the list is populated with all the defined function
3682/// and currently instantiated function template.
3683
3685{
3687
3688 if (!fMethod.load()) GetMethodList();
3689 if (load) {
3690 if (gDebug>0) Info("GetListOfMethods","Header Parsing - Asking for all the methods of class %s: this can involve parsing.",GetName());
3691 (*fMethod).Load();
3692 }
3693 return fMethod;
3694}
3695
3696////////////////////////////////////////////////////////////////////////////////
3697/// Return the collection of functions named "name".
3698
3700{
3701 return const_cast<TClass*>(this)->GetMethodList()->GetListForObject(name);
3702}
3703
3704
3705////////////////////////////////////////////////////////////////////////////////
3706/// Returns a list of all public methods of this class and its base classes.
3707/// Refers to a subset of the methods in GetListOfMethods() so don't do
3708/// GetListOfAllPublicMethods()->Delete().
3709/// Algorithm used to get the list is:
3710/// - put all methods of the class in the list (also protected and private
3711/// ones).
3712/// - loop over all base classes and add only those methods not already in the
3713/// list (also protected and private ones).
3714/// - once finished, loop over resulting list and remove all private and
3715/// protected methods.
3716
3718{
3720
3722 if (load) {
3723 if (gDebug>0) Info("GetListOfAllPublicMethods","Header Parsing - Asking for all the methods of class %s: this can involve parsing.",GetName());
3725 }
3726 return fAllPubMethod;
3727}
3728
3729////////////////////////////////////////////////////////////////////////////////
3730/// Returns a list of all public data members of this class and its base
3731/// classes. Refers to a subset of the data members in GetListOfDatamembers()
3732/// so don't do GetListOfAllPublicDataMembers()->Delete().
3733
3735{
3737
3739 if (load) fAllPubData->Load();
3740 return fAllPubData;
3741}
3742
3743////////////////////////////////////////////////////////////////////////////////
3744/// Returns list of methods accessible by context menu.
3745
3747{
3748 if (!HasInterpreterInfo()) return;
3749
3750 // get the base class
3751 TIter nextBase(GetListOfBases(), kIterBackward);
3752 TBaseClass *baseClass;
3753 while ((baseClass = (TBaseClass *) nextBase())) {
3754 TClass *base = baseClass->GetClassPointer();
3755 if (base) base->GetMenuItems(list);
3756 }
3757
3758 // remove methods redefined in this class with no menu
3759 TMethod *method, *m;
3761 while ((method = (TMethod*)next())) {
3762 m = (TMethod*)list->FindObject(method->GetName());
3763 if (method->IsMenuItem() != kMenuNoMenu) {
3764 if (!m)
3765 list->AddFirst(method);
3766 } else {
3767 if (m && m->GetNargs() == method->GetNargs())
3768 list->Remove(m);
3769 }
3770 }
3771}
3772
3773////////////////////////////////////////////////////////////////////////////////
3774/// Check whether a class has a dictionary or not.
3775/// This is equivalent to ask if a class is coming from a bootstrapping
3776/// procedure initiated during the loading of a library.
3777
3779{
3780 return IsLoaded();
3781}
3782
3783////////////////////////////////////////////////////////////////////////////////
3784/// Check whether a class has a dictionary or ROOT can load one.
3785/// This is equivalent to ask HasDictionary() or whether a library is known
3786/// where it can be loaded from, or whether a Dictionary function is
3787/// available because the class's dictionary library was already loaded.
3788
3790{
3791 if (TClass* cl = (TClass*)gROOT->GetListOfClasses()->FindObject(clname))
3792 return cl->IsLoaded();
3793 return gClassTable->GetDict(clname) || gInterpreter->GetClassSharedLibs(clname);
3794}
3795
3796////////////////////////////////////////////////////////////////////////////////
3797/// Verify the base classes always.
3798
3800{
3801 TList* lb = GetListOfBases();
3802 if (!lb) return;
3803 TIter nextBase(lb);
3804 TBaseClass* base = 0;
3805 while ((base = (TBaseClass*)nextBase())) {
3806 TClass* baseCl = base->GetClassPointer();
3807 if (baseCl) {
3808 baseCl->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3809 }
3810 }
3811}
3812
3813////////////////////////////////////////////////////////////////////////////////
3814/// Verify the Data Members.
3815
3817{
3819 if (!ldm) return ;
3820 TIter nextMemb(ldm);
3821 TDataMember * dm = 0;
3822 while ((dm = (TDataMember*)nextMemb())) {
3823 // If it is a transient
3824 if(!dm->IsPersistent()) {
3825 continue;
3826 }
3827 if (dm->Property() & kIsStatic) {
3828 continue;
3829 }
3830 // If it is a built-in data type.
3831 TClass* dmTClass = 0;
3832 if (dm->GetDataType()) {
3833 // We have a basic datatype.
3834 dmTClass = nullptr;
3835 // Otherwise get the string representing the type.
3836 } else if (dm->GetTypeName()) {
3837 dmTClass = TClass::GetClass(dm->GetTypeName());
3838 }
3839 if (dmTClass) {
3840 dmTClass->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3841 }
3842 }
3843}
3844
3846{
3847 // Pair is a special case and we have to check its elements for missing dictionaries
3848 // Pair is a transparent container so we should always look at its.
3849
3851 for (int i = 0; i < 2; i++) {
3852 TClass* pairElement = ((TStreamerElement*)SI->GetElements()->At(i))->GetClass();
3853 if (pairElement) {
3854 pairElement->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3855 }
3856 }
3857}
3858
3859////////////////////////////////////////////////////////////////////////////////
3860/// From the second level of recursion onwards it is different state check.
3861
3863{
3864 if (result.FindObject(this) || visited.FindObject(this)) return;
3865
3866 static TClassRef sCIString("string");
3867 if (this == sCIString) return;
3868
3869 TClassEdit::TSplitType splitType(fName);
3870 if (splitType.IsTemplate()) {
3871 // We now treat special cases:
3872 // - pair
3873 // - unique_ptr
3874 // - array
3875 // - tuple
3876
3877 // Small helper to get the TClass instance from a classname and recursively
3878 // investigate it
3879 auto checkDicts = [&](const string &clName){
3880 auto cl = TClass::GetClass(clName.c_str());
3881 if (!cl) {
3882 // We try to remove * and const from the type name if any
3883 const auto clNameShortType = TClassEdit::ShortType(clName.c_str(), 1);
3884 cl = TClass::GetClass(clNameShortType.c_str());
3885 }
3886 if (cl && !cl->HasDictionary()) {
3887 cl->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3888 }
3889 };
3890
3891 const auto &elements = splitType.fElements;
3892 const auto &templName = elements[0];
3893
3894 // Special treatment for pair.
3895 if (templName == "pair") {
3896 GetMissingDictionariesForPairElements(result, visited, recurse);
3897 return;
3898 }
3899
3900 // Special treatment of unique_ptr or array
3901 // They are treated together since they have 1 single template argument
3902 // which is interesting when checking for missing dictionaries.
3903 if (templName == "unique_ptr" || templName == "array") {
3904 checkDicts(elements[1]);
3905 return;
3906 }
3907
3908 // Special treatment of tuple
3909 // This type must be treated separately since it can have N template
3910 // arguments which are interesting, unlike unique_ptr or array.
3911 if (templName == "tuple") {
3912 // -1 because the elements end with a list of the "stars", i.e. number of
3913 // * after the type name
3914 const auto nTemplArgs = elements.size() - 1;
3915 // loop starts at 1 because the first element is the template name
3916 for (auto iTemplArg = 1U; iTemplArg < nTemplArgs; ++iTemplArg) {
3917 checkDicts(elements[iTemplArg]);
3918 }
3919 return;
3920 }
3921 } // this is not a template
3922
3923 if (!HasDictionary()) {
3924 result.Add(this);
3925 }
3926
3927 visited.Add(this);
3928 //Check whether a custom streamer
3930 if (GetCollectionProxy()) {
3931 // We need to look at the collection's content
3932 // The collection has different kind of elements the check would be required.
3933 TClass* t = 0;
3934 if ((t = GetCollectionProxy()->GetValueClass())) {
3935 if (!t->HasDictionary()) {
3936 t->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3937 }
3938 }
3939 } else {
3940 if (recurse) {
3941 GetMissingDictionariesForMembers(result, visited, recurse);
3942 }
3943 GetMissingDictionariesForBaseClasses(result, visited, recurse);
3944 }
3945 }
3946}
3947
3948////////////////////////////////////////////////////////////////////////////////
3949/// Get the classes that have a missing dictionary starting from this one.
3950/// - With recurse = false the classes checked for missing dictionaries are:
3951/// the class itself, all base classes, direct data members,
3952/// and for collection proxies the container's
3953/// elements without iterating over the element's data members;
3954/// - With recurse = true the classes checked for missing dictionaries are:
3955/// the class itself, all base classes, recursing on the data members,
3956/// and for the collection proxies recursion on the elements of the
3957/// collection and iterating over the element's data members.
3958
3960{
3961 // Top level recursion it different from the following levels of recursion.
3962
3963 if (result.FindObject(this)) return;
3964
3965 static TClassRef sCIString("string");
3966 if (this == sCIString) return;
3967
3968 THashTable visited;
3969
3970 if (strncmp(fName, "pair<", 5) == 0) {
3971 GetMissingDictionariesForPairElements(result, visited, recurse);
3972 return;
3973 }
3974
3975 if (!HasDictionary()) {
3976 result.Add(this);
3977 }
3978
3979 visited.Add(this);
3980
3981 //Check whether a custom streamer
3983 if (GetCollectionProxy()) {
3984 // We need to look at the collection's content
3985 // The collection has different kind of elements the check would be required.
3986 TClass* t = 0;
3987 if ((t = GetCollectionProxy()->GetValueClass())) {
3988 if (!t->HasDictionary()) {
3989 t->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3990 }
3991 }
3992 } else {
3993 GetMissingDictionariesForMembers(result, visited, recurse);
3994 GetMissingDictionariesForBaseClasses(result, visited, recurse);
3995 }
3996 }
3997}
3998
3999////////////////////////////////////////////////////////////////////////////////
4000/// Return kTRUE if the class has elements.
4001
4002Bool_t TClass::IsFolder(void *obj) const
4003{
4004 return Browse(obj,(TBrowser*)0);
4005}
4006
4007//______________________________________________________________________________
4008//______________________________________________________________________________
4009void TClass::ReplaceWith(TClass *newcl) const
4010{
4011 // Inform the other objects to replace this object by the new TClass (newcl)
4012
4014 //we must update the class pointers pointing to 'this' in all TStreamerElements
4015 TIter nextClass(gROOT->GetListOfClasses());
4016 TClass *acl;
4018 TList tobedeleted;
4019
4020 // Since we are in the process of replacing a TClass by a TClass
4021 // coming from a dictionary, there is no point in loading any
4022 // libraries during this search.
4024 while ((acl = (TClass*)nextClass())) {
4025 if (acl == newcl) continue;
4026
4027 TIter nextInfo(acl->GetStreamerInfos());
4028 while ((info = (TVirtualStreamerInfo*)nextInfo())) {
4029
4030 info->Update(this, newcl);
4031 }
4032 }
4033
4034 TIter delIter( &tobedeleted );
4035 while ((acl = (TClass*)delIter())) {
4036 delete acl;
4037 }
4038 gInterpreter->UnRegisterTClassUpdate(this);
4039}
4040
4041////////////////////////////////////////////////////////////////////////////////
4042/// Make sure that the current ClassInfo is up to date.
4043
4045{
4046 Warning("ResetClassInfo(Long_t tagnum)","Call to deprecated interface (does nothing)");
4047}
4048
4049////////////////////////////////////////////////////////////////////////////////
4050/// Make sure that the current ClassInfo is up to date.
4051
4053{
4055
4057
4058 if (fClassInfo) {
4060 gInterpreter->ClassInfo_Delete(fClassInfo);
4061 fClassInfo = 0;
4062 }
4063 // We can not check at this point whether after the unload there will
4064 // still be interpreter information about this class (as v5 was doing),
4065 // instead this function must only be called if the definition is (about)
4066 // to be unloaded.
4067
4068 ResetCaches();
4069
4070 // We got here because the definition Decl is about to be unloaded.
4072 if (fStreamerInfo->GetEntries() != 0) {
4074 } else {
4076 }
4077 } else {
4078 // if the ClassInfo was loaded for a class with a TClass Init and it
4079 // gets unloaded, should we guess it can be reloaded?
4081 }
4082}
4083
4084////////////////////////////////////////////////////////////////////////////////
4085/// To clean out all caches.
4086
4088{
4089 R__ASSERT(!TestBit(kLoading) && "Resetting the caches does not make sense during loading!" );
4090
4091 // Not owning lists, don't call Delete(), but unload
4092 if (fData)
4093 fData->Unload();
4094 if (fEnums.load())
4095 (*fEnums).Unload();
4096 if (fMethod.load())
4097 (*fMethod).Unload();
4098
4099 delete fAllPubData; fAllPubData = 0;
4100
4101 if (fBase.load())
4102 (*fBase).Delete();
4103 delete fBase.load(); fBase = 0;
4104
4105 if (fRealData)
4106 fRealData->Delete();
4107 delete fRealData; fRealData=0;
4108}
4109
4110////////////////////////////////////////////////////////////////////////////////
4111/// Resets the menu list to it's standard value.
4112
4114{
4115 if (fClassMenuList)
4117 else
4118 fClassMenuList = new TList();
4120}
4121
4122////////////////////////////////////////////////////////////////////////////////
4123/// The ls function lists the contents of a class on stdout. Ls output
4124/// is typically much less verbose then Dump().
4125/// If options contains 'streamerinfo', run ls on the list of streamerInfos
4126/// and the list of conversion streamerInfos.
4127
4128void TClass::ls(Option_t *options) const
4129{
4130 TNamed::ls(options);
4131 if (options==0 || options[0]==0) return;
4132
4133 if (strstr(options,"streamerinfo")!=0) {
4134 GetStreamerInfos()->ls(options);
4135
4136 if (fConversionStreamerInfo.load()) {
4137 std::map<std::string, TObjArray*>::iterator it;
4138 std::map<std::string, TObjArray*>::iterator end = (*fConversionStreamerInfo).end();
4139 for( it = (*fConversionStreamerInfo).begin(); it != end; ++it ) {
4140 it->second->ls(options);
4141 }
4142 }
4143 }
4144}
4145
4146////////////////////////////////////////////////////////////////////////////////
4147/// Makes a customizable version of the popup menu list, i.e. makes a list
4148/// of TClassMenuItem objects of methods accessible by context menu.
4149/// The standard (and different) way consists in having just one element
4150/// in this list, corresponding to the whole standard list.
4151/// Once the customizable version is done, one can remove or add elements.
4152
4154{
4156 TClassMenuItem *menuItem;
4157
4158 // Make sure fClassMenuList is initialized and empty.
4159 GetMenuList()->Delete();
4160
4161 TList* methodList = new TList;
4162 GetMenuItems(methodList);
4163
4164 TMethod *method;
4165 TMethodArg *methodArg;
4166 TClass *classPtr = 0;
4167 TIter next(methodList);
4168
4169 while ((method = (TMethod*) next())) {
4170 // if go to a mother class method, add separator
4171 if (classPtr != method->GetClass()) {
4172 menuItem = new TClassMenuItem(TClassMenuItem::kPopupSeparator, this);
4173 fClassMenuList->AddLast(menuItem);
4174 classPtr = method->GetClass();
4175 }
4176 // Build the signature of the method
4177 TString sig;
4178 TList* margsList = method->GetListOfMethodArgs();
4179 TIter nextarg(margsList);
4180 while ((methodArg = (TMethodArg*)nextarg())) {
4181 sig = sig+","+methodArg->GetFullTypeName();
4182 }
4183 if (sig.Length()!=0) sig.Remove(0,1); // remove first comma
4185 method->GetName(), method->GetName(),0,
4186 sig.Data(),-1,TClassMenuItem::kIsSelf);
4187 if (method->IsMenuItem() == kMenuToggle) menuItem->SetToggle();
4188 fClassMenuList->Add(menuItem);
4189 }
4190 delete methodList;
4191}
4192
4193////////////////////////////////////////////////////////////////////////////////
4194/// Register the fact that an object was moved from the memory location
4195/// 'arenaFrom' to the memory location 'arenaTo'.
4196
4197void TClass::Move(void *arenaFrom, void *arenaTo) const
4198{
4199 // If/when we have access to a copy constructor (or better to a move
4200 // constructor), this function should also perform the data move.
4201 // For now we just information the repository.
4202
4203 if ((GetState() <= kEmulated) && !fCollectionProxy) {
4204 MoveAddressInRepository("TClass::Move",arenaFrom,arenaTo,this);
4205 }
4206}
4207
4208////////////////////////////////////////////////////////////////////////////////
4209/// Return the list of menu items associated with the class.
4210
4212 if (!fClassMenuList) {
4213 fClassMenuList = new TList();
4215 }
4216 return fClassMenuList;
4217}
4218
4219////////////////////////////////////////////////////////////////////////////////
4220/// Return (create an empty one if needed) the list of functions.
4221/// The major difference with GetListOfMethod is that this returns
4222/// the internal type of fMethod and thus can not be made public.
4223/// It also never 'loads' the content of the list.
4224
4226{
4227 if (!fMethod.load()) {
4228 std::unique_ptr<TListOfFunctions> temp{ new TListOfFunctions(this) };
4229 TListOfFunctions* expected = nullptr;
4230 if(fMethod.compare_exchange_strong(expected, temp.get()) ) {
4231 temp.release();
4232 }
4233 }
4234 return fMethod;
4235}
4236
4237
4238////////////////////////////////////////////////////////////////////////////////
4239/// Return pointer to method without looking at parameters.
4240/// Does not look in (possible) base classes.
4241/// Has the side effect of loading all the TMethod object in the list
4242/// of the class.
4243
4244TMethod *TClass::GetMethodAny(const char *method)
4245{
4246 if (!HasInterpreterInfo()) return 0;
4247 return (TMethod*) GetMethodList()->FindObject(method);
4248}
4249
4250////////////////////////////////////////////////////////////////////////////////
4251/// Return pointer to method without looking at parameters.
4252/// Does look in all base classes.
4253
4255{
4256 if (!HasInterpreterInfo()) return 0;
4257
4258 TMethod* m = GetMethodAny(method);
4259 if (m) return m;
4260
4261 TBaseClass *base;
4262 TIter nextb(GetListOfBases());
4263 while ((base = (TBaseClass *) nextb())) {
4264 TClass *c = base->GetClassPointer();
4265 if (c) {
4266 m = c->GetMethodAllAny(method);
4267 if (m) return m;
4268 }
4269 }
4270
4271 return 0;
4272}
4273
4274////////////////////////////////////////////////////////////////////////////////
4275/// Find the best method (if there is one) matching the parameters.
4276/// The params string must contain argument values, like "3189, \"aap\", 1.3".
4277/// The function invokes GetClassMethod to search for a possible method
4278/// in the class itself or in its base classes. Returns 0 in case method
4279/// is not found.
4280
4281TMethod *TClass::GetMethod(const char *method, const char *params,
4282 Bool_t objectIsConst /* = kFALSE */)
4283{
4285 if (!fClassInfo) return 0;
4286
4287 if (!gInterpreter)
4288 Fatal("GetMethod", "gInterpreter not initialized");
4289
4290 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithValues(fClassInfo,
4291 method, params,
4292 objectIsConst);
4293
4294 if (!decl) return 0;
4295
4296 // search recursively in this class or its base classes
4298 if (f) return f;
4299
4300 Error("GetMethod",
4301 "\nDid not find matching TMethod <%s> with \"%s\" %sfor %s",
4302 method,params,objectIsConst ? "const " : "", GetName());
4303 return 0;
4304}
4305
4306
4307////////////////////////////////////////////////////////////////////////////////
4308/// Find a method with decl id in this class or its bases.
4309
4311 if (TFunction* method = GetMethodList()->Get(declId))
4312 return static_cast<TMethod *>(method);
4313
4314 for (auto item : *GetListOfBases())
4315 if (auto base = static_cast<TBaseClass *>(item)->GetClassPointer())
4316 if (TFunction* method = base->FindClassOrBaseMethodWithId(declId))
4317 return static_cast<TMethod *>(method);
4318
4319 return nullptr;
4320}
4321
4322////////////////////////////////////////////////////////////////////////////////
4323/// Find the method with a given prototype. The proto string must be of the
4324/// form: "char*,int,double". Returns 0 in case method is not found.
4325
4326TMethod *TClass::GetMethodWithPrototype(const char *method, const char *proto,
4327 Bool_t objectIsConst /* = kFALSE */,
4328 ROOT::EFunctionMatchMode mode /* = ROOT::kConversionMatch */)
4329{
4331 if (!fClassInfo) return 0;
4332
4333 if (!gInterpreter)
4334 Fatal("GetMethodWithPrototype", "gInterpreter not initialized");
4335
4336 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithPrototype(fClassInfo,
4337 method, proto,
4338 objectIsConst, mode);
4339
4340 if (!decl) return 0;
4342 if (f) return f;
4343 Error("GetMethodWithPrototype",
4344 "\nDid not find matching TMethod <%s> with \"%s\" %sfor %s",
4345 method,proto,objectIsConst ? "const " : "", GetName());
4346 return 0;
4347}
4348
4349////////////////////////////////////////////////////////////////////////////////
4350/// Look for a method in this class that has the interface function
4351/// address faddr.
4352
4354{
4355 if (!HasInterpreterInfo()) return 0;
4356
4357 TMethod *m;
4358 TIter next(GetListOfMethods());
4359 while ((m = (TMethod *) next())) {
4360 if (faddr == (Long_t)m->InterfaceMethod())
4361 return m;
4362 }
4363 return 0;
4364}
4365
4366////////////////////////////////////////////////////////////////////////////////
4367/// Look for a method in this class that has the name and matches the parameters.
4368/// The params string must contain argument values, like "3189, \"aap\", 1.3".
4369/// Returns 0 in case method is not found.
4370/// See TClass::GetMethod to also search the base classes.
4371
4372TMethod *TClass::GetClassMethod(const char *name, const char* params,
4373 Bool_t objectIsConst /* = kFALSE */)
4374{
4376 if (!fClassInfo) return 0;
4377
4378 if (!gInterpreter)
4379 Fatal("GetClassMethod", "gInterpreter not initialized");
4380
4381 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithValues(fClassInfo,
4382 name, params,
4383 objectIsConst);
4384
4385 if (!decl) return 0;
4386
4387 TFunction *f = GetMethodList()->Get(decl);
4388
4389 return (TMethod*)f; // Could be zero if the decl is actually in a base class.
4390}
4391
4392////////////////////////////////////////////////////////////////////////////////
4393/// Find the method with a given prototype. The proto string must be of the
4394/// form: "char*,int,double". Returns 0 in case method is not found.
4395/// See TClass::GetMethodWithPrototype to also search the base classes.
4396
4398 Bool_t objectIsConst /* = kFALSE */,
4399 ROOT::EFunctionMatchMode mode /* = ROOT::kConversionMatch */)
4400{
4402 if (!fClassInfo) return 0;
4403
4404 if (!gInterpreter)
4405 Fatal("GetClassMethodWithPrototype", "gInterpreter not initialized");
4406
4407 TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithPrototype(fClassInfo,
4408 name, proto,
4409 objectIsConst,
4410 mode);
4411
4412 if (!decl) return 0;
4413
4414 TFunction *f = GetMethodList()->Get(decl);
4415
4416 return (TMethod*)f; // Could be zero if the decl is actually in a base class.
4417}
4418
4419////////////////////////////////////////////////////////////////////////////////
4420/// Return the number of data members of this class
4421/// Note that in case the list of data members is not yet created, it will be done
4422/// by GetListOfDataMembers().
4423
4425{
4426 if (!HasDataMemberInfo()) return 0;
4427
4429 if (lm)
4430 return lm->GetSize();
4431 else
4432 return 0;
4433}
4434
4435////////////////////////////////////////////////////////////////////////////////
4436/// Return the number of methods of this class
4437/// Note that in case the list of methods is not yet created, it will be done
4438/// by GetListOfMethods().
4439/// This will also load/populate the list of methods, to get 'just' the
4440/// number of currently loaded methods use:
4441/// cl->GetListOfMethods(false)->GetSize();
4442
4444{
4445 if (!HasInterpreterInfo()) return 0;
4446
4447 TList *lm = GetListOfMethods();
4448 if (lm)
4449 return lm->GetSize();
4450 else
4451 return 0;
4452}
4453
4454////////////////////////////////////////////////////////////////////////////////
4455/// returns a pointer to the TVirtualStreamerInfo object for version
4456/// If the object does not exist, it is created
4457///
4458/// Note: There are two special version numbers:
4459///
4460/// - 0: Use the class version from the currently loaded class library.
4461/// - -1: Assume no class library loaded (emulated class).
4462///
4463/// Warning: If we create a new streamer info, whether or not the build
4464/// optimizes is controlled externally to us by a global variable!
4465/// Don't call us unless you have set that variable properly
4466/// with TStreamer::Optimize()!
4467///
4468
4470{
4472
4473 // Version 0 is special, it means the currently loaded version.
4474 // We need to set it at the beginning to be able to guess it correctly.
4475
4476 if (version == 0)
4477 version = fClassVersion;
4478
4479 // If the StreamerInfo is assigned to the fLastReadInfo, we are
4480 // guaranteed it was built and compiled.
4481 if (sinfo && sinfo->GetClassVersion() == version)
4482 return sinfo;
4483
4484 // Note that the access to fClassVersion above is technically not thread-safe with a low probably of problems.
4485 // fClassVersion is not an atomic and is modified TClass::SetClassVersion (called from RootClassVersion via
4486 // ROOT::ResetClassVersion) and is 'somewhat' protected by the atomic fVersionUsed.
4487 // However, direct access to fClassVersion should be replaced by calls to GetClassVersion to set fVersionUsed.
4488 // Even with such a change the code here and in these functions need to be reviewed as a cursory look seem
4489 // to indicates they are not yet properly protection against mutli-thread access.
4490 //
4491 // However, the use of these functions is rare and mostly done at library loading time which should
4492 // in almost all cases preceeds the possibility of GetStreamerInfo being called from multiple thread
4493 // on that same TClass object.
4494 //
4495 // Summary: need careful review but risk of problem is extremely low.
4496
4498
4499 // Warning: version may be -1 for an emulated class, or -2 if the
4500 // user requested the emulated streamerInfo for an abstract
4501 // base class, even though we have a dictionary for it.
4502
4503 if ((version < -1) || (version >= fStreamerInfo->GetSize())) {
4504 Error("GetStreamerInfo", "class: %s, attempting to access a wrong version: %d", GetName(), version);
4505 // FIXME: Shouldn't we go to -1 here, or better just abort?
4506 version = fClassVersion;
4507 }
4508
4509 sinfo = (TVirtualStreamerInfo *)fStreamerInfo->At(version);
4510
4511 if (!sinfo && (version != fClassVersion)) {
4512 // When the requested version does not exist we return
4513 // the TVirtualStreamerInfo for the currently loaded class version.
4514 // FIXME: This arguably makes no sense, we should warn and return nothing instead.
4515 // Note: This is done for STL collections
4516 // Note: fClassVersion could be -1 here (for an emulated class).
4517 // This is also the code path take for unversioned classes.
4519 }
4520
4521 if (!sinfo) {
4522 // We just were not able to find a streamer info, we have to make a new one.
4523 TMmallocDescTemp setreset;
4524 sinfo = TVirtualStreamerInfo::Factory()->NewInfo(const_cast<TClass*>(this));
4526 if (gDebug > 0) {
4527 printf("Creating StreamerInfo for class: %s, version: %d\n", GetName(), fClassVersion);
4528 }
4530 // If we do not have a StreamerInfo for this version and we do not
4531 // have dictionary information nor a proxy, there is nothing to build!
4532 sinfo->Build();
4533 }
4534 } else {
4535 if (!sinfo->IsCompiled()) {
4536 // Streamer info has not been compiled, but exists.
4537 // Therefore it was read in from a file and we have to do schema evolution?
4538 // Or it didn't have a dictionary before, but does now?
4539 sinfo->BuildOld();
4540 }
4541 }
4542
4543 // Cache the current info if we now have it.
4544 if (version == fClassVersion)
4545 fCurrentInfo = sinfo;
4546
4547 // If the compilation succeeded, remember this StreamerInfo.
4548 if (sinfo->IsCompiled())
4549 fLastReadInfo = sinfo;
4550
4551 return sinfo;
4552}
4553
4554////////////////////////////////////////////////////////////////////////////////
4555/// For the case where the requestor class is emulated and this class is abstract,
4556/// returns a pointer to the TVirtualStreamerInfo object for version with an emulated
4557/// representation whether or not the class is loaded.
4558///
4559/// If the object does not exist, it is created
4560///
4561/// Note: There are two special version numbers:
4562///
4563/// - 0: Use the class version from the currently loaded class library.
4564/// - -1: Assume no class library loaded (emulated class).
4565///
4566/// Warning: If we create a new streamer info, whether or not the build
4567/// optimizes is controlled externally to us by a global variable!
4568/// Don't call us unless you have set that variable properly
4569/// with TStreamer::Optimize()!
4570///
4571
4573{
4574 TVirtualStreamerInfo *sinfo = nullptr;
4575
4576 TString newname(GetName());
4577 newname += "@@emulated";
4578
4580
4581 TClass *emulated = TClass::GetClass(newname);
4582
4583 if (emulated)
4584 sinfo = emulated->GetStreamerInfo(version);
4585
4586 if (!sinfo) {
4587 // The emulated version of the streamerInfo is explicitly requested and has
4588 // not been built yet.
4589
4590 sinfo = (TVirtualStreamerInfo*) fStreamerInfo->At(version);
4591
4592 if (!sinfo && (version != fClassVersion)) {
4593 // When the requested version does not exist we return
4594 // the TVirtualStreamerInfo for the currently loaded class version.
4595 // FIXME: This arguably makes no sense, we should warn and return nothing instead.
4597 }
4598
4599 if (!sinfo) {
4600 // Let's take the first available StreamerInfo as a start
4601 Int_t ninfos = fStreamerInfo->GetEntriesFast() - 1;
4602 for (Int_t i = -1; sinfo == 0 && i < ninfos; ++i)
4604 }
4605
4606 if (sinfo) {
4607 sinfo = dynamic_cast<TVirtualStreamerInfo *>(sinfo->Clone());
4608 if (sinfo) {
4609 sinfo->SetClass(0);
4610 sinfo->SetName(newname);
4611 sinfo->BuildCheck();
4612 sinfo->BuildOld();
4613 sinfo->GetClass()->AddRule(TString::Format("sourceClass=%s targetClass=%s",GetName(),newname.Data()));
4614 } else {
4615 Error("GetStreamerInfoAbstractEmulated", "could not create TVirtualStreamerInfo");
4616 }
4617 }
4618 }
4619 return sinfo;
4620}
4621
4622////////////////////////////////////////////////////////////////////////////////
4623/// For the case where the requestor class is emulated and this class is abstract,
4624/// returns a pointer to the TVirtualStreamerInfo object for version with an emulated
4625/// representation whether or not the class is loaded.
4626///
4627/// If the object does not exist, it is created
4628///
4629/// Warning: If we create a new streamer info, whether or not the build
4630/// optimizes is controlled externally to us by a global variable!
4631/// Don't call us unless you have set that variable properly
4632/// with TStreamer::Optimize()!
4633///
4634
4636{
4637 TVirtualStreamerInfo *sinfo = nullptr;
4638
4639 TString newname(GetName());
4640 newname += "@@emulated";
4641
4643
4644 TClass *emulated = TClass::GetClass(newname);
4645
4646 if (emulated)
4647 sinfo = emulated->FindStreamerInfo(checksum);
4648
4649 if (!sinfo) {
4650 // The emulated version of the streamerInfo is explicitly requested and has
4651 // not been built yet.
4652
4653 sinfo = (TVirtualStreamerInfo*) FindStreamerInfo(checksum);
4654
4655 if (!sinfo && (checksum != fCheckSum)) {
4656 // When the requested version does not exist we return
4657 // the TVirtualStreamerInfo for the currently loaded class version.
4658 // FIXME: This arguably makes no sense, we should warn and return nothing instead.
4660 }
4661
4662 if (!sinfo) {
4663 // Let's take the first available StreamerInfo as a start
4664 Int_t ninfos = fStreamerInfo->GetEntriesFast() - 1;
4665 for (Int_t i = -1; sinfo == 0 && i < ninfos; ++i)
4667 }
4668
4669 if (sinfo) {
4670 sinfo = dynamic_cast<TVirtualStreamerInfo*>( sinfo->Clone() );
4671 if (sinfo) {
4672 sinfo->SetClass(0);
4673 sinfo->SetName( newname );
4674 sinfo->BuildCheck();
4675 sinfo->BuildOld();
4676 sinfo->GetClass()->AddRule(TString::Format("sourceClass=%s targetClass=%s",GetName(),newname.Data()));
4677 } else {
4678 Error("GetStreamerInfoAbstractEmulated", "could not create TVirtualStreamerInfo");
4679 }
4680 }
4681 }
4682 return sinfo;
4683}
4684
4685////////////////////////////////////////////////////////////////////////////////
4686/// When the class kIgnoreTObjectStreamer bit is set, the automatically
4687/// generated Streamer will not call TObject::Streamer.
4688/// This option saves the TObject space overhead on the file.
4689/// However, the information (fBits, fUniqueID) of TObject is lost.
4690///
4691/// Note that to be effective for objects streamed object-wise this function
4692/// must be called for the class deriving directly from TObject, eg, assuming
4693/// that BigTrack derives from Track and Track derives from TObject, one must do:
4694/// ~~~ {.cpp}
4695/// Track::Class()->IgnoreTObjectStreamer();
4696/// ~~~
4697/// and not:
4698/// ~~~ {.cpp}
4699/// BigTrack::Class()->IgnoreTObjectStreamer();
4700/// ~~~
4701/// To be effective for object streamed member-wise or split in a TTree,
4702/// this function must be called for the most derived class (i.e. BigTrack).
4703
4705{
4706 // We need to tak the lock since we are test and then setting fBits
4707 // and TStreamerInfo::fBits (and the StreamerInfo state in general)
4708 // which can also be modified by another thread.
4710
4711 if ( doIgnore && TestBit(kIgnoreTObjectStreamer)) return;
4712 if (!doIgnore && !TestBit(kIgnoreTObjectStreamer)) return;
4714 if (sinfo) {
4715 if (sinfo->IsCompiled()) {
4716 // -- Warn the user that what they are doing cannot work.
4717 // Note: The reason is that TVirtualStreamerInfo::Build() examines
4718 // the kIgnoreTObjectStreamer bit and sets the TStreamerElement
4719 // type for the TObject base class streamer element it creates
4720 // to -1 as a flag. Later on the TStreamerInfo::Compile()
4721 // member function sees the flag and does not insert the base
4722 // class element into the compiled streamer info. None of this
4723 // machinery works correctly if we are called after the streamer
4724 // info has already been built and compiled.
4725 Error("IgnoreTObjectStreamer","Must be called before the creation of StreamerInfo");
4726 return;
4727 }
4728 }
4729 if (doIgnore) SetBit (kIgnoreTObjectStreamer);
4731}
4732
4733////////////////////////////////////////////////////////////////////////////////
4734/// Return kTRUE if this class inherits from a class with name "classname".
4735/// note that the function returns kTRUE in case classname is the class itself
4736
4737Bool_t TClass::InheritsFrom(const char *classname) const
4738{
4739 if (strcmp(GetName(), classname) == 0) return kTRUE;
4740
4741 return InheritsFrom(TClass::GetClass(classname,kTRUE,kTRUE));
4742}
4743
4744////////////////////////////////////////////////////////////////////////////////
4745/// Return kTRUE if this class inherits from class cl.
4746/// note that the function returns KTRUE in case cl is the class itself
4747
4749{
4750 if (!cl) return kFALSE;
4751 if (cl == this) return kTRUE;
4752
4753 if (!HasDataMemberInfo()) {
4754 TVirtualStreamerInfo *sinfo = ((TClass *)this)->GetCurrentStreamerInfo();
4755 if (sinfo==0) sinfo = GetStreamerInfo();
4756 TIter next(sinfo->GetElements());
4757 TStreamerElement *element;
4758 while ((element = (TStreamerElement*)next())) {
4759 if (element->IsA() == TStreamerBase::Class()) {
4760 TClass *clbase = element->GetClassPointer();
4761 if (!clbase) return kFALSE; //missing class
4762 if (clbase->InheritsFrom(cl)) return kTRUE;
4763 }
4764 }
4765 return kFALSE;
4766 }
4767 // cast const away (only for member fBase which can be set in GetListOfBases())
4768 if (((TClass *)this)->GetBaseClass(cl)) return kTRUE;
4769 return kFALSE;
4770}
4771
4772////////////////////////////////////////////////////////////////////////////////
4773/// Cast obj of this class type up to baseclass cl if up is true.
4774/// Cast obj of this class type down from baseclass cl if up is false.
4775/// If this class is not a baseclass of cl return 0, else the pointer
4776/// to the cl part of this (up) or to this (down).
4777
4778void *TClass::DynamicCast(const TClass *cl, void *obj, Bool_t up)
4779{
4780 if (cl == this) return obj;
4781
4782 if (!HasDataMemberInfo()) return 0;
4783
4784 Int_t off;
4785 if ((off = GetBaseClassOffset(cl, obj)) != -1) {
4786 if (up)
4787 return (void*)((Long_t)obj+off);
4788 else
4789 return (void*)((Long_t)obj-off);
4790 }
4791 return 0;
4792}
4793
4794////////////////////////////////////////////////////////////////////////////////
4795/// Cast obj of this class type up to baseclass cl if up is true.
4796/// Cast obj of this class type down from baseclass cl if up is false.
4797/// If this class is not a baseclass of cl return 0, else the pointer
4798/// to the cl part of this (up) or to this (down).
4799
4800const void *TClass::DynamicCast(const TClass *cl, const void *obj, Bool_t up)
4801{
4802 return DynamicCast(cl,const_cast<void*>(obj),up);
4803}
4804
4805////////////////////////////////////////////////////////////////////////////////
4806/// Return a pointer to a newly allocated object of this class.
4807/// The class must have a default constructor. For meaning of
4808/// defConstructor, see TClass::IsCallingNew().
4809///
4810/// If quiet is true, do no issue a message via Error on case
4811/// of problems, just return 0.
4812///
4813/// The constructor actually called here can be customized by
4814/// using the rootcint pragma:
4815/// ~~~ {.cpp}
4816/// #pragma link C++ ioctortype UserClass;
4817/// ~~~
4818/// For example, with this pragma and a class named MyClass,
4819/// this method will called the first of the following 3
4820/// constructors which exists and is public:
4821/// ~~~ {.cpp}
4822/// MyClass(UserClass*);
4823/// MyClass(TRootIOCtor*);
4824/// MyClass(); // Or a constructor with all its arguments defaulted.
4825/// ~~~
4826///
4827/// When more than one pragma ioctortype is used, the first seen as priority
4828/// For example with:
4829/// ~~~ {.cpp}
4830/// #pragma link C++ ioctortype UserClass1;
4831/// #pragma link C++ ioctortype UserClass2;
4832/// ~~~
4833/// We look in the following order:
4834/// ~~~ {.cpp}
4835/// MyClass(UserClass1*);
4836/// MyClass(UserClass2*);
4837/// MyClass(TRootIOCtor*);
4838/// MyClass(); // Or a constructor with all its arguments defaulted.
4839/// ~~~
4840
4841void *TClass::New(ENewType defConstructor, Bool_t quiet) const
4842{
4843 void* p = 0;
4844
4845 if (fNew) {
4846 // We have the new operator wrapper function,
4847 // so there is a dictionary and it was generated
4848 // by rootcint, so there should be a default
4849 // constructor we can call through the wrapper.
4850 TClass__GetCallingNew() = defConstructor;
4851 p = fNew(0);
4853 if (!p && !quiet) {
4854 //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
4855 Error("New", "cannot create object of class %s", GetName());
4856 }
4857 } else if (HasInterpreterInfo()) {
4858 // We have the dictionary but do not have the
4859 // constructor wrapper, so the dictionary was
4860 // not generated by rootcint. Let's try to
4861 // create the object by having the interpreter
4862 // call the new operator, hopefully the class
4863 // library is loaded and there will be a default
4864 // constructor we can call.
4865 // [This is very unlikely to work, but who knows!]
4866 TClass__GetCallingNew() = defConstructor;
4869 if (!p && !quiet) {
4870 //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
4871 Error("New", "cannot create object of class %s", GetName());
4872 }
4873 } else if (!HasInterpreterInfo() && fCollectionProxy) {
4874 // There is no dictionary at all, so this is an emulated
4875 // class; however we do have the services of a collection proxy,
4876 // so this is an emulated STL class.
4877 TClass__GetCallingNew() = defConstructor;
4878 p = fCollectionProxy->New();
4880 if (!p && !quiet) {
4881 //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
4882 Error("New", "cannot create object of class %s", GetName());
4883 }
4884 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
4885 // There is no dictionary at all and we do not have
4886 // the services of a collection proxy available, so
4887 // use the streamer info to approximate calling a
4888 // constructor (basically we just make sure that the
4889 // pointer data members are null, unless they are marked
4890 // as preallocated with the "->" comment, in which case
4891 // we default-construct an object to point at).
4892
4893 // Do not register any TObject's that we create
4894 // as a result of creating this object.
4895 // FIXME: Why do we do this?
4896 // FIXME: Partial Answer: Is this because we may never actually deregister them???
4897
4898 Bool_t statsave = GetObjectStat();
4899 if(statsave) {
4901 }
4903 if (!sinfo && !quiet) {
4904 Error("New", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
4905 return 0;
4906 }
4907
4908 TClass__GetCallingNew() = defConstructor;
4909 p = sinfo->New();
4911
4912 // FIXME: Mistake? See note above at the GetObjectStat() call.
4913 // Allow TObject's to be registered again.
4914 if(statsave) {
4915 SetObjectStat(statsave);
4916 }
4917
4918 // Register the object for special handling in the destructor.
4919 if (p) {
4920 RegisterAddressInRepository("New",p,this);
4921 } else {
4922 Error("New", "Failed to construct class '%s' using streamer info", GetName());
4923 }
4924 } else {
4925 Fatal("New", "This cannot happen!");
4926 }
4927
4928 return p;
4929}
4930
4931////////////////////////////////////////////////////////////////////////////////
4932/// Return a pointer to a newly allocated object of this class.
4933/// The class must have a default constructor. For meaning of
4934/// defConstructor, see TClass::IsCallingNew().
4935
4936void *TClass::New(void *arena, ENewType defConstructor) const
4937{
4938 void* p = 0;
4939
4940 if (fNew) {
4941 // We have the new operator wrapper function,
4942 // so there is a dictionary and it was generated
4943 // by rootcint, so there should be a default
4944 // constructor we can call through the wrapper.
4945 TClass__GetCallingNew() = defConstructor;
4946 p = fNew(arena);
4948 if (!p) {
4949 Error("New with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
4950 }
4951 } else if (HasInterpreterInfo()) {
4952 // We have the dictionary but do not have the
4953 // constructor wrapper, so the dictionary was
4954 // not generated by rootcint. Let's try to
4955 // create the object by having the interpreter
4956 // call the new operator, hopefully the class
4957 // library is loaded and there will be a default
4958 // constructor we can call.
4959 // [This is very unlikely to work, but who knows!]
4960 TClass__GetCallingNew() = defConstructor;
4961 p = gCling->ClassInfo_New(GetClassInfo(),arena);
4963 if (!p) {
4964 Error("New with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
4965 }
4966 } else if (!HasInterpreterInfo() && fCollectionProxy) {
4967 // There is no dictionary at all, so this is an emulated
4968 // class; however we do have the services of a collection proxy,
4969 // so this is an emulated STL class.
4970 TClass__GetCallingNew() = defConstructor;
4971 p = fCollectionProxy->New(arena);
4973 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
4974 // There is no dictionary at all and we do not have
4975 // the services of a collection proxy available, so
4976 // use the streamer info to approximate calling a
4977 // constructor (basically we just make sure that the
4978 // pointer data members are null, unless they are marked
4979 // as preallocated with the "->" comment, in which case
4980 // we default-construct an object to point at).
4981
4982 // ???BUG??? ???WHY???
4983 // Do not register any TObject's that we create
4984 // as a result of creating this object.
4985 Bool_t statsave = GetObjectStat();
4986 if(statsave) {
4988 }
4989
4991 if (!sinfo) {
4992 Error("New with placement", "Cannot construct class '%s' version %d at address %p, no streamer info available!", GetName(), fClassVersion, arena);
4993 return 0;
4994 }
4995
4996 TClass__GetCallingNew() = defConstructor;
4997 p = sinfo->New(arena);
4999
5000 // ???BUG???
5001 // Allow TObject's to be registered again.
5002 if(statsave) {
5003 SetObjectStat(statsave);
5004 }
5005
5006 // Register the object for special handling in the destructor.
5007 if (p) {
5008 RegisterAddressInRepository("TClass::New with placement",p,this);
5009 }
5010 } else {
5011 Error("New with placement", "This cannot happen!");
5012 }
5013
5014 return p;
5015}
5016
5017////////////////////////////////////////////////////////////////////////////////
5018/// Return a pointer to a newly allocated array of objects
5019/// of this class.
5020/// The class must have a default constructor. For meaning of
5021/// defConstructor, see TClass::IsCallingNew().
5022
5023void *TClass::NewArray(Long_t nElements, ENewType defConstructor) const
5024{
5025 void* p = 0;
5026
5027 if (fNewArray) {
5028 // We have the new operator wrapper function,
5029 // so there is a dictionary and it was generated
5030 // by rootcint, so there should be a default
5031 // constructor we can call through the wrapper.
5032 TClass__GetCallingNew() = defConstructor;
5033 p = fNewArray(nElements, 0);
5035 if (!p) {
5036 Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
5037 }
5038 } else if (HasInterpreterInfo()) {
5039 // We have the dictionary but do not have the
5040 // constructor wrapper, so the dictionary was
5041 // not generated by rootcint. Let's try to
5042 // create the object by having the interpreter
5043 // call the new operator, hopefully the class
5044 // library is loaded and there will be a default
5045 // constructor we can call.
5046 // [This is very unlikely to work, but who knows!]
5047 TClass__GetCallingNew() = defConstructor;
5048 p = gCling->ClassInfo_New(GetClassInfo(),nElements);
5050 if (!p) {
5051 Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
5052 }
5053 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5054 // There is no dictionary at all, so this is an emulated
5055 // class; however we do have the services of a collection proxy,
5056 // so this is an emulated STL class.
5057 TClass__GetCallingNew() = defConstructor;
5058 p = fCollectionProxy->NewArray(nElements);
5060 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5061 // There is no dictionary at all and we do not have
5062 // the services of a collection proxy available, so
5063 // use the streamer info to approximate calling a
5064 // constructor (basically we just make sure that the
5065 // pointer data members are null, unless they are marked
5066 // as preallocated with the "->" comment, in which case
5067 // we default-construct an object to point at).
5068
5069 // ???BUG??? ???WHY???
5070 // Do not register any TObject's that we create
5071 // as a result of creating this object.
5072 Bool_t statsave = GetObjectStat();
5073 if(statsave) {
5075 }
5076
5078 if (!sinfo) {
5079 Error("NewArray", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
5080 return 0;
5081 }
5082
5083 TClass__GetCallingNew() = defConstructor;
5084 p = sinfo->NewArray(nElements);
5086
5087 // ???BUG???
5088 // Allow TObject's to be registered again.
5089 if(statsave) {
5090 SetObjectStat(statsave);
5091 }
5092
5093 // Register the object for special handling in the destructor.
5094 if (p) {
5095 RegisterAddressInRepository("TClass::NewArray",p,this);
5096 }
5097 } else {
5098 Error("NewArray", "This cannot happen!");
5099 }
5100
5101 return p;
5102}
5103
5104////////////////////////////////////////////////////////////////////////////////
5105/// Return a pointer to a newly allocated object of this class.
5106/// The class must have a default constructor. For meaning of
5107/// defConstructor, see TClass::IsCallingNew().
5108
5109void *TClass::NewArray(Long_t nElements, void *arena, ENewType defConstructor) const
5110{
5111 void* p = 0;
5112
5113 if (fNewArray) {
5114 // We have the new operator wrapper function,
5115 // so there is a dictionary and it was generated
5116 // by rootcint, so there should be a default
5117 // constructor we can call through the wrapper.
5118 TClass__GetCallingNew() = defConstructor;
5119 p = fNewArray(nElements, arena);
5121 if (!p) {
5122 Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
5123 }
5124 } else if (HasInterpreterInfo()) {
5125 // We have the dictionary but do not have the constructor wrapper,
5126 // so the dictionary was not generated by rootcint (it was made either
5127 // by cint or by some external mechanism). Let's try to create the
5128 // object by having the interpreter call the new operator, either the
5129 // class library is loaded and there is a default constructor we can
5130 // call, or the class is interpreted and we will call the default
5131 // constructor that way, or no default constructor is available and
5132 // we fail.
5133 TClass__GetCallingNew() = defConstructor;
5134 p = gCling->ClassInfo_New(GetClassInfo(),nElements, arena);
5136 if (!p) {
5137 Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
5138 }
5139 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5140 // There is no dictionary at all, so this is an emulated
5141 // class; however we do have the services of a collection proxy,
5142 // so this is an emulated STL class.
5143 TClass__GetCallingNew() = defConstructor;
5144 p = fCollectionProxy->NewArray(nElements, arena);
5146 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5147 // There is no dictionary at all and we do not have
5148 // the services of a collection proxy available, so
5149 // use the streamer info to approximate calling a
5150 // constructor (basically we just make sure that the
5151 // pointer data members are null, unless they are marked
5152 // as preallocated with the "->" comment, in which case
5153 // we default-construct an object to point at).
5154
5155 // ???BUG??? ???WHY???
5156 // Do not register any TObject's that we create
5157 // as a result of creating this object.
5158 Bool_t statsave = GetObjectStat();
5159 if(statsave) {
5161 }
5162
5164 if (!sinfo) {
5165 Error("NewArray with placement", "Cannot construct class '%s' version %d at address %p, no streamer info available!", GetName(), fClassVersion, arena);
5166 return 0;
5167 }
5168
5169 TClass__GetCallingNew() = defConstructor;
5170 p = sinfo->NewArray(nElements, arena);
5172
5173 // ???BUG???
5174 // Allow TObject's to be registered again.
5175 if(statsave) {
5176 SetObjectStat(statsave);
5177 }
5178
5180 // We always register emulated objects, we need to always
5181 // use the streamer info to destroy them.
5182 }
5183
5184 // Register the object for special handling in the destructor.
5185 if (p) {
5186 RegisterAddressInRepository("TClass::NewArray with placement",p,this);
5187 }
5188 } else {
5189 Error("NewArray with placement", "This cannot happen!");
5190 }
5191
5192 return p;
5193}
5194
5195////////////////////////////////////////////////////////////////////////////////
5196/// Explicitly call destructor for object.
5197
5198void TClass::Destructor(void *obj, Bool_t dtorOnly)
5199{
5200 // Do nothing if passed a null pointer.
5201 if (obj == 0) return;
5202
5203 void* p = obj;
5204
5205 if (dtorOnly && fDestructor) {
5206 // We have the destructor wrapper, use it.
5207 fDestructor(p);
5208 } else if ((!dtorOnly) && fDelete) {
5209 // We have the delete wrapper, use it.
5210 fDelete(p);
5211 } else if (HasInterpreterInfo()) {
5212 // We have the dictionary but do not have the
5213 // destruct/delete wrapper, so the dictionary was
5214 // not generated by rootcint (it could have been
5215 // created by cint or by some external mechanism).
5216 // Let's have the interpreter call the destructor,
5217 // either the code will be in a loaded library,
5218 // or it will be interpreted, otherwise we fail
5219 // because there is no destructor code at all.
5220 if (dtorOnly) {
5222 } else {
5224 }
5225 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5226 // There is no dictionary at all, so this is an emulated
5227 // class; however we do have the services of a collection proxy,
5228 // so this is an emulated STL class.
5229 fCollectionProxy->Destructor(p, dtorOnly);
5230 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5231 // There is no dictionary at all and we do not have
5232 // the services of a collection proxy available, so
5233 // use the streamer info to approximate calling a
5234 // destructor.
5235
5236 Bool_t inRepo = kTRUE;
5237 Bool_t verFound = kFALSE;
5238
5239 // Was this object allocated through TClass?
5240 std::multiset<Version_t> knownVersions;
5242
5243 {
5244 RepoCont_t::iterator iter = gObjectVersionRepository.find(p);
5245 if (iter == gObjectVersionRepository.end()) {
5246 // No, it wasn't, skip special version handling.
5247 //Error("Destructor2", "Attempt to delete unregistered object of class '%s' at address %p!", GetName(), p);
5248 inRepo = kFALSE;
5249 } else {
5250 //objVer = iter->second;
5251 for (; (iter != gObjectVersionRepository.end()) && (iter->first == p); ++iter) {
5252 Version_t ver = iter->second.fVersion;
5253 knownVersions.insert(ver);
5254 if (ver == fClassVersion && this == iter->second.fClass) {
5255 verFound = kTRUE;
5256 }
5257 }
5258 }
5259 }
5260
5261 if (!inRepo || verFound) {
5262 // The object was allocated using code for the same class version
5263 // as is loaded now. We may proceed without worry.
5265 if (si) {
5266 si->Destructor(p, dtorOnly);
5267 } else {
5268 Error("Destructor", "No streamer info available for class '%s' version %d at address %p, cannot destruct emulated object!", GetName(), fClassVersion, p);
5269 Error("Destructor", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5271 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5272 Error("Destructor", "fStreamerInfo->At(%d): %p", i, fStreamerInfo->At(i));
5273 if (fStreamerInfo->At(i) != 0) {
5274 Error("Destructor", "Doing Dump() ...");
5276 }
5277 }
5278 }
5279 } else {
5280 // The loaded class version is not the same as the version of the code
5281 // which was used to allocate this object. The best we can do is use
5282 // the TVirtualStreamerInfo to try to free up some of the allocated memory.
5283 Error("Destructor", "Loaded class %s version %d is not registered for addr %p", GetName(), fClassVersion, p);
5284#if 0
5286 if (si) {
5287 si->Destructor(p, dtorOnly);
5288 } else {
5289 Error("Destructor2", "No streamer info available for class '%s' version %d, cannot destruct object at addr: %p", GetName(), objVer, p);
5290 Error("Destructor2", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5292 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5293 Error("Destructor2", "fStreamerInfo->At(%d): %p", i, fStreamerInfo->At(i));
5294 if (fStreamerInfo->At(i) != 0) {
5295 // Do some debugging output.
5296 Error("Destructor2", "Doing Dump() ...");
5298 }
5299 }
5300 }
5301#endif
5302 }
5303
5304 if (inRepo && verFound && p) {
5305 UnregisterAddressInRepository("TClass::Destructor",p,this);
5306 }
5307 } else {
5308 Error("Destructor", "This cannot happen! (class %s)", GetName());
5309 }
5310}
5311
5312////////////////////////////////////////////////////////////////////////////////
5313/// Explicitly call operator delete[] for an array.
5314
5315void TClass::DeleteArray(void *ary, Bool_t dtorOnly)
5316{
5317 // Do nothing if passed a null pointer.
5318 if (ary == 0) return;
5319
5320 // Make a copy of the address.
5321 void* p = ary;
5322
5323 if (fDeleteArray) {
5324 if (dtorOnly) {
5325 Error("DeleteArray", "Destructor only is not supported!");
5326 } else {
5327 // We have the array delete wrapper, use it.
5328 fDeleteArray(ary);
5329 }
5330 } else if (HasInterpreterInfo()) {
5331 // We have the dictionary but do not have the
5332 // array delete wrapper, so the dictionary was
5333 // not generated by rootcint. Let's try to
5334 // delete the array by having the interpreter
5335 // call the array delete operator, hopefully
5336 // the class library is loaded and there will be
5337 // a destructor we can call.
5338 gCling->ClassInfo_DeleteArray(GetClassInfo(),ary, dtorOnly);
5339 } else if (!HasInterpreterInfo() && fCollectionProxy) {
5340 // There is no dictionary at all, so this is an emulated
5341 // class; however we do have the services of a collection proxy,
5342 // so this is an emulated STL class.
5343 fCollectionProxy->DeleteArray(ary, dtorOnly);
5344 } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5345 // There is no dictionary at all and we do not have
5346 // the services of a collection proxy available, so
5347 // use the streamer info to approximate calling the
5348 // array destructor.
5349
5350 Bool_t inRepo = kTRUE;
5351 Bool_t verFound = kFALSE;
5352
5353 // Was this array object allocated through TClass?
5354 std::multiset<Version_t> knownVersions;
5355 {
5357 RepoCont_t::iterator iter = gObjectVersionRepository.find(p);
5358 if (iter == gObjectVersionRepository.end()) {
5359 // No, it wasn't, we cannot know what to do.
5360 //Error("DeleteArray", "Attempt to delete unregistered array object, element type '%s', at address %p!", GetName(), p);
5361 inRepo = kFALSE;
5362 } else {
5363 for (; (iter != gObjectVersionRepository.end()) && (iter->first == p); ++iter) {
5364 Version_t ver = iter->second.fVersion;
5365 knownVersions.insert(ver);
5366 if (ver == fClassVersion && this == iter->second.fClass ) {
5367 verFound = kTRUE;
5368 }
5369 }
5370 }
5371 }
5372
5373 if (!inRepo || verFound) {
5374 // The object was allocated using code for the same class version
5375 // as is loaded now. We may proceed without worry.
5377 if (si) {
5378 si->DeleteArray(ary, dtorOnly);
5379 } else {
5380 Error("DeleteArray", "No streamer info available for class '%s' version %d at address %p, cannot destruct object!", GetName(), fClassVersion, ary);
5381 Error("DeleteArray", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5383 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5384 Error("DeleteArray", "fStreamerInfo->At(%d): %p", v, fStreamerInfo->At(i));
5385 if (fStreamerInfo->At(i)) {
5386 Error("DeleteArray", "Doing Dump() ...");
5388 }
5389 }
5390 }
5391 } else {
5392 // The loaded class version is not the same as the version of the code
5393 // which was used to allocate this array. The best we can do is use
5394 // the TVirtualStreamerInfo to try to free up some of the allocated memory.
5395 Error("DeleteArray", "Loaded class version %d is not registered for addr %p", fClassVersion, p);
5396
5397
5398
5399#if 0
5401 if (si) {
5402 si->DeleteArray(ary, dtorOnly);
5403 } else {
5404 Error("DeleteArray", "No streamer info available for class '%s' version %d at address %p, cannot destruct object!", GetName(), objVer, ary);
5405 Error("DeleteArray", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5407 for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5408 Error("DeleteArray", "fStreamerInfo->At(%d): %p", v, fStreamerInfo->At(i));
5409 if (fStreamerInfo->At(i)) {
5410 // Print some debugging info.
5411 Error("DeleteArray", "Doing Dump() ...");
5413 }
5414 }
5415 }
5416#endif
5417
5418
5419 }
5420
5421 // Deregister the object for special handling in the destructor.
5422 if (inRepo && verFound && p) {
5423 UnregisterAddressInRepository("TClass::DeleteArray",p,this);
5424 }
5425 } else {
5426 Error("DeleteArray", "This cannot happen! (class '%s')", GetName());
5427 }
5428}
5429
5430////////////////////////////////////////////////////////////////////////////////
5431/// Set the splitability of this class:
5432/// - -1: Use the default calculation
5433/// - 0: Disallow splitting
5434/// - 1: Always allow splitting.
5435/// - 2: Disallow splitting of the class and splitting of any it's derived classes.
5436
5438{
5439 fCanSplit = splitmode;
5440}
5441
5442////////////////////////////////////////////////////////////////////////////////
5443/// Private function. Set the class version for the 'class' represented by
5444/// this TClass object. See the public interface:
5445/// ROOT::ResetClassVersion
5446/// defined in TClassTable.cxx
5447///
5448/// Note on class version numbers:
5449/// - If no class number has been specified, TClass::GetVersion will return -1
5450/// - The Class Version 0 request the whole object to be transient
5451/// - The Class Version 1, unless specified via ClassDef indicates that the
5452/// I/O should use the TClass checksum to distinguish the layout of the class
5453
5455{
5456 fClassVersion = version;
5457 fCurrentInfo = 0;
5458}
5459
5460////////////////////////////////////////////////////////////////////////////////
5461/// Determine and set pointer to current TVirtualStreamerInfo
5462
5464{
5465 if(!fCurrentInfo.load()) {
5468 }
5469 return fCurrentInfo;
5470}
5471
5472////////////////////////////////////////////////////////////////////////////////
5473/// Set pointer to current TVirtualStreamerInfo
5474
5476{
5477 fCurrentInfo = info;
5478}
5479
5480////////////////////////////////////////////////////////////////////////////////
5481/// Return size of object of this class.
5482
5484{
5485 if (fSizeof!=-1) return fSizeof;
5488 return GetStreamerInfo()->GetSize();
5489}
5490
5491////////////////////////////////////////////////////////////////////////////////
5492/// Load class description from I/O buffer and return class object.
5493
5495{
5496 UInt_t maxsize = 256;
5497 char *s = new char[maxsize];
5498
5499 Int_t pos = b.Length();
5500
5501 b.ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end.
5502 while (strlen(s) == (maxsize - 1)) {
5503 // The classname is too large, try again with a large buffer.
5504 b.SetBufferOffset(pos);
5505 maxsize = 2*maxsize;
5506 delete [] s;
5507 s = new char[maxsize];
5508 b.ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end.
5509 }
5510
5512 if (!cl)
5513 ::Error("TClass::Load", "dictionary of class %s not found", s);
5514
5515 delete [] s;
5516 return cl;
5517}
5518
5519////////////////////////////////////////////////////////////////////////////////
5520/// Helper function used by TClass::GetClass().
5521/// This function attempts to load the dictionary for 'classname'
5522/// either from the TClassTable or from the list of generator.
5523/// If silent is 'true', do not warn about missing dictionary for the class.
5524/// (typically used for class that are used only for transient members)
5525///
5526/// The 'requestedname' is expected to be already normalized.
5527
5528TClass *TClass::LoadClass(const char *requestedname, Bool_t silent)
5529{
5530 // This function does not (and should not) attempt to check in the
5531 // list of loaded classes or in the typedef.
5532
5534
5535 TClass *result = LoadClassDefault(requestedname, silent);
5536
5537 if (result) return result;
5538 else return LoadClassCustom(requestedname,silent);
5539}
5540
5541////////////////////////////////////////////////////////////////////////////////
5542/// Helper function used by TClass::GetClass().
5543/// This function attempts to load the dictionary for 'classname' from
5544/// the TClassTable or the autoloader.
5545/// If silent is 'true', do not warn about missing dictionary for the class.
5546/// (typically used for class that are used only for transient members)
5547///
5548/// The 'requestedname' is expected to be already normalized.
5549
5550TClass *TClass::LoadClassDefault(const char *requestedname, Bool_t /* silent */)
5551{
5552 // This function does not (and should not) attempt to check in the
5553 // list of loaded classes or in the typedef.
5554
5555 DictFuncPtr_t dict = TClassTable::GetDictNorm(requestedname);
5556
5557 if (!dict) {
5558 if (gInterpreter->AutoLoad(requestedname,kTRUE)) {
5559 dict = TClassTable::GetDictNorm(requestedname);
5560 }
5561 }
5562
5563 if (dict) {
5564 TClass *ncl = (dict)();
5565 if (ncl) ncl->PostLoadCheck();
5566 return ncl;
5567 }
5568 return 0;
5569}
5570
5571////////////////////////////////////////////////////////////////////////////////
5572/// Helper function used by TClass::GetClass().
5573/// This function attempts to load the dictionary for 'classname'
5574/// from the list of generator.
5575/// If silent is 'true', do not warn about missing dictionary for the class.
5576/// (typically used for class that are used only for transient members)
5577///
5578/// The 'requestedname' is expected to be already normalized.
5579
5580TClass *TClass::LoadClassCustom(const char *requestedname, Bool_t silent)
5581{
5582 // This function does not (and should not) attempt to check in the
5583 // list of loaded classes or in the typedef.
5584
5585 TIter next(gROOT->GetListOfClassGenerators());
5586 TClassGenerator *gen;
5587 while ((gen = (TClassGenerator*) next())) {
5588 TClass *cl = gen->GetClass(requestedname, kTRUE, silent);
5589 if (cl) {
5590 cl->PostLoadCheck();
5591 return cl;
5592 }
5593 }
5594 return 0;
5595}
5596
5597////////////////////////////////////////////////////////////////////////////////
5598/// Try to load the ClassInfo if available. This function may require parsing
5599/// the header file and/or loading data from the clang pcm. If further calls to
5600/// this function cannot affect the value of fClassInfo, fCanLoadClassInfo is set
5601/// to false.
5602
5604{
5606
5607 // Return if another thread already loaded the info
5608 // while we were waiting for the lock
5609 if (!fCanLoadClassInfo)
5610 return;
5611
5612 bool autoParse = !gInterpreter->IsAutoParsingSuspended();
5613
5614 if (autoParse)
5615 gInterpreter->AutoParse(GetName());
5616
5617 if (!fClassInfo)
5618 gInterpreter->SetClassInfo(const_cast<TClass *>(this));
5619
5620 if (autoParse && !fClassInfo) {
5621 if (fImplFileLine == -1 && fClassVersion == 0) {
5622 // We have a 'transient' class with a ClassDefInline and apparently no interpreter
5623 // information. Since it is transient, it is more than likely that the lack
5624 // will be harmles.
5625 } else {
5626 ::Error("TClass::LoadClassInfo", "no interpreter information for class %s is available"
5627 " even though it has a TClass initialization routine.",
5628 fName.Data());
5629 }
5630 return;
5631 }
5632
5633 fCanLoadClassInfo = false;
5634}
5635
5636////////////////////////////////////////////////////////////////////////////////
5637/// Store class description on I/O buffer.
5638
5640{
5641 b.WriteString(GetName());
5642}
5643
5644////////////////////////////////////////////////////////////////////////////////
5645/// Global function called by a class' static Dictionary() method
5646/// (see the ClassDef macro).
5647
5648TClass *ROOT::CreateClass(const char *cname, Version_t id,
5649 const std::type_info &info, TVirtualIsAProxy *isa,
5650 const char *dfil, const char *ifil,
5651 Int_t dl, Int_t il)
5652{
5653 // When called via TMapFile (e.g. Update()) make sure that the dictionary
5654 // gets allocated on the heap and not in the mapped file.
5655 TMmallocDescTemp setreset;
5656 return new TClass(cname, id, info, isa, dfil, ifil, dl, il);
5657}
5658
5659////////////////////////////////////////////////////////////////////////////////
5660/// Global function called by a class' static Dictionary() method
5661/// (see the ClassDef macro).
5662
5663TClass *ROOT::CreateClass(const char *cname, Version_t id,
5664 const char *dfil, const char *ifil,
5665 Int_t dl, Int_t il)
5666{
5667 // When called via TMapFile (e.g. Update()) make sure that the dictionary
5668 // gets allocated on the heap and not in the mapped file.
5669 TMmallocDescTemp setreset;
5670 return new TClass(cname, id, dfil, ifil, dl, il);
5671}
5672
5673////////////////////////////////////////////////////////////////////////////////
5674/// Static method returning the defConstructor flag passed to TClass::New().
5675/// New type is either:
5676/// - TClass::kRealNew - when called via plain new
5677/// - TClass::kClassNew - when called via TClass::New()
5678/// - TClass::kDummyNew - when called via TClass::New() but object is a dummy,
5679/// in which case the object ctor might take short cuts
5680
5682{
5683 return TClass__GetCallingNew();
5684}
5685
5686////////////////////////////////////////////////////////////////////////////////
5687/// Return true if the shared library of this class is currently in the a
5688/// process's memory. Return false, after the shared library has been
5689/// unloaded or if this is an 'emulated' class created from a file's StreamerInfo.
5690
5692{
5693 return fState == kHasTClassInit;
5694}
5695
5696////////////////////////////////////////////////////////////////////////////////
5697/// Returns true if this class inherits from TObject and if the start of
5698/// the TObject parts is at the very beginning of the objects.
5699/// Concretely this means that the following code is proper for this class:
5700/// ~~~ {.cpp}
5701/// ThisClass *ptr;
5702/// void *void_ptr = (void)ptr;
5703/// TObject *obj = (TObject*)void_ptr;
5704/// ~~~
5705/// This code would be wrong if 'ThisClass' did not inherit 'first' from
5706/// TObject.
5707
5709{
5710 if (fProperty==(-1)) Property();
5711 return TestBit(kStartWithTObject);
5712}
5713
5714////////////////////////////////////////////////////////////////////////////////
5715/// Return kTRUE is the class inherits from TObject.
5716
5718{
5719 if (fProperty==(-1)) Property();
5720 return TestBit(kIsTObject);
5721}
5722
5723////////////////////////////////////////////////////////////////////////////////
5724/// Return kTRUE is the class is Foreign (the class does not have a Streamer method).
5725
5727{
5728 if (fProperty==(-1)) Property();
5729 return TestBit(kIsForeign);
5730}
5731
5732////////////////////////////////////////////////////////////////////////////////
5733/// Do the initialization that can only be done after the CINT dictionary has
5734/// been fully populated and can not be delayed efficiently.
5735
5737{
5738 // In the case of a Foreign class (loaded class without a Streamer function)
5739 // we reset fClassVersion to be -1 so that the current TVirtualStreamerInfo will not
5740 // be confused with a previously loaded streamerInfo.
5741
5742 if (IsLoaded() && HasInterpreterInfo() && fClassVersion==1 /*&& fStreamerInfo
5743 && fStreamerInfo->At(1)*/ && IsForeign() )
5744 {
5745 SetClassVersion(-1);
5746 }
5747 // Note: We are careful to check the class version first because checking
5748 // for foreign can trigger an AutoParse.
5749 else if (IsLoaded() && HasDataMemberInfo() && fStreamerInfo && ((fClassVersion > 1) || !IsForeign()))
5750 {
5752
5754 // Here we need to check whether this TVirtualStreamerInfo (which presumably has been
5755 // loaded from a file) is consistent with the definition in the library we just loaded.
5756 // BuildCheck is not appropriate here since it check a streamerinfo against the
5757 // 'current streamerinfo' which, at time point, would be the same as 'info'!
5758 if (info && GetListOfDataMembers() && !GetCollectionProxy()
5759 && (info->GetCheckSum()!=GetCheckSum() && !info->CompareContent(this,0,kFALSE,kFALSE, 0) && !(MatchLegacyCheckSum(info->GetCheckSum()))))
5760 {
5761 Bool_t warn = ! TestBit(kWarned);
5762 if (warn && info->GetOldVersion()<=2) {
5763 // Names of STL base classes was modified in vers==3. Allocators removed
5764 //
5765 TIter nextBC(GetListOfBases());
5766 TBaseClass *bc;
5767 while ((bc=(TBaseClass*)nextBC()))
5768 {if (TClassEdit::IsSTLCont(bc->GetName())) warn = kFALSE;}
5769 }
5770
5771 if (warn) {
5772 if (info->GetOnFileClassVersion()==1 && fClassVersion>1) {
5773 Warning("PostLoadCheck","\n\
5774 The class %s transitioned from not having a specified class version\n\
5775 to having a specified class version (the current class version is %d).\n\
5776 However too many different non-versioned layouts of the class have\n\
5777 already been loaded so far. To work around this problem you can\n\
5778 load fewer 'old' file in the same ROOT session or load the C++ library\n\
5779 describing the class %s before opening the files or increase the version\n\
5780 number of the class for example ClassDef(%s,%d).\n\
5781 Do not try to write objects with the current class definition,\n\
5782 the files might not be readable.\n",
5784 } else {
5785 Warning("PostLoadCheck","\n\
5786 The StreamerInfo version %d for the class %s which was read\n\
5787 from a file previously opened has the same version as the active class\n\
5788 but a different checksum. You should update the version to ClassDef(%s,%d).\n\
5789 Do not try to write objects with the current class definition,\n\
5790 the files will not be readable.\n"
5792 }
5793 info->CompareContent(this,0,kTRUE,kTRUE,0);
5794 SetBit(kWarned);
5795 }
5796 }
5797 }
5798}
5799
5800////////////////////////////////////////////////////////////////////////////////
5801/// Set TObject::fBits and fStreamerType to cache information about the
5802/// class. The bits are
5803/// ~~~ {.cpp}
5804/// kIsTObject : the class inherits from TObject
5805/// kStartWithTObject: TObject is the left-most class in the inheritance tree
5806/// kIsForeign : the class doe not have a Streamer method
5807/// ~~~
5808/// The value of fStreamerType are
5809/// ~~~ {.cpp}
5810/// kTObject : the class inherits from TObject
5811/// kForeign : the class does not have a Streamer method
5812/// kInstrumented: the class does have a Streamer method
5813/// kExternal: the class has a free standing way of streaming itself
5814/// kEmulatedStreamer: the class is missing its shared library.
5815/// ~~~
5816
5818{
5819 // Check if we can return without taking the lock,
5820 // this is valid since fProperty is atomic and set as
5821 // the last operation before return.
5822 if (fProperty!=(-1)) return fProperty;
5823
5825
5826 // Check if another thread set fProperty while we
5827 // were waiting.
5828 if (fProperty!=(-1)) return fProperty;
5829
5830 // Avoid asking about the class when it is still building
5831 if (TestBit(kLoading)) return fProperty;
5832
5833 // When called via TMapFile (e.g. Update()) make sure that the dictionary
5834 // gets allocated on the heap and not in the mapped file.
5835 TMmallocDescTemp setreset;
5836
5837 TClass *kl = const_cast<TClass*>(this);
5838
5841
5843 kl->SetBit(kIsTObject);
5844
5845 // Is it DIRECT inheritance from TObject?
5847 if (delta==0) kl->SetBit(kStartWithTObject);
5848
5849 kl->fStreamerType = kTObject;
5851 }
5852
5853 if (HasInterpreterInfo()) {
5854
5855 // This code used to use ClassInfo_Has|IsValidMethod but since v6
5856 // they return true if the routine is defined in the class or any of
5857 // its parent. We explicitly want to know whether the function is
5858 // defined locally.
5859 if (!const_cast<TClass*>(this)->GetClassMethodWithPrototype("Streamer","TBuffer&",kFALSE)) {
5860
5861 kl->SetBit(kIsForeign);
5862 kl->fStreamerType = kForeign;
5864
5865 } else if ( kl->fStreamerType == TClass::kDefault ) {
5866 if (kl->fConvStreamerFunc) {
5869 } else if (kl->fStreamerFunc) {
5872 } else {
5873 // We have an automatic streamer using the StreamerInfo .. no need to go through the
5874 // Streamer method function itself.
5877 }
5878 }
5879
5880 if (fStreamer) {
5883 }
5884
5885 if (const_cast<TClass *>(this)->GetClassMethodWithPrototype("Hash", "", kTRUE)) {
5887 }
5888
5889 if (GetClassInfo()) {
5890 // In the case where the TClass for one of ROOT's core class
5891 // (eg TClonesArray for map<int,TClonesArray*>) is requested
5892 // during the execution of rootcling, we could end up in a situation
5893 // where we should have the information (since TClonesArray has
5894 // a dictionary as part of libCore) but do not because the user
5895 // only include a forward declaration of TClonesArray and we do not
5896 // forcefully load the header file either (because the autoparsing
5897 // is intentionally disabled).
5899 // Must set this last since other threads may read fProperty
5900 // and think all test bits have been properly set.
5902 }
5903 } else {
5904
5905 if (fStreamer) {
5908 }
5909
5911 kl->SetStreamerImpl();
5912 // fProperty was *not* set so that it can be forced to be recalculated
5913 // next time.
5914 return 0;
5915 }
5916
5917 return fProperty;
5918}
5919
5920////////////////////////////////////////////////////////////////////////////////
5921/// Internal routine to set calculate the class properties that can only be
5922/// known at run-time, for example whether the Hash member function and the
5923/// destructor are consistent.
5924
5926{
5927 // For now, no need to lock this routines as fRuntimeProperties is
5928 // the only atomic set here and this is done at the end
5929 // and there is no downside if the execution is done twice.
5930
5931 // Note SetRuntimeProperties is set to const as it is technically
5932 // thread-safe.
5933
5934 UChar_t properties = static_cast<UChar_t>(ERuntimeProperties::kSet);
5935
5937 properties |= static_cast<UChar_t>(ERuntimeProperties::kConsistentHash);
5938
5939 const_cast<TClass *>(this)->fRuntimeProperties = properties;
5940}
5941
5942////////////////////////////////////////////////////////////////////////////////
5943/// Internal routine to set fStreamerImpl based on the value of
5944/// fStreamerType.
5945
5947{
5948 switch (fStreamerType) {
5952 case kInstrumented: {
5956 break;
5957 }
5958
5959 case kEmulatedStreamer: // intentional fall through
5960 case kForeign|kEmulatedStreamer: // intentional fall through
5965 default:
5966 Error("SetStreamerImpl","Unexpected value of fStreamerType: %d",fStreamerType);
5967 }
5968}
5969
5970
5971////////////////////////////////////////////////////////////////////////////////
5972/// Create the collection proxy object (and the streamer object) from
5973/// using the information in the TCollectionProxyInfo.
5974
5976{
5978
5979 delete fCollectionProxy;
5980
5981 // We can not use GetStreamerInfo() instead of TVirtualStreamerInfo::Factory()
5982 // because GetStreamerInfo call TStreamerInfo::Build which need to have fCollectionProxy
5983 // set correctly.
5984
5986 fCollectionProxy = p;
5987
5988 AdoptStreamer(TVirtualStreamerInfo::Factory()->GenExplicitClassStreamer(info,this));
5989
5991 // Numeric Collections have implicit conversions:
5993 }
5994 fCanSplit = -1;
5995}
5996
5997////////////////////////////////////////////////////////////////////////////////
5998/// Change (i.e. set) the title of the TNamed.
5999
6000void TClass::SetContextMenuTitle(const char *title)
6001{
6002 fContextMenuTitle = title;
6003}
6004
6005////////////////////////////////////////////////////////////////////////////////
6006/// This function installs a global IsA function for this class.
6007/// The global IsA function will be used if there is no local IsA function (fIsA)
6008///
6009/// A global IsA function has the signature:
6010///
6011/// ~~~ {.cpp}
6012/// TClass *func( TClass *cl, const void *obj);
6013/// ~~~
6014///
6015/// 'cl' is a pointer to the TClass object that corresponds to the
6016/// 'pointer type' used to retrieve the value 'obj'
6017///
6018/// For example with:
6019/// ~~~ {.cpp}
6020/// TNamed * m = new TNamed("example","test");
6021/// TObject* o = m
6022/// ~~~
6023/// and
6024/// the global IsA function would be called with TObject::Class() as
6025/// the first parameter and the exact numerical value in the pointer
6026/// 'o'.
6027///
6028/// In other word, inside the global IsA function. it is safe to C-style
6029/// cast the value of 'obj' into a pointer to the class described by 'cl'.
6030
6032{
6033 fGlobalIsA = func;
6034}
6035
6036////////////////////////////////////////////////////////////////////////////////
6037/// Call this method to indicate that the shared library containing this
6038/// class's code has been removed (unloaded) from the process's memory
6039
6041{
6042 if (TestBit(kUnloaded) && !TestBit(kUnloading)) {
6043 // Don't redo the work.
6044 return;
6045 }
6047
6048 //R__ASSERT(fState == kLoaded);
6049 if (fState != kLoaded) {
6050 Fatal("SetUnloaded","The TClass for %s is being unloaded when in state %d\n",
6051 GetName(),(int)fState);
6052 }
6053
6055
6056 // Make sure SetClassInfo, re-calculated the state.
6058
6059 delete fIsA; fIsA = 0;
6060 // Disable the autoloader while calling SetClassInfo, to prevent
6061 // the library from being reloaded!
6062 {
6065 gInterpreter->SetClassInfo(this,kTRUE);
6066 }
6067 fDeclFileName = 0;
6068 fDeclFileLine = 0;
6069 fImplFileName = 0;
6070 fImplFileLine = 0;
6071 fTypeInfo = 0;
6072
6073 if (fMethod.load()) {
6074 (*fMethod).Unload();
6075 }
6076 if (fData) {
6077 fData->Unload();
6078 }
6079 if (fEnums.load()) {
6080 (*fEnums).Unload();
6081 }
6082
6083 if (fState <= kForwardDeclared && fStreamerInfo->GetEntries() != 0) {
6084 fState = kEmulated;
6085 }
6086
6089}
6090
6091////////////////////////////////////////////////////////////////////////////////
6092/// Info is a string describing the names and types of attributes
6093/// written by the class Streamer function.
6094/// If info is an empty string (when called by TObject::StreamerInfo)
6095/// the default Streamer info string is build. This corresponds to
6096/// the case of an automatically generated Streamer.
6097/// In case of user defined Streamer function, it is the user responsibility
6098/// to implement a StreamerInfo function (override TObject::StreamerInfo).
6099/// The user must call IsA()->SetStreamerInfo(info) from this function.
6100
6101TVirtualStreamerInfo *TClass::SetStreamerInfo(Int_t /*version*/, const char * /*info*/)
6102{
6103 // info is specified, nothing to do, except that we should verify
6104 // that it contains a valid descriptor.
6105
6106/*
6107 TDataMember *dm;
6108 Int_t nch = strlen(info);
6109 Bool_t update = kTRUE;
6110 if (nch != 0) {
6111 //decode strings like "TObject;TAttLine;fA;fB;Int_t i,j,k;"
6112 char *save, *temp, *blank, *colon, *comma;
6113 save = new char[10000];
6114 temp = save;
6115 strlcpy(temp,info,10000);
6116 //remove heading and trailing blanks
6117 while (*temp == ' ') temp++;
6118 while (save[nch-1] == ' ') {nch--; save[nch] = 0;}
6119 if (nch == 0) {delete [] save; return;}
6120 if (save[nch-1] != ';') {save[nch] = ';'; save[nch+1] = 0;}
6121 //remove blanks around , or ;
6122 while ((blank = strstr(temp,"; "))) strcpy(blank+1,blank+2);
6123 while ((blank = strstr(temp," ;"))) strcpy(blank, blank+1);
6124 while ((blank = strstr(temp,", "))) strcpy(blank+1,blank+2);
6125 while ((blank = strstr(temp," ,"))) strcpy(blank, blank+1);
6126 while ((blank = strstr(temp," "))) strcpy(blank, blank+1);
6127 //loop on tokens separated by ;
6128 char *final = new char[1000];
6129 char token[100];
6130 while ((colon=strchr(temp,';'))) {
6131 *colon = 0;
6132 strlcpy(token,temp,100);
6133 blank = strchr(token,' ');
6134 if (blank) {
6135 *blank = 0;
6136 if (!gROOT->GetType(token)) {
6137 Error("SetStreamerInfo","Illegal type: %s in %s",token,info);
6138 return;
6139 }
6140 while (blank) {
6141 strlcat(final,token,1000);
6142 strlcat(final," ",1000);
6143 comma = strchr(blank+1,','); if (comma) *comma=0;
6144 strlcat(final,blank+1,1000);
6145 strlcat(final,";",1000);
6146 blank = comma;
6147 }
6148
6149 } else {
6150 if (TClass::GetClass(token,update)) {
6151 //a class name
6152 strlcat(final,token,1000); strlcat(final,";",1000);
6153 } else {
6154 //a data member name
6155 dm = (TDataMember*)GetListOfDataMembers()->FindObject(token);
6156 if (dm) {
6157 strlcat(final,dm->GetFullTypeName(),1000);
6158 strlcat(final," ",1000);
6159 strlcat(final,token,1000); strlcat(final,";",1000);
6160 } else {
6161 Error("SetStreamerInfo","Illegal name: %s in %s",token,info);
6162 return;
6163 }
6164 }
6165 update = kFALSE;
6166 }
6167 temp = colon+1;
6168 if (*temp == 0) break;
6169 }
6170 //// fStreamerInfo = final;
6171 delete [] final;
6172 delete [] save;
6173 return;
6174 }
6175
6176 //info is empty. Let's build the default Streamer descriptor
6177
6178 char *temp = new char[10000];
6179 temp[0] = 0;
6180 char local[100];
6181
6182 //add list of base classes
6183 TIter nextb(GetListOfBases());
6184 TBaseClass *base;
6185 while ((base = (TBaseClass*) nextb())) {
6186 snprintf(local,100,"%s;",base->GetName());
6187 strlcat(temp,local,10000);
6188 }
6189
6190 //add list of data members and types
6191 TIter nextd(GetListOfDataMembers());
6192 while ((dm = (TDataMember *) nextd())) {
6193 if (dm->IsEnum()) continue;
6194 if (!dm->IsPersistent()) continue;
6195 Long_t property = dm->Property();
6196 if (property & kIsStatic) continue;
6197 TClass *acl = TClass::GetClass(dm->GetTypeName(),update);
6198 update = kFALSE;
6199 if (acl) {
6200 if (acl->GetClassVersion() == 0) continue;
6201 }
6202
6203 // dm->GetArrayIndex() returns an empty string if it does not
6204 // applies
6205 const char * index = dm->GetArrayIndex();
6206 if (strlen(index)==0)
6207 snprintf(local,100,"%s %s;",dm->GetFullTypeName(),dm->GetName());
6208 else
6209 snprintf(local,100,"%s %s[%s];",dm->GetFullTypeName(),dm->GetName(),index);
6210 strlcat(temp,local,10000);
6211 }
6212 //fStreamerInfo = temp;
6213 delete [] temp;
6214*/
6215 return 0;
6216}
6217
6218////////////////////////////////////////////////////////////////////////////////
6219/// Return true if the checksum passed as argument is one of the checksum
6220/// value produced by the older checksum calculation algorithm.
6221
6223{
6224 for(UInt_t i = 1; i < kLatestCheckSum; ++i) {
6225 if ( checksum == GetCheckSum( (ECheckSum) i ) ) return kTRUE;
6226 }
6227 return kFALSE;
6228}
6229
6230////////////////////////////////////////////////////////////////////////////////
6231/// Call GetCheckSum with validity check.
6232
6234{
6235 bool isvalid;
6236 return GetCheckSum(code,isvalid);
6237}
6238
6239////////////////////////////////////////////////////////////////////////////////
6240/// Return GetCheckSum(kCurrentCheckSum,isvalid);
6241
6243{
6244 return GetCheckSum(kCurrentCheckSum,isvalid);
6245}
6246
6247////////////////////////////////////////////////////////////////////////////////
6248/// Compute and/or return the class check sum.
6249///
6250/// isvalid is set to false, if the function is unable to calculate the
6251/// checksum.
6252///
6253/// The class ckecksum is used by the automatic schema evolution algorithm
6254/// to uniquely identify a class version.
6255/// The check sum is built from the names/types of base classes and
6256/// data members.
6257/// Original algorithm from Victor Perevovchikov (perev@bnl.gov).
6258///
6259/// The valid range of code is determined by ECheckSum.
6260///
6261/// - kNoEnum: data members of type enum are not counted in the checksum
6262/// - kNoRange: return the checksum of data members and base classes, not including the ranges and array size found in comments.
6263/// - kWithTypeDef: use the sugared type name in the calculation.
6264///
6265/// This is needed for backward compatibility.
6266///
6267/// WARNING: this function must be kept in sync with TStreamerInfo::GetCheckSum.
6268/// They are both used to handle backward compatibility and should both return the same values.
6269/// TStreamerInfo uses the information in TStreamerElement while TClass uses the information
6270/// from TClass::GetListOfBases and TClass::GetListOfDataMembers.
6271
6273{
6274 // fCheckSum is an atomic variable. Also once it has
6275 // transition from a zero Value it never changes. If two
6276 // thread reach past this if statement and calculated the
6277 // 'kLastestCheckSum', they will by definition obtain the
6278 // same value, so technically we could simply have:
6279 // if (fCheckSum && code == kCurrentCheckSum) return fCheckSum;
6280 // However save a little bit of barrier time by calling load()
6281 // only once.
6282
6283 isvalid = kTRUE;
6284
6285 UInt_t currentChecksum = fCheckSum.load();
6286 if (currentChecksum && code == kCurrentCheckSum) return currentChecksum;
6287
6289
6290 // kCurrentCheckSum (0) is the default parameter value and should be kept
6291 // for backward compatibility, too be able to use the inequality checks,
6292 // we need to set the code to the largest value.
6293 if (code == kCurrentCheckSum) code = kLatestCheckSum;
6294
6295 UInt_t id = 0;
6296
6297 int il;
6298 TString name = GetName();
6299 TString type;
6300 il = name.Length();
6301 for (int i=0; i<il; i++) id = id*3+name[i];
6302
6303 // Here we skip he base classes in case this is a pair or STL collection,
6304 // otherwise, on some STL implementations, it can happen that pair has
6305 // base classes which are an internal implementation detail.
6306 TList *tlb = ((TClass*)this)->GetListOfBases();
6307 if (tlb && !GetCollectionProxy() && strncmp(GetName(), "pair<", 5)) {
6308 // Loop over bases if not a proxied collection or a pair
6309
6310 TIter nextBase(tlb);
6311
6312 TBaseClass *tbc=0;
6313 while((tbc=(TBaseClass*)nextBase())) {
6314 name = tbc->GetName();
6316 if (isSTL)
6318 il = name.Length();
6319 for (int i=0; i<il; i++) id = id*3+name[i];
6320 if (code > kNoBaseCheckSum && !isSTL) {
6321 if (tbc->GetClassPointer() == 0) {
6322 Error("GetCheckSum","Calculating the checksum for (%s) requires the base class (%s) meta information to be available!",
6323 GetName(),tbc->GetName());
6324 isvalid = kFALSE;
6325 return 0;
6326 } else
6327 id = id*3 + tbc->GetClassPointer()->GetCheckSum();
6328 }
6329 }/*EndBaseLoop*/
6330 }
6331 TList *tlm = ((TClass*)this)->GetListOfDataMembers();
6332 if (tlm) { // Loop over members
6333 TIter nextMemb(tlm);
6334 TDataMember *tdm=0;
6335 Long_t prop = 0;
6336 while((tdm=(TDataMember*)nextMemb())) {
6337 if (!tdm->IsPersistent()) continue;
6338 // combine properties
6339 prop = (tdm->Property());
6340 TDataType* tdt = tdm->GetDataType();
6341 if (tdt) prop |= tdt->Property();
6342
6343 if ( prop&kIsStatic) continue;
6344 name = tdm->GetName(); il = name.Length();
6345 if ( (code > kNoEnum) && code != kReflex && code != kReflexNoComment && prop&kIsEnum)
6346 id = id*3 + 1;
6347
6348 int i;
6349 for (i=0; i<il; i++) id = id*3+name[i];
6350
6351 if (code > kWithTypeDef || code == kReflexNoComment) {
6352 type = tdm->GetTrueTypeName();
6353 // GetTrueTypeName uses GetFullyQualifiedName which already drops
6354 // the default template parameter, so we no longer need to do this.
6355 //if (TClassEdit::IsSTLCont(type))
6356 // type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
6357 if (code == kReflex || code == kReflexNoComment) {
6358 if (prop&kIsEnum) {
6359 type = "int";
6360 } else {
6361 type.ReplaceAll("ULong64_t","unsigned long long");
6362 type.ReplaceAll("Long64_t","long long");
6363 type.ReplaceAll("<signed char","<char");
6364 type.ReplaceAll(",signed char",",char");
6365 if (type=="signed char") type = "char";
6366 }
6367 }
6368 } else {
6369 type = tdm->GetFullTypeName();
6370 // GetFullTypeName uses GetFullyQualifiedName which already drops
6371 // the default template parameter, so we no longer need to do this.
6372 //if (TClassEdit::IsSTLCont(type))
6373 // type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
6374 }
6375
6376 il = type.Length();
6377 for (i=0; i<il; i++) id = id*3+type[i];
6378
6379 int dim = tdm->GetArrayDim();
6380 if (prop&kIsArray) {
6381 for (int ii=0;ii<dim;ii++) id = id*3+tdm->GetMaxIndex(ii);
6382 }
6383 if (code > kNoRange) {
6384 const char *left;
6385 if (code > TClass::kNoRangeCheck)
6387 else
6388 left = strstr(tdm->GetTitle(),"[");
6389 if (left) {
6390 const char *right = strstr(left,"]");
6391 if (right) {
6392 ++left;
6393 while (left != right) {
6394 id = id*3 + *left;
6395 ++left;
6396 }
6397 }
6398 }
6399 }
6400 }/*EndMembLoop*/
6401 }
6402 // This should be moved to Initialization time however the last time
6403 // we tried this cause problem, in particular in the end-of-process operation.
6404 if (code==kLatestCheckSum) fCheckSum = id;
6405 return id;
6406}
6407
6408////////////////////////////////////////////////////////////////////////////////
6409/// Adopt the Reference proxy pointer to indicate that this class
6410/// represents a reference.
6411/// When a new proxy is adopted, the old one is deleted.
6412
6414{
6416
6417 if ( fRefProxy ) {
6418 fRefProxy->Release();
6419 }
6420 fRefProxy = proxy;
6421 if ( fRefProxy ) {
6422 fRefProxy->SetClass(this);
6423 }
6424 fCanSplit = -1;
6425}
6426
6427////////////////////////////////////////////////////////////////////////////////
6428/// Adopt the TMemberStreamer pointer to by p and use it to Stream non basic
6429/// member name.
6430
6432{
6433 if (!fRealData) return;
6434
6436
6437 TIter next(fRealData);
6438 TRealData *rd;
6439 while ((rd = (TRealData*)next())) {
6440 if (strcmp(rd->GetName(),name) == 0) {
6441 // If there is a TStreamerElement that took a pointer to the
6442 // streamer we should inform it!
6443 rd->AdoptStreamer(p);
6444 break;
6445 }
6446 }
6447
6448// NOTE: This alternative was proposed but not is not used for now,
6449// One of the major difference with the code above is that the code below
6450// did not require the RealData to have been built
6451// if (!fData) return;
6452// const char *n = name;
6453// while (*n=='*') n++;
6454// TString ts(n);
6455// int i = ts.Index("[");
6456// if (i>=0) ts.Remove(i,999);
6457// TDataMember *dm = (TDataMember*)fData->FindObject(ts.Data());
6458// if (!dm) {
6459// Warning("SetStreamer","Can not find member %s::%s",GetName(),name);
6460// return;
6461// }
6462// dm->SetStreamer(p);
6463 return;
6464}
6465
6466////////////////////////////////////////////////////////////////////////////////
6467/// Install a new member streamer (p will be copied).
6468
6470{
6472}
6473
6474////////////////////////////////////////////////////////////////////////////////
6475/// Function called by the Streamer functions to deserialize information
6476/// from buffer b into object at p.
6477/// This function assumes that the class version and the byte count information
6478/// have been read.
6479/// - version is the version number of the class
6480/// - start is the starting position in the buffer b
6481/// - count is the number of bytes for this object in the buffer
6482
6483Int_t TClass::ReadBuffer(TBuffer &b, void *pointer, Int_t version, UInt_t start, UInt_t count)
6484{
6485 return b.ReadClassBuffer(this,pointer,version,start,count);
6486}
6487
6488////////////////////////////////////////////////////////////////////////////////
6489/// Function called by the Streamer functions to deserialize information
6490/// from buffer b into object at p.
6491
6493{
6494 return b.ReadClassBuffer(this,pointer);
6495}
6496
6497////////////////////////////////////////////////////////////////////////////////
6498/// Function called by the Streamer functions to serialize object at p
6499/// to buffer b. The optional argument info may be specified to give an
6500/// alternative StreamerInfo instead of using the default StreamerInfo
6501/// automatically built from the class definition.
6502/// For more information, see class TVirtualStreamerInfo.
6503
6504Int_t TClass::WriteBuffer(TBuffer &b, void *pointer, const char * /*info*/)
6505{
6506 b.WriteClassBuffer(this,pointer);
6507 return 0;
6508}
6509
6510////////////////////////////////////////////////////////////////////////////////
6511///There is special streamer for the class
6512
6513void TClass::StreamerExternal(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6514{
6515 // case kExternal:
6516 // case kExternal|kEmulatedStreamer:
6517
6518 TClassStreamer *streamer = gThreadTsd ? pThis->GetStreamer() : pThis->fStreamer;
6519 streamer->Stream(b,object,onfile_class);
6520}
6521
6522////////////////////////////////////////////////////////////////////////////////
6523/// Case of TObjects
6524
6525void TClass::StreamerTObject(const TClass* pThis, void *object, TBuffer &b, const TClass * /* onfile_class */)
6526{
6527 // case kTObject:
6528
6529 if (!pThis->fIsOffsetStreamerSet) {
6530 pThis->CalculateStreamerOffset();
6531 }
6532 TObject *tobj = (TObject*)((Long_t)object + pThis->fOffsetStreamer);
6533 tobj->Streamer(b);
6534}
6535
6536////////////////////////////////////////////////////////////////////////////////
6537/// Case of TObjects when fIsOffsetStreamerSet is known to have been set.
6538
6539void TClass::StreamerTObjectInitialized(const TClass* pThis, void *object, TBuffer &b, const TClass * /* onfile_class */)
6540{
6541 TObject *tobj = (TObject*)((Long_t)object + pThis->fOffsetStreamer);
6542 tobj->Streamer(b);
6543}
6544
6545////////////////////////////////////////////////////////////////////////////////
6546/// Case of TObjects when we do not have the library defining the class.
6547
6548void TClass::StreamerTObjectEmulated(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6549{
6550 // case kTObject|kEmulatedStreamer :
6551 if (b.IsReading()) {
6552 b.ReadClassEmulated(pThis, object, onfile_class);
6553 } else {
6554 b.WriteClassBuffer(pThis, object);
6555 }
6556}
6557
6558////////////////////////////////////////////////////////////////////////////////
6559/// Case of instrumented class with a library
6560
6561void TClass::StreamerInstrumented(const TClass* pThis, void *object, TBuffer &b, const TClass * /* onfile_class */)
6562{
6563 // case kInstrumented:
6564 pThis->fStreamerFunc(b,object);
6565}
6566
6567////////////////////////////////////////////////////////////////////////////////
6568/// Case of instrumented class with a library
6569
6570void TClass::ConvStreamerInstrumented(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6571{
6572 // case kInstrumented:
6573 pThis->fConvStreamerFunc(b,object,onfile_class);
6574}
6575
6576////////////////////////////////////////////////////////////////////////////////
6577/// Case of where we should directly use the StreamerInfo.
6578/// - case kForeign:
6579/// - case kForeign|kEmulatedStreamer:
6580/// - case kInstrumented|kEmulatedStreamer:
6581/// - case kEmulatedStreamer:
6582
6583void TClass::StreamerStreamerInfo(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6584{
6585 if (b.IsReading()) {
6586 b.ReadClassBuffer(pThis, object, onfile_class);
6587 //ReadBuffer (b, object);
6588 } else {
6589 //WriteBuffer(b, object);
6590 b.WriteClassBuffer(pThis, object);
6591 }
6592}
6593
6594////////////////////////////////////////////////////////////////////////////////
6595/// Default streaming in cases where either we have no way to know what to do
6596/// or if Property() has not yet been called.
6597
6598void TClass::StreamerDefault(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6599{
6600 if (pThis->fProperty==(-1)) {
6601 pThis->Property();
6602 }
6603
6604 // We could get here because after this thread started StreamerDefault
6605 // *and* before check fProperty, another thread might have call Property
6606 // and this fProperty when we read it, is not -1 and fStreamerImpl is
6607 // supposed to be set properly (no longer pointing to the default).
6608 if (pThis->fStreamerImpl.load() == &TClass::StreamerDefault) {
6609 pThis->Fatal("StreamerDefault", "fStreamerImpl not properly initialized (%d)", pThis->fStreamerType);
6610 } else {
6611 (*pThis->fStreamerImpl)(pThis,object,b,onfile_class);
6612 }
6613}
6614
6615////////////////////////////////////////////////////////////////////////////////
6616/// Adopt a TClassStreamer object. Ownership is transfered to this TClass
6617/// object.
6618
6620{
6621// // This code can be used to quickly test the STL Emulation layer
6622// Int_t k = TClassEdit::IsSTLCont(GetName());
6623// if (k==1||k==-1) { delete str; return; }
6624
6626
6627 if (fStreamer) delete fStreamer;
6628 if (str) {
6630 fStreamer = str;
6632 } else if (fStreamer) {
6633 // Case where there was a custom streamer and it is hereby removed,
6634 // we need to reset fStreamerType
6635 fStreamer = str;
6637 if (fProperty != -1) {
6638 fProperty = -1;
6639 Property();
6640 }
6641 }
6642}
6643
6644////////////////////////////////////////////////////////////////////////////////
6645/// Set a wrapper/accessor function around this class custom streamer.
6646
6648{
6650 if (fProperty != -1 && !fConvStreamerFunc &&
6651 ( (fStreamerFunc == 0 && strm != 0) || (fStreamerFunc != 0 && strm == 0) ) )
6652 {
6653 fStreamerFunc = strm;
6654
6655 // Since initialization has already been done, make sure to tweak it
6656 // for the new state.
6660 }
6661 } else {
6662 fStreamerFunc = strm;
6663 }
6664 fCanSplit = -1;
6665}
6666
6667////////////////////////////////////////////////////////////////////////////////
6668/// Set a wrapper/accessor function around this class custom conversion streamer.
6669
6671{
6673 if (fProperty != -1 &&
6674 ( (fConvStreamerFunc == 0 && strm != 0) || (fConvStreamerFunc != 0 && strm == 0) ) )
6675 {
6676 fConvStreamerFunc = strm;
6677
6678 // Since initialization has already been done, make sure to tweak it
6679 // for the new state.
6683 }
6684 } else {
6685 fConvStreamerFunc = strm;
6686 }
6687 fCanSplit = -1;
6688}
6689
6690
6691////////////////////////////////////////////////////////////////////////////////
6692/// Install a new wrapper around 'Merge'.
6693
6695{
6696 fMerge = newMerge;
6697}
6698
6699////////////////////////////////////////////////////////////////////////////////
6700/// Install a new wrapper around 'ResetAfterMerge'.
6701
6703{
6704 fResetAfterMerge = newReset;
6705}
6706
6707////////////////////////////////////////////////////////////////////////////////
6708/// Install a new wrapper around 'new'.
6709
6711{
6712 fNew = newFunc;
6713}
6714
6715////////////////////////////////////////////////////////////////////////////////
6716/// Install a new wrapper around 'new []'.
6717
6719{
6720 fNewArray = newArrayFunc;
6721}
6722
6723////////////////////////////////////////////////////////////////////////////////
6724/// Install a new wrapper around 'delete'.
6725
6727{
6728 fDelete = deleteFunc;
6729}
6730
6731////////////////////////////////////////////////////////////////////////////////
6732/// Install a new wrapper around 'delete []'.
6733
6735{
6736 fDeleteArray = deleteArrayFunc;
6737}
6738
6739////////////////////////////////////////////////////////////////////////////////
6740/// Install a new wrapper around the destructor.
6741
6743{
6744 fDestructor = destructorFunc;
6745}
6746
6747////////////////////////////////////////////////////////////////////////////////
6748/// Install a new wrapper around the directory auto add function..
6749/// The function autoAddFunc has the signature void (*)(void *obj, TDirectory dir)
6750/// and should register 'obj' to the directory if dir is not null
6751/// and unregister 'obj' from its current directory if dir is null
6752
6754{
6755 fDirAutoAdd = autoAddFunc;
6756}
6757
6758////////////////////////////////////////////////////////////////////////////////
6759/// Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum
6760
6762{
6764 if (guess && guess->GetCheckSum() == checksum) {
6765 return guess;
6766 } else {
6767 if (fCheckSum == checksum) return GetStreamerInfo();
6768
6770 Int_t ninfos = fStreamerInfo->GetEntriesFast()-1;
6771 for (Int_t i=-1;i<ninfos;++i) {
6772 // TClass::fStreamerInfos has a lower bound not equal to 0,
6773 // so we have to use At and should not use UncheckedAt
6775 if (info && info->GetCheckSum() == checksum) {
6776 // R__ASSERT(i==info->GetClassVersion() || (i==-1&&info->GetClassVersion()==1));
6777 info->BuildOld();
6778 if (info->IsCompiled()) fLastReadInfo = info;
6779 return info;
6780 }
6781 }
6782 return 0;
6783 }
6784}
6785
6786////////////////////////////////////////////////////////////////////////////////
6787/// Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum
6788
6790{
6792 Int_t ninfos = arr->GetEntriesFast()-1;
6793 for (Int_t i=-1;i<ninfos;i++) {
6794 // TClass::fStreamerInfos has a lower bound not equal to 0,
6795 // so we have to use At and should not use UncheckedAt
6797 if (!info) continue;
6798 if (info->GetCheckSum() == checksum) {
6799 R__ASSERT(i==info->GetClassVersion() || (i==-1&&info->GetClassVersion()==1));
6800 return info;
6801 }
6802 }
6803 return 0;
6804}
6805
6806////////////////////////////////////////////////////////////////////////////////
6807/// Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this class, if any.
6808
6809TVirtualStreamerInfo *TClass::GetConversionStreamerInfo( const char* classname, Int_t version ) const
6810{
6811 TClass *cl = TClass::GetClass( classname );
6812 if( !cl )
6813 return 0;
6814 return GetConversionStreamerInfo( cl, version );
6815}
6816
6817////////////////////////////////////////////////////////////////////////////////
6818/// Return a Conversion StreamerInfo from the class represented by cl for version number 'version' to this class, if any.
6819
6821{
6822 //----------------------------------------------------------------------------
6823 // Check if the classname was specified correctly
6824 /////////////////////////////////////////////////////////////////////////////
6825
6826 if( !cl )
6827 return 0;
6828
6829 if( cl == this )
6830 return GetStreamerInfo( version );
6831
6832 //----------------------------------------------------------------------------
6833 // Check if we already have it
6834 /////////////////////////////////////////////////////////////////////////////
6835
6836 TObjArray* arr = 0;
6837 if (fConversionStreamerInfo.load()) {
6838 std::map<std::string, TObjArray*>::iterator it;
6840
6841 it = (*fConversionStreamerInfo).find( cl->GetName() );
6842
6843 if( it != (*fConversionStreamerInfo).end() ) {
6844 arr = it->second;
6845 }
6846
6847 if( arr && version > -1 && version < arr->GetSize() && arr->At( version ) )
6848 return (TVirtualStreamerInfo*) arr->At( version );
6849 }
6850
6852
6853 //----------------------------------------------------------------------------
6854 // We don't have the streamer info so find it in other class
6855 /////////////////////////////////////////////////////////////////////////////
6856
6857 const TObjArray *clSI = cl->GetStreamerInfos();
6858 TVirtualStreamerInfo* info = 0;
6859 if( version >= -1 && version < clSI->GetSize() )
6860 info = (TVirtualStreamerInfo*)clSI->At( version );
6861
6862 if (!info && cl->GetCollectionProxy()) {
6863 info = cl->GetStreamerInfo(); // instantiate the StreamerInfo for STL collections.
6864 }
6865
6866 if( !info )
6867 return 0;
6868
6869 //----------------------------------------------------------------------------
6870 // We have the right info so we need to clone it to create new object with
6871 // non artificial streamer elements and we should build it for current class
6872 /////////////////////////////////////////////////////////////////////////////
6873
6874 info = (TVirtualStreamerInfo*)info->Clone();
6875
6876 if( !info->BuildFor( this ) ) {
6877 delete info;
6878 return 0;
6879 }
6880
6881 if (!info->IsCompiled()) {
6882 // Streamer info has not been compiled, but exists.
6883 // Therefore it was read in from a file and we have to do schema evolution?
6884 // Or it didn't have a dictionary before, but does now?
6885 info->BuildOld();
6886 }
6887
6888 //----------------------------------------------------------------------------
6889 // Cache this streamer info
6890 /////////////////////////////////////////////////////////////////////////////
6891
6892 if (!arr) {
6893 arr = new TObjArray(version+10, -1);
6894 if (!fConversionStreamerInfo.load()) {
6895 fConversionStreamerInfo = new std::map<std::string, TObjArray*>();
6896 }
6897 (*fConversionStreamerInfo)[cl->GetName()] = arr;
6898 }
6899 arr->AddAtAndExpand( info, info->GetClassVersion() );
6900 return info;
6901}
6902
6903////////////////////////////////////////////////////////////////////////////////
6904/// Return a Conversion StreamerInfo from the class 'classname' for the layout represented by 'checksum' to this class, if any.
6905
6906TVirtualStreamerInfo *TClass::FindConversionStreamerInfo( const char* classname, UInt_t checksum ) const
6907{
6908 TClass *cl = TClass::GetClass( classname );
6909 if( !cl )
6910 return 0;
6911 return FindConversionStreamerInfo( cl, checksum );
6912}
6913
6914////////////////////////////////////////////////////////////////////////////////
6915/// Return a Conversion StreamerInfo from the class represented by cl for the layout represented by 'checksum' to this class, if any.
6916
6918{
6919 //---------------------------------------------------------------------------
6920 // Check if the classname was specified correctly
6921 /////////////////////////////////////////////////////////////////////////////
6922
6923 if( !cl )
6924 return 0;
6925
6926 if( cl == this )
6927 return FindStreamerInfo( checksum );
6928
6929 //----------------------------------------------------------------------------
6930 // Check if we already have it
6931 /////////////////////////////////////////////////////////////////////////////
6932
6933 TObjArray* arr = 0;
6934 TVirtualStreamerInfo* info = 0;
6935 if (fConversionStreamerInfo.load()) {
6936 std::map<std::string, TObjArray*>::iterator it;
6937
6939
6940 it = (*fConversionStreamerInfo).find( cl->GetName() );
6941
6942 if( it != (*fConversionStreamerInfo).end() ) {
6943 arr = it->second;
6944 }
6945 if (arr) {
6946 info = FindStreamerInfo( arr, checksum );
6947 }
6948 }
6949
6950 if( info )
6951 return info;
6952
6954
6955 //----------------------------------------------------------------------------
6956 // Get it from the foreign class
6957 /////////////////////////////////////////////////////////////////////////////
6958
6959 info = cl->FindStreamerInfo( checksum );
6960
6961 if( !info )
6962 return 0;
6963
6964 //----------------------------------------------------------------------------
6965 // We have the right info so we need to clone it to create new object with
6966 // non artificial streamer elements and we should build it for current class
6967 /////////////////////////////////////////////////////////////////////////////
6968
6969 info = (TVirtualStreamerInfo*)info->Clone();
6970 if( !info->BuildFor( this ) ) {
6971 delete info;
6972 return 0;
6973 }
6974
6975 if (!info->IsCompiled()) {
6976 // Streamer info has not been compiled, but exists.
6977 // Therefore it was read in from a file and we have to do schema evolution?
6978 // Or it didn't have a dictionary before, but does now?
6979 info->BuildOld();
6980 }
6981
6982 //----------------------------------------------------------------------------
6983 // Cache this streamer info
6984 /////////////////////////////////////////////////////////////////////////////
6985
6986 if (!arr) {
6987 arr = new TObjArray(16, -2);
6988 if (!fConversionStreamerInfo.load()) {
6989 fConversionStreamerInfo = new std::map<std::string, TObjArray*>();
6990 }
6991 (*fConversionStreamerInfo)[cl->GetName()] = arr;
6992 }
6993 arr->AddAtAndExpand( info, info->GetClassVersion() );
6994
6995 return info;
6996}
6997
6998////////////////////////////////////////////////////////////////////////////////
6999/// Register the StreamerInfo in the given slot, change the State of the
7000/// TClass as appropriate.
7001
7003{
7004 if (info) {
7006 Int_t slot = info->GetClassVersion();
7008 && fStreamerInfo->At(slot) != 0
7009 && fStreamerInfo->At(slot) != info) {
7010 Error("RegisterStreamerInfo",
7011 "Register StreamerInfo for %s on non-empty slot (%d).",
7012 GetName(),slot);
7013 }
7014 fStreamerInfo->AddAtAndExpand(info, slot);
7015 if (fState <= kForwardDeclared) {
7016 fState = kEmulated;
7017 if (fCheckSum==0 && slot==fClassVersion) fCheckSum = info->GetCheckSum();
7018 }
7019 }
7020}
7021
7022////////////////////////////////////////////////////////////////////////////////
7023/// Remove and delete the StreamerInfo in the given slot.
7024/// Update the slot accordingly.
7025
7027{
7028 if (fStreamerInfo->GetSize() >= slot) {
7032 delete info;
7033 if (fState == kEmulated && fStreamerInfo->GetEntries() == 0) {
7035 }
7036 }
7037}
7038
7039////////////////////////////////////////////////////////////////////////////////
7040/// Return true is the Hash/RecursiveRemove setup is consistent, i.e. when all
7041/// classes in the class hierarchy that overload TObject::Hash do call
7042/// ROOT::CallRecursiveRemoveIfNeeded in their destructor.
7043/// i.e. it is safe to call the Hash virtual function during the RecursiveRemove operation.
7044/// This routines is used for a small subset of the class for which we need
7045/// the answer before gROOT is properly initialized.
7046
7048{
7049 // Hand selection of correct classes, those classes should be
7050 // cross-checked in testHashRecursiveRemove.cxx
7051 static const char *handVerified[] = {
7052 "TEnvRec", "TDataType", "TObjArray", "TList", "THashList",
7053 "TClass", "TCling", "TInterpreter", "TMethod", "ROOT::Internal::TCheckHashRecursiveRemoveConsistency",
7054 "TCheckHashRecursiveRemoveConsistency", "TGWindow",
7055 "TDirectory", "TDirectoryFile", "TObject", "TH1",
7056 "TQClass", "TGlobal" };
7057
7058 if (cname && cname[0]) {
7059 for (auto cursor : handVerified) {
7060 if (strcmp(cname, cursor) == 0)
7061 return true;
7062 }
7063 }
7064 return false;
7065}
7066
7067////////////////////////////////////////////////////////////////////////////////
7068/// Return true is the Hash/RecursiveRemove setup is consistent, i.e. when all
7069/// classes in the class hierarchy that overload TObject::Hash do call
7070/// ROOT::CallRecursiveRemoveIfNeeded in their destructor.
7071/// i.e. it is safe to call the Hash virtual function during the RecursiveRemove operation.
7072
7074{
7075 return clRef.HasConsistentHashMember();
7076}
7077
7078////////////////////////////////////////////////////////////////////////////////
7079/// Return true if we have access to a constructor useable for I/O. This is
7080/// typically the default constructor but can also be a constructor specifically
7081/// marked for I/O (for example a constructor taking a TRootIOCtor* as an
7082/// argument). In other words, if this routine returns true, TClass::New is
7083/// guarantee to succeed.
7084/// To know if the class described by this TClass has a default constructor
7085/// (public or not), use
7086/// \code{.cpp}
7087/// cl->GetProperty() & kClassHasDefaultCtor
7088/// \code
7089/// To know if the class described by this TClass has a public default
7090/// constructor use:
7091/// \code{.cpp}
7092/// gInterpreter->ClassInfo_HasDefaultConstructor(aClass->GetClassInfo());
7093/// \code
7094
7096{
7097
7098 if (fNew) return kTRUE;
7099
7100 if (HasInterpreterInfo()) {
7103 }
7104 if (fCollectionProxy) {
7105 return kTRUE;
7106 }
7107 if (fCurrentInfo.load()) {
7108 // Emulated class, we know how to construct them via the TStreamerInfo
7109 return kTRUE;
7110 }
7111 return kFALSE;
7112}
7113
7114////////////////////////////////////////////////////////////////////////////////
7115/// Returns true if this class has an definition and/or overload of the
7116/// member function Hash.
7117///
7118/// For example to test if the class overload TObject::Hash use
7119/// ~~~ {.cpp}
7120/// if (cl->IsTObject() && cl->HasLocalHashMember())
7121/// ~~~
7122
7124{
7125 if (fProperty == (-1))
7126 Property();
7128}
7129
7130////////////////////////////////////////////////////////////////////////////////
7131/// Return the wrapper around Merge.
7132
7134{
7135 return fMerge;
7136}
7137
7138////////////////////////////////////////////////////////////////////////////////
7139/// Return the wrapper around Merge.
7140
7142{
7143 return fResetAfterMerge;
7144}
7145
7146////////////////////////////////////////////////////////////////////////////////
7147/// Return the wrapper around new ThisClass().
7148
7150{
7151 return fNew;
7152}
7153
7154////////////////////////////////////////////////////////////////////////////////
7155/// Return the wrapper around new ThisClass[].
7156
7158{
7159 return fNewArray;
7160}
7161
7162////////////////////////////////////////////////////////////////////////////////
7163/// Return the wrapper around delete ThiObject.
7164
7166{
7167 return fDelete;
7168}
7169
7170////////////////////////////////////////////////////////////////////////////////
7171/// Return the wrapper around delete [] ThiObject.
7172
7174{
7175 return fDeleteArray;
7176}
7177
7178////////////////////////////////////////////////////////////////////////////////
7179/// Return the wrapper around the destructor
7180
7182{
7183 return fDestructor;
7184}
7185
7186////////////////////////////////////////////////////////////////////////////////
7187/// Return the wrapper around the directory auto add function.
7188
7190{
7191 return fDirAutoAdd;
7192}
void Class()
Definition: Class.C:29
SVector< double, 2 > v
Definition: Dict.h:5
#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:91
@ 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:554
#define gInterpreter
Definition: TInterpreter.h:553
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:414
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:6233
ShowMembersFunc_t fShowMembers
Definition: TClass.h:199
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition: TClass.cxx:3288
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:4469
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:2239
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:6753
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:5023
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:6413
TVirtualStreamerInfo * DetermineCurrentStreamerInfo()
Determine and set pointer to current TVirtualStreamerInfo.
Definition: TClass.cxx:5463
EState GetState() const
Definition: TClass.h:458
ROOT::ESTLType GetCollectionType() const
Return the 'type' of the STL the TClass is representing.
Definition: TClass.cxx:2813
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:6431
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:2866
void RemoveStreamerInfo(Int_t slot)
Remove and delete the StreamerInfo in the given slot.
Definition: TClass.cxx:7026
void SetCanSplit(Int_t splitmode)
Set the splitability of this class:
Definition: TClass.cxx:5437
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:2334
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:4572
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4841
void SetMerge(ROOT::MergeFunc_t mergeFunc)
Install a new wrapper around 'Merge'.
Definition: TClass.cxx:6694
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:4211
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:4281
virtual void Browse(TBrowser *b)
This method is called by a browser to get the class information.
Definition: TClass.cxx:1929
static TClass * Load(TBuffer &b)
Load class description from I/O buffer and return class object.
Definition: TClass.cxx:5494
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:4326
void CopyCollectionProxy(const TVirtualCollectionProxy &)
Copy the argument.
Definition: TClass.cxx:2397
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:1950
std::atomic< TList * > fBase
Definition: TClass.h:176
Bool_t HasDictionary() const
Check whether a class has a dictionary or not.
Definition: TClass.cxx:3778
Long_t GetDataMemberOffset(const char *membername) const
return offset for member name.
Definition: TClass.cxx:3326
const TList * GetListOfAllPublicMethods(Bool_t load=kTRUE)
Returns a list of all public methods of this class and its base classes.
Definition: TClass.cxx:3717
TMethod * GetClassMethod(Long_t faddr)
Look for a method in this class that has the interface function address faddr.
Definition: TClass.cxx:4353
TList * GetListOfAllPublicDataMembers(Bool_t load=kTRUE)
Returns a list of all public data members of this class and its base classes.
Definition: TClass.cxx:3734
void BuildEmulatedRealData(const char *name, Long_t offset, TClass *cl)
Build the list of real data for an emulated class.
Definition: TClass.cxx:2031
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:1583
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5198
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:3670
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:4778
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:7002
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:6718
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:2124
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:5975
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:3789
void AdoptSchemaRules(ROOT::Detail::TSchemaRuleSet *rules)
Adopt a new set of Data Model Evolution rules.
Definition: TClass.cxx:1839
static void StreamerInstrumented(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of instrumented class with a library.
Definition: TClass.cxx:6561
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:6101
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:1871
TCollection * GetListOfMethodOverloads(const char *name) const
Return the collection of functions named "name".
Definition: TClass.cxx:3699
std::atomic< TListOfEnums * > fEnums
Definition: TClass.h:179
static Bool_t HasNoInfoOrEmuOrFwdDeclaredDecl(const char *)
Definition: TClass.cxx:3247
TList * GetListOfEnums(Bool_t load=kTRUE)
Return a list containing the TEnums of a class.
Definition: TClass.cxx:3579
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:5708
TList * GetListOfMethods(Bool_t load=kTRUE)
Return list containing the TMethods of a class.
Definition: TClass.cxx:3684
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:4443
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:4704
TClassStreamer * GetStreamer() const
Return the Streamer Class allowing streaming (if any).
Definition: TClass.cxx:2841
static IdMap_t * GetIdMap()
Definition: TClass.cxx:425
void SetDelete(ROOT::DelFunc_t deleteFunc)
Install a new wrapper around 'delete'.
Definition: TClass.cxx:6726
static Int_t AutoBrowse(TObject *obj, TBrowser *browser)
Browse external object inherited from TObject.
Definition: TClass.cxx:1885
ROOT::NewFunc_t GetNew() const
TClass * GetBaseClass(const char *classname)
Return pointer to the base class "classname".
Definition: TClass.cxx:2582
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:4424
void SetDestructor(ROOT::DesFunc_t destructorFunc)
Install a new wrapper around the destructor.
Definition: TClass.cxx:6742
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:5736
void LoadClassInfo() const
Try to load the ClassInfo if available.
Definition: TClass.cxx:5603
void SetResetAfterMerge(ROOT::ResetAfterMergeFunc_t resetFunc)
Install a new wrapper around 'ResetAfterMerge'.
Definition: TClass.cxx:6702
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:6222
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:3799
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:6598
void SetUnloaded()
Call this method to indicate that the shared library containing this class's code has been removed (u...
Definition: TClass.cxx:6040
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:5925
static TClass * LoadClass(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition: TClass.cxx:5528
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:3635
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:4197
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:6647
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:5483
void SetCurrentStreamerInfo(TVirtualStreamerInfo *info)
Set pointer to current TVirtualStreamerInfo.
Definition: TClass.cxx:5475
static DictFuncPtr_t GetDict(const char *cname)
Return a pointer to the dictionary loading function generated by rootcint.
Definition: TClass.cxx:3271
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:6548
ROOT::NewFunc_t fNew
Definition: TClass.h:209
@ kLoading
Definition: TClass.h:298
@ kUnloading
Definition: TClass.h:298
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:4397
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:365
void SetGlobalIsA(IsAGlobalFunc_t)
This function installs a global IsA function for this class.
Definition: TClass.cxx:6031
void GetMissingDictionariesForMembers(TCollection &result, TCollection &visited, bool recurse)
Verify the Data Members.
Definition: TClass.cxx:3816
TObjArray * fStreamerInfo
Definition: TClass.h:173
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1851
TVirtualCollectionProxy * fCollectionProxy
Definition: TClass.h:194
static ENewType IsCallingNew()
Static method returning the defConstructor flag passed to TClass::New().
Definition: TClass.cxx:5681
void ls(Option_t *opt="") const
The ls function lists the contents of a class on stdout.
Definition: TClass.cxx:4128
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3525
void Store(TBuffer &b) const
Store class description on I/O buffer.
Definition: TClass.cxx:5639
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:2161
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:6583
const TObjArray * GetStreamerInfos() const
Definition: TClass.h:462
void SetClassVersion(Version_t version)
Private function.
Definition: TClass.cxx:5454
char * EscapeChars(const char *text) const
Introduce an escape character (@) in front of a special chars.
Definition: TClass.cxx:2496
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:6525
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition: TClass.cxx:5691
@ 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:1809
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5717
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:5315
ClassConvStreamerFunc_t GetConvStreamerFunc() const
Get a wrapper/accessor function around this class custom conversion streamer (member function).
Definition: TClass.cxx:2874
Bool_t IsForeign() const
Return kTRUE is the class is Foreign (the class does not have a Streamer method).
Definition: TClass.cxx:5726
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:2718
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:6619
TClass * GetBaseDataMember(const char *datamember)
Return pointer to (base) class that contains datamember.
Definition: TClass.cxx:2754
Long_t Property() const
Set TObject::fBits and fStreamerType to cache information about the class.
Definition: TClass.cxx:5817
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:2824
void ResetCaches()
To clean out all caches.
Definition: TClass.cxx:4087
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:2324
void SetStreamerImpl()
Internal routine to set fStreamerImpl based on the value of fStreamerType.
Definition: TClass.cxx:5946
const char * GetSharedLibs()
Get the list of shared libraries containing the code for class cls.
Definition: TClass.cxx:3512
void CalculateStreamerOffset() const
Calculate the offset between an object of this class to its base class TObject.
Definition: TClass.cxx:2102
void GetMissingDictionariesForPairElements(TCollection &result, TCollection &visited, bool recurse)
Definition: TClass.cxx:3845
void ReplaceWith(TClass *newcl) const
Definition: TClass.cxx:4009
void GetMenuItems(TList *listitems)
Returns list of methods accessible by context menu.
Definition: TClass.cxx:3746
void SetNew(ROOT::NewFunc_t newFunc)
Install a new wrapper around 'new'.
Definition: TClass.cxx:6710
void Draw(Option_t *option="")
Draw detailed class inheritance structure.
Definition: TClass.cxx:2414
std::atomic< TMethodCall * > fIsAMethod
Definition: TClass.h:205
static Int_t ReadRules()
Read the class.rules files from the default location:.
Definition: TClass.cxx:1739
Bool_t CanSplitBaseAllow()
Pointer to the function implementing streaming for this class.
Definition: TClass.cxx:2166
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:6000
void SetMemberStreamer(const char *name, MemberStreamerFunc_t strm)
Install a new member streamer (p will be copied).
Definition: TClass.cxx:6469
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:6809
Short_t GetImplFileLine() const
Definition: TClass.h:427
TMethod * GetMethodAllAny(const char *method)
Return pointer to method without looking at parameters.
Definition: TClass.cxx:4254
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:6906
Int_t GetBaseClassOffsetRecurse(const TClass *toBase)
Return data member offset to the base class "cl".
Definition: TClass.cxx:2632
ROOT::DelFunc_t GetDelete() const
static TClass * LoadClassDefault(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition: TClass.cxx:5550
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:4310
static void StreamerExternal(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
There is special streamer for the class.
Definition: TClass.cxx:6513
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:6539
static void ConvStreamerInstrumented(const TClass *pThis, void *object, TBuffer &b, const TClass *onfile_class)
Case of instrumented class with a library.
Definition: TClass.cxx:6570
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:6670
TVirtualStreamerInfo * FindStreamerInfo(TObjArray *arr, UInt_t checksum) const
Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum.
Definition: TClass.cxx:6789
void GetMissingDictionaries(THashTable &result, bool recurse=false)
Get the classes that have a missing dictionary starting from this one.
Definition: TClass.cxx:3959
void MakeCustomMenuList()
Makes a customizable version of the popup menu list, i.e.
Definition: TClass.cxx:4153
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:4635
TMethod * GetMethodAny(const char *method)
Return pointer to method without looking at parameters.
Definition: TClass.cxx:4244
TVirtualIsAProxy * GetIsAProxy() const
Return the proxy implementing the IsA functionality.
Definition: TClass.cxx:2882
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:4737
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition: TClass.cxx:2535
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:3312
TRealData * GetRealData(const char *name) const
Return pointer to TRealData element with name "name".
Definition: TClass.cxx:3352
void SetDeleteArray(ROOT::DelArrFunc_t deleteArrayFunc)
Install a new wrapper around 'delete []'.
Definition: TClass.cxx:6734
TFunctionTemplate * GetFunctionTemplate(const char *name)
Definition: TClass.cxx:3496
void ResetClassInfo()
Make sure that the current ClassInfo is up to date.
Definition: TClass.cxx:4052
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:6483
void GetMissingDictionariesWithRecursionCheck(TCollection &result, TCollection &visited, bool recurse)
From the second level of recursion onwards it is different state check.
Definition: TClass.cxx:3862
@ 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:4225
void ResetMenuList()
Resets the menu list to it's standard value.
Definition: TClass.cxx:4113
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:2895
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:6504
static TClass * LoadClassCustom(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition: TClass.cxx:5580
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:159
const void * DeclId_t
Definition: TDictionary.h:206
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:406
virtual const char * DataMemberInfo_Name(DataMemberInfo_t *) const
Definition: TInterpreter.h:462
virtual const char * DataMemberInfo_TypeName(DataMemberInfo_t *) const
Definition: TInterpreter.h:460
virtual int DataMemberInfo_TypeSize(DataMemberInfo_t *) const
Definition: TInterpreter.h:459
virtual Long_t ClassInfo_GetBaseOffset(ClassInfo_t *, ClassInfo_t *, void *=0, bool=true) const
Definition: TInterpreter.h:402
virtual void * ClassInfo_New(ClassInfo_t *) const
Definition: TInterpreter.h:418
virtual Bool_t ClassInfo_IsValid(ClassInfo_t *) const
Definition: TInterpreter.h:414
virtual Int_t AutoParse(const char *cls)=0
virtual int SetClassAutoloading(int) const
Definition: TInterpreter.h:260
virtual void ClassInfo_Delete(ClassInfo_t *) const
Definition: TInterpreter.h:394
virtual void ClassInfo_DeleteArray(ClassInfo_t *, void *, bool) const
Definition: TInterpreter.h:396
virtual Long_t ClassInfo_Property(ClassInfo_t *) const
Definition: TInterpreter.h:422
virtual Bool_t ClassInfo_HasDefaultConstructor(ClassInfo_t *) const
Definition: TInterpreter.h:405
virtual DataMemberInfo_t * DataMemberInfo_Factory(ClassInfo_t *=0) const
Definition: TInterpreter.h:450
virtual int ClassInfo_Size(ClassInfo_t *) const
Definition: TInterpreter.h:423
virtual const char * ClassInfo_FullName(ClassInfo_t *) const
Definition: TInterpreter.h:426
virtual const char * ClassInfo_Title(ClassInfo_t *) const
Definition: TInterpreter.h:428
virtual Long_t DataMemberInfo_TypeProperty(DataMemberInfo_t *) const
Definition: TInterpreter.h:458
virtual int DataMemberInfo_Next(DataMemberInfo_t *) const
Definition: TInterpreter.h:455
virtual Long_t DataMemberInfo_Property(DataMemberInfo_t *) const
Definition: TInterpreter.h:457
virtual int DataMemberInfo_ArrayDim(DataMemberInfo_t *) const
Definition: TInterpreter.h:448
virtual void DataMemberInfo_Delete(DataMemberInfo_t *) const
Definition: TInterpreter.h:449
virtual int DataMemberInfo_MaxIndex(DataMemberInfo_t *, Int_t) const
Definition: TInterpreter.h:454
TDictionary::DeclId_t DeclId_t
Definition: TInterpreter.h:281
virtual Long_t ClassInfo_ClassProperty(ClassInfo_t *) const
Definition: TInterpreter.h:393
virtual void ClassInfo_Destruct(ClassInfo_t *, void *) const
Definition: TInterpreter.h:397
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:3028
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:1071
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:309
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:7073
Namespace for new ROOT classes and functions.
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:5648
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:152
@ kExactMatch
Definition: TDictionary.h:153
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:821
@ 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:492
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