]> git.lizzy.rs Git - rust.git/commitdiff
Do not ICE in codegen given a extern_type static
authorDan Robertson <dan@dlrobertson.com>
Tue, 5 Feb 2019 15:52:54 +0000 (15:52 +0000)
committerDan Robertson <dan@dlrobertson.com>
Tue, 5 Feb 2019 21:20:07 +0000 (21:20 +0000)
The layout of a extern_type static is unsized, but may pass the
Well-Formed check in typeck. As a result, we cannot assume that
a static is sized when generating the `Place` for an r-value.

src/librustc_codegen_ssa/mir/place.rs
src/test/run-make-fulldeps/static-extern-type/Makefile [new file with mode: 0644]
src/test/run-make-fulldeps/static-extern-type/define-foo.c [new file with mode: 0644]
src/test/run-make-fulldeps/static-extern-type/use-foo.rs [new file with mode: 0644]

index b10611e5ac7977954f25aed3f45e82503de1752d..596f97a038892678a01520619a43b108b2b9c0f0 100644 (file)
@@ -41,6 +41,21 @@ pub fn new_sized(
         }
     }
 
+    fn new_thin_place<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
+        bx: &mut Bx,
+        llval: V,
+        layout: TyLayout<'tcx>,
+        align: Align,
+    ) -> PlaceRef<'tcx, V> {
+        assert!(!bx.cx().type_has_metadata(layout.ty));
+        PlaceRef {
+            llval,
+            llextra: None,
+            layout,
+            align
+        }
+    }
+
     pub fn alloca<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         bx: &mut Bx,
         layout: TyLayout<'tcx>,
@@ -421,8 +436,10 @@ pub fn codegen_place(
                 }
             }
             mir::Place::Static(box mir::Static { def_id, ty }) => {
+                // NB: The layout of a static may be unsized as is the case when working
+                // with a static that is an extern_type.
                 let layout = cx.layout_of(self.monomorphize(&ty));
-                PlaceRef::new_sized(bx.get_static(def_id), layout, layout.align.abi)
+                PlaceRef::new_thin_place(bx, bx.get_static(def_id), layout, layout.align.abi)
             },
             mir::Place::Projection(box mir::Projection {
                 ref base,
diff --git a/src/test/run-make-fulldeps/static-extern-type/Makefile b/src/test/run-make-fulldeps/static-extern-type/Makefile
new file mode 100644 (file)
index 0000000..5879fc0
--- /dev/null
@@ -0,0 +1,5 @@
+-include ../tools.mk
+
+all: $(call NATIVE_STATICLIB,define-foo)
+       $(RUSTC) -ldefine-foo use-foo.rs
+       $(call RUN,use-foo) || exit 1
diff --git a/src/test/run-make-fulldeps/static-extern-type/define-foo.c b/src/test/run-make-fulldeps/static-extern-type/define-foo.c
new file mode 100644 (file)
index 0000000..39be5ac
--- /dev/null
@@ -0,0 +1,11 @@
+#include <stdint.h>
+
+struct Foo {
+    uint8_t x;
+};
+
+struct Foo FOO = { 42 };
+
+uint8_t bar(const struct Foo* foo) {
+    return foo->x;
+}
diff --git a/src/test/run-make-fulldeps/static-extern-type/use-foo.rs b/src/test/run-make-fulldeps/static-extern-type/use-foo.rs
new file mode 100644 (file)
index 0000000..932b5b5
--- /dev/null
@@ -0,0 +1,14 @@
+#![feature(extern_types)]
+
+extern "C" {
+    type Foo;
+    static FOO: Foo;
+    fn bar(foo: *const Foo) -> u8;
+}
+
+fn main() {
+    unsafe {
+        let foo = &FOO;
+        assert_eq!(bar(foo), 42);
+    }
+}