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