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