From 3480baae47f10dfed8f31bf477416c35b8a9d57a Mon Sep 17 00:00:00 2001 From: Thomas Alexander Date: Mon, 1 Apr 2024 17:11:43 -0300 Subject: [PATCH] Fix diagnostic outputs for piping stdin. --- .../Frontend/OpenQASM3/QUIRGenQASM3Visitor.h | 17 ++++++--- lib/Frontend/OpenQASM3/OpenQASM3Frontend.cpp | 35 +++++++++++++------ .../OpenQASM3/QUIRGenQASM3Visitor.cpp | 15 +++++--- .../OpenQASM3/diagnostics-parse-error.qasm | 16 +++++++++ .../diagnostics-unsupported-error.qasm | 21 +++++++++++ 5 files changed, 84 insertions(+), 20 deletions(-) create mode 100644 test/Frontend/OpenQASM3/diagnostics-parse-error.qasm create mode 100644 test/Frontend/OpenQASM3/diagnostics-unsupported-error.qasm diff --git a/include/Frontend/OpenQASM3/QUIRGenQASM3Visitor.h b/include/Frontend/OpenQASM3/QUIRGenQASM3Visitor.h index 562e011d6..8dae976f3 100644 --- a/include/Frontend/OpenQASM3/QUIRGenQASM3Visitor.h +++ b/include/Frontend/OpenQASM3/QUIRGenQASM3Visitor.h @@ -47,10 +47,11 @@ class QUIRGenQASM3Visitor : public BaseQASM3Visitor { mlir::OpBuilder circuitParentBuilder; mlir::ModuleOp newModule; mlir::quir::CircuitOp currentCircuitOp; - std::string filename; bool hasFailed{false}; bool buildingInCircuit{false}; uint circuitCount{0}; + std::string fileName; + bool requiresParserLocationFix; mlir::Location getLocation(const QASM::ASTBase *); bool assign(mlir::Value &, const std::string &); @@ -117,17 +118,23 @@ class QUIRGenQASM3Visitor : public BaseQASM3Visitor { public: QUIRGenQASM3Visitor(QASM::ASTStatementList *sList, mlir::OpBuilder b, - mlir::ModuleOp newModule, std::string f) + mlir::ModuleOp newModule, std::string fileName, + bool requiresParserLocationFix = false) : BaseQASM3Visitor(sList), builder(b), topLevelBuilder(b), - circuitParentBuilder(b), newModule(newModule), filename(std::move(f)), + circuitParentBuilder(b), newModule(newModule), + fileName(std::move(fileName)), + requiresParserLocationFix(requiresParserLocationFix), expression(llvm::createStringError(llvm::inconvertibleErrorCode(), "Testing error")), varHandler(builder) {} QUIRGenQASM3Visitor(mlir::OpBuilder b, mlir::ModuleOp newModule, - std::string filename) + std::string fileName, + bool requiresParserLocationFix = false) : builder(b), topLevelBuilder(b), circuitParentBuilder(b), - newModule(newModule), filename(std::move(filename)), + fileName(std::move(fileName)), + requiresParserLocationFix(requiresParserLocationFix), + newModule(newModule), expression(llvm::createStringError(llvm::inconvertibleErrorCode(), "Testing error")), varHandler(builder) {} diff --git a/lib/Frontend/OpenQASM3/OpenQASM3Frontend.cpp b/lib/Frontend/OpenQASM3/OpenQASM3Frontend.cpp index 9b91c40d3..0a1b4e24e 100644 --- a/lib/Frontend/OpenQASM3/OpenQASM3Frontend.cpp +++ b/lib/Frontend/OpenQASM3/OpenQASM3Frontend.cpp @@ -142,13 +142,14 @@ llvm::Error qssc::frontend::openqasm3::parse( diagnosticCallback.has_value() ? &diagnosticCallback.value() : nullptr; sourceMgr_ = &sourceMgr; QASM::QasmDiagnosticEmitter::SetHandler( - [](const std::string &File, QASM::ASTLocation Loc, // NOLINT - const std::string &Msg, QASM::QasmDiagnosticEmitter::DiagLevel DL) { + [](const std::string &file, QASM::ASTLocation qasmLoc, // NOLINT + const std::string &msg, + QASM::QasmDiagnosticEmitter::DiagLevel qasmDiagLevel) { qssc::Severity diagLevel = qssc::Severity::Error; llvm::SourceMgr::DiagKind sourceMgrDiagKind = llvm::SourceMgr::DiagKind::DK_Error; - switch (DL) { + switch (qasmDiagLevel) { case QASM::QasmDiagnosticEmitter::DiagLevel::Error: diagLevel = qssc::Severity::Error; sourceMgrDiagKind = llvm::SourceMgr::DiagKind::DK_Error; @@ -178,13 +179,19 @@ llvm::Error qssc::frontend::openqasm3::parse( // Capture source context for including it in error messages assert(sourceMgr_); auto &sourceMgr = *sourceMgr_; - auto loc = sourceMgr.FindLocForLineAndColumn(1, Loc.LineNo, Loc.ColNo); + + auto lineNo = qasmLoc.LineNo; + // Workaround for https://github.com/openqasm/qe-qasm/issues/35 + // TODO: Remove once this bug is fixed + if (file == "\"-\"") + lineNo++; + + auto loc = sourceMgr.FindLocForLineAndColumn(1, lineNo, qasmLoc.ColNo); std::string errMsg; llvm::raw_string_ostream ostream(errMsg); sourceMgr.PrintMessage(ostream, loc, sourceMgrDiagKind, - "While parsing OpenQASM3 input: \n" + Msg + - "\n"); + "While parsing OpenQASM3 input: " + msg); llvm::errs() << errMsg << "\n"; @@ -195,14 +202,18 @@ llvm::Error qssc::frontend::openqasm3::parse( (*diagnosticCallback_)(diag); } - if (DL == QASM::QasmDiagnosticEmitter::DiagLevel::Error || - DL == QASM::QasmDiagnosticEmitter::DiagLevel::ICE) { + if (qasmDiagLevel == QASM::QasmDiagnosticEmitter::DiagLevel::Error || + qasmDiagLevel == QASM::QasmDiagnosticEmitter::DiagLevel::ICE) { // give up parsing after errors right away // TODO: update to recent qss-qasm to support continuing throw std::runtime_error("Failure parsing"); } }); + // Workaround for https://github.com/openqasm/qe-qasm/issues/35 + // TODO: Remove once this bug is fixed + bool requiresParserLocationFix = false; + try { auto sourceFile = sourceBuffer->getBufferIdentifier(); @@ -212,8 +223,10 @@ llvm::Error qssc::frontend::openqasm3::parse( if (!(sourceFile == "" || sourceFile == "")) { QASM::QasmPreprocessor::Instance().SetTranslationUnit(sourceFile.str()); root.reset(parser.ParseAST()); - } else + } else { root.reset(parser.ParseAST(sourceBuffer->getBuffer().str())); + requiresParserLocationFix = true; + } } catch (std::exception &e) { return llvm::createStringError( @@ -252,8 +265,8 @@ llvm::Error qssc::frontend::openqasm3::parse( QASM::ASTStatementList *statementList = QASM::ASTStatementBuilder::Instance().List(); - qssc::frontend::openqasm3::QUIRGenQASM3Visitor visitor(builder, newModule, - /*filename=*/""); + qssc::frontend::openqasm3::QUIRGenQASM3Visitor visitor( + builder, newModule, "", requiresParserLocationFix); auto result = parseDurationStr(shotDelay); if (auto err = result.takeError()) diff --git a/lib/Frontend/OpenQASM3/QUIRGenQASM3Visitor.cpp b/lib/Frontend/OpenQASM3/QUIRGenQASM3Visitor.cpp index 8722c9f6d..fe15ba242 100644 --- a/lib/Frontend/OpenQASM3/QUIRGenQASM3Visitor.cpp +++ b/lib/Frontend/OpenQASM3/QUIRGenQASM3Visitor.cpp @@ -149,8 +149,15 @@ llvm::cl::opt debugCircuits("debug-circuits", } // anonymous namespace auto QUIRGenQASM3Visitor::getLocation(const ASTBase *node) -> Location { - return mlir::FileLineColLoc::get(builder.getContext(), filename, - node->GetLineNo(), node->GetColNo()); + + // Workaround for https://github.com/openqasm/qe-qasm/issues/35 + // TODO: Remove once this bug is fixed + auto lineNo = node->GetLineNo(); + if (requiresParserLocationFix) + lineNo++; + + return mlir::FileLineColLoc::get(builder.getContext(), fileName, lineNo, + node->GetColNo()); } auto QUIRGenQASM3Visitor::assign(Value &val, const std::string &valName) @@ -264,7 +271,7 @@ void QUIRGenQASM3Visitor::initialize( uint numShots, const double &shotDelay, const mlir::quir::TimeUnits &shotDelayUnits) { Location const initialLocation = - mlir::FileLineColLoc::get(topLevelBuilder.getContext(), filename, 0, 0); + mlir::FileLineColLoc::get(topLevelBuilder.getContext(), fileName, 0, 0); // create the "main" function auto func = topLevelBuilder.create( @@ -326,7 +333,7 @@ void QUIRGenQASM3Visitor::initialize( } void QUIRGenQASM3Visitor::setInputFile(std::string fName) { - filename = std::move(fName); + fileName = std::move(fName); } mlir::LogicalResult QUIRGenQASM3Visitor::walkAST() { diff --git a/test/Frontend/OpenQASM3/diagnostics-parse-error.qasm b/test/Frontend/OpenQASM3/diagnostics-parse-error.qasm new file mode 100644 index 000000000..108119efb --- /dev/null +++ b/test/Frontend/OpenQASM3/diagnostics-parse-error.qasm @@ -0,0 +1,16 @@ +OPENQASM 3.0; +// Ensure piping of input also works with diagnostics. +// TODO: Once https://github.com/openqasm/qe-qasm/issues/35 +// is fixed this test will error and the workaround +// in OpenQASM3Frontend.cpp for line number offsets +// will need to be removed for the test to pass. +// RUN: cat %s | ( qss-compiler -X=qasm --emit=mlir || true ) 2>&1 | FileCheck %s --dump-input=fail +// RUN: ( qss-compiler -X=qasm --emit=mlir %s || true ) 2>&1 | FileCheck %s --dump-input=fail + +int a; +int b; + +a &&& b; +// CHECK: error: While parsing OpenQASM3 input: syntax error, unexpected '&' +// CHECK: a &&& b; +// CHECK: ^ diff --git a/test/Frontend/OpenQASM3/diagnostics-unsupported-error.qasm b/test/Frontend/OpenQASM3/diagnostics-unsupported-error.qasm new file mode 100644 index 000000000..9c41e5942 --- /dev/null +++ b/test/Frontend/OpenQASM3/diagnostics-unsupported-error.qasm @@ -0,0 +1,21 @@ +OPENQASM 3.0; +// Ensure piping of input also works with diagnostics. +// TODO: Once https://github.com/openqasm/qe-qasm/issues/35 +// is fixed this test will error and the workaround +// in QUIRGenQASM3Visitor.cpp +// for line number offsets +// will need to be removed for the test to pass. +// RUN: cat %s | ( qss-compiler -X=qasm --emit=mlir || true ) 2>&1 | FileCheck %s --dump-input=fail +// RUN: ( qss-compiler -X=qasm --emit=mlir %s || true ) 2>&1 | FileCheck %s --dump-input=fail + +int a; +float b; +int c; +c = float(a) + b; + +// CHECK: error: Unsupported cast destination type ASTTypeFloat +// CHECK: c = float(a) + b; +// CHECK: ^ +// CHECK: error: Addition is not supported on value of type: 'none' +// CHECK: c = float(a) + b; +// CHECK: ^