[JSON] Leave json::OStream in valid state on failure (#7684)

Make sure that calls to begin/end functions are balanced even when an
error occurs. This leaves the `json::OStream` object in a valid state
and allows surrounding code to handle the failure gracefully. Otherwise
an assertion in the destructor of `json::OStream` would fire because of
unclosed JSON scopes.
This commit is contained in:
Fabian Schuiki 2024-10-08 22:00:42 -07:00 committed by GitHub
parent 4e7c90631d
commit 307160cad5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 12 additions and 5 deletions

View File

@ -11,12 +11,14 @@
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/OperationSupport.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/TypeSwitch.h"
namespace json = llvm::json;
using namespace circt;
using llvm::make_scope_exit;
using mlir::UnitAttr;
// NOLINTBEGIN(misc-no-recursion)
@ -25,21 +27,21 @@ LogicalResult circt::convertAttributeToJSON(llvm::json::OStream &json,
return TypeSwitch<Attribute, LogicalResult>(attr)
.Case<DictionaryAttr>([&](auto attr) {
json.objectBegin();
auto guard = make_scope_exit([&] { json.objectEnd(); });
for (auto subAttr : attr) {
json.attributeBegin(subAttr.getName());
auto guard = make_scope_exit([&] { json.attributeEnd(); });
if (failed(convertAttributeToJSON(json, subAttr.getValue())))
return failure();
json.attributeEnd();
}
json.objectEnd();
return success();
})
.Case<ArrayAttr>([&](auto attr) {
json.arrayBegin();
auto guard = make_scope_exit([&] { json.arrayEnd(); });
for (auto subAttr : attr)
if (failed(convertAttributeToJSON(json, subAttr)))
return failure();
json.arrayEnd();
return success();
})
.Case<BoolAttr, StringAttr>([&](auto attr) {
@ -50,8 +52,10 @@ LogicalResult circt::convertAttributeToJSON(llvm::json::OStream &json,
// If the integer can be accurately represented by a double, print
// it as an integer. Otherwise, convert it to an exact decimal string.
const auto &apint = attr.getValue();
if (!apint.isSignedIntN(64))
if (!apint.isSignedIntN(64)) {
json.value(nullptr);
return failure();
}
json.value(apint.getSExtValue());
return success();
})
@ -60,7 +64,10 @@ LogicalResult circt::convertAttributeToJSON(llvm::json::OStream &json,
json.value(apfloat.convertToDouble());
return success();
})
.Default([&](auto) -> LogicalResult { return failure(); });
.Default([&](auto) -> LogicalResult {
json.value(nullptr);
return failure();
});
}
// NOLINTEND(misc-no-recursion)