[MinGW] Reject explicit non-default visibility applied to dllexport/dllimport declaration

dllimport/dllexport is incompatible with protected/hidden visibilities.
(Arguably dllexport semantics is compatible with protected but let's reject the
combo for simplicity.)

When an explicit visibility attribute applies on a dllexport/dllimport
declaration, report a Frontend error (Sema does not compute visibility).

Reviewed By: mstorsjo

Differential Revision: https://reviews.llvm.org/D133266
This commit is contained in:
Fangrui Song 2022-09-05 10:17:19 -07:00
parent 05737fa209
commit 91d8324366
3 changed files with 32 additions and 2 deletions

View File

@ -282,6 +282,8 @@ def err_duplicate_mangled_name : Error<
"definition with same mangled name '%0' as another definition">;
def err_cyclic_alias : Error<
"%select{alias|ifunc}0 definition is part of a cycle">;
def err_non_default_visibility_dllstorage : Error<
"non-default visibility cannot be applied to '%0' declaration">;
def err_ifunc_resolver_return : Error<
"ifunc resolver function must return a pointer">;

View File

@ -1099,8 +1099,6 @@ llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) {
void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
const NamedDecl *D) const {
if (GV->hasDLLExportStorageClass() || GV->hasDLLImportStorageClass())
return;
// Internal definitions always have default visibility.
if (GV->hasLocalLinkage()) {
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
@ -1111,6 +1109,14 @@ void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
// Set visibility for definitions, and for declarations if requested globally
// or set explicitly.
LinkageInfo LV = D->getLinkageAndVisibility();
if (GV->hasDLLExportStorageClass() || GV->hasDLLImportStorageClass()) {
// Reject explicit non-default visibility on dllexport/dllimport.
if (LV.isVisibilityExplicit() && LV.getVisibility() != DefaultVisibility)
getDiags().Report(D->getLocation(),
diag::err_non_default_visibility_dllstorage)
<< (GV->hasDLLExportStorageClass() ? "dllexport" : "dllimport");
return;
}
if (LV.isVisibilityExplicit() || getLangOpts().SetVisibilityForExternDecls ||
!GV->isDeclarationForLinker())
GV->setVisibility(GetLLVMVisibility(LV.getVisibility()));

View File

@ -4,10 +4,18 @@
// RUN: %clang_cc1 -emit-llvm -triple x86_64-windows-gnu -fdeclspec -fvisibility-inlines-hidden -o - %s | FileCheck %s --check-prefix=GNU
// RUN: %clang_cc1 -emit-llvm -triple x86_64-windows-gnu -fdeclspec -fvisibility=hidden -o - %s | FileCheck %s --check-prefix=GNU
// RUN: %clang_cc1 -emit-llvm-only -verify -triple x86_64-windows-gnu -fdeclspec -DERR1 -o - %s
// RUN: %clang_cc1 -emit-llvm-only -verify -triple x86_64-windows-gnu -fdeclspec -fvisibility=hidden -DERR1 -o - %s
// RUN: %clang_cc1 -emit-llvm-only -verify -triple x86_64-windows-gnu -fdeclspec -DERR2 -o - %s
#define CONCAT2(x, y) x##y
#define CONCAT(x, y) CONCAT2(x, y)
#define USE(func) void CONCAT(use, __LINE__)() { func(); }
#define HIDDEN __attribute__((visibility("hidden")))
#define PROTECTED __attribute__((visibility("protected")))
#define DEFAULT __attribute__((visibility("default")))
// MSVC-DAG: declare dllimport void @"?bar@foo@@QEAAXXZ"(
// GNU-DAG: define linkonce_odr hidden void @_ZN3foo3barEv(
@ -24,3 +32,17 @@ __attribute__((dllexport)) void exported() {}
// GNU-DAG: define weak_odr dso_local dllexport void @_Z15exported_inlinev(
__declspec(dllexport) inline void exported_inline() {}
USE(exported_inline)
#if defined(ERR1)
// expected-error@+1 {{non-default visibility cannot be applied to 'dllimport' declaration}}
__attribute__((dllimport)) HIDDEN void imported_hidden();
__attribute__((dllexport)) DEFAULT void exported_default() {}
// expected-error@+1 {{non-default visibility cannot be applied to 'dllexport' declaration}}
__attribute__((dllexport)) HIDDEN void exported_hidden() { imported_hidden(); }
#elif defined(ERR2)
struct PROTECTED C {
// expected-error@+1 {{non-default visibility cannot be applied to 'dllexport' declaration}}
__attribute__((dllexport)) void exported_protected() {}
};
#endif