llvm.org GIT mirror llvm / bdd4e13
[Support][ErrorOr] Add optimized specialization of ErrorOr<void>. ErrorOr<void> represents an operation that returns nothing, but can still fail. It should be used in cases where you need the aditional user data that ErrorOr provides over error_code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173209 91177308-0d34-0410-b5e6-96231b3b80d8 Michael J. Spencer 7 years ago
2 changed file(s) with 109 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
1515 #ifndef LLVM_SUPPORT_ERROR_OR_H
1616 #define LLVM_SUPPORT_ERROR_OR_H
1717
18 #include "llvm/ADT/PointerIntPair.h"
1819 #include "llvm/Support/AlignOf.h"
1920 #include "llvm/Support/system_error.h"
2021 #include "llvm/Support/type_traits.h"
256257
257258 return *this;
258259 }
260 #endif
259261
260262 ~ErrorOr() {
261263 if (!IsValid)
265267 else
266268 get()->~storage_type();
267269 }
268 #endif
269270
270271 template
271272 ET getError() const {
330331 bool IsValid : 1;
331332 };
332333
334 // ErrorOr specialization for void.
335 template <>
336 class ErrorOr {
337 public:
338 ErrorOr() : Error(nullptr, 0) {}
339
340 ErrorOr(llvm::error_code EC) : Error(nullptr, 0) {
341 if (EC == errc::success) {
342 Error.setInt(1);
343 return;
344 }
345 ErrorHolderBase *E = new ErrorHolderBase;
346 E->Error = EC;
347 E->HasUserData = false;
348 Error.setPointer(E);
349 }
350
351 template
352 ErrorOr(UserDataT UD, typename
353 enable_if_c::value>::type* = 0)
354 : Error(nullptr, 0) {
355 ErrorHolderBase *E = new ErrorHolder(llvm_move(UD));
356 E->Error = ErrorOrUserDataTraits::error();
357 E->HasUserData = true;
358 Error.setPointer(E);
359 }
360
361 ErrorOr(const ErrorOr &Other) : Error(nullptr, 0) {
362 Error = Other.Error;
363 if (Other.Error.getPointer()->Error) {
364 Error.getPointer()->aquire();
365 }
366 }
367
368 ErrorOr &operator =(const ErrorOr &Other) {
369 if (this == &Other)
370 return *this;
371
372 this->~ErrorOr();
373 new (this) ErrorOr(Other);
374
375 return *this;
376 }
377
378 #if LLVM_HAS_RVALUE_REFERENCES
379 ErrorOr(ErrorOr &&Other) : Error(nullptr) {
380 // Get other's error.
381 Error = Other.Error;
382 // Tell other not to do any destruction.
383 Other.Error.setPointer(nullptr);
384 }
385
386 ErrorOr &operator =(ErrorOr &&Other) {
387 if (this == &Other)
388 return *this;
389
390 this->~ErrorOr();
391 new (this) ErrorOr(std::move(Other));
392
393 return *this;
394 }
395 #endif
396
397 ~ErrorOr() {
398 if (Error.getPointer())
399 Error.getPointer()->release();
400 }
401
402 template
403 ET getError() const {
404 assert(ErrorOrUserDataTraits::error() == *this &&
405 "Incorrect user error data type for error!");
406 if (!Error.getPointer()->HasUserData)
407 return ET();
408 return reinterpret_cast *>(
409 Error.getPointer())->UserData;
410 }
411
412 typedef void (*unspecified_bool_type)();
413 static void unspecified_bool_true() {}
414
415 /// \brief Return false if there is an error.
416 operator unspecified_bool_type() const {
417 return Error.getInt() ? unspecified_bool_true : 0;
418 }
419
420 operator llvm::error_code() const {
421 return Error.getInt() ? make_error_code(errc::success)
422 : Error.getPointer()->Error;
423 }
424
425 private:
426 // If the bit is 1, the error is success.
427 llvm::PointerIntPair Error;
428 };
429
333430 template
334431 typename enable_if_c::value ||
335432 is_error_condition_enum::value, bool>::type
4444 *a = 42;
4545 EXPECT_EQ(42, x);
4646
47 EXPECT_FALSE(ErrorOr(make_error_code(errc::broken_pipe)));
48 EXPECT_TRUE(ErrorOr(make_error_code(errc::success)));
49
4750 #if LLVM_HAS_CXX11_STDLIB
4851 // Move only types.
4952 EXPECT_EQ(3, **t3());
7073 return InvalidArgError("adena");
7174 }
7275
76 ErrorOr t5() {
77 return InvalidArgError("pie");
78 }
79
7380 namespace {
7481 TEST(ErrorOr, UserErrorData) {
7582 ErrorOr a = t4();
7683 EXPECT_EQ(errc::invalid_argument, a);
7784 EXPECT_EQ("adena", t4().getError().ArgName);
85
86 ErrorOr b = t5();
87 EXPECT_EQ(errc::invalid_argument, b);
88 EXPECT_EQ("pie", b.getError().ArgName);
7889 }
7990 } // end anon namespace