@@ -102,23 +102,48 @@ enum ForDefinition_t : bool {
102102 ForDefinition = true
103103};
104104
105- class CounterPair : public std ::pair<uint32_t , uint32_t > {
106- private:
107- static constexpr uint32_t None = (1u << 31 ); // / None is set
108-
105+ // / The Counter with an optional additional Counter for
106+ // / branches. `Skipped` counter can be calculated with `Executed` and
107+ // / a common Counter (like `Parent`) as `(Parent-Executed)`.
108+ // /
109+ // / In SingleByte mode, Counters are binary. Subtraction is not
110+ // / applicable (but addition is capable). In this case, both
111+ // / `Executed` and `Skipped` counters are required. `Skipped` is
112+ // / `None` by default. It is allocated in the coverage mapping.
113+ // /
114+ // / There might be cases that `Parent` could be induced with
115+ // / `(Executed+Skipped)`. This is not always applicable.
116+ class CounterPair {
109117public:
110- static constexpr uint32_t Mask = None - 1 ;
118+ // / Optional value.
119+ class ValueOpt {
120+ private:
121+ static constexpr uint32_t None = (1u << 31 ); // / None is allocated.
122+ static constexpr uint32_t Mask = None - 1 ;
111123
112- public:
113- CounterPair (unsigned Val = 0 ) {
114- assert (!(Val & ~Mask));
115- first = Val;
116- second = None;
117- }
124+ uint32_t Val;
118125
119- std::pair<bool , bool > getIsCounterPair () const {
120- return {!(first & None), !(second & None)};
121- }
126+ public:
127+ ValueOpt () : Val(None) {}
128+
129+ ValueOpt (unsigned InitVal) {
130+ assert (!(InitVal & ~Mask));
131+ Val = InitVal;
132+ }
133+
134+ bool hasValue () const { return !(Val & None); }
135+
136+ operator uint32_t () const { return Val; }
137+ };
138+
139+ ValueOpt Executed;
140+ ValueOpt Skipped; // / May be None.
141+
142+ // / Initialized with Skipped=None.
143+ CounterPair (unsigned Val) : Executed(Val) {}
144+
145+ // FIXME: Should work with {None, None}
146+ CounterPair () : Executed(0 ) {}
122147};
123148
124149struct OrderGlobalInitsOrStermFinalizers {
0 commit comments