|
1 | 1 | // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s
|
2 | 2 |
|
3 | 3 | #include "mock-types.h"
|
4 |
| -//#include <type_traits> |
5 | 4 |
|
6 | 5 | void WTFBreakpointTrap();
|
7 | 6 | void WTFCrashWithInfo(int, const char*, const char*, int);
|
@@ -60,11 +59,86 @@ NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void WTFCrashWithInfo(int line, const char*
|
60 | 59 | WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason));
|
61 | 60 | }
|
62 | 61 |
|
| 62 | +enum class Flags : unsigned short { |
| 63 | + Flag1 = 1 << 0, |
| 64 | + Flag2 = 1 << 1, |
| 65 | + Flag3 = 1 << 2, |
| 66 | +}; |
| 67 | + |
| 68 | +template<typename E> class OptionSet { |
| 69 | +public: |
| 70 | + using StorageType = unsigned short; |
| 71 | + |
| 72 | + static constexpr OptionSet fromRaw(StorageType rawValue) { |
| 73 | + return OptionSet(static_cast<E>(rawValue), FromRawValue); |
| 74 | + } |
| 75 | + |
| 76 | + constexpr OptionSet() = default; |
| 77 | + |
| 78 | + constexpr OptionSet(E e) |
| 79 | + : m_storage(static_cast<StorageType>(e)) { |
| 80 | + } |
| 81 | + |
| 82 | + constexpr StorageType toRaw() const { return m_storage; } |
| 83 | + |
| 84 | + constexpr bool isEmpty() const { return !m_storage; } |
| 85 | + |
| 86 | + constexpr explicit operator bool() const { return !isEmpty(); } |
| 87 | + |
| 88 | + constexpr bool contains(E option) const { return containsAny(option); } |
| 89 | + constexpr bool containsAny(OptionSet optionSet) const { |
| 90 | + return !!(*this & optionSet); |
| 91 | + } |
| 92 | + |
| 93 | + constexpr bool containsAll(OptionSet optionSet) const { |
| 94 | + return (*this & optionSet) == optionSet; |
| 95 | + } |
| 96 | + |
| 97 | + constexpr void add(OptionSet optionSet) { m_storage |= optionSet.m_storage; } |
| 98 | + |
| 99 | + constexpr void remove(OptionSet optionSet) |
| 100 | + { |
| 101 | + m_storage &= ~optionSet.m_storage; |
| 102 | + } |
| 103 | + |
| 104 | + constexpr void set(OptionSet optionSet, bool value) |
| 105 | + { |
| 106 | + if (value) |
| 107 | + add(optionSet); |
| 108 | + else |
| 109 | + remove(optionSet); |
| 110 | + } |
| 111 | + |
| 112 | + constexpr friend OptionSet operator|(OptionSet lhs, OptionSet rhs) { |
| 113 | + return fromRaw(lhs.m_storage | rhs.m_storage); |
| 114 | + } |
| 115 | + |
| 116 | + constexpr friend OptionSet operator&(OptionSet lhs, OptionSet rhs) { |
| 117 | + return fromRaw(lhs.m_storage & rhs.m_storage); |
| 118 | + } |
| 119 | + |
| 120 | + constexpr friend OptionSet operator-(OptionSet lhs, OptionSet rhs) { |
| 121 | + return fromRaw(lhs.m_storage & ~rhs.m_storage); |
| 122 | + } |
| 123 | + |
| 124 | + constexpr friend OptionSet operator^(OptionSet lhs, OptionSet rhs) { |
| 125 | + return fromRaw(lhs.m_storage ^ rhs.m_storage); |
| 126 | + } |
| 127 | + |
| 128 | +private: |
| 129 | + enum InitializationTag { FromRawValue }; |
| 130 | + constexpr OptionSet(E e, InitializationTag) |
| 131 | + : m_storage(static_cast<StorageType>(e)) { |
| 132 | + } |
| 133 | + StorageType m_storage { 0 }; |
| 134 | +}; |
| 135 | + |
63 | 136 | class Number {
|
64 | 137 | public:
|
65 | 138 | Number(int v) : v(v) { }
|
66 | 139 | Number(double);
|
67 | 140 | Number operator+(const Number&);
|
| 141 | + const int& value() const { return v; } |
68 | 142 | private:
|
69 | 143 | int v;
|
70 | 144 | };
|
@@ -112,6 +186,19 @@ class RefCounted {
|
112 | 186 | RefCounted& trivial18() const { RELEASE_ASSERT(this, "this must be not null"); return const_cast<RefCounted&>(*this); }
|
113 | 187 | void trivial19() const { return; }
|
114 | 188 |
|
| 189 | + static constexpr unsigned numBits = 4; |
| 190 | + int trivial20() { return v >> numBits; } |
| 191 | + |
| 192 | + const int* trivial21() { return number ? &number->value() : nullptr; } |
| 193 | + |
| 194 | + enum class Enum : unsigned short { |
| 195 | + Value1 = 1, |
| 196 | + Value2 = 2, |
| 197 | + }; |
| 198 | + bool trivial22() { return enumValue == Enum::Value1; } |
| 199 | + |
| 200 | + bool trivial23() const { return OptionSet<Flags>::fromRaw(v).contains(Flags::Flag1); } |
| 201 | + |
115 | 202 | static RefCounted& singleton() {
|
116 | 203 | static RefCounted s_RefCounted;
|
117 | 204 | s_RefCounted.ref();
|
@@ -170,6 +257,8 @@ class RefCounted {
|
170 | 257 | }
|
171 | 258 |
|
172 | 259 | unsigned v { 0 };
|
| 260 | + Number* number { nullptr }; |
| 261 | + Enum enumValue { Enum::Value1 }; |
173 | 262 | };
|
174 | 263 |
|
175 | 264 | RefCounted* refCountedObj();
|
@@ -208,6 +297,10 @@ class UnrelatedClass {
|
208 | 297 | getFieldTrivial().trivial17(); // no-warning
|
209 | 298 | getFieldTrivial().trivial18(); // no-warning
|
210 | 299 | getFieldTrivial().trivial19(); // no-warning
|
| 300 | + getFieldTrivial().trivial20(); // no-warning |
| 301 | + getFieldTrivial().trivial21(); // no-warning |
| 302 | + getFieldTrivial().trivial22(); // no-warning |
| 303 | + getFieldTrivial().trivial23(); // no-warning |
211 | 304 | RefCounted::singleton().trivial18(); // no-warning
|
212 | 305 | RefCounted::singleton().someFunction(); // no-warning
|
213 | 306 |
|
|
0 commit comments