Bläddra i källkod

Implementation of unformed state for global variables. (#1571)

- Allocate UninitializedValue on heap when a VariableDeclaration does not have initialization.
- Added test cases.
Zenong Zhang 3 år sedan
förälder
incheckning
075b3aba1b

+ 3 - 0
explorer/interpreter/interpreter.cpp

@@ -1627,6 +1627,9 @@ auto Interpreter::StepDeclaration() -> ErrorOr<Success> {
           return todo_.FinishAction();
           return todo_.FinishAction();
         }
         }
       } else {
       } else {
+        Nonnull<const Value*> v =
+            arena_->New<UninitializedValue>(&var_decl.binding().value());
+        todo_.Initialize(&var_decl.binding(), v);
         return todo_.FinishAction();
         return todo_.FinishAction();
       }
       }
     }
     }

+ 3 - 2
explorer/testdata/uninitialized/fail_uninitialized_return.carbon → explorer/testdata/uninitialized/fail_global_uninitialized.carbon

@@ -10,8 +10,9 @@
 
 
 package ExplorerTest api;
 package ExplorerTest api;
 
 
+var x: i32;
+
 fn Main() -> i32 {
 fn Main() -> i32 {
-  var x: i32;
-  // CHECK: RUNTIME ERROR: {{.*}}/explorer/testdata/uninitialized/fail_uninitialized_return.carbon:[[@LINE+1]]: undefined behavior: access to uninitialized value Uninit<Placeholder<x>>
+  // CHECK: RUNTIME ERROR: {{.*}}/explorer/testdata/uninitialized/fail_global_uninitialized.carbon:[[@LINE+1]]: undefined behavior: access to uninitialized value Uninit<Placeholder<x>>
   return x;
   return x;
 }
 }

+ 1 - 1
explorer/testdata/uninitialized/fail_uninitialized_assign.carbon → explorer/testdata/uninitialized/fail_local_uninitialized_assign.carbon

@@ -13,7 +13,7 @@ package ExplorerTest api;
 fn Main() -> i32 {
 fn Main() -> i32 {
   var x: i32;
   var x: i32;
   var y: i32;
   var y: i32;
-  // CHECK: RUNTIME ERROR: {{.*}}/explorer/testdata/uninitialized/fail_uninitialized_assign.carbon:[[@LINE+1]]: undefined behavior: access to uninitialized value Uninit<Placeholder<x>>
+  // CHECK: RUNTIME ERROR: {{.*}}/explorer/testdata/uninitialized/fail_local_uninitialized_assign.carbon:[[@LINE+1]]: undefined behavior: access to uninitialized value Uninit<Placeholder<x>>
   y = x;
   y = x;
   return y;
   return y;
 }
 }

+ 1 - 1
explorer/testdata/uninitialized/fail_uninitialized_init.carbon → explorer/testdata/uninitialized/fail_local_uninitialized_init.carbon

@@ -12,7 +12,7 @@ package ExplorerTest api;
 
 
 fn Main() -> i32 {
 fn Main() -> i32 {
   var x: i32;
   var x: i32;
-  // CHECK: RUNTIME ERROR: {{.*}}/explorer/testdata/uninitialized/fail_uninitialized_init.carbon:[[@LINE+1]]: undefined behavior: access to uninitialized value Uninit<Placeholder<x>>
+  // CHECK: RUNTIME ERROR: {{.*}}/explorer/testdata/uninitialized/fail_local_uninitialized_init.carbon:[[@LINE+1]]: undefined behavior: access to uninitialized value Uninit<Placeholder<x>>
   var y: i32 = x;
   var y: i32 = x;
   return x;
   return x;
 }
 }

+ 1 - 1
explorer/testdata/uninitialized/fail_uninitialized_param.carbon → explorer/testdata/uninitialized/fail_local_uninitialized_param.carbon

@@ -16,6 +16,6 @@ fn AddInt(a: i32, b: i32) -> auto {
 
 
 fn Main() -> i32 {
 fn Main() -> i32 {
   var x: i32;
   var x: i32;
-  // CHECK: RUNTIME ERROR: {{.*}}/explorer/testdata/uninitialized/fail_uninitialized_param.carbon:[[@LINE+1]]: undefined behavior: access to uninitialized value Uninit<Placeholder<x>>
+  // CHECK: RUNTIME ERROR: {{.*}}/explorer/testdata/uninitialized/fail_local_uninitialized_param.carbon:[[@LINE+1]]: undefined behavior: access to uninitialized value Uninit<Placeholder<x>>
   return AddInt(x, 2);
   return AddInt(x, 2);
 }
 }

+ 1 - 1
explorer/testdata/uninitialized/fail_uninitialized_pattern.carbon → explorer/testdata/uninitialized/fail_local_uninitialized_pattern.carbon

@@ -13,6 +13,6 @@ package ExplorerTest api;
 fn Main() -> i32 {
 fn Main() -> i32 {
   var (x: i32, y: i32);
   var (x: i32, y: i32);
   x = 1;
   x = 1;
-  // CHECK: RUNTIME ERROR: {{.*}}/explorer/testdata/uninitialized/fail_uninitialized_pattern.carbon:[[@LINE+1]]: undefined behavior: access to uninitialized value Uninit<Placeholder<y>>
+  // CHECK: RUNTIME ERROR: {{.*}}/explorer/testdata/uninitialized/fail_local_uninitialized_pattern.carbon:[[@LINE+1]]: undefined behavior: access to uninitialized value Uninit<Placeholder<y>>
   return y;
   return y;
 }
 }

+ 17 - 0
explorer/testdata/uninitialized/fail_local_uninitialized_return.carbon

@@ -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
+//
+// RUN: %{not} %{explorer} %s 2>&1 | \
+// RUN:   %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s
+// RUN: %{not} %{explorer} --parser_debug --trace_file=- %s 2>&1 | \
+// RUN:   %{FileCheck} --match-full-lines --allow-unused-prefixes %s
+// AUTOUPDATE: %{explorer} %s
+
+package ExplorerTest api;
+
+fn Main() -> i32 {
+  var x: i32;
+  // CHECK: RUNTIME ERROR: {{.*}}/explorer/testdata/uninitialized/fail_local_uninitialized_return.carbon:[[@LINE+1]]: undefined behavior: access to uninitialized value Uninit<Placeholder<x>>
+  return x;
+}

+ 19 - 0
explorer/testdata/uninitialized/global_declare.carbon

@@ -0,0 +1,19 @@
+// 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
+//
+// RUN: %{explorer} %s 2>&1 | \
+// RUN:   %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s
+// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \
+// RUN:   %{FileCheck} --match-full-lines --allow-unused-prefixes %s
+// AUTOUPDATE: %{explorer} %s
+// CHECK: result: 1
+
+package ExplorerTest api;
+
+var x: i32;
+
+fn Main() -> i32 {
+  x = 1;
+  return x;
+}

+ 18 - 0
explorer/testdata/uninitialized/global_uninit_without_use.carbon

@@ -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
+//
+// RUN: %{explorer} %s 2>&1 | \
+// RUN:   %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s
+// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \
+// RUN:   %{FileCheck} --match-full-lines --allow-unused-prefixes %s
+// AUTOUPDATE: %{explorer} %s
+// CHECK: result: 1
+
+package ExplorerTest api;
+
+var x: i32;
+
+fn Main() -> i32 {
+  return 1;
+}

+ 25 - 0
explorer/testdata/uninitialized/global_uninitialized_escape.carbon

@@ -0,0 +1,25 @@
+// 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
+//
+// RUN: %{explorer} %s 2>&1 | \
+// RUN:   %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s
+// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \
+// RUN:   %{FileCheck} --match-full-lines --allow-unused-prefixes %s
+// AUTOUPDATE: %{explorer} %s
+// CHECK: result: 42
+
+package ExplorerTest api;
+
+// `y` is unformed here.
+var y: i32;
+
+fn AssignIntTo(x: i32, destination: i32*) {
+  *destination = x;
+}
+
+fn Main() -> i32 {
+  AssignIntTo(42, &y);
+  // `y` is fully formed and usable.
+  return y;
+}

+ 0 - 0
explorer/testdata/uninitialized/uninitialized_escape.carbon → explorer/testdata/uninitialized/local_uninitialized_escape.carbon