Logo ROOT   6.12/07
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);
176  fClassNamesSet.insert(s);
177 }
178 
179 ////////////////////////////////////////////////////////////////////////////////
180 
182 {
183  Bool_t found = false;
184  {
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  {
251  R__LOCKGUARD2(gOVRMutex);
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 
272  R__LOCKGUARD2(gOVRMutex);
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;
294  R__LOCKGUARD2(gOVRMutex);
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 
448  R__LOCKGUARD(gInterpreterMutex);
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 
474  R__LOCKGUARD(gInterpreterMutex);
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 
919  std::string clmName(TClassEdit::ShortType(gCling->DataMemberInfo_TypeName(m),
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 
1037  R__LOCKGUARD(gInterpreterMutex);
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),
1057  fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
1060  fInstanceCount(0), fOnHeap(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),
1068  fState(kNoInfo),
1071 {
1072  R__LOCKGUARD(gInterpreterMutex);
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),
1104  fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
1107  fInstanceCount(0), fOnHeap(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),
1115  fState(kNoInfo),
1118 {
1119  R__LOCKGUARD(gInterpreterMutex);
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),
1131  fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
1134  fInstanceCount(0), fOnHeap(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),
1142  fState(theState),
1145 {
1146  R__LOCKGUARD(gInterpreterMutex);
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),
1175  fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
1178  fInstanceCount(0), fOnHeap(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),
1186  fState(kNoInfo),
1189 {
1190  R__LOCKGUARD(gInterpreterMutex);
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 
1207  R__LOCKGUARD(gInterpreterMutex);
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),
1225  fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
1228  fInstanceCount(0), fOnHeap(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),
1236  fState(kNoInfo),
1239 {
1240  R__LOCKGUARD(gInterpreterMutex);
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),
1255  fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
1256  fAllPubMethod(0),
1257  fClassMenuList(0),
1259  fInstanceCount(0), fOnHeap(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),
1270 {
1271  R__LOCKGUARD(gInterpreterMutex);
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++;
1467  SetUniqueID(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 
1481  fgClassTypedefHash->Add (new TNameMapNode (name, fName));
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 {
1577  R__LOCKGUARD(gInterpreterMutex);
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 
1809  R__LOCKGUARD(gInterpreterMutex);
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 {
1833  R__LOCKGUARD(gInterpreterMutex);
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 
1945  R__LOCKGUARD(gInterpreterMutex);
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 {
2025  R__LOCKGUARD(gInterpreterMutex);
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 {
2096  R__LOCKGUARD(gInterpreterMutex);
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 
2164  R__LOCKGUARD(gInterpreterMutex);
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 
2241  R__LOCKGUARD(gInterpreterMutex);
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
2334  R__LOCKGUARD(gInterpreterMutex);
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) {
2555  R__LOCKGUARD(gInterpreterMutex);
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 
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.
3349  TRealData* rd = (TRealData*) fRealData->FindObject(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 
3485  return (TFunctionTemplate*)fFuncTemplate->FindObject(name);
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 
3513  R__LOCKGUARD(gInterpreterMutex);
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 
3536  R__LOCKGUARD(gInterpreterMutex);
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();
3582  R__LOCKGUARD(gInterpreterMutex);
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 
3596  R__LOCKGUARD(gInterpreterMutex);
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 {
3619  R__LOCKGUARD(gInterpreterMutex);
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 {
3654  R__LOCKGUARD(gInterpreterMutex);
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 {
3668  R__LOCKGUARD(gInterpreterMutex);
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 {
3701  R__LOCKGUARD(gInterpreterMutex);
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 {
3718  R__LOCKGUARD(gInterpreterMutex);
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 
3858  const auto uniquePtrClName = TClassEdit::GetUniquePtrType(fName);
3859  auto uniquePtrCl = TClass::GetClass(uniquePtrClName.c_str());
3860  if (uniquePtrCl && !uniquePtrCl->HasDictionary()) {
3861  uniquePtrCl->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3862  }
3863  return;
3864  }
3865 
3866  if (!HasDictionary()) {
3867  result.Add(this);
3868  }
3869 
3870  visited.Add(this);
3871  //Check whether a custom streamer
3873  if (GetCollectionProxy()) {
3874  // We need to look at the collection's content
3875  // The collection has different kind of elements the check would be required.
3876  TClass* t = 0;
3877  if ((t = GetCollectionProxy()->GetValueClass())) {
3878  if (!t->HasDictionary()) {
3879  t->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3880  }
3881  }
3882  } else {
3883  if (recurse) {
3884  GetMissingDictionariesForMembers(result, visited, recurse);
3885  }
3886  GetMissingDictionariesForBaseClasses(result, visited, recurse);
3887  }
3888  }
3889 }
3890 
3891 ////////////////////////////////////////////////////////////////////////////////
3892 /// Get the classes that have a missing dictionary starting from this one.
3893 /// - With recurse = false the classes checked for missing dictionaries are:
3894 /// the class itself, all base classes, direct data members,
3895 /// and for collection proxies the container's
3896 /// elements without iterating over the element's data members;
3897 /// - With recurse = true the classes checked for missing dictionaries are:
3898 /// the class itself, all base classes, recursing on the data members,
3899 /// and for the collection proxies recursion on the elements of the
3900 /// collection and iterating over the element's data members.
3901 
3902 void TClass::GetMissingDictionaries(THashTable& result, bool recurse)
3903 {
3904  // Top level recursion it different from the following levels of recursion.
3905 
3906  if (result.FindObject(this)) return;
3907 
3908  static TClassRef sCIString("string");
3909  if (this == sCIString) return;
3910 
3911  THashTable visited;
3912 
3913  if (strncmp(fName, "pair<", 5) == 0) {
3914  GetMissingDictionariesForPairElements(result, visited, recurse);
3915  return;
3916  }
3917 
3918  if (!HasDictionary()) {
3919  result.Add(this);
3920  }
3921 
3922  visited.Add(this);
3923 
3924  //Check whether a custom streamer
3926  if (GetCollectionProxy()) {
3927  // We need to look at the collection's content
3928  // The collection has different kind of elements the check would be required.
3929  TClass* t = 0;
3930  if ((t = GetCollectionProxy()->GetValueClass())) {
3931  if (!t->HasDictionary()) {
3932  t->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
3933  }
3934  }
3935  } else {
3936  GetMissingDictionariesForMembers(result, visited, recurse);
3937  GetMissingDictionariesForBaseClasses(result, visited, recurse);
3938  }
3939  }
3940 }
3941 
3942 ////////////////////////////////////////////////////////////////////////////////
3943 /// Return kTRUE if the class has elements.
3944 
3945 Bool_t TClass::IsFolder(void *obj) const
3946 {
3947  return Browse(obj,(TBrowser*)0);
3948 }
3949 
3950 //______________________________________________________________________________
3951 //______________________________________________________________________________
3952 void TClass::ReplaceWith(TClass *newcl) const
3953 {
3954  // Inform the other objects to replace this object by the new TClass (newcl)
3955 
3956  R__LOCKGUARD(gInterpreterMutex);
3957  //we must update the class pointers pointing to 'this' in all TStreamerElements
3958  TIter nextClass(gROOT->GetListOfClasses());
3959  TClass *acl;
3960  TVirtualStreamerInfo *info;
3961  TList tobedeleted;
3962 
3963  // Since we are in the process of replacing a TClass by a TClass
3964  // coming from a dictionary, there is no point in loading any
3965  // libraries during this search.
3966  Bool_t autoload = gInterpreter->SetClassAutoloading(kFALSE);
3967 
3968  while ((acl = (TClass*)nextClass())) {
3969  if (acl == newcl) continue;
3970 
3971  TIter nextInfo(acl->GetStreamerInfos());
3972  while ((info = (TVirtualStreamerInfo*)nextInfo())) {
3973 
3974  info->Update(this, newcl);
3975  }
3976 
3977  if (acl->GetCollectionProxy()) {
3978  acl->GetCollectionProxy()->UpdateValueClass(this, newcl);
3979  }
3980  // We should also inform all the TBranchElement :( but we do not have a master list :(
3981  }
3982 
3983  TIter delIter( &tobedeleted );
3984  while ((acl = (TClass*)delIter())) {
3985  delete acl;
3986  }
3987  gInterpreter->UnRegisterTClassUpdate(this);
3988 
3989  gInterpreter->SetClassAutoloading(autoload);
3990 }
3991 
3992 ////////////////////////////////////////////////////////////////////////////////
3993 /// Make sure that the current ClassInfo is up to date.
3994 
3995 void TClass::ResetClassInfo(Long_t /* tagnum */)
3996 {
3997  Warning("ResetClassInfo(Long_t tagnum)","Call to deprecated interface (does nothing)");
3998 }
3999 
4000 ////////////////////////////////////////////////////////////////////////////////
4001 /// Make sure that the current ClassInfo is up to date.
4002 
4004 {
4005  R__LOCKGUARD(gInterpreterMutex);
4006 
4008 
4009  if (fClassInfo) {
4011  gInterpreter->ClassInfo_Delete(fClassInfo);
4012  fClassInfo = 0;
4013  }
4014  // We can not check at this point whether after the unload there will
4015  // still be interpreter information about this class (as v5 was doing),
4016  // instead this function must only be called if the definition is (about)
4017  // to be unloaded.
4018 
4019  ResetCaches();
4020 
4021  // We got here because the definition Decl is about to be unloaded.
4022  if (fState != TClass::kHasTClassInit) {
4023  if (fStreamerInfo->GetEntries() != 0) {
4025  } else {
4027  }
4028  } else {
4029  // if the ClassInfo was loaded for a class with a TClass Init and it
4030  // gets unloaded, should we guess it can be reloaded?
4032  }
4033 }
4034 
4035 ////////////////////////////////////////////////////////////////////////////////
4036 /// To clean out all caches.
4037 
4039 {
4040  R__ASSERT(!TestBit(kLoading) && "Resetting the caches does not make sense during loading!" );
4041 
4042  // Not owning lists, don't call Delete(), but unload
4043  if (fData)
4044  fData->Unload();
4045  if (fEnums.load())
4046  (*fEnums).Unload();
4047  if (fMethod.load())
4048  (*fMethod).Unload();
4049 
4050  delete fAllPubData; fAllPubData = 0;
4051 
4052  if (fBase.load())
4053  (*fBase).Delete();
4054  delete fBase.load(); fBase = 0;
4055 
4056  if (fRealData)
4057  fRealData->Delete();
4058  delete fRealData; fRealData=0;
4059 }
4060 
4061 ////////////////////////////////////////////////////////////////////////////////
4062 /// Resets the menu list to it's standard value.
4063 
4065 {
4066  if (fClassMenuList)
4068  else
4069  fClassMenuList = new TList();
4071 }
4072 
4073 ////////////////////////////////////////////////////////////////////////////////
4074 /// The ls function lists the contents of a class on stdout. Ls output
4075 /// is typically much less verbose then Dump().
4076 /// If options contains 'streamerinfo', run ls on the list of streamerInfos
4077 /// and the list of conversion streamerInfos.
4078 
4079 void TClass::ls(Option_t *options) const
4080 {
4081  TNamed::ls(options);
4082  if (options==0 || options[0]==0) return;
4083 
4084  if (strstr(options,"streamerinfo")!=0) {
4085  GetStreamerInfos()->ls(options);
4086 
4087  if (fConversionStreamerInfo.load()) {
4088  std::map<std::string, TObjArray*>::iterator it;
4089  std::map<std::string, TObjArray*>::iterator end = (*fConversionStreamerInfo).end();
4090  for( it = (*fConversionStreamerInfo).begin(); it != end; ++it ) {
4091  it->second->ls(options);
4092  }
4093  }
4094  }
4095 }
4096 
4097 ////////////////////////////////////////////////////////////////////////////////
4098 /// Makes a customizable version of the popup menu list, i.e. makes a list
4099 /// of TClassMenuItem objects of methods accessible by context menu.
4100 /// The standard (and different) way consists in having just one element
4101 /// in this list, corresponding to the whole standard list.
4102 /// Once the customizable version is done, one can remove or add elements.
4103 
4105 {
4106  R__LOCKGUARD(gInterpreterMutex);
4107  TClassMenuItem *menuItem;
4108 
4109  // Make sure fClassMenuList is initialized and empty.
4110  GetMenuList()->Delete();
4111 
4112  TList* methodList = new TList;
4113  GetMenuItems(methodList);
4114 
4115  TMethod *method;
4116  TMethodArg *methodArg;
4117  TClass *classPtr = 0;
4118  TIter next(methodList);
4119 
4120  while ((method = (TMethod*) next())) {
4121  // if go to a mother class method, add separator
4122  if (classPtr != method->GetClass()) {
4123  menuItem = new TClassMenuItem(TClassMenuItem::kPopupSeparator, this);
4124  fClassMenuList->AddLast(menuItem);
4125  classPtr = method->GetClass();
4126  }
4127  // Build the signature of the method
4128  TString sig;
4129  TList* margsList = method->GetListOfMethodArgs();
4130  TIter nextarg(margsList);
4131  while ((methodArg = (TMethodArg*)nextarg())) {
4132  sig = sig+","+methodArg->GetFullTypeName();
4133  }
4134  if (sig.Length()!=0) sig.Remove(0,1); // remove first comma
4136  method->GetName(), method->GetName(),0,
4137  sig.Data(),-1,TClassMenuItem::kIsSelf);
4138  if (method->IsMenuItem() == kMenuToggle) menuItem->SetToggle();
4139  fClassMenuList->Add(menuItem);
4140  }
4141  delete methodList;
4142 }
4143 
4144 ////////////////////////////////////////////////////////////////////////////////
4145 /// Register the fact that an object was moved from the memory location
4146 /// 'arenaFrom' to the memory location 'arenaTo'.
4147 
4148 void TClass::Move(void *arenaFrom, void *arenaTo) const
4149 {
4150  // If/when we have access to a copy constructor (or better to a move
4151  // constructor), this function should also perform the data move.
4152  // For now we just information the repository.
4153 
4154  if ((GetState() <= kEmulated) && !fCollectionProxy) {
4155  MoveAddressInRepository("TClass::Move",arenaFrom,arenaTo,this);
4156  }
4157 }
4158 
4159 ////////////////////////////////////////////////////////////////////////////////
4160 /// Return the list of menu items associated with the class.
4161 
4163  if (!fClassMenuList) {
4164  fClassMenuList = new TList();
4165  fClassMenuList->Add(new TClassMenuItem(TClassMenuItem::kPopupStandardList, const_cast<TClass*>(this)));
4166  }
4167  return fClassMenuList;
4168 }
4169 
4170 ////////////////////////////////////////////////////////////////////////////////
4171 /// Return (create an empty one if needed) the list of functions.
4172 /// The major difference with GetListOfMethod is that this returns
4173 /// the internal type of fMethod and thus can not be made public.
4174 /// It also never 'loads' the content of the list.
4175 
4177 {
4178  if (!fMethod.load()) {
4179  std::unique_ptr<TListOfFunctions> temp{ new TListOfFunctions(this) };
4180  TListOfFunctions* expected = nullptr;
4181  if(fMethod.compare_exchange_strong(expected, temp.get()) ) {
4182  temp.release();
4183  }
4184  }
4185  return fMethod;
4186 }
4187 
4188 
4189 ////////////////////////////////////////////////////////////////////////////////
4190 /// Return pointer to method without looking at parameters.
4191 /// Does not look in (possible) base classes.
4192 /// Has the side effect of loading all the TMethod object in the list
4193 /// of the class.
4194 
4195 TMethod *TClass::GetMethodAny(const char *method)
4196 {
4197  if (!HasInterpreterInfo()) return 0;
4198  return (TMethod*) GetMethodList()->FindObject(method);
4199 }
4200 
4201 ////////////////////////////////////////////////////////////////////////////////
4202 /// Return pointer to method without looking at parameters.
4203 /// Does look in all base classes.
4204 
4205 TMethod *TClass::GetMethodAllAny(const char *method)
4206 {
4207  if (!HasInterpreterInfo()) return 0;
4208 
4209  TMethod* m = GetMethodAny(method);
4210  if (m) return m;
4211 
4212  TBaseClass *base;
4213  TIter nextb(GetListOfBases());
4214  while ((base = (TBaseClass *) nextb())) {
4215  TClass *c = base->GetClassPointer();
4216  if (c) {
4217  m = c->GetMethodAllAny(method);
4218  if (m) return m;
4219  }
4220  }
4221 
4222  return 0;
4223 }
4224 
4225 ////////////////////////////////////////////////////////////////////////////////
4226 /// Find the best method (if there is one) matching the parameters.
4227 /// The params string must contain argument values, like "3189, \"aap\", 1.3".
4228 /// The function invokes GetClassMethod to search for a possible method
4229 /// in the class itself or in its base classes. Returns 0 in case method
4230 /// is not found.
4231 
4232 TMethod *TClass::GetMethod(const char *method, const char *params,
4233  Bool_t objectIsConst /* = kFALSE */)
4234 {
4236  if (!fClassInfo) return 0;
4237 
4238  if (!gInterpreter)
4239  Fatal("GetMethod", "gInterpreter not initialized");
4240 
4241  TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithValues(fClassInfo,
4242  method, params,
4243  objectIsConst);
4244 
4245  if (!decl) return 0;
4246 
4247  // search recursively in this class or its base classes
4249  if (f) return f;
4250 
4251  Error("GetMethod",
4252  "\nDid not find matching TMethod <%s> with \"%s\" %sfor %s",
4253  method,params,objectIsConst ? "const " : "", GetName());
4254  return 0;
4255 }
4256 
4257 
4258 ////////////////////////////////////////////////////////////////////////////////
4259 /// Find a method with decl id in this class or its bases.
4260 
4262  if (TFunction* method = GetMethodList()->Get(declId))
4263  return static_cast<TMethod *>(method);
4264 
4265  for (auto item : *GetListOfBases())
4266  if (auto base = static_cast<TBaseClass *>(item)->GetClassPointer())
4267  if (TFunction* method = base->FindClassOrBaseMethodWithId(declId))
4268  return static_cast<TMethod *>(method);
4269 
4270  return nullptr;
4271 }
4272 
4273 ////////////////////////////////////////////////////////////////////////////////
4274 /// Find the method with a given prototype. The proto string must be of the
4275 /// form: "char*,int,double". Returns 0 in case method is not found.
4276 
4277 TMethod *TClass::GetMethodWithPrototype(const char *method, const char *proto,
4278  Bool_t objectIsConst /* = kFALSE */,
4279  ROOT::EFunctionMatchMode mode /* = ROOT::kConversionMatch */)
4280 {
4282  if (!fClassInfo) return 0;
4283 
4284  if (!gInterpreter)
4285  Fatal("GetMethodWithPrototype", "gInterpreter not initialized");
4286 
4287  TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithPrototype(fClassInfo,
4288  method, proto,
4289  objectIsConst, mode);
4290 
4291  if (!decl) return 0;
4293  if (f) return f;
4294  Error("GetMethodWithPrototype",
4295  "\nDid not find matching TMethod <%s> with \"%s\" %sfor %s",
4296  method,proto,objectIsConst ? "const " : "", GetName());
4297  return 0;
4298 }
4299 
4300 ////////////////////////////////////////////////////////////////////////////////
4301 /// Look for a method in this class that has the interface function
4302 /// address faddr.
4303 
4305 {
4306  if (!HasInterpreterInfo()) return 0;
4307 
4308  TMethod *m;
4309  TIter next(GetListOfMethods());
4310  while ((m = (TMethod *) next())) {
4311  if (faddr == (Long_t)m->InterfaceMethod())
4312  return m;
4313  }
4314  return 0;
4315 }
4316 
4317 ////////////////////////////////////////////////////////////////////////////////
4318 /// Look for a method in this class that has the name and matches the parameters.
4319 /// The params string must contain argument values, like "3189, \"aap\", 1.3".
4320 /// Returns 0 in case method is not found.
4321 /// See TClass::GetMethod to also search the base classes.
4322 
4323 TMethod *TClass::GetClassMethod(const char *name, const char* params,
4324  Bool_t objectIsConst /* = kFALSE */)
4325 {
4327  if (!fClassInfo) return 0;
4328 
4329  if (!gInterpreter)
4330  Fatal("GetClassMethod", "gInterpreter not initialized");
4331 
4332  TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithValues(fClassInfo,
4333  name, params,
4334  objectIsConst);
4335 
4336  if (!decl) return 0;
4337 
4338  TFunction *f = GetMethodList()->Get(decl);
4339 
4340  return (TMethod*)f; // Could be zero if the decl is actually in a base class.
4341 }
4342 
4343 ////////////////////////////////////////////////////////////////////////////////
4344 /// Find the method with a given prototype. The proto string must be of the
4345 /// form: "char*,int,double". Returns 0 in case method is not found.
4346 /// See TClass::GetMethodWithPrototype to also search the base classes.
4347 
4349  Bool_t objectIsConst /* = kFALSE */,
4350  ROOT::EFunctionMatchMode mode /* = ROOT::kConversionMatch */)
4351 {
4353  if (!fClassInfo) return 0;
4354 
4355  if (!gInterpreter)
4356  Fatal("GetClassMethodWithPrototype", "gInterpreter not initialized");
4357 
4358  TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithPrototype(fClassInfo,
4359  name, proto,
4360  objectIsConst,
4361  mode);
4362 
4363  if (!decl) return 0;
4364 
4365  TFunction *f = GetMethodList()->Get(decl);
4366 
4367  return (TMethod*)f; // Could be zero if the decl is actually in a base class.
4368 }
4369 
4370 ////////////////////////////////////////////////////////////////////////////////
4371 /// Return the number of data members of this class
4372 /// Note that in case the list of data members is not yet created, it will be done
4373 /// by GetListOfDataMembers().
4374 
4376 {
4377  if (!HasDataMemberInfo()) return 0;
4378 
4379  TList *lm = GetListOfDataMembers();
4380  if (lm)
4381  return lm->GetSize();
4382  else
4383  return 0;
4384 }
4385 
4386 ////////////////////////////////////////////////////////////////////////////////
4387 /// Return the number of methods of this class
4388 /// Note that in case the list of methods is not yet created, it will be done
4389 /// by GetListOfMethods().
4390 /// This will also load/populate the list of methods, to get 'just' the
4391 /// number of currently loaded methods use:
4392 /// cl->GetListOfMethods(false)->GetSize();
4393 
4395 {
4396  if (!HasInterpreterInfo()) return 0;
4397 
4398  TList *lm = GetListOfMethods();
4399  if (lm)
4400  return lm->GetSize();
4401  else
4402  return 0;
4403 }
4404 
4405 ////////////////////////////////////////////////////////////////////////////////
4406 /// returns a pointer to the TVirtualStreamerInfo object for version
4407 /// If the object does not exist, it is created
4408 ///
4409 /// Note: There are two special version numbers:
4410 ///
4411 /// - 0: Use the class version from the currently loaded class library.
4412 /// - -1: Assume no class library loaded (emulated class).
4413 ///
4414 /// Warning: If we create a new streamer info, whether or not the build
4415 /// optimizes is controlled externally to us by a global variable!
4416 /// Don't call us unless you have set that variable properly
4417 /// with TStreamer::Optimize()!
4418 ///
4419 
4421 {
4423 
4424  // Version 0 is special, it means the currently loaded version.
4425  // We need to set it at the beginning to be able to guess it correctly.
4426 
4427  if (version == 0)
4428  version = fClassVersion;
4429 
4430  // If the StreamerInfo is assigned to the fLastReadInfo, we are
4431  // guaranteed it was built and compiled.
4432  if (sinfo && sinfo->GetClassVersion() == version)
4433  return sinfo;
4434 
4435  // Note that the access to fClassVersion above is technically not thread-safe with a low probably of problems.
4436  // fClassVersion is not an atomic and is modified TClass::SetClassVersion (called from RootClassVersion via
4437  // ROOT::ResetClassVersion) and is 'somewhat' protected by the atomic fVersionUsed.
4438  // However, direct access to fClassVersion should be replaced by calls to GetClassVersion to set fVersionUsed.
4439  // Even with such a change the code here and in these functions need to be reviewed as a cursory look seem
4440  // to indicates they are not yet properly protection against mutli-thread access.
4441  //
4442  // However, the use of these functions is rare and mostly done at library loading time which should
4443  // in almost all cases preceeds the possibility of GetStreamerInfo being called from multiple thread
4444  // on that same TClass object.
4445  //
4446  // Summary: need careful review but risk of problem is extremely low.
4447 
4448  R__LOCKGUARD(gInterpreterMutex);
4449 
4450  // Warning: version may be -1 for an emulated class, or -2 if the
4451  // user requested the emulated streamerInfo for an abstract
4452  // base class, even though we have a dictionary for it.
4453 
4454  if ((version < -1) || (version >= fStreamerInfo->GetSize())) {
4455  Error("GetStreamerInfo", "class: %s, attempting to access a wrong version: %d", GetName(), version);
4456  // FIXME: Shouldn't we go to -1 here, or better just abort?
4457  version = fClassVersion;
4458  }
4459 
4460  sinfo = (TVirtualStreamerInfo *)fStreamerInfo->At(version);
4461 
4462  if (!sinfo && (version != fClassVersion)) {
4463  // When the requested version does not exist we return
4464  // the TVirtualStreamerInfo for the currently loaded class version.
4465  // FIXME: This arguably makes no sense, we should warn and return nothing instead.
4466  // Note: This is done for STL collections
4467  // Note: fClassVersion could be -1 here (for an emulated class).
4468  // This is also the code path take for unversioned classes.
4470  }
4471 
4472  if (!sinfo) {
4473  // We just were not able to find a streamer info, we have to make a new one.
4474  TMmallocDescTemp setreset;
4475  sinfo = TVirtualStreamerInfo::Factory()->NewInfo(const_cast<TClass*>(this));
4477  if (gDebug > 0) {
4478  printf("Creating StreamerInfo for class: %s, version: %d\n", GetName(), fClassVersion);
4479  }
4481  // If we do not have a StreamerInfo for this version and we do not
4482  // have dictionary information nor a proxy, there is nothing to build!
4483  sinfo->Build();
4484  }
4485  } else {
4486  if (!sinfo->IsCompiled()) {
4487  // Streamer info has not been compiled, but exists.
4488  // Therefore it was read in from a file and we have to do schema evolution?
4489  // Or it didn't have a dictionary before, but does now?
4490  sinfo->BuildOld();
4491  }
4492  }
4493 
4494  // Cache the current info if we now have it.
4495  if (version == fClassVersion)
4496  fCurrentInfo = sinfo;
4497 
4498  // If the compilation succeeded, remember this StreamerInfo.
4499  if (sinfo->IsCompiled())
4500  fLastReadInfo = sinfo;
4501 
4502  return sinfo;
4503 }
4504 
4505 ////////////////////////////////////////////////////////////////////////////////
4506 /// For the case where the requestor class is emulated and this class is abstract,
4507 /// returns a pointer to the TVirtualStreamerInfo object for version with an emulated
4508 /// representation whether or not the class is loaded.
4509 ///
4510 /// If the object does not exist, it is created
4511 ///
4512 /// Note: There are two special version numbers:
4513 ///
4514 /// - 0: Use the class version from the currently loaded class library.
4515 /// - -1: Assume no class library loaded (emulated class).
4516 ///
4517 /// Warning: If we create a new streamer info, whether or not the build
4518 /// optimizes is controlled externally to us by a global variable!
4519 /// Don't call us unless you have set that variable properly
4520 /// with TStreamer::Optimize()!
4521 ///
4522 
4524 {
4525  TVirtualStreamerInfo *sinfo = nullptr;
4526 
4527  TString newname(GetName());
4528  newname += "@@emulated";
4529 
4530  R__LOCKGUARD(gInterpreterMutex);
4531 
4532  TClass *emulated = TClass::GetClass(newname);
4533 
4534  if (emulated)
4535  sinfo = emulated->GetStreamerInfo(version);
4536 
4537  if (!sinfo) {
4538  // The emulated version of the streamerInfo is explicitly requested and has
4539  // not been built yet.
4540 
4541  sinfo = (TVirtualStreamerInfo*) fStreamerInfo->At(version);
4542 
4543  if (!sinfo && (version != fClassVersion)) {
4544  // When the requested version does not exist we return
4545  // the TVirtualStreamerInfo for the currently loaded class version.
4546  // FIXME: This arguably makes no sense, we should warn and return nothing instead.
4548  }
4549 
4550  if (!sinfo) {
4551  // Let's take the first available StreamerInfo as a start
4552  Int_t ninfos = fStreamerInfo->GetEntriesFast() - 1;
4553  for (Int_t i = -1; sinfo == 0 && i < ninfos; ++i)
4555  }
4556 
4557  if (sinfo) {
4558  sinfo = dynamic_cast<TVirtualStreamerInfo *>(sinfo->Clone());
4559  if (sinfo) {
4560  sinfo->SetClass(0);
4561  sinfo->SetName(newname);
4562  sinfo->BuildCheck();
4563  sinfo->BuildOld();
4564  sinfo->GetClass()->AddRule(TString::Format("sourceClass=%s targetClass=%s",GetName(),newname.Data()));
4565  } else {
4566  Error("GetStreamerInfoAbstractEmulated", "could not create TVirtualStreamerInfo");
4567  }
4568  }
4569  }
4570  return sinfo;
4571 }
4572 
4573 ////////////////////////////////////////////////////////////////////////////////
4574 /// For the case where the requestor class is emulated and this class is abstract,
4575 /// returns a pointer to the TVirtualStreamerInfo object for version with an emulated
4576 /// representation whether or not the class is loaded.
4577 ///
4578 /// If the object does not exist, it is created
4579 ///
4580 /// Warning: If we create a new streamer info, whether or not the build
4581 /// optimizes is controlled externally to us by a global variable!
4582 /// Don't call us unless you have set that variable properly
4583 /// with TStreamer::Optimize()!
4584 ///
4585 
4587 {
4588  TVirtualStreamerInfo *sinfo = nullptr;
4589 
4590  TString newname(GetName());
4591  newname += "@@emulated";
4592 
4593  R__LOCKGUARD(gInterpreterMutex);
4594 
4595  TClass *emulated = TClass::GetClass(newname);
4596 
4597  if (emulated)
4598  sinfo = emulated->FindStreamerInfo(checksum);
4599 
4600  if (!sinfo) {
4601  // The emulated version of the streamerInfo is explicitly requested and has
4602  // not been built yet.
4603 
4604  sinfo = (TVirtualStreamerInfo*) FindStreamerInfo(checksum);
4605 
4606  if (!sinfo && (checksum != fCheckSum)) {
4607  // When the requested version does not exist we return
4608  // the TVirtualStreamerInfo for the currently loaded class version.
4609  // FIXME: This arguably makes no sense, we should warn and return nothing instead.
4611  }
4612 
4613  if (!sinfo) {
4614  // Let's take the first available StreamerInfo as a start
4615  Int_t ninfos = fStreamerInfo->GetEntriesFast() - 1;
4616  for (Int_t i = -1; sinfo == 0 && i < ninfos; ++i)
4618  }
4619 
4620  if (sinfo) {
4621  sinfo = dynamic_cast<TVirtualStreamerInfo*>( sinfo->Clone() );
4622  if (sinfo) {
4623  sinfo->SetClass(0);
4624  sinfo->SetName( newname );
4625  sinfo->BuildCheck();
4626  sinfo->BuildOld();
4627  sinfo->GetClass()->AddRule(TString::Format("sourceClass=%s targetClass=%s",GetName(),newname.Data()));
4628  } else {
4629  Error("GetStreamerInfoAbstractEmulated", "could not create TVirtualStreamerInfo");
4630  }
4631  }
4632  }
4633  return sinfo;
4634 }
4635 
4636 ////////////////////////////////////////////////////////////////////////////////
4637 /// When the class kIgnoreTObjectStreamer bit is set, the automatically
4638 /// generated Streamer will not call TObject::Streamer.
4639 /// This option saves the TObject space overhead on the file.
4640 /// However, the information (fBits, fUniqueID) of TObject is lost.
4641 ///
4642 /// Note that to be effective for objects streamed object-wise this function
4643 /// must be called for the class deriving directly from TObject, eg, assuming
4644 /// that BigTrack derives from Track and Track derives from TObject, one must do:
4645 /// ~~~ {.cpp}
4646 /// Track::Class()->IgnoreTObjectStreamer();
4647 /// ~~~
4648 /// and not:
4649 /// ~~~ {.cpp}
4650 /// BigTrack::Class()->IgnoreTObjectStreamer();
4651 /// ~~~
4652 /// To be effective for object streamed member-wise or split in a TTree,
4653 /// this function must be called for the most derived class (i.e. BigTrack).
4654 
4656 {
4657  // We need to tak the lock since we are test and then setting fBits
4658  // and TStreamerInfo::fBits (and the StreamerInfo state in general)
4659  // which can also be modified by another thread.
4660  R__LOCKGUARD(gInterpreterMutex);
4661 
4662  if ( doIgnore && TestBit(kIgnoreTObjectStreamer)) return;
4663  if (!doIgnore && !TestBit(kIgnoreTObjectStreamer)) return;
4665  if (sinfo) {
4666  if (sinfo->IsCompiled()) {
4667  // -- Warn the user that what they are doing cannot work.
4668  // Note: The reason is that TVirtualStreamerInfo::Build() examines
4669  // the kIgnoreTObjectStreamer bit and sets the TStreamerElement
4670  // type for the TObject base class streamer element it creates
4671  // to -1 as a flag. Later on the TStreamerInfo::Compile()
4672  // member function sees the flag and does not insert the base
4673  // class element into the compiled streamer info. None of this
4674  // machinery works correctly if we are called after the streamer
4675  // info has already been built and compiled.
4676  Error("IgnoreTObjectStreamer","Must be called before the creation of StreamerInfo");
4677  return;
4678  }
4679  }
4680  if (doIgnore) SetBit (kIgnoreTObjectStreamer);
4682 }
4683 
4684 ////////////////////////////////////////////////////////////////////////////////
4685 /// Return kTRUE if this class inherits from a class with name "classname".
4686 /// note that the function returns kTRUE in case classname is the class itself
4687 
4688 Bool_t TClass::InheritsFrom(const char *classname) const
4689 {
4690  if (strcmp(GetName(), classname) == 0) return kTRUE;
4691 
4692  return InheritsFrom(TClass::GetClass(classname,kTRUE,kTRUE));
4693 }
4694 
4695 ////////////////////////////////////////////////////////////////////////////////
4696 /// Return kTRUE if this class inherits from class cl.
4697 /// note that the function returns KTRUE in case cl is the class itself
4698 
4700 {
4701  if (!cl) return kFALSE;
4702  if (cl == this) return kTRUE;
4703 
4704  if (!HasDataMemberInfo()) {
4705  TVirtualStreamerInfo *sinfo = ((TClass *)this)->GetCurrentStreamerInfo();
4706  if (sinfo==0) sinfo = GetStreamerInfo();
4707  TIter next(sinfo->GetElements());
4708  TStreamerElement *element;
4709  while ((element = (TStreamerElement*)next())) {
4710  if (element->IsA() == TStreamerBase::Class()) {
4711  TClass *clbase = element->GetClassPointer();
4712  if (!clbase) return kFALSE; //missing class
4713  if (clbase->InheritsFrom(cl)) return kTRUE;
4714  }
4715  }
4716  return kFALSE;
4717  }
4718  // cast const away (only for member fBase which can be set in GetListOfBases())
4719  if (((TClass *)this)->GetBaseClass(cl)) return kTRUE;
4720  return kFALSE;
4721 }
4722 
4723 ////////////////////////////////////////////////////////////////////////////////
4724 /// Cast obj of this class type up to baseclass cl if up is true.
4725 /// Cast obj of this class type down from baseclass cl if up is false.
4726 /// If this class is not a baseclass of cl return 0, else the pointer
4727 /// to the cl part of this (up) or to this (down).
4728 
4729 void *TClass::DynamicCast(const TClass *cl, void *obj, Bool_t up)
4730 {
4731  if (cl == this) return obj;
4732 
4733  if (!HasDataMemberInfo()) return 0;
4734 
4735  Int_t off;
4736  if ((off = GetBaseClassOffset(cl, obj)) != -1) {
4737  if (up)
4738  return (void*)((Long_t)obj+off);
4739  else
4740  return (void*)((Long_t)obj-off);
4741  }
4742  return 0;
4743 }
4744 
4745 ////////////////////////////////////////////////////////////////////////////////
4746 /// Cast obj of this class type up to baseclass cl if up is true.
4747 /// Cast obj of this class type down from baseclass cl if up is false.
4748 /// If this class is not a baseclass of cl return 0, else the pointer
4749 /// to the cl part of this (up) or to this (down).
4750 
4751 const void *TClass::DynamicCast(const TClass *cl, const void *obj, Bool_t up)
4752 {
4753  return DynamicCast(cl,const_cast<void*>(obj),up);
4754 }
4755 
4756 ////////////////////////////////////////////////////////////////////////////////
4757 /// Return a pointer to a newly allocated object of this class.
4758 /// The class must have a default constructor. For meaning of
4759 /// defConstructor, see TClass::IsCallingNew().
4760 ///
4761 /// If quiet is true, do no issue a message via Error on case
4762 /// of problems, just return 0.
4763 ///
4764 /// The constructor actually called here can be customized by
4765 /// using the rootcint pragma:
4766 /// ~~~ {.cpp}
4767 /// #pragma link C++ ioctortype UserClass;
4768 /// ~~~
4769 /// For example, with this pragma and a class named MyClass,
4770 /// this method will called the first of the following 3
4771 /// constructors which exists and is public:
4772 /// ~~~ {.cpp}
4773 /// MyClass(UserClass*);
4774 /// MyClass(TRootIOCtor*);
4775 /// MyClass(); // Or a constructor with all its arguments defaulted.
4776 /// ~~~
4777 ///
4778 /// When more than one pragma ioctortype is used, the first seen as priority
4779 /// For example with:
4780 /// ~~~ {.cpp}
4781 /// #pragma link C++ ioctortype UserClass1;
4782 /// #pragma link C++ ioctortype UserClass2;
4783 /// ~~~
4784 /// We look in the following order:
4785 /// ~~~ {.cpp}
4786 /// MyClass(UserClass1*);
4787 /// MyClass(UserClass2*);
4788 /// MyClass(TRootIOCtor*);
4789 /// MyClass(); // Or a constructor with all its arguments defaulted.
4790 /// ~~~
4791 
4792 void *TClass::New(ENewType defConstructor, Bool_t quiet) const
4793 {
4794  void* p = 0;
4795 
4796  if (fNew) {
4797  // We have the new operator wrapper function,
4798  // so there is a dictionary and it was generated
4799  // by rootcint, so there should be a default
4800  // constructor we can call through the wrapper.
4801  TClass__GetCallingNew() = defConstructor;
4802  p = fNew(0);
4804  if (!p && !quiet) {
4805  //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
4806  Error("New", "cannot create object of class %s", GetName());
4807  }
4808  } else if (HasInterpreterInfo()) {
4809  // We have the dictionary but do not have the
4810  // constructor wrapper, so the dictionary was
4811  // not generated by rootcint. Let's try to
4812  // create the object by having the interpreter
4813  // call the new operator, hopefully the class
4814  // library is loaded and there will be a default
4815  // constructor we can call.
4816  // [This is very unlikely to work, but who knows!]
4817  TClass__GetCallingNew() = defConstructor;
4820  if (!p && !quiet) {
4821  //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
4822  Error("New", "cannot create object of class %s", GetName());
4823  }
4824  } else if (!HasInterpreterInfo() && fCollectionProxy) {
4825  // There is no dictionary at all, so this is an emulated
4826  // class; however we do have the services of a collection proxy,
4827  // so this is an emulated STL class.
4828  TClass__GetCallingNew() = defConstructor;
4829  p = fCollectionProxy->New();
4831  if (!p && !quiet) {
4832  //Error("New", "cannot create object of class %s version %d", GetName(), fClassVersion);
4833  Error("New", "cannot create object of class %s", GetName());
4834  }
4835  } else if (!HasInterpreterInfo() && !fCollectionProxy) {
4836  // There is no dictionary at all and we do not have
4837  // the services of a collection proxy available, so
4838  // use the streamer info to approximate calling a
4839  // constructor (basically we just make sure that the
4840  // pointer data members are null, unless they are marked
4841  // as preallocated with the "->" comment, in which case
4842  // we default-construct an object to point at).
4843 
4844  // Do not register any TObject's that we create
4845  // as a result of creating this object.
4846  // FIXME: Why do we do this?
4847  // FIXME: Partial Answer: Is this because we may never actually deregister them???
4848 
4849  Bool_t statsave = GetObjectStat();
4850  if(statsave) {
4852  }
4854  if (!sinfo && !quiet) {
4855  Error("New", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
4856  return 0;
4857  }
4858 
4859  TClass__GetCallingNew() = defConstructor;
4860  p = sinfo->New();
4862 
4863  // FIXME: Mistake? See note above at the GetObjectStat() call.
4864  // Allow TObject's to be registered again.
4865  if(statsave) {
4866  SetObjectStat(statsave);
4867  }
4868 
4869  // Register the object for special handling in the destructor.
4870  if (p) {
4871  RegisterAddressInRepository("New",p,this);
4872  } else {
4873  Error("New", "Failed to construct class '%s' using streamer info", GetName());
4874  }
4875  } else {
4876  Fatal("New", "This cannot happen!");
4877  }
4878 
4879  return p;
4880 }
4881 
4882 ////////////////////////////////////////////////////////////////////////////////
4883 /// Return a pointer to a newly allocated object of this class.
4884 /// The class must have a default constructor. For meaning of
4885 /// defConstructor, see TClass::IsCallingNew().
4886 
4887 void *TClass::New(void *arena, ENewType defConstructor) const
4888 {
4889  void* p = 0;
4890 
4891  if (fNew) {
4892  // We have the new operator wrapper function,
4893  // so there is a dictionary and it was generated
4894  // by rootcint, so there should be a default
4895  // constructor we can call through the wrapper.
4896  TClass__GetCallingNew() = defConstructor;
4897  p = fNew(arena);
4899  if (!p) {
4900  Error("New with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
4901  }
4902  } else if (HasInterpreterInfo()) {
4903  // We have the dictionary but do not have the
4904  // constructor wrapper, so the dictionary was
4905  // not generated by rootcint. Let's try to
4906  // create the object by having the interpreter
4907  // call the new operator, hopefully the class
4908  // library is loaded and there will be a default
4909  // constructor we can call.
4910  // [This is very unlikely to work, but who knows!]
4911  TClass__GetCallingNew() = defConstructor;
4912  p = gCling->ClassInfo_New(GetClassInfo(),arena);
4914  if (!p) {
4915  Error("New with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
4916  }
4917  } else if (!HasInterpreterInfo() && fCollectionProxy) {
4918  // There is no dictionary at all, so this is an emulated
4919  // class; however we do have the services of a collection proxy,
4920  // so this is an emulated STL class.
4921  TClass__GetCallingNew() = defConstructor;
4922  p = fCollectionProxy->New(arena);
4924  } else if (!HasInterpreterInfo() && !fCollectionProxy) {
4925  // There is no dictionary at all and we do not have
4926  // the services of a collection proxy available, so
4927  // use the streamer info to approximate calling a
4928  // constructor (basically we just make sure that the
4929  // pointer data members are null, unless they are marked
4930  // as preallocated with the "->" comment, in which case
4931  // we default-construct an object to point at).
4932 
4933  // ???BUG??? ???WHY???
4934  // Do not register any TObject's that we create
4935  // as a result of creating this object.
4936  Bool_t statsave = GetObjectStat();
4937  if(statsave) {
4939  }
4940 
4942  if (!sinfo) {
4943  Error("New with placement", "Cannot construct class '%s' version %d at address %p, no streamer info available!", GetName(), fClassVersion, arena);
4944  return 0;
4945  }
4946 
4947  TClass__GetCallingNew() = defConstructor;
4948  p = sinfo->New(arena);
4950 
4951  // ???BUG???
4952  // Allow TObject's to be registered again.
4953  if(statsave) {
4954  SetObjectStat(statsave);
4955  }
4956 
4957  // Register the object for special handling in the destructor.
4958  if (p) {
4959  RegisterAddressInRepository("TClass::New with placement",p,this);
4960  }
4961  } else {
4962  Error("New with placement", "This cannot happen!");
4963  }
4964 
4965  return p;
4966 }
4967 
4968 ////////////////////////////////////////////////////////////////////////////////
4969 /// Return a pointer to a newly allocated array of objects
4970 /// of this class.
4971 /// The class must have a default constructor. For meaning of
4972 /// defConstructor, see TClass::IsCallingNew().
4973 
4974 void *TClass::NewArray(Long_t nElements, ENewType defConstructor) const
4975 {
4976  void* p = 0;
4977 
4978  if (fNewArray) {
4979  // We have the new operator wrapper function,
4980  // so there is a dictionary and it was generated
4981  // by rootcint, so there should be a default
4982  // constructor we can call through the wrapper.
4983  TClass__GetCallingNew() = defConstructor;
4984  p = fNewArray(nElements, 0);
4986  if (!p) {
4987  Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
4988  }
4989  } else if (HasInterpreterInfo()) {
4990  // We have the dictionary but do not have the
4991  // constructor wrapper, so the dictionary was
4992  // not generated by rootcint. Let's try to
4993  // create the object by having the interpreter
4994  // call the new operator, hopefully the class
4995  // library is loaded and there will be a default
4996  // constructor we can call.
4997  // [This is very unlikely to work, but who knows!]
4998  TClass__GetCallingNew() = defConstructor;
4999  p = gCling->ClassInfo_New(GetClassInfo(),nElements);
5001  if (!p) {
5002  Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
5003  }
5004  } else if (!HasInterpreterInfo() && fCollectionProxy) {
5005  // There is no dictionary at all, so this is an emulated
5006  // class; however we do have the services of a collection proxy,
5007  // so this is an emulated STL class.
5008  TClass__GetCallingNew() = defConstructor;
5009  p = fCollectionProxy->NewArray(nElements);
5011  } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5012  // There is no dictionary at all and we do not have
5013  // the services of a collection proxy available, so
5014  // use the streamer info to approximate calling a
5015  // constructor (basically we just make sure that the
5016  // pointer data members are null, unless they are marked
5017  // as preallocated with the "->" comment, in which case
5018  // we default-construct an object to point at).
5019 
5020  // ???BUG??? ???WHY???
5021  // Do not register any TObject's that we create
5022  // as a result of creating this object.
5023  Bool_t statsave = GetObjectStat();
5024  if(statsave) {
5026  }
5027 
5029  if (!sinfo) {
5030  Error("NewArray", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
5031  return 0;
5032  }
5033 
5034  TClass__GetCallingNew() = defConstructor;
5035  p = sinfo->NewArray(nElements);
5037 
5038  // ???BUG???
5039  // Allow TObject's to be registered again.
5040  if(statsave) {
5041  SetObjectStat(statsave);
5042  }
5043 
5044  // Register the object for special handling in the destructor.
5045  if (p) {
5046  RegisterAddressInRepository("TClass::NewArray",p,this);
5047  }
5048  } else {
5049  Error("NewArray", "This cannot happen!");
5050  }
5051 
5052  return p;
5053 }
5054 
5055 ////////////////////////////////////////////////////////////////////////////////
5056 /// Return a pointer to a newly allocated object of this class.
5057 /// The class must have a default constructor. For meaning of
5058 /// defConstructor, see TClass::IsCallingNew().
5059 
5060 void *TClass::NewArray(Long_t nElements, void *arena, ENewType defConstructor) const
5061 {
5062  void* p = 0;
5063 
5064  if (fNewArray) {
5065  // We have the new operator wrapper function,
5066  // so there is a dictionary and it was generated
5067  // by rootcint, so there should be a default
5068  // constructor we can call through the wrapper.
5069  TClass__GetCallingNew() = defConstructor;
5070  p = fNewArray(nElements, arena);
5072  if (!p) {
5073  Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
5074  }
5075  } else if (HasInterpreterInfo()) {
5076  // We have the dictionary but do not have the constructor wrapper,
5077  // so the dictionary was not generated by rootcint (it was made either
5078  // by cint or by some external mechanism). Let's try to create the
5079  // object by having the interpreter call the new operator, either the
5080  // class library is loaded and there is a default constructor we can
5081  // call, or the class is interpreted and we will call the default
5082  // constructor that way, or no default constructor is available and
5083  // we fail.
5084  TClass__GetCallingNew() = defConstructor;
5085  p = gCling->ClassInfo_New(GetClassInfo(),nElements, arena);
5087  if (!p) {
5088  Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
5089  }
5090  } else if (!HasInterpreterInfo() && fCollectionProxy) {
5091  // There is no dictionary at all, so this is an emulated
5092  // class; however we do have the services of a collection proxy,
5093  // so this is an emulated STL class.
5094  TClass__GetCallingNew() = defConstructor;
5095  p = fCollectionProxy->NewArray(nElements, arena);
5097  } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5098  // There is no dictionary at all and we do not have
5099  // the services of a collection proxy available, so
5100  // use the streamer info to approximate calling a
5101  // constructor (basically we just make sure that the
5102  // pointer data members are null, unless they are marked
5103  // as preallocated with the "->" comment, in which case
5104  // we default-construct an object to point at).
5105 
5106  // ???BUG??? ???WHY???
5107  // Do not register any TObject's that we create
5108  // as a result of creating this object.
5109  Bool_t statsave = GetObjectStat();
5110  if(statsave) {
5112  }
5113 
5115  if (!sinfo) {
5116  Error("NewArray with placement", "Cannot construct class '%s' version %d at address %p, no streamer info available!", GetName(), fClassVersion, arena);
5117  return 0;
5118  }
5119 
5120  TClass__GetCallingNew() = defConstructor;
5121  p = sinfo->NewArray(nElements, arena);
5123 
5124  // ???BUG???
5125  // Allow TObject's to be registered again.
5126  if(statsave) {
5127  SetObjectStat(statsave);
5128  }
5129 
5131  // We always register emulated objects, we need to always
5132  // use the streamer info to destroy them.
5133  }
5134 
5135  // Register the object for special handling in the destructor.
5136  if (p) {
5137  RegisterAddressInRepository("TClass::NewArray with placement",p,this);
5138  }
5139  } else {
5140  Error("NewArray with placement", "This cannot happen!");
5141  }
5142 
5143  return p;
5144 }
5145 
5146 ////////////////////////////////////////////////////////////////////////////////
5147 /// Explicitly call destructor for object.
5148 
5149 void TClass::Destructor(void *obj, Bool_t dtorOnly)
5150 {
5151  // Do nothing if passed a null pointer.
5152  if (obj == 0) return;
5153 
5154  void* p = obj;
5155 
5156  if (dtorOnly && fDestructor) {
5157  // We have the destructor wrapper, use it.
5158  fDestructor(p);
5159  } else if ((!dtorOnly) && fDelete) {
5160  // We have the delete wrapper, use it.
5161  fDelete(p);
5162  } else if (HasInterpreterInfo()) {
5163  // We have the dictionary but do not have the
5164  // destruct/delete wrapper, so the dictionary was
5165  // not generated by rootcint (it could have been
5166  // created by cint or by some external mechanism).
5167  // Let's have the interpreter call the destructor,
5168  // either the code will be in a loaded library,
5169  // or it will be interpreted, otherwise we fail
5170  // because there is no destructor code at all.
5171  if (dtorOnly) {
5173  } else {
5175  }
5176  } else if (!HasInterpreterInfo() && fCollectionProxy) {
5177  // There is no dictionary at all, so this is an emulated
5178  // class; however we do have the services of a collection proxy,
5179  // so this is an emulated STL class.
5180  fCollectionProxy->Destructor(p, dtorOnly);
5181  } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5182  // There is no dictionary at all and we do not have
5183  // the services of a collection proxy available, so
5184  // use the streamer info to approximate calling a
5185  // destructor.
5186 
5187  Bool_t inRepo = kTRUE;
5188  Bool_t verFound = kFALSE;
5189 
5190  // Was this object allocated through TClass?
5191  std::multiset<Version_t> knownVersions;
5192  R__LOCKGUARD2(gOVRMutex);
5193 
5194  {
5195  RepoCont_t::iterator iter = gObjectVersionRepository.find(p);
5196  if (iter == gObjectVersionRepository.end()) {
5197  // No, it wasn't, skip special version handling.
5198  //Error("Destructor2", "Attempt to delete unregistered object of class '%s' at address %p!", GetName(), p);
5199  inRepo = kFALSE;
5200  } else {
5201  //objVer = iter->second;
5202  for (; (iter != gObjectVersionRepository.end()) && (iter->first == p); ++iter) {
5203  Version_t ver = iter->second.fVersion;
5204  knownVersions.insert(ver);
5205  if (ver == fClassVersion && this == iter->second.fClass) {
5206  verFound = kTRUE;
5207  }
5208  }
5209  }
5210  }
5211 
5212  if (!inRepo || verFound) {
5213  // The object was allocated using code for the same class version
5214  // as is loaded now. We may proceed without worry.
5216  if (si) {
5217  si->Destructor(p, dtorOnly);
5218  } else {
5219  Error("Destructor", "No streamer info available for class '%s' version %d at address %p, cannot destruct emulated object!", GetName(), fClassVersion, p);
5220  Error("Destructor", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5222  for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5223  Error("Destructor", "fStreamerInfo->At(%d): %p", i, fStreamerInfo->At(i));
5224  if (fStreamerInfo->At(i) != 0) {
5225  Error("Destructor", "Doing Dump() ...");
5227  }
5228  }
5229  }
5230  } else {
5231  // The loaded class version is not the same as the version of the code
5232  // which was used to allocate this object. The best we can do is use
5233  // the TVirtualStreamerInfo to try to free up some of the allocated memory.
5234  Error("Destructor", "Loaded class %s version %d is not registered for addr %p", GetName(), fClassVersion, p);
5235 #if 0
5237  if (si) {
5238  si->Destructor(p, dtorOnly);
5239  } else {
5240  Error("Destructor2", "No streamer info available for class '%s' version %d, cannot destruct object at addr: %p", GetName(), objVer, p);
5241  Error("Destructor2", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5243  for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5244  Error("Destructor2", "fStreamerInfo->At(%d): %p", i, fStreamerInfo->At(i));
5245  if (fStreamerInfo->At(i) != 0) {
5246  // Do some debugging output.
5247  Error("Destructor2", "Doing Dump() ...");
5249  }
5250  }
5251  }
5252 #endif
5253  }
5254 
5255  if (inRepo && verFound && p) {
5256  UnregisterAddressInRepository("TClass::Destructor",p,this);
5257  }
5258  } else {
5259  Error("Destructor", "This cannot happen! (class %s)", GetName());
5260  }
5261 }
5262 
5263 ////////////////////////////////////////////////////////////////////////////////
5264 /// Explicitly call operator delete[] for an array.
5265 
5266 void TClass::DeleteArray(void *ary, Bool_t dtorOnly)
5267 {
5268  // Do nothing if passed a null pointer.
5269  if (ary == 0) return;
5270 
5271  // Make a copy of the address.
5272  void* p = ary;
5273 
5274  if (fDeleteArray) {
5275  if (dtorOnly) {
5276  Error("DeleteArray", "Destructor only is not supported!");
5277  } else {
5278  // We have the array delete wrapper, use it.
5279  fDeleteArray(ary);
5280  }
5281  } else if (HasInterpreterInfo()) {
5282  // We have the dictionary but do not have the
5283  // array delete wrapper, so the dictionary was
5284  // not generated by rootcint. Let's try to
5285  // delete the array by having the interpreter
5286  // call the array delete operator, hopefully
5287  // the class library is loaded and there will be
5288  // a destructor we can call.
5289  gCling->ClassInfo_DeleteArray(GetClassInfo(),ary, dtorOnly);
5290  } else if (!HasInterpreterInfo() && fCollectionProxy) {
5291  // There is no dictionary at all, so this is an emulated
5292  // class; however we do have the services of a collection proxy,
5293  // so this is an emulated STL class.
5294  fCollectionProxy->DeleteArray(ary, dtorOnly);
5295  } else if (!HasInterpreterInfo() && !fCollectionProxy) {
5296  // There is no dictionary at all and we do not have
5297  // the services of a collection proxy available, so
5298  // use the streamer info to approximate calling the
5299  // array destructor.
5300 
5301  Bool_t inRepo = kTRUE;
5302  Bool_t verFound = kFALSE;
5303 
5304  // Was this array object allocated through TClass?
5305  std::multiset<Version_t> knownVersions;
5306  {
5307  R__LOCKGUARD2(gOVRMutex);
5308  RepoCont_t::iterator iter = gObjectVersionRepository.find(p);
5309  if (iter == gObjectVersionRepository.end()) {
5310  // No, it wasn't, we cannot know what to do.
5311  //Error("DeleteArray", "Attempt to delete unregistered array object, element type '%s', at address %p!", GetName(), p);
5312  inRepo = kFALSE;
5313  } else {
5314  for (; (iter != gObjectVersionRepository.end()) && (iter->first == p); ++iter) {
5315  Version_t ver = iter->second.fVersion;
5316  knownVersions.insert(ver);
5317  if (ver == fClassVersion && this == iter->second.fClass ) {
5318  verFound = kTRUE;
5319  }
5320  }
5321  }
5322  }
5323 
5324  if (!inRepo || verFound) {
5325  // The object was allocated using code for the same class version
5326  // as is loaded now. We may proceed without worry.
5328  if (si) {
5329  si->DeleteArray(ary, dtorOnly);
5330  } else {
5331  Error("DeleteArray", "No streamer info available for class '%s' version %d at address %p, cannot destruct object!", GetName(), fClassVersion, ary);
5332  Error("DeleteArray", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5334  for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5335  Error("DeleteArray", "fStreamerInfo->At(%d): %p", v, fStreamerInfo->At(i));
5336  if (fStreamerInfo->At(i)) {
5337  Error("DeleteArray", "Doing Dump() ...");
5339  }
5340  }
5341  }
5342  } else {
5343  // The loaded class version is not the same as the version of the code
5344  // which was used to allocate this array. The best we can do is use
5345  // the TVirtualStreamerInfo to try to free up some of the allocated memory.
5346  Error("DeleteArray", "Loaded class version %d is not registered for addr %p", fClassVersion, p);
5347 
5348 
5349 
5350 #if 0
5352  if (si) {
5353  si->DeleteArray(ary, dtorOnly);
5354  } else {
5355  Error("DeleteArray", "No streamer info available for class '%s' version %d at address %p, cannot destruct object!", GetName(), objVer, ary);
5356  Error("DeleteArray", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
5358  for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
5359  Error("DeleteArray", "fStreamerInfo->At(%d): %p", v, fStreamerInfo->At(i));
5360  if (fStreamerInfo->At(i)) {
5361  // Print some debugging info.
5362  Error("DeleteArray", "Doing Dump() ...");
5364  }
5365  }
5366  }
5367 #endif
5368 
5369 
5370  }
5371 
5372  // Deregister the object for special handling in the destructor.
5373  if (inRepo && verFound && p) {
5374  UnregisterAddressInRepository("TClass::DeleteArray",p,this);
5375  }
5376  } else {
5377  Error("DeleteArray", "This cannot happen! (class '%s')", GetName());
5378  }
5379 }
5380 
5381 ////////////////////////////////////////////////////////////////////////////////
5382 /// Set the splitability of this class:
5383 /// - -1: Use the default calculation
5384 /// - 0: Disallow splitting
5385 /// - 1: Always allow splitting.
5386 /// - 2: Disallow splitting of the class and splitting of any it's derived classes.
5387 
5389 {
5390  fCanSplit = splitmode;
5391 }
5392 
5393 ////////////////////////////////////////////////////////////////////////////////
5394 /// Private function. Set the class version for the 'class' represented by
5395 /// this TClass object. See the public interface:
5396 /// ROOT::ResetClassVersion
5397 /// defined in TClassTable.cxx
5398 ///
5399 /// Note on class version numbers:
5400 /// - If no class number has been specified, TClass::GetVersion will return -1
5401 /// - The Class Version 0 request the whole object to be transient
5402 /// - The Class Version 1, unless specified via ClassDef indicates that the
5403 /// I/O should use the TClass checksum to distinguish the layout of the class
5404 
5406 {
5407  fClassVersion = version;
5408  fCurrentInfo = 0;
5409 }
5410 
5411 ////////////////////////////////////////////////////////////////////////////////
5412 /// Determine and set pointer to current TVirtualStreamerInfo
5413 
5415 {
5416  if(!fCurrentInfo.load()) {
5417  R__LOCKGUARD(gInterpreterMutex);
5419  }
5420  return fCurrentInfo;
5421 }
5422 
5423 ////////////////////////////////////////////////////////////////////////////////
5424 /// Set pointer to current TVirtualStreamerInfo
5425 
5427 {
5428  fCurrentInfo = info;
5429 }
5430 
5431 ////////////////////////////////////////////////////////////////////////////////
5432 /// Return size of object of this class.
5433 
5435 {
5436  if (fSizeof!=-1) return fSizeof;
5437  if (fCollectionProxy) return fCollectionProxy->Sizeof();
5439  return GetStreamerInfo()->GetSize();
5440 }
5441 
5442 ////////////////////////////////////////////////////////////////////////////////
5443 /// Load class description from I/O buffer and return class object.
5444 
5446 {
5447  UInt_t maxsize = 256;
5448  char *s = new char[maxsize];
5449 
5450  Int_t pos = b.Length();
5451 
5452  b.ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end.
5453  while (strlen(s) == (maxsize - 1)) {
5454  // The classname is too large, try again with a large buffer.
5455  b.SetBufferOffset(pos);
5456  maxsize = 2*maxsize;
5457  delete [] s;
5458  s = new char[maxsize];
5459  b.ReadString(s, maxsize); // Reads at most maxsize - 1 characters, plus null at end.
5460  }
5461 
5462  TClass *cl = TClass::GetClass(s, kTRUE);
5463  if (!cl)
5464  ::Error("TClass::Load", "dictionary of class %s not found", s);
5465 
5466  delete [] s;
5467  return cl;
5468 }
5469 
5470 ////////////////////////////////////////////////////////////////////////////////
5471 /// Helper function used by TClass::GetClass().
5472 /// This function attempts to load the dictionary for 'classname'
5473 /// either from the TClassTable or from the list of generator.
5474 /// If silent is 'true', do not warn about missing dictionary for the class.
5475 /// (typically used for class that are used only for transient members)
5476 ///
5477 /// The 'requestedname' is expected to be already normalized.
5478 
5479 TClass *TClass::LoadClass(const char *requestedname, Bool_t silent)
5480 {
5481  // This function does not (and should not) attempt to check in the
5482  // list of loaded classes or in the typedef.
5483 
5484  R__LOCKGUARD(gInterpreterMutex);
5485 
5486  TClass *result = LoadClassDefault(requestedname, silent);
5487 
5488  if (result) return result;
5489  else return LoadClassCustom(requestedname,silent);
5490 }
5491 
5492 ////////////////////////////////////////////////////////////////////////////////
5493 /// Helper function used by TClass::GetClass().
5494 /// This function attempts to load the dictionary for 'classname' from
5495 /// the TClassTable or the autoloader.
5496 /// If silent is 'true', do not warn about missing dictionary for the class.
5497 /// (typically used for class that are used only for transient members)
5498 ///
5499 /// The 'requestedname' is expected to be already normalized.
5500 
5501 TClass *TClass::LoadClassDefault(const char *requestedname, Bool_t /* silent */)
5502 {
5503  // This function does not (and should not) attempt to check in the
5504  // list of loaded classes or in the typedef.
5505 
5506  DictFuncPtr_t dict = TClassTable::GetDictNorm(requestedname);
5507 
5508  if (!dict) {
5509  if (gInterpreter->AutoLoad(requestedname,kTRUE)) {
5510  dict = TClassTable::GetDictNorm(requestedname);
5511  }
5512  }
5513 
5514  if (dict) {
5515  TClass *ncl = (dict)();
5516  if (ncl) ncl->PostLoadCheck();
5517  return ncl;
5518  }
5519  return 0;
5520 }
5521 
5522 ////////////////////////////////////////////////////////////////////////////////
5523 /// Helper function used by TClass::GetClass().
5524 /// This function attempts to load the dictionary for 'classname'
5525 /// from the list of generator.
5526 /// If silent is 'true', do not warn about missing dictionary for the class.
5527 /// (typically used for class that are used only for transient members)
5528 ///
5529 /// The 'requestedname' is expected to be already normalized.
5530 
5531 TClass *TClass::LoadClassCustom(const char *requestedname, Bool_t silent)
5532 {
5533  // This function does not (and should not) attempt to check in the
5534  // list of loaded classes or in the typedef.
5535 
5536  TIter next(gROOT->GetListOfClassGenerators());
5537  TClassGenerator *gen;
5538  while ((gen = (TClassGenerator*) next())) {
5539  TClass *cl = gen->GetClass(requestedname, kTRUE, silent);
5540  if (cl) {
5541  cl->PostLoadCheck();
5542  return cl;
5543  }
5544  }
5545  return 0;
5546 }
5547 
5548 ////////////////////////////////////////////////////////////////////////////////
5549 /// Try to load the ClassInfo if available. This function may require parsing
5550 /// the header file and/or loading data from the clang pcm. If further calls to
5551 /// this function cannot affect the value of fClassInfo, fCanLoadClassInfo is set
5552 /// to false.
5553 
5555 {
5556  R__LOCKGUARD(gInterpreterMutex);
5557 
5558  // Return if another thread already loaded the info
5559  // while we were waiting for the lock
5560  if (!fCanLoadClassInfo)
5561  return;
5562 
5563  bool autoParse = !gInterpreter->IsAutoParsingSuspended();
5564 
5565  if (autoParse)
5566  gInterpreter->AutoParse(GetName());
5567 
5568  if (!fClassInfo)
5569  gInterpreter->SetClassInfo(const_cast<TClass *>(this));
5570 
5571  if (autoParse && !fClassInfo) {
5572  if (fImplFileLine == -1 && fClassVersion == 0) {
5573  // We have a 'transient' class with a ClassDefInline and apparently no interpreter
5574  // information. Since it is transient, it is more than likely that the lack
5575  // will be harmles.
5576  } else {
5577  ::Error("TClass::LoadClassInfo", "no interpreter information for class %s is available"
5578  " even though it has a TClass initialization routine.",
5579  fName.Data());
5580  }
5581  return;
5582  }
5583 
5584  fCanLoadClassInfo = false;
5585 }
5586 
5587 ////////////////////////////////////////////////////////////////////////////////
5588 /// Store class description on I/O buffer.
5589 
5591 {
5592  b.WriteString(GetName());
5593 }
5594 
5595 ////////////////////////////////////////////////////////////////////////////////
5596 /// Global function called by a class' static Dictionary() method
5597 /// (see the ClassDef macro).
5598 
5599 TClass *ROOT::CreateClass(const char *cname, Version_t id,
5600  const std::type_info &info, TVirtualIsAProxy *isa,
5601  const char *dfil, const char *ifil,
5602  Int_t dl, Int_t il)
5603 {
5604  // When called via TMapFile (e.g. Update()) make sure that the dictionary
5605  // gets allocated on the heap and not in the mapped file.
5606  TMmallocDescTemp setreset;
5607  return new TClass(cname, id, info, isa, dfil, ifil, dl, il);
5608 }
5609 
5610 ////////////////////////////////////////////////////////////////////////////////
5611 /// Global function called by a class' static Dictionary() method
5612 /// (see the ClassDef macro).
5613 
5614 TClass *ROOT::CreateClass(const char *cname, Version_t id,
5615  const char *dfil, const char *ifil,
5616  Int_t dl, Int_t il)
5617 {
5618  // When called via TMapFile (e.g. Update()) make sure that the dictionary
5619  // gets allocated on the heap and not in the mapped file.
5620  TMmallocDescTemp setreset;
5621  return new TClass(cname, id, dfil, ifil, dl, il);
5622 }
5623 
5624 ////////////////////////////////////////////////////////////////////////////////
5625 /// Static method returning the defConstructor flag passed to TClass::New().
5626 /// New type is either:
5627 /// - TClass::kRealNew - when called via plain new
5628 /// - TClass::kClassNew - when called via TClass::New()
5629 /// - TClass::kDummyNew - when called via TClass::New() but object is a dummy,
5630 /// in which case the object ctor might take short cuts
5631 
5633 {
5634  return TClass__GetCallingNew();
5635 }
5636 
5637 ////////////////////////////////////////////////////////////////////////////////
5638 /// Return true if the shared library of this class is currently in the a
5639 /// process's memory. Return false, after the shared library has been
5640 /// unloaded or if this is an 'emulated' class created from a file's StreamerInfo.
5641 
5643 {
5644  return fState == kHasTClassInit;
5645 }
5646 
5647 ////////////////////////////////////////////////////////////////////////////////
5648 /// Returns true if this class inherits from TObject and if the start of
5649 /// the TObject parts is at the very beginning of the objects.
5650 /// Concretely this means that the following code is proper for this class:
5651 /// ~~~ {.cpp}
5652 /// ThisClass *ptr;
5653 /// void *void_ptr = (void)ptr;
5654 /// TObject *obj = (TObject*)void_ptr;
5655 /// ~~~
5656 /// This code would be wrong if 'ThisClass' did not inherit 'first' from
5657 /// TObject.
5658 
5660 {
5661  if (fProperty==(-1)) Property();
5662  return TestBit(kStartWithTObject);
5663 }
5664 
5665 ////////////////////////////////////////////////////////////////////////////////
5666 /// Return kTRUE is the class inherits from TObject.
5667 
5669 {
5670  if (fProperty==(-1)) Property();
5671  return TestBit(kIsTObject);
5672 }
5673 
5674 ////////////////////////////////////////////////////////////////////////////////
5675 /// Return kTRUE is the class is Foreign (the class does not have a Streamer method).
5676 
5678 {
5679  if (fProperty==(-1)) Property();
5680  return TestBit(kIsForeign);
5681 }
5682 
5683 ////////////////////////////////////////////////////////////////////////////////
5684 /// Do the initialization that can only be done after the CINT dictionary has
5685 /// been fully populated and can not be delayed efficiently.
5686 
5688 {
5689  // In the case of a Foreign class (loaded class without a Streamer function)
5690  // we reset fClassVersion to be -1 so that the current TVirtualStreamerInfo will not
5691  // be confused with a previously loaded streamerInfo.
5692 
5693  if (IsLoaded() && HasInterpreterInfo() && fClassVersion==1 /*&& fStreamerInfo
5694  && fStreamerInfo->At(1)*/ && IsForeign() )
5695  {
5696  SetClassVersion(-1);
5697  }
5698  // Note: We are careful to check the class version first because checking
5699  // for foreign can trigger an AutoParse.
5700  else if (IsLoaded() && HasDataMemberInfo() && fStreamerInfo && ((fClassVersion > 1) || !IsForeign()))
5701  {
5702  R__LOCKGUARD(gInterpreterMutex);
5703 
5705  // Here we need to check whether this TVirtualStreamerInfo (which presumably has been
5706  // loaded from a file) is consistent with the definition in the library we just loaded.
5707  // BuildCheck is not appropriate here since it check a streamerinfo against the
5708  // 'current streamerinfo' which, at time point, would be the same as 'info'!
5709  if (info && GetListOfDataMembers() && !GetCollectionProxy()
5710  && (info->GetCheckSum()!=GetCheckSum() && !info->CompareContent(this,0,kFALSE,kFALSE, 0) && !(MatchLegacyCheckSum(info->GetCheckSum()))))
5711  {
5712  Bool_t warn = ! TestBit(kWarned);
5713  if (warn && info->GetOldVersion()<=2) {
5714  // Names of STL base classes was modified in vers==3. Allocators removed
5715  //
5716  TIter nextBC(GetListOfBases());
5717  TBaseClass *bc;
5718  while ((bc=(TBaseClass*)nextBC()))
5719  {if (TClassEdit::IsSTLCont(bc->GetName())) warn = kFALSE;}
5720  }
5721 
5722  if (warn) {
5723  if (info->GetOnFileClassVersion()==1 && fClassVersion>1) {
5724  Warning("PostLoadCheck","\n\
5725  The class %s transitioned from not having a specified class version\n\
5726  to having a specified class version (the current class version is %d).\n\
5727  However too many different non-versioned layouts of the class have\n\
5728  already been loaded so far. To work around this problem you can\n\
5729  load fewer 'old' file in the same ROOT session or load the C++ library\n\
5730  describing the class %s before opening the files or increase the version\n\
5731  number of the class for example ClassDef(%s,%d).\n\
5732  Do not try to write objects with the current class definition,\n\
5733  the files might not be readable.\n",
5735  } else {
5736  Warning("PostLoadCheck","\n\
5737  The StreamerInfo version %d for the class %s which was read\n\
5738  from a file previously opened has the same version as the active class\n\
5739  but a different checksum. You should update the version to ClassDef(%s,%d).\n\
5740  Do not try to write objects with the current class definition,\n\
5741  the files will not be readable.\n"
5743  }
5744  info->CompareContent(this,0,kTRUE,kTRUE,0);
5745  SetBit(kWarned);
5746  }
5747  }
5748  }
5749 }
5750 
5751 ////////////////////////////////////////////////////////////////////////////////
5752 /// Set TObject::fBits and fStreamerType to cache information about the
5753 /// class. The bits are
5754 /// ~~~ {.cpp}
5755 /// kIsTObject : the class inherits from TObject
5756 /// kStartWithTObject: TObject is the left-most class in the inheritance tree
5757 /// kIsForeign : the class doe not have a Streamer method
5758 /// ~~~
5759 /// The value of fStreamerType are
5760 /// ~~~ {.cpp}
5761 /// kTObject : the class inherits from TObject
5762 /// kForeign : the class does not have a Streamer method
5763 /// kInstrumented: the class does have a Streamer method
5764 /// kExternal: the class has a free standing way of streaming itself
5765 /// kEmulatedStreamer: the class is missing its shared library.
5766 /// ~~~
5767 
5769 {
5770  // Check if we can return without taking the lock,
5771  // this is valid since fProperty is atomic and set as
5772  // the last operation before return.
5773  if (fProperty!=(-1)) return fProperty;
5774 
5775  R__LOCKGUARD(gInterpreterMutex);
5776 
5777  // Check if another thread set fProperty while we
5778  // were waiting.
5779  if (fProperty!=(-1)) return fProperty;
5780 
5781  // Avoid asking about the class when it is still building
5782  if (TestBit(kLoading)) return fProperty;
5783 
5784  // When called via TMapFile (e.g. Update()) make sure that the dictionary
5785  // gets allocated on the heap and not in the mapped file.
5786  TMmallocDescTemp setreset;
5787 
5788  TClass *kl = const_cast<TClass*>(this);
5789 
5792 
5793  if (InheritsFrom(TObject::Class())) {
5794  kl->SetBit(kIsTObject);
5795 
5796  // Is it DIRECT inheritance from TObject?
5798  if (delta==0) kl->SetBit(kStartWithTObject);
5799 
5800  kl->fStreamerType = kTObject;
5802  }
5803 
5804  if (HasInterpreterInfo()) {
5805 
5806  // This code used to use ClassInfo_Has|IsValidMethod but since v6
5807  // they return true if the routine is defined in the class or any of
5808  // its parent. We explicitly want to know whether the function is
5809  // defined locally.
5810  if (!const_cast<TClass*>(this)->GetClassMethodWithPrototype("Streamer","TBuffer&",kFALSE)) {
5811 
5812  kl->SetBit(kIsForeign);
5813  kl->fStreamerType = kForeign;
5815 
5816  } else if ( kl->fStreamerType == TClass::kDefault ) {
5817  if (kl->fConvStreamerFunc) {
5820  } else if (kl->fStreamerFunc) {
5823  } else {
5824  // We have an automatic streamer using the StreamerInfo .. no need to go through the
5825  // Streamer method function itself.
5828  }
5829  }
5830 
5831  if (fStreamer) {
5832  kl->fStreamerType = kExternal;
5834  }
5835 
5836  if (const_cast<TClass *>(this)->GetClassMethodWithPrototype("Hash", "", kTRUE)) {
5838  }
5839 
5840  if (GetClassInfo()) {
5841  // In the case where the TClass for one of ROOT's core class
5842  // (eg TClonesArray for map<int,TClonesArray*>) is requested
5843  // during the execution of rootcling, we could end up in a situation
5844  // where we should have the information (since TClonesArray has
5845  // a dictionary as part of libCore) but do not because the user
5846  // only include a forward declaration of TClonesArray and we do not
5847  // forcefully load the header file either (because the autoparsing
5848  // is intentionally disabled).
5850  // Must set this last since other threads may read fProperty
5851  // and think all test bits have been properly set.
5853  }
5854  } else {
5855 
5856  if (fStreamer) {
5857  kl->fStreamerType = kExternal;
5859  }
5860 
5862  kl->SetStreamerImpl();
5863  // fProperty was *not* set so that it can be forced to be recalculated
5864  // next time.
5865  return 0;
5866  }
5867 
5868  return fProperty;
5869 }
5870 
5871 ////////////////////////////////////////////////////////////////////////////////
5872 /// Internal routine to set calculate the class properties that can only be
5873 /// known at run-time, for example whether the Hash member function and the
5874 /// destructor are consistent.
5875 
5877 {
5878  // For now, no need to lock this routines as fRuntimeProperties is
5879  // the only atomic set here and this is done at the end
5880  // and there is no downside if the execution is done twice.
5881 
5882  // Note SetRuntimeProperties is set to const as it is technically
5883  // thread-safe.
5884 
5885  UChar_t properties = static_cast<UChar_t>(ERuntimeProperties::kSet);
5886 
5888  properties |= static_cast<UChar_t>(ERuntimeProperties::kConsistentHash);
5889 
5890  const_cast<TClass *>(this)->fRuntimeProperties = properties;
5891 }
5892 
5893 ////////////////////////////////////////////////////////////////////////////////
5894 /// Internal routine to set fStreamerImpl based on the value of
5895 /// fStreamerType.
5896 
5898 {
5899  switch (fStreamerType) {
5903  case kInstrumented: {
5907  break;
5908  }
5909 
5910  case kEmulatedStreamer: // intentional fall through
5911  case kForeign|kEmulatedStreamer: // intentional fall through
5916  default:
5917  Error("SetStreamerImpl","Unexpected value of fStreamerType: %d",fStreamerType);
5918  }
5919 }
5920 
5921 
5922 ////////////////////////////////////////////////////////////////////////////////
5923 /// Create the collection proxy object (and the streamer object) from
5924 /// using the information in the TCollectionProxyInfo.
5925 
5927 {
5928  R__LOCKGUARD(gInterpreterMutex);
5929 
5930  delete fCollectionProxy;
5931 
5932  // We can not use GetStreamerInfo() instead of TVirtualStreamerInfo::Factory()
5933  // because GetStreamerInfo call TStreamerInfo::Build which need to have fCollectionProxy
5934  // set correctly.
5935 
5937  fCollectionProxy = p;
5938 
5939  AdoptStreamer(TVirtualStreamerInfo::Factory()->GenExplicitClassStreamer(info,this));
5940 
5941  if (fCollectionProxy && !fSchemaRules) {
5942  // Numeric Collections have implicit conversions:
5944  }
5945  fCanSplit = -1;
5946 }
5947 
5948 ////////////////////////////////////////////////////////////////////////////////
5949 /// Change (i.e. set) the title of the TNamed.
5950 
5951 void TClass::SetContextMenuTitle(const char *title)
5952 {
5953  fContextMenuTitle = title;
5954 }
5955 
5956 ////////////////////////////////////////////////////////////////////////////////
5957 /// This function installs a global IsA function for this class.
5958 /// The global IsA function will be used if there is no local IsA function (fIsA)
5959 ///
5960 /// A global IsA function has the signature:
5961 ///
5962 /// ~~~ {.cpp}
5963 /// TClass *func( TClass *cl, const void *obj);
5964 /// ~~~
5965 ///
5966 /// 'cl' is a pointer to the TClass object that corresponds to the
5967 /// 'pointer type' used to retrieve the value 'obj'
5968 ///
5969 /// For example with:
5970 /// ~~~ {.cpp}
5971 /// TNamed * m = new TNamed("example","test");
5972 /// TObject* o = m
5973 /// ~~~
5974 /// and
5975 /// the global IsA function would be called with TObject::Class() as
5976 /// the first parameter and the exact numerical value in the pointer
5977 /// 'o'.
5978 ///
5979 /// In other word, inside the global IsA function. it is safe to C-style
5980 /// cast the value of 'obj' into a pointer to the class described by 'cl'.
5981 
5983 {
5984  fGlobalIsA = func;
5985 }
5986 
5987 ////////////////////////////////////////////////////////////////////////////////
5988 /// Call this method to indicate that the shared library containing this
5989 /// class's code has been removed (unloaded) from the process's memory
5990 
5992 {
5993  if (TestBit(kUnloaded) && !TestBit(kUnloading)) {
5994  // Don't redo the work.
5995  return;
5996  }
5997  SetBit(kUnloading);
5998 
5999  //R__ASSERT(fState == kLoaded);
6000  if (fState != kLoaded) {
6001  Fatal("SetUnloaded","The TClass for %s is being unloaded when in state %d\n",
6002  GetName(),(int)fState);
6003  }
6004 
6005  // Make sure SetClassInfo, re-calculated the state.
6007 
6008  delete fIsA; fIsA = 0;
6009  // Disable the autoloader while calling SetClassInfo, to prevent
6010  // the library from being reloaded!
6011  {
6012  int autoload_old = gCling->SetClassAutoloading(0);
6014 
6015  gInterpreter->SetClassInfo(this,kTRUE);
6016 
6017  gCling->SetClassAutoloading(autoload_old);
6018  }
6019  fDeclFileName = 0;
6020  fDeclFileLine = 0;
6021  fImplFileName = 0;
6022  fImplFileLine = 0;
6023  fTypeInfo = 0;
6024 
6025  if (fMethod.load()) {
6026  (*fMethod).Unload();
6027  }
6028  if (fData) {
6029  fData->Unload();
6030  }
6031  if (fEnums.load()) {
6032  (*fEnums).Unload();
6033  }
6034 
6035  if (fState <= kForwardDeclared && fStreamerInfo->GetEntries() != 0) {
6036  fState = kEmulated;
6037  }
6038 
6040  SetBit(kUnloaded);
6041 }
6042 
6043 ////////////////////////////////////////////////////////////////////////////////
6044 /// Info is a string describing the names and types of attributes
6045 /// written by the class Streamer function.
6046 /// If info is an empty string (when called by TObject::StreamerInfo)
6047 /// the default Streamer info string is build. This corresponds to
6048 /// the case of an automatically generated Streamer.
6049 /// In case of user defined Streamer function, it is the user responsibility
6050 /// to implement a StreamerInfo function (override TObject::StreamerInfo).
6051 /// The user must call IsA()->SetStreamerInfo(info) from this function.
6052 
6053 TVirtualStreamerInfo *TClass::SetStreamerInfo(Int_t /*version*/, const char * /*info*/)
6054 {
6055  // info is specified, nothing to do, except that we should verify
6056  // that it contains a valid descriptor.
6057 
6058 /*
6059  TDataMember *dm;
6060  Int_t nch = strlen(info);
6061  Bool_t update = kTRUE;
6062  if (nch != 0) {
6063  //decode strings like "TObject;TAttLine;fA;fB;Int_t i,j,k;"
6064  char *save, *temp, *blank, *colon, *comma;
6065  save = new char[10000];
6066  temp = save;
6067  strlcpy(temp,info,10000);
6068  //remove heading and trailing blanks
6069  while (*temp == ' ') temp++;
6070  while (save[nch-1] == ' ') {nch--; save[nch] = 0;}
6071  if (nch == 0) {delete [] save; return;}
6072  if (save[nch-1] != ';') {save[nch] = ';'; save[nch+1] = 0;}
6073  //remove blanks around , or ;
6074  while ((blank = strstr(temp,"; "))) strcpy(blank+1,blank+2);
6075  while ((blank = strstr(temp," ;"))) strcpy(blank, blank+1);
6076  while ((blank = strstr(temp,", "))) strcpy(blank+1,blank+2);
6077  while ((blank = strstr(temp," ,"))) strcpy(blank, blank+1);
6078  while ((blank = strstr(temp," "))) strcpy(blank, blank+1);
6079  //loop on tokens separated by ;
6080  char *final = new char[1000];
6081  char token[100];
6082  while ((colon=strchr(temp,';'))) {
6083  *colon = 0;
6084  strlcpy(token,temp,100);
6085  blank = strchr(token,' ');
6086  if (blank) {
6087  *blank = 0;
6088  if (!gROOT->GetType(token)) {
6089  Error("SetStreamerInfo","Illegal type: %s in %s",token,info);
6090  return;
6091  }
6092  while (blank) {
6093  strlcat(final,token,1000);
6094  strlcat(final," ",1000);
6095  comma = strchr(blank+1,','); if (comma) *comma=0;
6096  strlcat(final,blank+1,1000);
6097  strlcat(final,";",1000);
6098  blank = comma;
6099  }
6100 
6101  } else {
6102  if (TClass::GetClass(token,update)) {
6103  //a class name
6104  strlcat(final,token,1000); strlcat(final,";",1000);
6105  } else {
6106  //a data member name
6107  dm = (TDataMember*)GetListOfDataMembers()->FindObject(token);
6108  if (dm) {
6109  strlcat(final,dm->GetFullTypeName(),1000);
6110  strlcat(final," ",1000);
6111  strlcat(final,token,1000); strlcat(final,";",1000);
6112  } else {
6113  Error("SetStreamerInfo","Illegal name: %s in %s",token,info);
6114  return;
6115  }
6116  }
6117  update = kFALSE;
6118  }
6119  temp = colon+1;
6120  if (*temp == 0) break;
6121  }
6122  //// fStreamerInfo = final;
6123  delete [] final;
6124  delete [] save;
6125  return;
6126  }
6127 
6128  //info is empty. Let's build the default Streamer descriptor
6129 
6130  char *temp = new char[10000];
6131  temp[0] = 0;
6132  char local[100];
6133 
6134  //add list of base classes
6135  TIter nextb(GetListOfBases());
6136  TBaseClass *base;
6137  while ((base = (TBaseClass*) nextb())) {
6138  snprintf(local,100,"%s;",base->GetName());
6139  strlcat(temp,local,10000);
6140  }
6141 
6142  //add list of data members and types
6143  TIter nextd(GetListOfDataMembers());
6144  while ((dm = (TDataMember *) nextd())) {
6145  if (dm->IsEnum()) continue;
6146  if (!dm->IsPersistent()) continue;
6147  Long_t property = dm->Property();
6148  if (property & kIsStatic) continue;
6149  TClass *acl = TClass::GetClass(dm->GetTypeName(),update);
6150  update = kFALSE;
6151  if (acl) {
6152  if (acl->GetClassVersion() == 0) continue;
6153  }
6154 
6155  // dm->GetArrayIndex() returns an empty string if it does not
6156  // applies
6157  const char * index = dm->GetArrayIndex();
6158  if (strlen(index)==0)
6159  snprintf(local,100,"%s %s;",dm->GetFullTypeName(),dm->GetName());
6160  else
6161  snprintf(local,100,"%s %s[%s];",dm->GetFullTypeName(),dm->GetName(),index);
6162  strlcat(temp,local,10000);
6163  }
6164  //fStreamerInfo = temp;
6165  delete [] temp;
6166 */
6167  return 0;
6168 }
6169 
6170 ////////////////////////////////////////////////////////////////////////////////
6171 /// Return true if the checksum passed as argument is one of the checksum
6172 /// value produced by the older checksum calculation algorithm.
6173 
6175 {
6176  for(UInt_t i = 1; i < kLatestCheckSum; ++i) {
6177  if ( checksum == GetCheckSum( (ECheckSum) i ) ) return kTRUE;
6178  }
6179  return kFALSE;
6180 }
6181 
6182 ////////////////////////////////////////////////////////////////////////////////
6183 /// Call GetCheckSum with validity check.
6184 
6186 {
6187  bool isvalid;
6188  return GetCheckSum(code,isvalid);
6189 }
6190 
6191 ////////////////////////////////////////////////////////////////////////////////
6192 /// Return GetCheckSum(kCurrentCheckSum,isvalid);
6193 
6195 {
6196  return GetCheckSum(kCurrentCheckSum,isvalid);
6197 }
6198 
6199 ////////////////////////////////////////////////////////////////////////////////
6200 /// Compute and/or return the class check sum.
6201 ///
6202 /// isvalid is set to false, if the function is unable to calculate the
6203 /// checksum.
6204 ///
6205 /// The class ckecksum is used by the automatic schema evolution algorithm
6206 /// to uniquely identify a class version.
6207 /// The check sum is built from the names/types of base classes and
6208 /// data members.
6209 /// Original algorithm from Victor Perevovchikov (perev@bnl.gov).
6210 ///
6211 /// The valid range of code is determined by ECheckSum.
6212 ///
6213 /// - kNoEnum: data members of type enum are not counted in the checksum
6214 /// - kNoRange: return the checksum of data members and base classes, not including the ranges and array size found in comments.
6215 /// - kWithTypeDef: use the sugared type name in the calculation.
6216 ///
6217 /// This is needed for backward compatibility.
6218 ///
6219 /// WARNING: this function must be kept in sync with TStreamerInfo::GetCheckSum.
6220 /// They are both used to handle backward compatibility and should both return the same values.
6221 /// TStreamerInfo uses the information in TStreamerElement while TClass uses the information
6222 /// from TClass::GetListOfBases and TClass::GetListOfDataMembers.
6223 
6225 {
6226  // fCheckSum is an atomic variable. Also once it has
6227  // transition from a zero Value it never changes. If two
6228  // thread reach past this if statement and calculated the
6229  // 'kLastestCheckSum', they will by definition obtain the
6230  // same value, so technically we could simply have:
6231  // if (fCheckSum && code == kCurrentCheckSum) return fCheckSum;
6232  // However save a little bit of barrier time by calling load()
6233  // only once.
6234 
6235  isvalid = kTRUE;
6236 
6237  UInt_t currentChecksum = fCheckSum.load();
6238  if (currentChecksum && code == kCurrentCheckSum) return currentChecksum;
6239 
6240  R__LOCKGUARD(gInterpreterMutex);
6241 
6242  // kCurrentCheckSum (0) is the default parameter value and should be kept
6243  // for backward compatibility, too be able to use the inequality checks,
6244  // we need to set the code to the largest value.
6245  if (code == kCurrentCheckSum) code = kLatestCheckSum;
6246 
6247  UInt_t id = 0;
6248 
6249  int il;
6250  TString name = GetName();
6251  TString type;
6252  il = name.Length();
6253  for (int i=0; i<il; i++) id = id*3+name[i];
6254 
6255  TList *tlb = ((TClass*)this)->GetListOfBases();
6256  if (tlb && !GetCollectionProxy()) { // Loop over bases if not a proxied collection
6257 
6258  TIter nextBase(tlb);
6259 
6260  TBaseClass *tbc=0;
6261  while((tbc=(TBaseClass*)nextBase())) {
6262  name = tbc->GetName();
6263  Bool_t isSTL = TClassEdit::IsSTLCont(name);
6264  if (isSTL)
6266  il = name.Length();
6267  for (int i=0; i<il; i++) id = id*3+name[i];
6268  if (code > kNoBaseCheckSum && !isSTL) {
6269  if (tbc->GetClassPointer() == 0) {
6270  Error("GetCheckSum","Calculating the checksum for (%s) requires the base class (%s) meta information to be available!",
6271  GetName(),tbc->GetName());
6272  isvalid = kFALSE;
6273  return 0;
6274  } else
6275  id = id*3 + tbc->GetClassPointer()->GetCheckSum();
6276  }
6277  }/*EndBaseLoop*/
6278  }
6279  TList *tlm = ((TClass*)this)->GetListOfDataMembers();
6280  if (tlm) { // Loop over members
6281  TIter nextMemb(tlm);
6282  TDataMember *tdm=0;
6283  Long_t prop = 0;
6284  while((tdm=(TDataMember*)nextMemb())) {
6285  if (!tdm->IsPersistent()) continue;
6286  // combine properties
6287  prop = (tdm->Property());
6288  TDataType* tdt = tdm->GetDataType();
6289  if (tdt) prop |= tdt->Property();
6290 
6291  if ( prop&kIsStatic) continue;
6292  name = tdm->GetName(); il = name.Length();
6293  if ( (code > kNoEnum) && code != kReflex && code != kReflexNoComment && prop&kIsEnum)
6294  id = id*3 + 1;
6295 
6296  int i;
6297  for (i=0; i<il; i++) id = id*3+name[i];
6298 
6299  if (code > kWithTypeDef || code == kReflexNoComment) {
6300  type = tdm->GetTrueTypeName();
6301  // GetTrueTypeName uses GetFullyQualifiedName which already drops
6302  // the default template parameter, so we no longer need to do this.
6303  //if (TClassEdit::IsSTLCont(type))
6304  // type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
6305  if (code == kReflex || code == kReflexNoComment) {
6306  if (prop&kIsEnum) {
6307  type = "int";
6308  } else {
6309  type.ReplaceAll("ULong64_t","unsigned long long");
6310  type.ReplaceAll("Long64_t","long long");
6311  type.ReplaceAll("<signed char","<char");
6312  type.ReplaceAll(",signed char",",char");
6313  if (type=="signed char") type = "char";
6314  }
6315  }
6316  } else {
6317  type = tdm->GetFullTypeName();
6318  // GetFullTypeName uses GetFullyQualifiedName which already drops
6319  // the default template parameter, so we no longer need to do this.
6320  //if (TClassEdit::IsSTLCont(type))
6321  // type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
6322  }
6323 
6324  il = type.Length();
6325  for (i=0; i<il; i++) id = id*3+type[i];
6326 
6327  int dim = tdm->GetArrayDim();
6328  if (prop&kIsArray) {
6329  for (int ii=0;ii<dim;ii++) id = id*3+tdm->GetMaxIndex(ii);
6330  }
6331  if (code > kNoRange) {
6332  const char *left;
6333  if (code > TClass::kNoRangeCheck)
6335  else
6336  left = strstr(tdm->GetTitle(),"[");
6337  if (left) {
6338  const char *right = strstr(left,"]");
6339  if (right) {
6340  ++left;
6341  while (left != right) {
6342  id = id*3 + *left;
6343  ++left;
6344  }
6345  }
6346  }
6347  }
6348  }/*EndMembLoop*/
6349  }
6350  // This should be moved to Initialization time however the last time
6351  // we tried this cause problem, in particular in the end-of-process operation.
6352  if (code==kLatestCheckSum) fCheckSum = id;
6353  return id;
6354 }
6355 
6356 ////////////////////////////////////////////////////////////////////////////////
6357 /// Adopt the Reference proxy pointer to indicate that this class
6358 /// represents a reference.
6359 /// When a new proxy is adopted, the old one is deleted.
6360 
6362 {
6363  R__LOCKGUARD(gInterpreterMutex);
6364 
6365  if ( fRefProxy ) {
6366  fRefProxy->Release();
6367  }
6368  fRefProxy = proxy;
6369  if ( fRefProxy ) {
6370  fRefProxy->SetClass(this);
6371  }
6372  fCanSplit = -1;
6373 }
6374 
6375 ////////////////////////////////////////////////////////////////////////////////
6376 /// Adopt the TMemberStreamer pointer to by p and use it to Stream non basic
6377 /// member name.
6378 
6380 {
6381  if (!fRealData) return;
6382 
6383  R__LOCKGUARD(gInterpreterMutex);
6384 
6385  TIter next(fRealData);
6386  TRealData *rd;
6387  while ((rd = (TRealData*)next())) {
6388  if (strcmp(rd->GetName(),name) == 0) {
6389  // If there is a TStreamerElement that took a pointer to the
6390  // streamer we should inform it!
6391  rd->AdoptStreamer(p);
6392  break;
6393  }
6394  }
6395 
6396 // NOTE: This alternative was proposed but not is not used for now,
6397 // One of the major difference with the code above is that the code below
6398 // did not require the RealData to have been built
6399 // if (!fData) return;
6400 // const char *n = name;
6401 // while (*n=='*') n++;
6402 // TString ts(n);
6403 // int i = ts.Index("[");
6404 // if (i>=0) ts.Remove(i,999);
6405 // TDataMember *dm = (TDataMember*)fData->FindObject(ts.Data());
6406 // if (!dm) {
6407 // Warning("SetStreamer","Can not find member %s::%s",GetName(),name);
6408 // return;
6409 // }
6410 // dm->SetStreamer(p);
6411  return;
6412 }
6413 
6414 ////////////////////////////////////////////////////////////////////////////////
6415 /// Install a new member streamer (p will be copied).
6416 
6418 {
6419  AdoptMemberStreamer(name,new TMemberStreamer(p));
6420 }
6421 
6422 ////////////////////////////////////////////////////////////////////////////////
6423 /// Function called by the Streamer functions to deserialize information
6424 /// from buffer b into object at p.
6425 /// This function assumes that the class version and the byte count information
6426 /// have been read.
6427 /// - version is the version number of the class
6428 /// - start is the starting position in the buffer b
6429 /// - count is the number of bytes for this object in the buffer
6430 
6431 Int_t TClass::ReadBuffer(TBuffer &b, void *pointer, Int_t version, UInt_t start, UInt_t count)
6432 {
6433  return b.ReadClassBuffer(this,pointer,version,start,count);
6434 }
6435 
6436 ////////////////////////////////////////////////////////////////////////////////
6437 /// Function called by the Streamer functions to deserialize information
6438 /// from buffer b into object at p.
6439 
6441 {
6442  return b.ReadClassBuffer(this,pointer);
6443 }
6444 
6445 ////////////////////////////////////////////////////////////////////////////////
6446 /// Function called by the Streamer functions to serialize object at p
6447 /// to buffer b. The optional argument info may be specified to give an
6448 /// alternative StreamerInfo instead of using the default StreamerInfo
6449 /// automatically built from the class definition.
6450 /// For more information, see class TVirtualStreamerInfo.
6451 
6452 Int_t TClass::WriteBuffer(TBuffer &b, void *pointer, const char * /*info*/)
6453 {
6454  b.WriteClassBuffer(this,pointer);
6455  return 0;
6456 }
6457 
6458 ////////////////////////////////////////////////////////////////////////////////
6459 ///There is special streamer for the class
6460 
6461 void TClass::StreamerExternal(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6462 {
6463  // case kExternal:
6464  // case kExternal|kEmulatedStreamer:
6465 
6466  TClassStreamer *streamer = gThreadTsd ? pThis->GetStreamer() : pThis->fStreamer;
6467  streamer->Stream(b,object,onfile_class);
6468 }
6469 
6470 ////////////////////////////////////////////////////////////////////////////////
6471 /// Case of TObjects
6472 
6473 void TClass::StreamerTObject(const TClass* pThis, void *object, TBuffer &b, const TClass * /* onfile_class */)
6474 {
6475  // case kTObject:
6476 
6477  if (!pThis->fIsOffsetStreamerSet) {
6478  pThis->CalculateStreamerOffset();
6479  }
6480  TObject *tobj = (TObject*)((Long_t)object + pThis->fOffsetStreamer);
6481  tobj->Streamer(b);
6482 }
6483 
6484 ////////////////////////////////////////////////////////////////////////////////
6485 /// Case of TObjects when fIsOffsetStreamerSet is known to have been set.
6486 
6487 void TClass::StreamerTObjectInitialized(const TClass* pThis, void *object, TBuffer &b, const TClass * /* onfile_class */)
6488 {
6489  TObject *tobj = (TObject*)((Long_t)object + pThis->fOffsetStreamer);
6490  tobj->Streamer(b);
6491 }
6492 
6493 ////////////////////////////////////////////////////////////////////////////////
6494 /// Case of TObjects when we do not have the library defining the class.
6495 
6496 void TClass::StreamerTObjectEmulated(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6497 {
6498  // case kTObject|kEmulatedStreamer :
6499  if (b.IsReading()) {
6500  b.ReadClassEmulated(pThis, object, onfile_class);
6501  } else {
6502  b.WriteClassBuffer(pThis, object);
6503  }
6504 }
6505 
6506 ////////////////////////////////////////////////////////////////////////////////
6507 /// Case of instrumented class with a library
6508 
6509 void TClass::StreamerInstrumented(const TClass* pThis, void *object, TBuffer &b, const TClass * /* onfile_class */)
6510 {
6511  // case kInstrumented:
6512  pThis->fStreamerFunc(b,object);
6513 }
6514 
6515 ////////////////////////////////////////////////////////////////////////////////
6516 /// Case of instrumented class with a library
6517 
6518 void TClass::ConvStreamerInstrumented(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6519 {
6520  // case kInstrumented:
6521  pThis->fConvStreamerFunc(b,object,onfile_class);
6522 }
6523 
6524 ////////////////////////////////////////////////////////////////////////////////
6525 /// Case of where we should directly use the StreamerInfo.
6526 /// - case kForeign:
6527 /// - case kForeign|kEmulatedStreamer:
6528 /// - case kInstrumented|kEmulatedStreamer:
6529 /// - case kEmulatedStreamer:
6530 
6531 void TClass::StreamerStreamerInfo(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6532 {
6533  if (b.IsReading()) {
6534  b.ReadClassBuffer(pThis, object, onfile_class);
6535  //ReadBuffer (b, object);
6536  } else {
6537  //WriteBuffer(b, object);
6538  b.WriteClassBuffer(pThis, object);
6539  }
6540 }
6541 
6542 ////////////////////////////////////////////////////////////////////////////////
6543 /// Default streaming in cases where either we have no way to know what to do
6544 /// or if Property() has not yet been called.
6545 
6546 void TClass::StreamerDefault(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
6547 {
6548  if (pThis->fProperty==(-1)) {
6549  pThis->Property();
6550  }
6551 
6552  // We could get here because after this thread started StreamerDefault
6553  // *and* before check fProperty, another thread might have call Property
6554  // and this fProperty when we read it, is not -1 and fStreamerImpl is
6555  // supposed to be set properly (no longer pointing to the default).
6556  if (pThis->fStreamerImpl.load() == &TClass::StreamerDefault) {
6557  pThis->Fatal("StreamerDefault", "fStreamerImpl not properly initialized (%d)", pThis->fStreamerType);
6558  } else {
6559  (*pThis->fStreamerImpl)(pThis,object,b,onfile_class);
6560  }
6561 }
6562 
6563 ////////////////////////////////////////////////////////////////////////////////
6564 /// Adopt a TClassStreamer object. Ownership is transfered to this TClass
6565 /// object.
6566 
6568 {
6569 // // This code can be used to quickly test the STL Emulation layer
6570 // Int_t k = TClassEdit::IsSTLCont(GetName());
6571 // if (k==1||k==-1) { delete str; return; }
6572 
6573  R__LOCKGUARD(gInterpreterMutex);
6574 
6575  if (fStreamer) delete fStreamer;
6576  if (str) {
6578  fStreamer = str;
6580  } else if (fStreamer) {
6581  // Case where there was a custom streamer and it is hereby removed,
6582  // we need to reset fStreamerType
6583  fStreamer = str;
6585  if (fProperty != -1) {
6586  fProperty = -1;
6587  Property();
6588  }
6589  }
6590 }
6591 
6592 ////////////////////////////////////////////////////////////////////////////////
6593 /// Set a wrapper/accessor function around this class custom streamer.
6594 
6596 {
6597  R__LOCKGUARD(gInterpreterMutex);
6598  if (fProperty != -1 && !fConvStreamerFunc &&
6599  ( (fStreamerFunc == 0 && strm != 0) || (fStreamerFunc != 0 && strm == 0) ) )
6600  {
6601  fStreamerFunc = strm;
6602 
6603  // Since initialization has already been done, make sure to tweak it
6604  // for the new state.
6608  }
6609  } else {
6610  fStreamerFunc = strm;
6611  }
6612  fCanSplit = -1;
6613 }
6614 
6615 ////////////////////////////////////////////////////////////////////////////////
6616 /// Set a wrapper/accessor function around this class custom conversion streamer.
6617 
6619 {
6620  R__LOCKGUARD(gInterpreterMutex);
6621  if (fProperty != -1 &&
6622  ( (fConvStreamerFunc == 0 && strm != 0) || (fConvStreamerFunc != 0 && strm == 0) ) )
6623  {
6624  fConvStreamerFunc = strm;
6625 
6626  // Since initialization has already been done, make sure to tweak it
6627  // for the new state.
6631  }
6632  } else {
6633  fConvStreamerFunc = strm;
6634  }
6635  fCanSplit = -1;
6636 }
6637 
6638 
6639 ////////////////////////////////////////////////////////////////////////////////
6640 /// Install a new wrapper around 'Merge'.
6641 
6643 {
6644  fMerge = newMerge;
6645 }
6646 
6647 ////////////////////////////////////////////////////////////////////////////////
6648 /// Install a new wrapper around 'ResetAfterMerge'.
6649 
6651 {
6652  fResetAfterMerge = newReset;
6653 }
6654 
6655 ////////////////////////////////////////////////////////////////////////////////
6656 /// Install a new wrapper around 'new'.
6657 
6659 {
6660  fNew = newFunc;
6661 }
6662 
6663 ////////////////////////////////////////////////////////////////////////////////
6664 /// Install a new wrapper around 'new []'.
6665 
6667 {
6668  fNewArray = newArrayFunc;
6669 }
6670 
6671 ////////////////////////////////////////////////////////////////////////////////
6672 /// Install a new wrapper around 'delete'.
6673 
6675 {
6676  fDelete = deleteFunc;
6677 }
6678 
6679 ////////////////////////////////////////////////////////////////////////////////
6680 /// Install a new wrapper around 'delete []'.
6681 
6683 {
6684  fDeleteArray = deleteArrayFunc;
6685 }
6686 
6687 ////////////////////////////////////////////////////////////////////////////////
6688 /// Install a new wrapper around the destructor.
6689 
6691 {
6692  fDestructor = destructorFunc;
6693 }
6694 
6695 ////////////////////////////////////////////////////////////////////////////////
6696 /// Install a new wrapper around the directory auto add function..
6697 /// The function autoAddFunc has the signature void (*)(void *obj, TDirectory dir)
6698 /// and should register 'obj' to the directory if dir is not null
6699 /// and unregister 'obj' from its current directory if dir is null
6700 
6702 {
6703  fDirAutoAdd = autoAddFunc;
6704 }
6705 
6706 ////////////////////////////////////////////////////////////////////////////////
6707 /// Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum
6708 
6710 {
6712  if (guess && guess->GetCheckSum() == checksum) {
6713  return guess;
6714  } else {
6715  if (fCheckSum == checksum) return GetStreamerInfo();
6716 
6717  R__LOCKGUARD(gInterpreterMutex);
6718  Int_t ninfos = fStreamerInfo->GetEntriesFast()-1;
6719  for (Int_t i=-1;i<ninfos;++i) {
6720  // TClass::fStreamerInfos has a lower bound not equal to 0,
6721  // so we have to use At and should not use UncheckedAt
6723  if (info && info->GetCheckSum() == checksum) {
6724  // R__ASSERT(i==info->GetClassVersion() || (i==-1&&info->GetClassVersion()==1));
6725  info->BuildOld();
6726  if (info->IsCompiled()) fLastReadInfo = info;
6727  return info;
6728  }
6729  }
6730  return 0;
6731  }
6732 }
6733 
6734 ////////////////////////////////////////////////////////////////////////////////
6735 /// Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum
6736 
6738 {
6739  R__LOCKGUARD(gInterpreterMutex);
6740  Int_t ninfos = arr->GetEntriesFast()-1;
6741  for (Int_t i=-1;i<ninfos;i++) {
6742  // TClass::fStreamerInfos has a lower bound not equal to 0,
6743  // so we have to use At and should not use UncheckedAt
6745  if (!info) continue;
6746  if (info->GetCheckSum() == checksum) {
6747  R__ASSERT(i==info->GetClassVersion() || (i==-1&&info->GetClassVersion()==1));
6748  return info;
6749  }
6750  }
6751  return 0;
6752 }
6753 
6754 ////////////////////////////////////////////////////////////////////////////////
6755 /// Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this class, if any.
6756 
6757 TVirtualStreamerInfo *TClass::GetConversionStreamerInfo( const char* classname, Int_t version ) const
6758 {
6759  TClass *cl = TClass::GetClass( classname );
6760  if( !cl )
6761  return 0;
6762  return GetConversionStreamerInfo( cl, version );
6763 }
6764 
6765 ////////////////////////////////////////////////////////////////////////////////
6766 /// Return a Conversion StreamerInfo from the class represented by cl for version number 'version' to this class, if any.
6767 
6769 {
6770  //----------------------------------------------------------------------------
6771  // Check if the classname was specified correctly
6772  /////////////////////////////////////////////////////////////////////////////
6773 
6774  if( !cl )
6775  return 0;
6776 
6777  if( cl == this )
6778  return GetStreamerInfo( version );
6779 
6780  //----------------------------------------------------------------------------
6781  // Check if we already have it
6782  /////////////////////////////////////////////////////////////////////////////
6783 
6784  TObjArray* arr = 0;
6785  if (fConversionStreamerInfo.load()) {
6786  std::map<std::string, TObjArray*>::iterator it;
6787  R__LOCKGUARD(gInterpreterMutex);
6788 
6789  it = (*fConversionStreamerInfo).find( cl->GetName() );
6790 
6791  if( it != (*fConversionStreamerInfo).end() ) {
6792  arr = it->second;
6793  }
6794 
6795  if( arr && version > -1 && version < arr->GetSize() && arr->At( version ) )
6796  return (TVirtualStreamerInfo*) arr->At( version );
6797  }
6798 
6799  R__LOCKGUARD(gInterpreterMutex);
6800 
6801  //----------------------------------------------------------------------------
6802  // We don't have the streamer info so find it in other class
6803  /////////////////////////////////////////////////////////////////////////////
6804 
6805  const TObjArray *clSI = cl->GetStreamerInfos();
6806  TVirtualStreamerInfo* info = 0;
6807  if( version >= -1 && version < clSI->GetSize() )
6808  info = (TVirtualStreamerInfo*)clSI->At( version );
6809 
6810  if (!info && cl->GetCollectionProxy()) {
6811  info = cl->GetStreamerInfo(); // instantiate the StreamerInfo for STL collections.
6812  }
6813 
6814  if( !info )
6815  return 0;
6816 
6817  //----------------------------------------------------------------------------
6818  // We have the right info so we need to clone it to create new object with
6819  // non artificial streamer elements and we should build it for current class
6820  /////////////////////////////////////////////////////////////////////////////
6821 
6822  info = (TVirtualStreamerInfo*)info->Clone();
6823 
6824  if( !info->BuildFor( this ) ) {
6825  delete info;
6826  return 0;
6827  }
6828 
6829  if (!info->IsCompiled()) {
6830  // Streamer info has not been compiled, but exists.
6831  // Therefore it was read in from a file and we have to do schema evolution?
6832  // Or it didn't have a dictionary before, but does now?
6833  info->BuildOld();
6834  }
6835 
6836  //----------------------------------------------------------------------------
6837  // Cache this streamer info
6838  /////////////////////////////////////////////////////////////////////////////
6839 
6840  if (!arr) {
6841  arr = new TObjArray(version+10, -1);
6842  if (!fConversionStreamerInfo.load()) {
6843  fConversionStreamerInfo = new std::map<std::string, TObjArray*>();
6844  }
6845  (*fConversionStreamerInfo)[cl->GetName()] = arr;
6846  }
6847  arr->AddAtAndExpand( info, info->GetClassVersion() );
6848  return info;
6849 }
6850 
6851 ////////////////////////////////////////////////////////////////////////////////
6852 /// Return a Conversion StreamerInfo from the class 'classname' for the layout represented by 'checksum' to this class, if any.
6853 
6854 TVirtualStreamerInfo *TClass::FindConversionStreamerInfo( const char* classname, UInt_t checksum ) const
6855 {
6856  TClass *cl = TClass::GetClass( classname );
6857  if( !cl )
6858  return 0;
6859  return FindConversionStreamerInfo( cl, checksum );
6860 }
6861 
6862 ////////////////////////////////////////////////////////////////////////////////
6863 /// Return a Conversion StreamerInfo from the class represented by cl for the layout represented by 'checksum' to this class, if any.
6864 
6866 {
6867  //---------------------------------------------------------------------------
6868  // Check if the classname was specified correctly
6869  /////////////////////////////////////////////////////////////////////////////
6870 
6871  if( !cl )
6872  return 0;
6873 
6874  if( cl == this )
6875  return FindStreamerInfo( checksum );
6876 
6877  //----------------------------------------------------------------------------
6878  // Check if we already have it
6879  /////////////////////////////////////////////////////////////////////////////
6880 
6881  TObjArray* arr = 0;
6882  TVirtualStreamerInfo* info = 0;
6883  if (fConversionStreamerInfo.load()) {
6884  std::map<std::string, TObjArray*>::iterator it;
6885 
6886  R__LOCKGUARD(gInterpreterMutex);
6887 
6888  it = (*fConversionStreamerInfo).find( cl->GetName() );
6889 
6890  if( it != (*fConversionStreamerInfo).end() ) {
6891  arr = it->second;
6892  }
6893  if (arr) {
6894  info = FindStreamerInfo( arr, checksum );
6895  }
6896  }
6897 
6898  if( info )
6899  return info;
6900 
6901  R__LOCKGUARD(gInterpreterMutex);
6902 
6903  //----------------------------------------------------------------------------
6904  // Get it from the foreign class
6905  /////////////////////////////////////////////////////////////////////////////
6906 
6907  info = cl->FindStreamerInfo( checksum );
6908 
6909  if( !info )
6910  return 0;
6911 
6912  //----------------------------------------------------------------------------
6913  // We have the right info so we need to clone it to create new object with
6914  // non artificial streamer elements and we should build it for current class
6915  /////////////////////////////////////////////////////////////////////////////
6916 
6917  info = (TVirtualStreamerInfo*)info->Clone();
6918  if( !info->BuildFor( this ) ) {
6919  delete info;
6920  return 0;
6921  }
6922 
6923  if (!info->IsCompiled()) {
6924  // Streamer info has not been compiled, but exists.
6925  // Therefore it was read in from a file and we have to do schema evolution?
6926  // Or it didn't have a dictionary before, but does now?
6927  info->BuildOld();
6928  }
6929 
6930  //----------------------------------------------------------------------------
6931  // Cache this streamer info
6932  /////////////////////////////////////////////////////////////////////////////
6933 
6934  if (!arr) {
6935  arr = new TObjArray(16, -2);
6936  if (!fConversionStreamerInfo.load()) {
6937  fConversionStreamerInfo = new std::map<std::string, TObjArray*>();
6938  }
6939  (*fConversionStreamerInfo)[cl->GetName()] = arr;
6940  }
6941  arr->AddAtAndExpand( info, info->GetClassVersion() );
6942 
6943  return info;
6944 }
6945 
6946 ////////////////////////////////////////////////////////////////////////////////
6947 /// Register the StreamerInfo in the given slot, change the State of the
6948 /// TClass as appropriate.
6949 
6951 {
6952  if (info) {
6953  R__LOCKGUARD(gInterpreterMutex);
6954  Int_t slot = info->GetClassVersion();
6955  if (fStreamerInfo->GetSize() > (slot-fStreamerInfo->LowerBound())
6956  && fStreamerInfo->At(slot) != 0
6957  && fStreamerInfo->At(slot) != info) {
6958  Error("RegisterStreamerInfo",
6959  "Register StreamerInfo for %s on non-empty slot (%d).",
6960  GetName(),slot);
6961  }
6962  fStreamerInfo->AddAtAndExpand(info, slot);
6963  if (fState <= kForwardDeclared) {
6964  fState = kEmulated;
6965  if (fCheckSum==0 && slot==fClassVersion) fCheckSum = info->GetCheckSum();
6966  }
6967  }
6968 }
6969 
6970 ////////////////////////////////////////////////////////////////////////////////
6971 /// Remove and delete the StreamerInfo in the given slot.
6972 /// Update the slot accordingly.
6973 
6975 {
6976  if (fStreamerInfo->GetSize() >= slot) {
6977  R__LOCKGUARD(gInterpreterMutex);
6980  delete info;
6981  if (fState == kEmulated && fStreamerInfo->GetEntries() == 0) {
6983  }
6984  }
6985 }
6986 
6987 ////////////////////////////////////////////////////////////////////////////////
6988 /// Return true is the Hash/RecursiveRemove setup is consistent, i.e. when all
6989 /// classes in the class hierarchy that overload TObject::Hash do call
6990 /// ROOT::CallRecursiveRemoveIfNeeded in their destructor.
6991 /// i.e. it is safe to call the Hash virtual function during the RecursiveRemove operation.
6992 /// This routines is used for a small subset of the class for which we need
6993 /// the answer before gROOT is properly initialized.
6994 
6996 {
6997  // Hand selection of correct classes, those classes should be
6998  // cross-checked in testHashRecursiveRemove.cxx
6999  static const char *handVerified[] = {
7000  "TEnvRec", "TDataType", "TObjArray", "TList", "THashList",
7001  "TClass", "TCling", "TInterpreter", "TMethod", "ROOT::Internal::TCheckHashRecursiveRemoveConsistency",
7002  "TCheckHashRecursiveRemoveConsistency", "TGWindow",
7003  "TDirectory", "TDirectoryFile", "TObject", "TH1",
7004  "TQClass" };
7005 
7006  if (cname && cname[0]) {
7007  for (auto cursor : handVerified) {
7008  if (strcmp(cname, cursor) == 0)
7009  return true;
7010  }
7011  }
7012  return false;
7013 }
7014 
7015 ////////////////////////////////////////////////////////////////////////////////
7016 /// Return true is the Hash/RecursiveRemove setup is consistent, i.e. when all
7017 /// classes in the class hierarchy that overload TObject::Hash do call
7018 /// ROOT::CallRecursiveRemoveIfNeeded in their destructor.
7019 /// i.e. it is safe to call the Hash virtual function during the RecursiveRemove operation.
7020 
7022 {
7023  return clRef.HasConsistentHashMember();
7024 }
7025 
7026 ////////////////////////////////////////////////////////////////////////////////
7027 /// Return true if we have access to a constructor useable for I/O. This is
7028 /// typically the default constructor but can also be a constructor specifically
7029 /// marked for I/O (for example a constructor taking a TRootIOCtor* as an
7030 /// argument). In other words, if this routine returns true, TClass::New is
7031 /// guarantee to succeed.
7032 /// To know if the class described by this TClass has a default constructor
7033 /// (public or not), use
7034 /// \code{.cpp}
7035 /// cl->GetProperty() & kClassHasDefaultCtor
7036 /// \code
7037 /// To know if the class described by this TClass has a public default
7038 /// constructor use:
7039 /// \code{.cpp}
7040 /// gInterpreter->ClassInfo_HasDefaultConstructor(aClass->GetClassInfo());
7041 /// \code
7042 
7044 {
7045 
7046  if (fNew) return kTRUE;
7047 
7048  if (HasInterpreterInfo()) {
7049  R__LOCKGUARD(gInterpreterMutex);
7051  }
7052  if (fCollectionProxy) {
7053  return kTRUE;
7054  }
7055  if (fCurrentInfo.load()) {
7056  // Emulated class, we know how to construct them via the TStreamerInfo
7057  return kTRUE;
7058  }
7059  return kFALSE;
7060 }
7061 
7062 ////////////////////////////////////////////////////////////////////////////////
7063 /// Returns true if this class has an definition and/or overload of the
7064 /// member function Hash.
7065 ///
7066 /// For example to test if the class overload TObject::Hash use
7067 /// ~~~ {.cpp}
7068 /// if (cl->IsTObject() && cl->HasLocalHashMember())
7069 /// ~~~
7070 
7072 {
7073  if (fProperty == (-1))
7074  Property();
7075  return TestBit(kHasLocalHashMember);
7076 }
7077 
7078 ////////////////////////////////////////////////////////////////////////////////
7079 /// Return the wrapper around Merge.
7080 
7082 {
7083  return fMerge;
7084 }
7085 
7086 ////////////////////////////////////////////////////////////////////////////////
7087 /// Return the wrapper around Merge.
7088 
7090 {
7091  return fResetAfterMerge;
7092 }
7093 
7094 ////////////////////////////////////////////////////////////////////////////////
7095 /// Return the wrapper around new ThisClass().
7096 
7098 {
7099  return fNew;
7100 }
7101 
7102 ////////////////////////////////////////////////////////////////////////////////
7103 /// Return the wrapper around new ThisClass[].
7104 
7106 {
7107  return fNewArray;
7108 }
7109 
7110 ////////////////////////////////////////////////////////////////////////////////
7111 /// Return the wrapper around delete ThiObject.
7112 
7114 {
7115  return fDelete;
7116 }
7117 
7118 ////////////////////////////////////////////////////////////////////////////////
7119 /// Return the wrapper around delete [] ThiObject.
7120 
7122 {
7123  return fDeleteArray;
7124 }
7125 
7126 ////////////////////////////////////////////////////////////////////////////////
7127 /// Return the wrapper around the destructor
7128 
7130 {
7131  return fDestructor;
7132 }
7133 
7134 ////////////////////////////////////////////////////////////////////////////////
7135 /// Return the wrapper around the directory auto add function.
7136 
7138 {
7139  return fDirAutoAdd;
7140 }
void Add(TObject *obj, const char *name=0, Int_t check=-1)
Add object with name to browser.
Definition: TBrowser.cxx:261
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:4038
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:4375
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:90
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...
Bool_t IsReading() const
Definition: TBuffer.h:83
static TClass * LoadClassCustom(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition: TClass.cxx:5531
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:5677
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
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
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:5687
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:6361
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:4394
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:6854
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:6757
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:6674
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:6417
void SetConvStreamerFunc(ClassConvStreamerFunc_t strm)
Set a wrapper/accessor function around this class custom conversion streamer.
Definition: TClass.cxx:6618
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:4162
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:6461
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:5405
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:4064
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:4420
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:6682
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:4348
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:6509
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:402
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:5659
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:5951
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:6487
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:3952
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:6531
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:6567
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:4205
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:5266
ROOT::NewFunc_t fNew
Definition: TClass.h:209
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
Int_t Length() const
Definition: TBuffer.h:96
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:6431
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:4148
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:6496
Int_t GetBaseClassOffset(const TClass *toBase, void *address=0, bool isDerivedObject=true)
Definition: TClass.cxx:2710
TDeclNameRegistry & fNoInfoOrEmuOrFwdDeclNameRegistry
Definition: TClass.h:152
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:4261
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
Bool_t FillTClass(TClass *pcl)
Move data from this TProtoClass into cl.
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
void * InterfaceMethod() const
Return pointer to the interface method.
Definition: TFunction.cxx:208
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:4523
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:5642
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:4003
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:6595
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:4974
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:6950
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:5632
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:6452
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:6053
TObject * Value() const
Definition: TMap.h:121
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:4079
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:6658
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
virtual char * ReadString(char *s, Int_t max)=0
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:6737
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:6379
void MakeCustomMenuList()
Makes a customizable version of the popup menu list, i.e.
Definition: TClass.cxx:4104
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:6690
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:5982
void Store(TBuffer &b) const
Store class description on I/O buffer.
Definition: TClass.cxx:5590
void SetUnloaded()
Call this method to indicate that the shared library containing this class&#39;s code has been removed (u...
Definition: TClass.cxx:5991
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:6701
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5149
void IgnoreTObjectStreamer(Bool_t ignore=kTRUE)
When the class kIgnoreTObjectStreamer bit is set, the automatically generated Streamer will not call ...
Definition: TClass.cxx:4655
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:6473
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:5434
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:5599
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:3902
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:4688
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:5768
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:6174
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:5926
TListOfFunctions * GetMethodList()
Return (create an empty one if needed) the list of functions.
Definition: TClass.cxx:4176
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:6546
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:4304
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:5876
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
std::unordered_set< std::string > fClassNamesSet
Definition: TClass.h:144
long Long_t
Definition: RtypesCore.h:50
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
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:5388
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:6974
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
int type
Definition: TGX11.cxx:120
static void AddClass(TClass *cl)
static: Add a class to the list and map of classes.
Definition: TClass.cxx: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:5897
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:4232
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:5414
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:5479
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:5668
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:5501
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:5445
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.
bool IsUniquePtr(std::string_view name)
Definition: TClassEdit.h:181
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:6642
void SetCurrentStreamerInfo(TVirtualStreamerInfo *info)
Set pointer to current TVirtualStreamerInfo.
Definition: TClass.cxx:5426
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:6518
void LoadClassInfo() const
Try to load the ClassInfo if available.
Definition: TClass.cxx:5554
virtual Int_t ReadClassEmulated(const TClass *cl, void *object, const TClass *onfile_class=0)=0
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:4729
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:6650
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:4195
Definition: first.py:1
Bool_t HasConsistentHashMember(TClass &clRef)
Return true is the Hash/RecursiveRemove setup is consistent, i.e.
Definition: TClass.cxx:7021
UInt_t GetCheckSum(ECheckSum code=kCurrentCheckSum) const
Call GetCheckSum with validity check.
Definition: TClass.cxx:6185
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
std::string GetUniquePtrType(std::string_view name)
Definition: TClassEdit.h:185
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:4586
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:4277
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:6666
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
virtual void WriteString(const char *s)=0
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4792
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