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