diff --git a/gen/declarations.cpp b/gen/declarations.cpp index e8c3a4ad5a..b1eeffb95d 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -253,9 +253,12 @@ class CodegenVisitor : public Visitor { decl->toPrettyChars()); LOG_SCOPE; - if (decl->ir->isDefined()) { + if (decl->ir->isDefined()) + return; + + // skip external declarations (IR-declared lazily) + if (decl->storage_class & STCextern) return; - } if (decl->type->ty == TY::Terror) { error(decl->loc, "%s `%s` had semantic errors when compiling", diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 8472433603..4ff6bf60bf 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -957,6 +957,9 @@ DValue *DtoDeclarationExp(Dsymbol *declaration) { // static if (vd->isDataseg()) { Declaration_codegen(vd); + if (vd->storage_class & STCextern) { + DtoResolveVariable(vd); // make sure there's an IR declaration + } } else { DtoVarDeclaration(vd); } diff --git a/tests/codegen/avr.d b/tests/codegen/avr.d index c473cc7dc1..1e0c4073df 100644 --- a/tests/codegen/avr.d +++ b/tests/codegen/avr.d @@ -11,3 +11,5 @@ version (D_SoftFloat) {} else static assert(0); int definedGlobal = 123; // CHECK: @_D3avr14declaredGlobali = external global i32 extern int declaredGlobal; + +int dummyRef() { return declaredGlobal; } // make sure `declaredGlobal` is IR-declared diff --git a/tests/codegen/export.d b/tests/codegen/export.d index 0d16c77c69..72ef5332c2 100644 --- a/tests/codegen/export.d +++ b/tests/codegen/export.d @@ -5,26 +5,22 @@ export { - // non-TLS: - __gshared - { - // CHECK: @{{.*}}exportedGlobal{{.*}} = dllexport - void* exportedGlobal; - - // CHECK: @{{.*}}importedGlobal{{.*}} = external dllimport - extern void* importedGlobal; - } + // CHECK: @{{.*}}exportedGlobal{{.*}} = dllexport + __gshared void* exportedGlobal; // TLS: unsupported => linker errors - version (all) + // CHECK: @{{.*}}exportedTlsGlobal{{.*}} = thread_local + // CHECK-NOT: dllexport + void* exportedTlsGlobal; + + extern { - // CHECK: @{{.*}}exportedTlsGlobal{{.*}} = thread_local - // CHECK-NOT: dllexport - void* exportedTlsGlobal; + // CHECK: @{{.*}}importedGlobal{{.*}} = external dllimport + __gshared void* importedGlobal; // CHECK: @{{.*}}importedTlsGlobal{{.*}} = external thread_local // CHECK-NOT: dllimport - extern void* importedTlsGlobal; + void* importedTlsGlobal; } // CHECK: define dllexport {{.*}}_D6export11exportedFooFZv @@ -38,6 +34,8 @@ export void bar() { - exportedFoo(); + // make sure the imported symbols are IR-declared + importedGlobal = null; + importedTlsGlobal = null; importedFoo(); } diff --git a/tests/codegen/wasi.d b/tests/codegen/wasi.d index c5c7b8fe44..711100ae30 100644 --- a/tests/codegen/wasi.d +++ b/tests/codegen/wasi.d @@ -15,8 +15,6 @@ version (CRuntime_WASI) {} else static assert(0); // CHECK: @_D4wasi13definedGlobali = global i32 123 int definedGlobal = 123; -// CHECK: @_D4wasi14declaredGlobali = external global i32 -extern int declaredGlobal; // make sure the ModuleInfo ref is emitted into the __minfo section: diff --git a/tests/fail_compilation/global_var_collision.d b/tests/fail_compilation/global_var_collision.d index c51992cc5d..8760b6e3ba 100644 --- a/tests/fail_compilation/global_var_collision.d +++ b/tests/fail_compilation/global_var_collision.d @@ -1,9 +1,18 @@ -// RUN: not %ldc -c %s 2>&1 | FileCheck %s +// It should compile fine when not referencing the colliding external global: +// RUN: %ldc -c %s -d-version=DontReference + +// But fail if referenced: +// RUN: not %ldc -c %s -verrors-context=false 2>&1 | FileCheck %s extern(C) extern int myGlobal; -// CHECK: global_var_collision.d(9): Error: Global variable type does not match previous declaration with same mangled name: `myGlobal` -// CHECK: Previous IR type: i32, mutable, thread-local +version (DontReference) {} else +{ + int dummyRef() { return myGlobal; } +} + +// CHECK: global_var_collision.d([[@LINE+4]]): Error: Global variable type does not match previous declaration with same mangled name: `myGlobal` +// CHECK-NEXT: Previous IR type: i32, mutable, thread-local // CHECK-NEXT: New IR type: i64, const, non-thread-local pragma(mangle, myGlobal.mangleof) extern(C) __gshared const long myGlobal2 = 123;