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