Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TStatusBitsChecker.cxx
Go to the documentation of this file.
1// Author: Philippe Canal, 2017
2
3/*************************************************************************
4 * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11/** \class TStatusBitsChecker
12
13 TStatusBitsChecker::Check and TStatusBitsChecker::CheckAllClasses will
14 determine if the set of "status bit" declared in the class and its
15 base classes presents any overlap. The status bit are declared in
16 a given class by declaring an enum type named EStatusBits.
17 If some of the duplication is intentional, those duplication can
18 be registered in an enum type named EStatusBitsDupExceptions.
19
20 ~~~ {.cpp}
21 // TStreamerElement status bits
22 enum EStatusBits {
23 kHasRange = BIT(6),
24 kCache = BIT(9),
25 kRepeat = BIT(10),
26 kRead = BIT(11),
27 kWrite = BIT(12),
28 kDoNotDelete = BIT(13),
29 kWholeObject = BIT(14)
30 };
31
32 enum class EStatusBitsDupExceptions {
33 // This bit duplicates TObject::kInvalidObject. As the semantic of kDoNotDelete is a persistent,
34 // we can not change its value without breaking forward compatibility.
35 // Furthermore, TObject::kInvalidObject and its semantic is not (and should not be)
36 // used in TStreamerElement
37 kDoNotDelete = TStreamerElement::kDoNotDelete,
38
39 // This bit duplicates TObject::kCannotPick. As the semantic of kHasRange is a persistent,
40 // we can not change its value without breaking forward compatibility.
41 // Furthermore, TObject::kCannotPick and its semantic is not (and should not be)
42 // used in TStreamerElement
43 kHasRange = TStreamerElement::kHasRange
44 };
45 ~~~ {.cpp}
46
47 Without the EStatusBitsDupExceptions enum you would see
48
49 ~~~ {.cpp}
50 TStatusBitsChecker::Check("TStreamerElement");
51
52 Error in `<TStatusBitsChecker>`: In TStreamerElement class hierarchy, there are duplicates bits:
53 Error in `<TStatusBitsChecker>`: Bit 6 used in TStreamerElement as kHasRange
54 Error in `<TStatusBitsChecker>`: Bit 6 used in TObject as kCannotPick
55 Error in `<TStatusBitsChecker>`: Bit 13 used in TStreamerElement as kDoNotDelete
56 Error in `<TStatusBitsChecker>`: Bit 13 used in TObject as kInvalidObject
57 ~~~ {.cpp}
58
59*/
60
61#include "TStatusBitsChecker.h"
62
63#include "TBaseClass.h"
64#include "TClass.h"
65#include "TClassTable.h"
66#include "TEnum.h"
67#include "TEnumConstant.h"
68#include "TError.h"
69
70#include <cmath>
71#include <set>
72
73namespace ROOT {
74namespace Detail {
75
77 Info() = default;
78 Info(const Info &) = default;
79 Info(Info &&) = default;
80
81 Info(TClass &o, std::string &&n, bool intentionalDup) : fOwner(&o), fConstantName(n), fIntentionalDup(intentionalDup)
82 {
83 }
84
85 ~Info() = default;
86
88 std::string fConstantName;
89 bool fIntentionalDup = false;
90};
91
92/// Default constructor. Implemented in source file to allow hiding of the Info struct.
94
95/// Default destructor. Implemented in source file to allow hiding of the Info struct.
97
98/// Figure out which bit the constant has been set from/to.
99/// Return 255 if the constant is not an integer or out of range.
100UChar_t TStatusBitsChecker::ConvertToBit(Long64_t constant, TClass &classRef, const char *constantName)
101{
102
103 if (constant <= 0) {
104 Error("TStatusBitsChecker::ConvertBit", "In %s the value of %s is %lld which was not produced by BIT macro.",
105 classRef.GetName(), constantName, constant);
106 return 255;
107 }
108
109 int backshift;
110 double fraction = std::frexp(constant, &backshift);
111 // frexp doc is:
112 // if no errors occur,
113 // returns the value x in the range (-1;-0.5], [0.5; 1)
114 // and stores an integer value in *exp such that x×2^(*exp) = arg
115 --backshift; // frexp is such that BIT(0) == 1 == 0.5*2^(*exp) with *exp == 1
116
117 if (backshift < 0 || std::abs(0.5 - fraction) > 0.00001f) {
118 Error("TStatusBitsChecker::ConvertBit", "In %s the value of %s is %lld which was not produced by BIT macro.",
119 classRef.GetName(), constantName, constant);
120 return 255;
121 }
122
123 if (backshift > 24) {
124 Error("TStatusBitsChecker::ConvertBit", "In %s the value of %s is %lld (>23) which is ignored by SetBit.",
125 classRef.GetName(), constantName, constant);
126
127 if (backshift > 255) // really we could snip it sooner.
128 backshift = 255;
129 }
130
131 return backshift;
132}
133
134/// @brief Add to fRegister the Info about the bits in this class and its base
135/// classes.
137{
138 TEnum *eStatusBits = (TEnum *)classRef.GetListOfEnums()->FindObject("EStatusBits");
139 TEnum *exceptionBits = (TEnum *)classRef.GetListOfEnums()->FindObject("EStatusBitsDupExceptions");
140
141 if (eStatusBits) {
142
143 for (auto constant : TRangeStaticCast<TEnumConstant>(*eStatusBits->GetConstants())) {
144
145 // Ignore the known/intentional duplication.
146 bool intentionalDup = exceptionBits && exceptionBits->GetConstant(constant->GetName());
147
148 auto value = constant->GetValue();
149 auto bit = ConvertToBit(value, classRef, constant->GetName());
150
151 if (bit < 24) {
152 bool need = true;
153 for (auto &reg : fRegister[bit]) {
154 if (reg.fOwner == &classRef) {
155 // We have a duplicate declared in the same class
156 // let's accept this as an alias.
157 need = false;
158 }
159 }
160
161 if (need)
162 fRegister[bit].emplace_back(classRef, std::string(constant->GetName()), intentionalDup);
163 }
164 }
165 }
166
167 TList *lb = classRef.GetListOfBases();
168 if (lb) {
169 for (auto base : TRangeStaticCast<TBaseClass>(*lb)) {
170 TClass *bcl = base->GetClassPointer();
171 if (bcl)
172 RegisterBits(*bcl);
173 }
174 }
175}
176
177/// @brief Return false and print error messages if there is any unexpected
178/// duplicates BIT constant in the class hierarchy or any of the bits
179/// already registered.
180/// If verbose is true, also print all the bit declare in this class
181/// and all its bases.
182bool TStatusBitsChecker::Registry::Check(TClass &classRef, bool verbose /* = false */)
183{
184 RegisterBits(classRef);
185
186 if (verbose) {
187 for (auto &cursor : fRegister) {
188 for (auto &constant : cursor.second) {
189 Printf("Bit %3d declared in %s as %s", cursor.first, constant.fOwner->GetName(),
190 constant.fConstantName.c_str());
191 }
192 }
193 }
194
195 bool issuedHeader = false;
196 bool result = true;
197 for (auto &cursor : fRegister) {
198 unsigned int nDuplicate = 0;
199 for (auto &constant : cursor.second) {
200 if (!constant.fIntentionalDup)
201 ++nDuplicate;
202 }
203 if (nDuplicate > 1) {
204 if (!issuedHeader) {
205 Error("TStatusBitsChecker", "In %s class hierarchy, there are duplicates bits:", classRef.GetName());
206 issuedHeader = true;
207 }
208 for (auto &constant : cursor.second) {
209 if (!constant.fIntentionalDup) {
210 Error("TStatusBitsChecker", " Bit %3d used in %s as %s", cursor.first, constant.fOwner->GetName(),
211 constant.fConstantName.c_str());
212 result = false;
213 }
214 }
215 }
216 }
217
218 return result;
219}
220
221/// Return false and print error messages if there is any unexpected
222/// duplicates BIT constant in the class hierarchy.
223/// If verbose is true, also print all the bit declare in this class
224/// and all its bases.
225bool TStatusBitsChecker::Check(TClass &classRef, bool verbose /* = false */)
226{
227 return Registry().Check(classRef, verbose);
228}
229
230/// Return false and print error messages if there is any unexpected
231/// duplicates BIT constant in the class hierarchy.
232/// If verbose is true, also print all the bit declare in this class
233/// and all its bases.
234bool TStatusBitsChecker::Check(const char *classname, bool verbose)
235{
236 TClass *cl = TClass::GetClass(classname);
237 if (cl)
238 return Check(*cl, verbose);
239 else
240 return true;
241}
242
243/// Return false and print error messages if there is any unexpected
244/// duplicates BIT constant in any of the class hierarchy knows
245/// to TClassTable.
246/// If verbose is true, also print all the bit declare in eacho of the classes
247/// and all their bases.
248bool TStatusBitsChecker::CheckAllClasses(bool verbosity /* = false */)
249{
250 bool result = true;
251
252 // Start from beginning
253 gClassTable->Init();
254
255 std::set<std::string> rootLibs;
256 TList classesDeclFileNotFound;
257 TList classesImplFileNotFound;
258
259 Int_t totalNumberOfClasses = gClassTable->Classes();
260 for (Int_t i = 0; i < totalNumberOfClasses; i++) {
261
262 // get class name
263 const char *cname = gClassTable->Next();
264 if (!cname)
265 continue;
266
267 // get class & filename - use TROOT::GetClass, as we also
268 // want those classes without decl file name!
269 TClass *classPtr = TClass::GetClass((const char *)cname, kTRUE);
270 if (!classPtr)
271 continue;
272
273 result = Check(*classPtr, verbosity) && result;
274 }
275
276 return result;
277}
278
279} // namespace Detail
280} // namespace ROOT
unsigned char UChar_t
Definition RtypesCore.h:38
long long Long64_t
Definition RtypesCore.h:80
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
R__EXTERN TClassTable * gClassTable
Definition TClassTable.h:97
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
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 result
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 reg
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2503
std::map< UChar_t, std::list< Info > > fRegister
! Register of bits seen so far.
Registry()
Default constructor. Implemented in source file to allow hiding of the Info struct.
bool Check(TClass &classRef, bool verbose=false)
Return false and print error messages if there is any unexpected duplicates BIT constant in the class...
void RegisterBits(TClass &classRef)
Add to fRegister the Info about the bits in this class and its base classes.
~Registry()
Default destructor. Implemented in source file to allow hiding of the Info struct.
static bool Check(TClass &classRef, bool verbose=false)
Return false and print error messages if there is any unexpected duplicates BIT constant in the class...
static UChar_t ConvertToBit(Long64_t constant, TClass &classRef, const char *constantName)
Figure out which bit the constant has been set from/to.
static bool CheckAllClasses(bool verbosity=false)
Return false and print error messages if there is any unexpected duplicates BIT constant in any of th...
static char * Next()
Returns next class from sorted class table.
static void Init()
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
TList * GetListOfEnums(Bool_t load=kTRUE)
Return a list containing the TEnums of a class.
Definition TClass.cxx:3686
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition TClass.cxx:3636
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:2968
The TEnum class implements the enum type.
Definition TEnum.h:33
const TSeqCollection * GetConstants() const
Definition TEnum.h:63
const TEnumConstant * GetConstant(const char *name) const
Definition TEnum.h:64
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
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const Int_t n
Definition legend1.C:16
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Info(TClass &o, std::string &&n, bool intentionalDup)