[clang] [clang][OpenMP] Emit host diagnostics that were deferred and never flushed (PR #220316)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 4 09:49:45 PDT 2026
https://github.com/pgerell updated https://github.com/llvm/llvm-project/pull/220316
>From 16ffd747b087751da3d9aa14c2e5ef88e8f17e2a Mon Sep 17 00:00:00 2001
From: Peter Gerell <peter at gerell.se>
Date: Mon, 31 Aug 2026 17:49:48 +0200
Subject: [PATCH] [clang][OpenMP] Emit host diagnostics that were deferred and
never flushed
---
clang/docs/ReleaseNotes.md | 11 ++++++
clang/lib/Sema/Sema.cpp | 4 +-
clang/lib/Sema/SemaDecl.cpp | 3 +-
clang/test/CodeGen/X86/mmx-inline-asm-error.c | 7 +---
clang/test/OpenMP/declare_target_messages.cpp | 12 +++---
clang/test/OpenMP/host_asm_messages.c | 9 +++++
.../test/OpenMP/host_exceptions_messages.cpp | 37 +++++++++++++++++++
7 files changed, 69 insertions(+), 14 deletions(-)
create mode 100644 clang/test/OpenMP/host_asm_messages.c
create mode 100644 clang/test/OpenMP/host_exceptions_messages.cpp
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 7ec126a065ae5..5dbc0eaf85421 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -129,6 +129,10 @@ features cannot lower the translation-unit ABI level;
target triples (except 32b arm targets). Can be disabled via
`-fno-stack-clash-protection`.
+- A host `-fopenmp` or `-fopenmp-simd` compilation now emits diagnostics it previously
+ deferred and then dropped when no offload target was configured. Code that used to
+ compile may be rejected, matching a compilation without those flags.
+
### Clang Python Bindings Potentially Breaking Changes
- `CompletionChunkKind` instance's `__str__` representation has been adapted to be consistent with other enums in the library.
@@ -1127,6 +1131,13 @@ The `alpha.cplusplus.UseAfterLifetimeEnd` checker was renamed to `alpha.core.Use
To ensure correct behavior, either use the original variable directly in the
target region or map the bindings explicitly instead.
+- Fixed a host OpenMP compilation never flushing its deferred diagnostics unless an
+ offload target was configured, which accepted `try`/`throw` with exceptions disabled
+ and let an invalid inline asm constraint crash CodeGen. (#GH147515)
+- Fixed `-fopenmp-simd` deferring diagnostics as if it were a device compilation. It has
+ no device compilation and ignores `declare target`, so its diagnostics are now emitted
+ directly.
+
### SYCL Support
#### Improvements
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 29158cfff6231..c9b894eac406b 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -2262,7 +2262,9 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
Sema::SemaDiagnosticBuilder
Sema::targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD) {
FD = FD ? FD : getCurFunctionDecl();
- if (LangOpts.OpenMP)
+ // -fopenmp-simd has no device compilation and ignores 'declare target', so
+ // there is nothing to defer for.
+ if (LangOpts.OpenMP && !LangOpts.OpenMPSimd)
return LangOpts.OpenMPIsTargetDevice
? OpenMP().diagIfOpenMPDeviceCode(Loc, DiagID, FD)
: OpenMP().diagIfOpenMPHostCode(Loc, DiagID, FD);
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 094601a58d508..0e4e133094f72 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -17375,8 +17375,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, bool IsInstantiation,
DiscardCleanupsInEvaluationContext();
}
- if (FD && (LangOpts.isTargetDevice() || LangOpts.CUDA ||
- (LangOpts.OpenMP && !LangOpts.OMPTargetTriples.empty()))) {
+ if (FD && (LangOpts.isTargetDevice() || LangOpts.CUDA || LangOpts.OpenMP)) {
auto ES = getEmissionStatus(FD);
if (ES == Sema::FunctionEmissionStatus::Emitted ||
ES == Sema::FunctionEmissionStatus::Unknown)
diff --git a/clang/test/CodeGen/X86/mmx-inline-asm-error.c b/clang/test/CodeGen/X86/mmx-inline-asm-error.c
index 7f7f53a553057..da5b60fdac64c 100644
--- a/clang/test/CodeGen/X86/mmx-inline-asm-error.c
+++ b/clang/test/CodeGen/X86/mmx-inline-asm-error.c
@@ -1,16 +1,13 @@
// RUN: %clang_cc1 -verify -triple x86_64-unknown-unknown -emit-llvm-only %s
-// RUN: %clang_cc1 -verify=omp -triple x86_64-unknown-unknown -emit-llvm-only -fopenmp %s
+// RUN: %clang_cc1 -verify -triple x86_64-unknown-unknown -emit-llvm-only -fopenmp %s
+// RUN: %clang_cc1 -verify -triple x86_64-unknown-unknown -emit-llvm-only -fopenmp-simd %s
typedef int vec256 __attribute__((ext_vector_type(8)));
-// omp-warning at +2 {{AVX vector return of type 'vec256' (vector of 8 'int' values) without 'avx' enabled changes the ABI}}
-// omp-warning at +1 {{AVX vector argument of type 'vec256' (vector of 8 'int' values) without 'avx' enabled changes the ABI}}
vec256 foo(vec256 in) {
vec256 out;
asm("something %0" : : "y"(in)); // expected-error {{invalid input size for constraint 'y'}}
- // omp-error at +1 {{invalid type 'vec256' (vector of 8 'int' values) in asm input for constraint 'y'}}
asm("something %0" : "=y"(out)); // expected-error {{invalid output size for constraint '=y'}}
- // omp-error at +1 {{invalid type 'vec256' (vector of 8 'int' values) in asm input for constraint 'y'}}
asm("something %0, %0" : "+y"(out)); // expected-error {{invalid output size for constraint '+y'}}
return out;
diff --git a/clang/test/OpenMP/declare_target_messages.cpp b/clang/test/OpenMP/declare_target_messages.cpp
index 6fe477755dbe7..62a12d40b7271 100644
--- a/clang/test/OpenMP/declare_target_messages.cpp
+++ b/clang/test/OpenMP/declare_target_messages.cpp
@@ -21,16 +21,16 @@
// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp60,omp52-or-later,ompvar,omp5-or-later,omp5-or-later-var %{openmp60_simd} -fopenmp-is-target-device %{target_mac} %{limit} -o - %s
// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp45,omp45-to-51,omp45-to-51-var,omp45-to-51-clause -fopenmp-version=45 -fopenmp-simd %{limit} -o - %s
-// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp51,ompvar,omp45-to-51,omp5-and-51,omp5-or-later,omp5-or-later-var,omp45-to-51-var,omp45-to-51-clause,host-5-and-51,no-host5-and-51 -fopenmp %{limit} -o - %s
-// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp51,ompvar,omp45-to-51,omp5-and-51,omp5-or-later,omp5-or-later-var,omp45-to-51-var,omp45-to-51-clause,host-5-and-51,no-host5-and-51 -fopenmp %{limit} -DTESTEND=1 -o - %s
-// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp51,ompvar,omp45-to-51,omp5-and-51,omp5-or-later,omp5-or-later-var,omp45-to-51-var,omp45-to-51-clause,host-5-and-51,no-host5-and-51 -fopenmp %{limit} -I%S/Inputs -DTESTENDINC=1 -o - %s
-// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp51,ompvar,omp45-to-51,omp5-and-51,omp5-or-later,omp5-or-later-var,omp45-to-51-var,omp45-to-51-clause,host-5-and-51,no-host5-and-51 -fopenmp-simd %{limit} -o - %s
+// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp51,ompvar,omp45-to-51,omp5-and-51,omp5-or-later,omp5-or-later-var,omp45-to-51-var,omp45-to-51-clause,host5,host-5-and-51,no-host5-and-51 -fopenmp %{limit} -o - %s
+// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp51,ompvar,omp45-to-51,omp5-and-51,omp5-or-later,omp5-or-later-var,omp45-to-51-var,omp45-to-51-clause,host5,host-5-and-51,no-host5-and-51 -fopenmp %{limit} -DTESTEND=1 -o - %s
+// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp51,ompvar,omp45-to-51,omp5-and-51,omp5-or-later,omp5-or-later-var,omp45-to-51-var,omp45-to-51-clause,host5,host-5-and-51,no-host5-and-51 -fopenmp %{limit} -I%S/Inputs -DTESTENDINC=1 -o - %s
+// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp51,ompvar,omp45-to-51,omp5-and-51,omp5-or-later,omp5-or-later-var,omp45-to-51-var,omp45-to-51-clause,host5,host-5-and-51,no-host5-and-51 -fopenmp-simd %{limit} -o - %s
// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp52,omp52-or-later,ompvar,omp5-or-later,omp5-or-later-var %{openmp52} -DVERBOSE_MODE=1 %{limit} -o - %s
// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp60,omp52-or-later,ompvar,omp5-or-later,omp5-or-later-var %{openmp60} -DVERBOSE_MODE=1 %{limit} -o - %s
-// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp5,ompvar,omp45-to-51,omp5-and-51,omp5-or-later,omp5-or-later-var,omp45-to-51-var,omp45-to-51-clause,host-5-and-51,no-host5-and-51 %{openmp50} %{limit} -o - %s
-// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp51,ompvar,omp45-to-51,omp5-and-51,omp5-or-later,omp5-or-later-var,omp45-to-51-var,omp45-to-51-clause,host-5-and-51,no-host5-and-51 -fopenmp %{limit} -o - %s
+// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp5,ompvar,omp45-to-51,omp5-and-51,omp5-or-later,omp5-or-later-var,omp45-to-51-var,omp45-to-51-clause,host5,host-5-and-51,no-host5-and-51 %{openmp50} %{limit} -o - %s
+// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp51,ompvar,omp45-to-51,omp5-and-51,omp5-or-later,omp5-or-later-var,omp45-to-51-var,omp45-to-51-clause,host5,host-5-and-51,no-host5-and-51 -fopenmp %{limit} -o - %s
// RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp60,omp52-or-later,ompvar,omp5-or-later,omp5-or-later-var %{openmp60} %{limit} -o - %s
#pragma omp begin declare target
diff --git a/clang/test/OpenMP/host_asm_messages.c b/clang/test/OpenMP/host_asm_messages.c
new file mode 100644
index 0000000000000..48126712f5437
--- /dev/null
+++ b/clang/test/OpenMP/host_asm_messages.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -verify -triple x86_64-unknown-unknown -emit-llvm-only %s
+// RUN: %clang_cc1 -verify -triple x86_64-unknown-unknown -emit-llvm-only -fopenmp %s
+// RUN: %clang_cc1 -verify -triple x86_64-unknown-unknown -emit-llvm-only -fopenmp-simd %s
+
+// An invalid asm constraint must be diagnosed rather than reaching CodeGen.
+
+void f(void) {
+ __asm__("nop" ::: "no_such_register"); // expected-error {{unknown register name 'no_such_register' in asm}}
+}
diff --git a/clang/test/OpenMP/host_exceptions_messages.cpp b/clang/test/OpenMP/host_exceptions_messages.cpp
new file mode 100644
index 0000000000000..7a176f4df5f8a
--- /dev/null
+++ b/clang/test/OpenMP/host_exceptions_messages.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -verify=expected,host -fopenmp -fsyntax-only %s
+// RUN: %clang_cc1 -verify=expected,simd -fopenmp-simd -fsyntax-only %s
+// RUN: %clang_cc1 -verify=expected,host -fopenmp -fopenmp-targets=x86_64 -triple x86_64 -fsyntax-only %s
+
+// Exceptions are disabled, so a host compilation must diagnose 'try' and 'throw'
+// whether or not an offload target is configured.
+
+void foo();
+
+void bar() {
+ try { // expected-error {{cannot use 'try' with exceptions disabled}}
+ foo();
+ } catch (...) {
+ }
+}
+
+void baz(bool b) {
+ if (b)
+ throw 1; // expected-error {{cannot use 'throw' with exceptions disabled}}
+}
+
+// A 'device_type(nohost)' function is not emitted by a host -fopenmp compilation, but
+// -fopenmp-simd ignores 'declare target' and does emit it.
+#pragma omp begin declare target device_type(nohost)
+void devonly() {
+ try { // simd-error {{cannot use 'try' with exceptions disabled}}
+ foo();
+ } catch (...) {
+ }
+}
+#pragma omp end declare target
+
+// Same, but marked 'nohost' only after the body has been parsed.
+void late() {
+ throw 1; // simd-error {{cannot use 'throw' with exceptions disabled}}
+}
+#pragma omp declare target to(late) device_type(nohost)
More information about the cfe-commits
mailing list