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