Skip to content

Conversation

@ilovepi
Copy link
Contributor

@ilovepi ilovepi commented Nov 19, 2025

In BitcodeReader, we were using consumeError(), which drops the error
and hides it from normal usage. To avoid that, we can just slightly
tweak the API to return an Expected, and propagate the error
accordingly.

In BitcodeReader, we were using consumeError(), which drops the error
and hides it from normal usage. To avoid that, we can just slightly
tweak the API to return an Expected<T>, and propagate the error
accordingly.
Copy link
Contributor Author

ilovepi commented Nov 19, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

@llvmbot
Copy link
Member

llvmbot commented Nov 19, 2025

@llvm/pr-subscribers-clang-tools-extra

Author: Paul Kirth (ilovepi)

Changes

In BitcodeReader, we were using consumeError(), which drops the error
and hides it from normal usage. To avoid that, we can just slightly
tweak the API to return an Expected<T>, and propagate the error
accordingly.


Full diff: https://github.com/llvm/llvm-project/pull/168759.diff

2 Files Affected:

  • (modified) clang-tools-extra/clang-doc/BitcodeReader.cpp (+20-26)
  • (modified) clang-tools-extra/clang-doc/BitcodeReader.h (+1-1)
diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp
index 4efbbd34730cf..0af7aeb1d3500 100644
--- a/clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -847,9 +847,11 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
 
   while (true) {
     unsigned BlockOrCode = 0;
-    Cursor Res = skipUntilRecordOrBlock(BlockOrCode);
+    llvm::Expected<Cursor> C = skipUntilRecordOrBlock(BlockOrCode);
+    if (!C)
+      return C.takeError();
 
-    switch (Res) {
+    switch (*C) {
     case Cursor::BadBlock:
       return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                      "bad block found");
@@ -985,45 +987,39 @@ llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
   }
 }
 
-ClangDocBitcodeReader::Cursor
+llvm::Expected<ClangDocBitcodeReader::Cursor>
 ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) {
   llvm::TimeTraceScope("Reducing infos", "skipUntilRecordOrBlock");
   BlockOrRecordID = 0;
 
   while (!Stream.AtEndOfStream()) {
-    Expected<unsigned> MaybeCode = Stream.ReadCode();
-    if (!MaybeCode) {
-      // FIXME this drops the error on the floor.
-      consumeError(MaybeCode.takeError());
-      return Cursor::BadBlock;
-    }
+    Expected<unsigned> Code = Stream.ReadCode();
+    if (!Code)
+      return Code.takeError();
 
-    unsigned Code = MaybeCode.get();
-    if (Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) {
+    if (*Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) {
       BlockOrRecordID = Code;
       return Cursor::Record;
     }
-    switch (static_cast<llvm::bitc::FixedAbbrevIDs>(Code)) {
+    switch (static_cast<llvm::bitc::FixedAbbrevIDs>(*Code)) {
     case llvm::bitc::ENTER_SUBBLOCK:
       if (Expected<unsigned> MaybeID = Stream.ReadSubBlockID())
         BlockOrRecordID = MaybeID.get();
-      else {
-        // FIXME this drops the error on the floor.
-        consumeError(MaybeID.takeError());
-      }
+      else
+        return MaybeID.takeError();
       return Cursor::BlockBegin;
     case llvm::bitc::END_BLOCK:
       if (Stream.ReadBlockEnd())
-        return Cursor::BadBlock;
+        return llvm::createStringError(llvm::inconvertibleErrorCode(),
+                                       "error at end of block");
       return Cursor::BlockEnd;
     case llvm::bitc::DEFINE_ABBREV:
-      if (llvm::Error Err = Stream.ReadAbbrevRecord()) {
-        // FIXME this drops the error on the floor.
-        consumeError(std::move(Err));
-      }
+      if (llvm::Error Err = Stream.ReadAbbrevRecord())
+        return std::move(Err);
       continue;
     case llvm::bitc::UNABBREV_RECORD:
-      return Cursor::BadBlock;
+      return llvm::createStringError(llvm::inconvertibleErrorCode(),
+                                     "found unabbreviated record");
     case llvm::bitc::FIRST_APPLICATION_ABBREV:
       llvm_unreachable("Unexpected abbrev id.");
     }
@@ -1149,10 +1145,8 @@ ClangDocBitcodeReader::readBitcode() {
         return std::move(Err);
       continue;
     default:
-      if (llvm::Error Err = Stream.SkipBlock()) {
-        // FIXME this drops the error on the floor.
-        consumeError(std::move(Err));
-      }
+      if (llvm::Error Err = Stream.SkipBlock())
+        return std::move(Err);
       continue;
     }
   }
diff --git a/clang-tools-extra/clang-doc/BitcodeReader.h b/clang-tools-extra/clang-doc/BitcodeReader.h
index 4947721f0a06d..0f7f4f256f15b 100644
--- a/clang-tools-extra/clang-doc/BitcodeReader.h
+++ b/clang-tools-extra/clang-doc/BitcodeReader.h
@@ -59,7 +59,7 @@ class ClangDocBitcodeReader {
 
   // Helper function to step through blocks to find and dispatch the next record
   // or block to be read.
-  Cursor skipUntilRecordOrBlock(unsigned &BlockOrRecordID);
+  llvm::Expected<Cursor> skipUntilRecordOrBlock(unsigned &BlockOrRecordID);
 
   // Helper function to set up the appropriate type of Info.
   llvm::Expected<std::unique_ptr<Info>> readBlockToInfo(unsigned ID);

@github-actions
Copy link

🐧 Linux x64 Test Results

The build failed before running any tests. Click on a failure below to see the details.

tools/clang/tools/extra/clang-doc/CMakeFiles/obj.clangDoc.dir/BitcodeReader.cpp.o
FAILED: tools/clang/tools/extra/clang-doc/CMakeFiles/obj.clangDoc.dir/BitcodeReader.cpp.o
sccache /opt/llvm/bin/clang++ -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GLIBCXX_USE_CXX11_ABI=1 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/clang-doc -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clang-doc -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include -gmlt -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wno-pass-failed -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -fno-common -Woverloaded-virtual -Wno-nested-anon-types -O3 -DNDEBUG -std=c++17  -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -MD -MT tools/clang/tools/extra/clang-doc/CMakeFiles/obj.clangDoc.dir/BitcodeReader.cpp.o -MF tools/clang/tools/extra/clang-doc/CMakeFiles/obj.clangDoc.dir/BitcodeReader.cpp.o.d -o tools/clang/tools/extra/clang-doc/CMakeFiles/obj.clangDoc.dir/BitcodeReader.cpp.o -c /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clang-doc/BitcodeReader.cpp
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clang-doc/BitcodeReader.cpp:1001:25: error: assigning to 'unsigned int' from incompatible type 'Expected<unsigned int>'
1001 |       BlockOrRecordID = Code;
|                         ^~~~
1 error generated.

If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the infrastructure label.

Copy link
Member

@evelez7 evelez7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM except for the error the bot caught.

unsigned Code = MaybeCode.get();
if (Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) {
if (*Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) {
BlockOrRecordID = Code;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bot caught this, Code needs to be dereferenced since it's Expected now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants