Sfoglia il codice sorgente

Switch from assert to a CHECK macro to run in all build modes. (#595)

Jon Meow 4 anni fa
parent
commit
6c259dd5de

+ 18 - 0
common/BUILD

@@ -4,6 +4,24 @@
 
 package(default_visibility = ["//visibility:public"])
 
+cc_library(
+    name = "check",
+    hdrs = ["check.h"],
+    deps = [
+        "@llvm-project//llvm:Support",
+    ],
+)
+
+cc_test(
+    name = "check_test",
+    srcs = ["check_test.cpp"],
+    deps = [
+        ":check",
+        "@llvm-project//llvm:gtest",
+        "@llvm-project//llvm:gtest_main",
+    ],
+)
+
 cc_library(
     name = "indirect_value",
     srcs = ["indirect_value.h"],

+ 18 - 0
common/check.h

@@ -0,0 +1,18 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#ifndef COMMON_CHECK_H_
+#define COMMON_CHECK_H_
+
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/raw_ostream.h"
+
+#define CHECK(condition)                                    \
+  if (!(condition)) {                                       \
+    llvm::sys::PrintStackTrace(llvm::errs());               \
+    llvm::report_fatal_error("CHECK failure: " #condition); \
+  }
+
+#endif  // COMMON_CHECK_H_

+ 17 - 0
common/check_test.cpp

@@ -0,0 +1,17 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#include "common/check.h"
+
+#include "gtest/gtest.h"
+
+namespace Carbon {
+
+TEST(CheckTest, CheckTrue) { CHECK(true); }
+
+TEST(CheckTest, CheckFalse) {
+  ASSERT_DEATH({ CHECK(false); }, "LLVM ERROR: CHECK failure: false");
+}
+
+}  // namespace Carbon

+ 4 - 1
executable_semantics/ast/BUILD

@@ -49,7 +49,10 @@ cc_library(
     name = "statement",
     srcs = ["statement.cpp"],
     hdrs = ["statement.h"],
-    deps = [":expression"],
+    deps = [
+        ":expression",
+        "//common:check",
+    ],
 )
 
 cc_library(

+ 0 - 1
executable_semantics/ast/expression.cpp

@@ -4,7 +4,6 @@
 
 #include "executable_semantics/ast/expression.h"
 
-#include <cassert>
 #include <iostream>
 
 namespace Carbon {

+ 13 - 12
executable_semantics/ast/statement.cpp

@@ -4,63 +4,64 @@
 
 #include "executable_semantics/ast/statement.h"
 
-#include <cassert>
 #include <iostream>
 
+#include "common/check.h"
+
 namespace Carbon {
 
 const Expression* Statement::GetExpression() const {
-  assert(tag == StatementKind::ExpressionStatement);
+  CHECK(tag == StatementKind::ExpressionStatement);
   return u.exp;
 }
 
 Assignment Statement::GetAssign() const {
-  assert(tag == StatementKind::Assign);
+  CHECK(tag == StatementKind::Assign);
   return u.assign;
 }
 
 VariableDefinition Statement::GetVariableDefinition() const {
-  assert(tag == StatementKind::VariableDefinition);
+  CHECK(tag == StatementKind::VariableDefinition);
   return u.variable_definition;
 }
 
 IfStatement Statement::GetIf() const {
-  assert(tag == StatementKind::If);
+  CHECK(tag == StatementKind::If);
   return u.if_stmt;
 }
 
 const Expression* Statement::GetReturn() const {
-  assert(tag == StatementKind::Return);
+  CHECK(tag == StatementKind::Return);
   return u.return_stmt;
 }
 
 Sequence Statement::GetSequence() const {
-  assert(tag == StatementKind::Sequence);
+  CHECK(tag == StatementKind::Sequence);
   return u.sequence;
 }
 
 Block Statement::GetBlock() const {
-  assert(tag == StatementKind::Block);
+  CHECK(tag == StatementKind::Block);
   return u.block;
 }
 
 While Statement::GetWhile() const {
-  assert(tag == StatementKind::While);
+  CHECK(tag == StatementKind::While);
   return u.while_stmt;
 }
 
 Match Statement::GetMatch() const {
-  assert(tag == StatementKind::Match);
+  CHECK(tag == StatementKind::Match);
   return u.match_stmt;
 }
 
 Continuation Statement::GetContinuation() const {
-  assert(tag == StatementKind::Continuation);
+  CHECK(tag == StatementKind::Continuation);
   return u.continuation;
 }
 
 Run Statement::GetRun() const {
-  assert(tag == StatementKind::Run);
+  CHECK(tag == StatementKind::Run);
   return u.run;
 }
 

+ 2 - 0
executable_semantics/interpreter/BUILD

@@ -23,6 +23,7 @@ cc_library(
     ],
     deps = [
         ":containers",
+        "//common:check",
         "//executable_semantics:tracing_flag",
         "//executable_semantics/ast:declaration",
         "//executable_semantics/ast:expression",
@@ -41,4 +42,5 @@ cc_library(
         "dictionary.h",
         "stack.h",
     ],
+    deps = ["//common:check"],
 )

+ 4 - 4
executable_semantics/interpreter/interpreter.cpp

@@ -4,7 +4,6 @@
 
 #include "executable_semantics/interpreter/interpreter.h"
 
-#include <cassert>
 #include <iostream>
 #include <iterator>
 #include <list>
@@ -13,6 +12,7 @@
 #include <utility>
 #include <vector>
 
+#include "common/check.h"
 #include "executable_semantics/ast/expression.h"
 #include "executable_semantics/ast/function_definition.h"
 #include "executable_semantics/interpreter/stack.h"
@@ -36,7 +36,7 @@ auto Heap::AllocateValue(const Value* v) -> Address {
   // ensures that we don't do anything else in between, which is really bad!
   // Consider whether to include a copy of the input v in this function
   // or to leave it up to the caller.
-  assert(v != nullptr);
+  CHECK(v != nullptr);
   Address a = values_.size();
   values_.push_back(v);
   alive_.push_back(true);
@@ -49,7 +49,7 @@ auto Heap::Read(Address a, int line_num) -> const Value* {
 }
 
 auto Heap::Write(Address a, const Value* v, int line_num) -> void {
-  assert(v != nullptr);
+  CHECK(v != nullptr);
   this->CheckAlive(a, line_num);
   values_[a] = v;
 }
@@ -838,7 +838,7 @@ void StepStmt() {
   Frame* frame = state->stack.Top();
   Action* act = frame->todo.Top();
   const Statement* stmt = act->u.stmt;
-  assert(stmt != nullptr && "null statement!");
+  CHECK(stmt != nullptr && "null statement!");
   if (tracing_output) {
     std::cout << "--- step stmt ";
     PrintStatement(stmt, 1);

+ 5 - 5
executable_semantics/interpreter/stack.h

@@ -5,10 +5,10 @@
 #ifndef EXECUTABLE_SEMANTICS_INTERPRETER_STACK_H_
 #define EXECUTABLE_SEMANTICS_INTERPRETER_STACK_H_
 
-#include <cassert>
 #include <cstddef>
 #include <iterator>
 
+#include "common/check.h"
 #include "executable_semantics/interpreter/list_node.h"
 
 namespace Carbon {
@@ -73,7 +73,7 @@ struct Stack {
   //
   // - Requires: !this->IsEmpty()
   auto Pop() -> T {
-    assert(!IsEmpty() && "Can't pop from empty stack.");
+    CHECK(!IsEmpty() && "Can't pop from empty stack.");
     auto r = head->curr;
     head = head->next;
     return r;
@@ -83,9 +83,9 @@ struct Stack {
   //
   // - Requires: n >= 0 && n <= Count()
   void Pop(int n) {
-    assert(n >= 0 && "Negative pop count disallowed.");
+    CHECK(n >= 0 && "Negative pop count disallowed.");
     while (n--) {
-      assert(head != nullptr && "Can only pop as many elements as stack has.");
+      CHECK(head != nullptr && "Can only pop as many elements as stack has.");
       head = head->next;
     }
   }
@@ -103,7 +103,7 @@ struct Stack {
   //
   // - Requires: !this->IsEmpty()
   auto Top() const -> T {
-    assert(!IsEmpty() && "Empty stack has no Top().");
+    CHECK(!IsEmpty() && "Empty stack has no Top().");
     return head->curr;
   }
 

+ 17 - 17
executable_semantics/interpreter/value.cpp

@@ -5,85 +5,85 @@
 #include "executable_semantics/interpreter/value.h"
 
 #include <algorithm>
-#include <cassert>
 #include <iostream>
 
+#include "common/check.h"
 #include "executable_semantics/interpreter/interpreter.h"
 
 namespace Carbon {
 
 int Value::GetInteger() const {
-  assert(tag == ValKind::IntV);
+  CHECK(tag == ValKind::IntV);
   return u.integer;
 }
 
 bool Value::GetBoolean() const {
-  assert(tag == ValKind::BoolV);
+  CHECK(tag == ValKind::BoolV);
   return u.boolean;
 }
 
 Function Value::GetFunction() const {
-  assert(tag == ValKind::FunV);
+  CHECK(tag == ValKind::FunV);
   return u.fun;
 }
 
 StructConstructor Value::GetStruct() const {
-  assert(tag == ValKind::StructV);
+  CHECK(tag == ValKind::StructV);
   return u.struct_val;
 }
 
 AlternativeConstructor Value::GetAlternativeConstructor() const {
-  assert(tag == ValKind::AltConsV);
+  CHECK(tag == ValKind::AltConsV);
   return u.alt_cons;
 }
 
 Alternative Value::GetAlternative() const {
-  assert(tag == ValKind::AltV);
+  CHECK(tag == ValKind::AltV);
   return u.alt;
 }
 
 TupleValue Value::GetTuple() const {
-  assert(tag == ValKind::TupleV);
+  CHECK(tag == ValKind::TupleV);
   return u.tuple;
 }
 
 Address Value::GetPointer() const {
-  assert(tag == ValKind::PtrV);
+  CHECK(tag == ValKind::PtrV);
   return u.ptr;
 }
 
 std::string* Value::GetVariableType() const {
-  assert(tag == ValKind::VarTV);
+  CHECK(tag == ValKind::VarTV);
   return u.var_type;
 }
 
 VariablePatternValue Value::GetVariablePattern() const {
-  assert(tag == ValKind::VarPatV);
+  CHECK(tag == ValKind::VarPatV);
   return u.var_pat;
 }
 
 FunctionTypeValue Value::GetFunctionType() const {
-  assert(tag == ValKind::FunctionTV);
+  CHECK(tag == ValKind::FunctionTV);
   return u.fun_type;
 }
 
 PointerType Value::GetPointerType() const {
-  assert(tag == ValKind::PointerTV);
+  CHECK(tag == ValKind::PointerTV);
   return u.ptr_type;
 }
 
 StructType Value::GetStructType() const {
-  assert(tag == ValKind::StructTV);
+  CHECK(tag == ValKind::StructTV);
   return u.struct_type;
 }
 
 ChoiceType Value::GetChoiceType() const {
-  assert(tag == ValKind::ChoiceTV);
+  CHECK(tag == ValKind::ChoiceTV);
   return u.choice_type;
 }
 
 ContinuationValue Value::GetContinuation() const {
-  assert(tag == ValKind::ContinuationV);
+  CHECK(tag == ValKind::ContinuationV);
   return u.continuation;
 }
 
@@ -116,7 +116,7 @@ auto FieldsEqual(VarValues* ts1, VarValues* ts2) -> bool {
 
 auto FindTupleField(const std::string& name, const Value* tuple)
     -> std::optional<Address> {
-  assert(tuple->tag == ValKind::TupleV);
+  CHECK(tuple->tag == ValKind::TupleV);
   for (const TupleElement& element : *tuple->GetTuple().elements) {
     if (element.name == name) {
       return element.address;