[PATCH] D26482: Prevent at compile time converting from Error::success() to Expected<T>

Mehdi AMINI via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 9 16:01:28 PST 2016


mehdi_amini created this revision.
mehdi_amini added a reviewer: lhames.
mehdi_amini added a subscriber: llvm-commits.

This would trigger an assertion at runtime otherwise.


https://reviews.llvm.org/D26482

Files:
  llvm/include/llvm/Support/Error.h
  llvm/lib/Bitcode/Reader/BitcodeReader.cpp


Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp
===================================================================
--- llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -4318,7 +4318,7 @@
     case BitstreamEntry::Error:
       return error("Malformed block");
     case BitstreamEntry::EndBlock:
-      return Error::success();
+      return "";
 
     case BitstreamEntry::SubBlock:
       if (Entry.ID == bitc::MODULE_BLOCK_ID)
@@ -4352,7 +4352,7 @@
     case BitstreamEntry::Error:
       return error("Malformed block");
     case BitstreamEntry::EndBlock:
-      return Error::success();
+      return "";
 
     case BitstreamEntry::SubBlock:
       if (Entry.ID == bitc::IDENTIFICATION_BLOCK_ID) {
@@ -4403,7 +4403,7 @@
     case BitstreamEntry::Error:
       return error("Malformed block");
     case BitstreamEntry::EndBlock:
-      return Error::success();
+      return false;
 
     case BitstreamEntry::SubBlock:
       if (Entry.ID == bitc::MODULE_BLOCK_ID)
Index: llvm/include/llvm/Support/Error.h
===================================================================
--- llvm/include/llvm/Support/Error.h
+++ llvm/include/llvm/Support/Error.h
@@ -27,6 +27,7 @@
 
 class Error;
 class ErrorList;
+class ErrorSuccess;
 
 /// Base class for error info classes. Do not extend this directly: Extend
 /// the ErrorInfo template subclass instead.
@@ -159,7 +160,7 @@
 public:
   /// Create a success value. This is equivalent to calling the default
   /// constructor, but should be preferred for readability where possible.
-  static Error success() { return Error(); }
+  static ErrorSuccess success();
 
   // Errors are not copy-constructable.
   Error(const Error &Other) = delete;
@@ -279,6 +280,13 @@
   ErrorInfoBase *Payload;
 };
 
+/// Subclass of Error for the sole purpose of identifying the success path in
+/// the type system. This allows to catch invalid conversion to Expected<T> at
+/// compile time.
+class ErrorSuccess : public Error {};
+
+inline ErrorSuccess Error::success() { return ErrorSuccess(); }
+
 /// Make a Error instance representing failure using the given error info
 /// type.
 template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) {
@@ -645,6 +653,11 @@
     new (getErrorStorage()) error_type(Err.takePayload());
   }
 
+  /// Forbid to convert from Error::success() implicitly, this avoids having
+  /// Expected<T> foo() { return Error::success(); } which compiles otherwise
+  /// but triggers the assertion above.
+  Expected(ErrorSuccess) = delete;
+
   /// Create an Expected<T> success value from the given OtherT value, which
   /// must be convertible to T.
   template <typename OtherT>


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D26482.77417.patch
Type: text/x-patch
Size: 2712 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161110/fe927da9/attachment.bin>


More information about the llvm-commits mailing list