@@ -132,172 +132,154 @@ namespace llvm {
132
132
133
133
namespace clang {
134
134
135
- // Basic
136
135
class StreamingDiagnostic ;
137
136
138
137
// Determines whether the low bit of the result pointer for the
139
138
// given UID is always zero. If so, ActionResult will use that bit
140
139
// for it's "invalid" flag.
141
140
template <class Ptr > struct IsResultPtrLowBitFree {
142
141
static const bool value = false ;
143
- };
144
-
145
- // / ActionResult - This structure is used while parsing/acting on
146
- // / expressions, stmts, etc. It encapsulates both the object returned by
147
- // / the action, plus a sense of whether or not it is valid.
148
- // / When CompressInvalid is true, the "invalid" flag will be
149
- // / stored in the low bit of the Val pointer.
150
- template <class PtrTy ,
151
- bool CompressInvalid = IsResultPtrLowBitFree<PtrTy>::value>
152
- class ActionResult {
153
- PtrTy Val;
154
- bool Invalid;
155
-
156
- public:
157
- ActionResult (bool Invalid = false ) : Val(PtrTy()), Invalid(Invalid) {}
158
- ActionResult (PtrTy val) : Val(val), Invalid(false ) {}
159
- ActionResult (const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true ) {}
160
-
161
- // These two overloads prevent void* -> bool conversions.
162
- ActionResult (const void *) = delete ;
163
- ActionResult (volatile void *) = delete ;
164
-
165
- bool isInvalid () const { return Invalid; }
166
- bool isUsable () const { return !Invalid && Val; }
167
- bool isUnset () const { return !Invalid && !Val; }
168
-
169
- PtrTy get () const { return Val; }
170
- template <typename T> T *getAs () { return static_cast <T*>(get ()); }
171
-
172
- void set (PtrTy V) { Val = V; }
173
-
174
- const ActionResult &operator =(PtrTy RHS) {
175
- Val = RHS;
176
- Invalid = false ;
177
- return *this ;
178
- }
179
- };
180
-
181
- // This ActionResult partial specialization places the "invalid"
182
- // flag into the low bit of the pointer.
183
- template <typename PtrTy>
184
- class ActionResult <PtrTy, true > {
185
- // A pointer whose low bit is 1 if this result is invalid, 0
186
- // otherwise.
187
- uintptr_t PtrWithInvalid;
188
-
189
- using PtrTraits = llvm::PointerLikeTypeTraits<PtrTy>;
190
-
191
- public:
192
- ActionResult (bool Invalid = false )
193
- : PtrWithInvalid(static_cast <uintptr_t >(Invalid)) {}
194
-
195
- ActionResult (PtrTy V) {
196
- void *VP = PtrTraits::getAsVoidPointer (V);
197
- PtrWithInvalid = reinterpret_cast <uintptr_t >(VP);
198
- assert ((PtrWithInvalid & 0x01 ) == 0 && " Badly aligned pointer" );
199
- }
200
-
201
- ActionResult (const DiagnosticBuilder &) : PtrWithInvalid(0x01 ) {}
202
-
203
- // These two overloads prevent void* -> bool conversions.
204
- ActionResult (const void *) = delete ;
205
- ActionResult (volatile void *) = delete ;
206
-
207
- bool isInvalid () const { return PtrWithInvalid & 0x01 ; }
208
- bool isUsable () const { return PtrWithInvalid > 0x01 ; }
209
- bool isUnset () const { return PtrWithInvalid == 0 ; }
210
-
211
- PtrTy get () const {
212
- void *VP = reinterpret_cast <void *>(PtrWithInvalid & ~0x01 );
213
- return PtrTraits::getFromVoidPointer (VP);
214
- }
215
-
216
- template <typename T> T *getAs () { return static_cast <T*>(get ()); }
217
-
218
- void set (PtrTy V) {
219
- void *VP = PtrTraits::getAsVoidPointer (V);
220
- PtrWithInvalid = reinterpret_cast <uintptr_t >(VP);
221
- assert ((PtrWithInvalid & 0x01 ) == 0 && " Badly aligned pointer" );
222
- }
223
-
224
- const ActionResult &operator =(PtrTy RHS) {
225
- void *VP = PtrTraits::getAsVoidPointer (RHS);
226
- PtrWithInvalid = reinterpret_cast <uintptr_t >(VP);
227
- assert ((PtrWithInvalid & 0x01 ) == 0 && " Badly aligned pointer" );
228
- return *this ;
229
- }
230
-
231
- // For types where we can fit a flag in with the pointer, provide
232
- // conversions to/from pointer type.
233
- static ActionResult getFromOpaquePointer (void *P) {
234
- ActionResult Result;
235
- Result.PtrWithInvalid = (uintptr_t )P;
236
- return Result;
237
- }
238
- void *getAsOpaquePointer () const { return (void *)PtrWithInvalid; }
239
- };
142
+ };
143
+
144
+ // / The result of parsing/analyzing an expression, statement etc.
145
+ // /
146
+ // / It may be:
147
+ // / - a valid pointer to the result object
148
+ // / - unset (null but valid), for constructs that may legitimately be absent
149
+ // / (for example, the condition of a for loop)
150
+ // / - invalid, indicating an error
151
+ // / (no detail is provided, usually the error has already been diagnosed)
152
+ template <class PtrTy , bool Compress = IsResultPtrLowBitFree<PtrTy>::value>
153
+ class ActionResult {
154
+ PtrTy Val = {};
155
+ bool Invalid;
156
+
157
+ public:
158
+ ActionResult (bool Invalid = false ) : Val(PtrTy()), Invalid(Invalid) {}
159
+ ActionResult (PtrTy Val) { *this = Val; }
160
+ ActionResult (const DiagnosticBuilder &) : ActionResult(/* Invalid=*/ true ) {}
161
+
162
+ // These two overloads prevent void* -> bool conversions.
163
+ ActionResult (const void *) = delete ;
164
+ ActionResult (volatile void *) = delete ;
165
+
166
+ bool isInvalid () const { return Invalid; }
167
+ bool isUnset () const { return !Invalid && !Val; }
168
+ bool isUsable () const { return !isInvalid () && !isUnset (); }
169
+
170
+ PtrTy get () const { return Val; }
171
+ template <typename T> T *getAs () { return static_cast <T *>(get ()); }
172
+
173
+ ActionResult &operator =(PtrTy RHS) {
174
+ Val = RHS;
175
+ Invalid = false ;
176
+ return *this ;
177
+ }
178
+ };
240
179
241
- // / An opaque type for threading parsed type information through the
242
- // / parser.
243
- using ParsedType = OpaquePtr<QualType> ;
244
- using UnionParsedType = UnionOpaquePtr<QualType> ;
180
+ // If we PtrTy has a free bit, we can represent "invalid" as nullptr|1.
181
+ template < typename PtrTy> class ActionResult <PtrTy, true > {
182
+ static constexpr uintptr_t UnsetValue = 0x0 ;
183
+ static constexpr uintptr_t InvalidValue = 0x1 ;
245
184
246
- // We can re-use the low bit of expression, statement, base, and
247
- // member-initializer pointers for the "invalid" flag of
248
- // ActionResult.
249
- template <> struct IsResultPtrLowBitFree <Expr*> {
250
- static const bool value = true ;
251
- };
252
- template <> struct IsResultPtrLowBitFree <Stmt*> {
253
- static const bool value = true ;
254
- };
255
- template <> struct IsResultPtrLowBitFree <CXXBaseSpecifier*> {
256
- static const bool value = true ;
257
- };
258
- template <> struct IsResultPtrLowBitFree <CXXCtorInitializer*> {
259
- static const bool value = true ;
260
- };
185
+ uintptr_t Value = UnsetValue;
261
186
262
- using ExprResult = ActionResult<Expr *>;
263
- using StmtResult = ActionResult<Stmt *>;
264
- using TypeResult = ActionResult<ParsedType>;
265
- using BaseResult = ActionResult<CXXBaseSpecifier *>;
266
- using MemInitResult = ActionResult<CXXCtorInitializer *>;
187
+ using PtrTraits = llvm::PointerLikeTypeTraits<PtrTy>;
267
188
268
- using DeclResult = ActionResult<Decl *>;
269
- using ParsedTemplateTy = OpaquePtr<TemplateName>;
270
- using UnionParsedTemplateTy = UnionOpaquePtr<TemplateName>;
189
+ public:
190
+ ActionResult (bool Invalid = false )
191
+ : Value(Invalid ? InvalidValue : UnsetValue) {}
192
+ ActionResult (PtrTy V) { *this = V; }
193
+ ActionResult (const DiagnosticBuilder &) : ActionResult(/* Invalid=*/ true ) {}
271
194
272
- using MultiExprArg = MutableArrayRef<Expr *>;
273
- using MultiStmtArg = MutableArrayRef<Stmt *>;
274
- using ASTTemplateArgsPtr = MutableArrayRef<ParsedTemplateArgument>;
275
- using MultiTypeArg = MutableArrayRef<ParsedType>;
276
- using MultiTemplateParamsArg = MutableArrayRef<TemplateParameterList *>;
195
+ // These two overloads prevent void* -> bool conversions.
196
+ ActionResult (const void *) = delete ;
197
+ ActionResult (volatile void *) = delete ;
277
198
278
- inline ExprResult ExprError () { return ExprResult ( true ) ; }
279
- inline StmtResult StmtError () { return StmtResult ( true ) ; }
280
- inline TypeResult TypeError () { return TypeResult ( true ); }
199
+ bool isInvalid () const { return Value == InvalidValue ; }
200
+ bool isUnset () const { return Value == UnsetValue ; }
201
+ bool isUsable () const { return ! isInvalid () && ! isUnset ( ); }
281
202
282
- inline ExprResult ExprError (const StreamingDiagnostic &) {
283
- return ExprError ();
203
+ PtrTy get () const {
204
+ void *VP = reinterpret_cast <void *>(Value & ~0x01 );
205
+ return PtrTraits::getFromVoidPointer (VP);
284
206
}
285
- inline StmtResult StmtError (const StreamingDiagnostic &) {
286
- return StmtError ();
287
- }
288
-
289
- inline ExprResult ExprEmpty () { return ExprResult (false ); }
290
- inline StmtResult StmtEmpty () { return StmtResult (false ); }
207
+ template <typename T> T *getAs () { return static_cast <T *>(get ()); }
291
208
292
- inline Expr *AssertSuccess (ExprResult R) {
293
- assert (!R.isInvalid () && " operation was asserted to never fail!" );
294
- return R.get ();
209
+ ActionResult &operator =(PtrTy RHS) {
210
+ void *VP = PtrTraits::getAsVoidPointer (RHS);
211
+ Value = reinterpret_cast <uintptr_t >(VP);
212
+ assert ((Value & 0x01 ) == 0 && " Badly aligned pointer" );
213
+ return *this ;
295
214
}
296
215
297
- inline Stmt *AssertSuccess (StmtResult R) {
298
- assert (!R.isInvalid () && " operation was asserted to never fail!" );
299
- return R.get ();
216
+ // For types where we can fit a flag in with the pointer, provide
217
+ // conversions to/from pointer type.
218
+ static ActionResult getFromOpaquePointer (void *P) {
219
+ ActionResult Result;
220
+ Result.Value = (uintptr_t )P;
221
+ assert (Result.isInvalid () ||
222
+ PtrTraits::getAsVoidPointer (Result.get ()) == P);
223
+ return Result;
300
224
}
225
+ void *getAsOpaquePointer () const { return (void *)Value; }
226
+ };
227
+
228
+ // / An opaque type for threading parsed type information through the parser.
229
+ using ParsedType = OpaquePtr<QualType>;
230
+ using UnionParsedType = UnionOpaquePtr<QualType>;
231
+
232
+ // We can re-use the low bit of expression, statement, base, and
233
+ // member-initializer pointers for the "invalid" flag of
234
+ // ActionResult.
235
+ template <> struct IsResultPtrLowBitFree <Expr *> {
236
+ static const bool value = true ;
237
+ };
238
+ template <> struct IsResultPtrLowBitFree <Stmt *> {
239
+ static const bool value = true ;
240
+ };
241
+ template <> struct IsResultPtrLowBitFree <CXXBaseSpecifier *> {
242
+ static const bool value = true ;
243
+ };
244
+ template <> struct IsResultPtrLowBitFree <CXXCtorInitializer *> {
245
+ static const bool value = true ;
246
+ };
247
+
248
+ using ExprResult = ActionResult<Expr *>;
249
+ using StmtResult = ActionResult<Stmt *>;
250
+ using TypeResult = ActionResult<ParsedType>;
251
+ using BaseResult = ActionResult<CXXBaseSpecifier *>;
252
+ using MemInitResult = ActionResult<CXXCtorInitializer *>;
253
+
254
+ using DeclResult = ActionResult<Decl *>;
255
+ using ParsedTemplateTy = OpaquePtr<TemplateName>;
256
+ using UnionParsedTemplateTy = UnionOpaquePtr<TemplateName>;
257
+
258
+ using MultiExprArg = MutableArrayRef<Expr *>;
259
+ using MultiStmtArg = MutableArrayRef<Stmt *>;
260
+ using ASTTemplateArgsPtr = MutableArrayRef<ParsedTemplateArgument>;
261
+ using MultiTypeArg = MutableArrayRef<ParsedType>;
262
+ using MultiTemplateParamsArg = MutableArrayRef<TemplateParameterList *>;
263
+
264
+ inline ExprResult ExprError () { return ExprResult (true ); }
265
+ inline StmtResult StmtError () { return StmtResult (true ); }
266
+ inline TypeResult TypeError () { return TypeResult (true ); }
267
+
268
+ inline ExprResult ExprError (const StreamingDiagnostic &) { return ExprError (); }
269
+ inline StmtResult StmtError (const StreamingDiagnostic &) { return StmtError (); }
270
+
271
+ inline ExprResult ExprEmpty () { return ExprResult (false ); }
272
+ inline StmtResult StmtEmpty () { return StmtResult (false ); }
273
+
274
+ inline Expr *AssertSuccess (ExprResult R) {
275
+ assert (!R.isInvalid () && " operation was asserted to never fail!" );
276
+ return R.get ();
277
+ }
278
+
279
+ inline Stmt *AssertSuccess (StmtResult R) {
280
+ assert (!R.isInvalid () && " operation was asserted to never fail!" );
281
+ return R.get ();
282
+ }
301
283
302
284
} // namespace clang
303
285
0 commit comments