Преглед изворни кода

Have the driver return errors on SemanticsIR errors. (#2471)

This does a high level check on diagnostics in order to be minimally invasive on the semantics code.
Jon Ross-Perkins пре 3 година
родитељ
комит
8e6d48004b

+ 8 - 4
toolchain/driver/driver.cpp

@@ -162,24 +162,28 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
     return false;
   }
 
+  bool has_errors = false;
+
   CARBON_VLOG() << "*** TokenizedBuffer::Lex ***\n";
   auto tokenized_source = TokenizedBuffer::Lex(*source, consumer);
+  has_errors |= tokenized_source.has_errors();
   CARBON_VLOG() << "*** TokenizedBuffer::Lex done ***\n";
   if (dump_mode == DumpMode::TokenizedBuffer) {
     CARBON_VLOG() << "Finishing output.";
     consumer.Flush();
     tokenized_source.Print(output_stream_);
-    return !tokenized_source.has_errors();
+    return !has_errors;
   }
   CARBON_VLOG() << "tokenized_buffer: " << tokenized_source;
 
   CARBON_VLOG() << "*** ParseTree::Parse ***\n";
   auto parse_tree = ParseTree::Parse(tokenized_source, consumer, vlog_stream_);
+  has_errors |= parse_tree.has_errors();
   CARBON_VLOG() << "*** ParseTree::Parse done ***\n";
   if (dump_mode == DumpMode::ParseTree) {
     consumer.Flush();
     parse_tree.Print(output_stream_, parse_tree_preorder);
-    return !tokenized_source.has_errors() && !parse_tree.has_errors();
+    return !has_errors;
   }
   CARBON_VLOG() << "parse_tree: " << parse_tree;
 
@@ -187,12 +191,12 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
   CARBON_VLOG() << "*** SemanticsIR::MakeFromParseTree ***\n";
   const SemanticsIR semantics_ir = SemanticsIR::MakeFromParseTree(
       builtin_ir, tokenized_source, parse_tree, consumer, vlog_stream_);
+  has_errors |= semantics_ir.has_errors();
   CARBON_VLOG() << "*** SemanticsIR::MakeFromParseTree done ***\n";
   if (dump_mode == DumpMode::SemanticsIR) {
     consumer.Flush();
     semantics_ir.Print(output_stream_);
-    // TODO: Return false when SemanticsIR has errors (not supported right now).
-    return !tokenized_source.has_errors() && !parse_tree.has_errors();
+    return !has_errors;
   }
   CARBON_VLOG() << "semantics_ir: " << semantics_ir;
 

+ 3 - 1
toolchain/semantics/semantics_ir.cpp

@@ -66,9 +66,11 @@ auto SemanticsIR::MakeFromParseTree(const SemanticsIR& builtin_ir,
 
   TokenizedBuffer::TokenLocationTranslator translator(
       &tokens, /*last_line_lexed_to_column=*/nullptr);
-  TokenDiagnosticEmitter emitter(translator, consumer);
+  ErrorTrackingDiagnosticConsumer err_tracker(consumer);
+  TokenDiagnosticEmitter emitter(translator, err_tracker);
   SemanticsParseTreeHandler(tokens, emitter, parse_tree, semantics, vlog_stream)
       .Build();
+  semantics.has_errors_ = err_tracker.seen_error();
   return semantics;
 }
 

+ 5 - 0
toolchain/semantics/semantics_ir.h

@@ -56,6 +56,9 @@ class SemanticsIR {
   // Prints the full IR.
   auto Print(llvm::raw_ostream& out) const -> void;
 
+  // Returns true if there were errors creating the semantics IR.
+  auto has_errors() const -> bool { return has_errors_; }
+
  private:
   friend class SemanticsParseTreeHandler;
 
@@ -128,6 +131,8 @@ class SemanticsIR {
     return node_id;
   }
 
+  bool has_errors_ = false;
+
   // Related IRs. There will always be at least 2 entries, the builtin IR (used
   // for references of builtins) followed by the current IR (used for references
   // crossing node blocks).

+ 2 - 2
toolchain/semantics/testdata/operators/type_mismatch.carbon → toolchain/semantics/testdata/operators/fail_type_mismatch.carbon

@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 // AUTOUPDATE
-// RUN: %{carbon-run-semantics}
+// RUN: %{not} %{carbon-run-semantics}
 // CHECK:STDOUT: cross_reference_irs.size == 2,
 // CHECK:STDOUT: cross_references = {
 // CHECK:STDOUT:   node_xref0 = xref(ir0, block0, node0);
@@ -32,6 +32,6 @@
 // CHECK:STDOUT: }
 
 fn Main() {
-  // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/operators/type_mismatch.carbon:[[@LINE+1]]:13: Type mismatch
+  // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/operators/fail_type_mismatch.carbon:[[@LINE+1]]:13: Type mismatch
   return 12 + 3.4;
 }

+ 2 - 2
toolchain/semantics/testdata/operators/type_mismatch_once.carbon → toolchain/semantics/testdata/operators/fail_type_mismatch_once.carbon

@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 // AUTOUPDATE
-// RUN: %{carbon-run-semantics}
+// RUN: %{not} %{carbon-run-semantics}
 // CHECK:STDOUT: cross_reference_irs.size == 2,
 // CHECK:STDOUT: cross_references = {
 // CHECK:STDOUT:   node_xref0 = xref(ir0, block0, node0);
@@ -37,6 +37,6 @@
 fn Main() {
   // The following line has two mismatches, but after the first, it shouldn't
   // keep erroring.
-  // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/operators/type_mismatch_once.carbon:[[@LINE+1]]:13: Type mismatch
+  // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/operators/fail_type_mismatch_once.carbon:[[@LINE+1]]:13: Type mismatch
   return 12 + 3.4 + 12;
 }

+ 2 - 2
toolchain/semantics/testdata/var/init_type_mismatch.carbon → toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon

@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 // AUTOUPDATE
-// RUN: %{carbon-run-semantics}
+// RUN: %{not} %{carbon-run-semantics}
 // CHECK:STDOUT: cross_reference_irs.size == 2,
 // CHECK:STDOUT: cross_references = {
 // CHECK:STDOUT:   node_xref0 = xref(ir0, block0, node0);
@@ -32,6 +32,6 @@
 // CHECK:STDOUT: }
 
 fn Main() {
-  // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/var/init_type_mismatch.carbon:[[@LINE+1]]:19: Type mismatch
+  // CHECK:STDERR: {{.*}}/toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon:[[@LINE+1]]:19: Type mismatch
   var x: i32 = 1.0;
 }