aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2025-05-27 11:29:30 -0400
committerGitHub <noreply@github.com>2025-05-27 11:29:30 -0400
commitcc5237c7af6417139fb32f3e312b9489a6e0bf62 (patch)
treeeb88386f2a9def74f9f151fc7f77d9cffda606ce
parent97f6076dedc6ba78ccdb36f53a6953a66abfd395 (diff)
downloadllvm-cc5237c7af6417139fb32f3e312b9489a6e0bf62.zip
llvm-cc5237c7af6417139fb32f3e312b9489a6e0bf62.tar.gz
llvm-cc5237c7af6417139fb32f3e312b9489a6e0bf62.tar.bz2
[C2y] Correctly handle incomplete types in generic selections (#141596)
We were emitting a non-error diagnostic but claiming we emitted an error, which caused some obvious follow-on problems. Fixes #141549
-rw-r--r--clang/lib/Sema/SemaExpr.cpp8
-rw-r--r--clang/test/C/C2y/n3409.c29
-rw-r--r--clang/test/SemaCXX/generic-selection.cpp2
3 files changed, 31 insertions, 8 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 11dddac..5aa3393 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1874,9 +1874,11 @@ ExprResult Sema::CreateGenericSelectionExpr(
if (D != 0) {
Diag(Types[i]->getTypeLoc().getBeginLoc(), D)
- << Types[i]->getTypeLoc().getSourceRange()
- << Types[i]->getType();
- TypeErrorFound = true;
+ << Types[i]->getTypeLoc().getSourceRange() << Types[i]->getType();
+ if (getDiagnostics().getDiagnosticLevel(
+ D, Types[i]->getTypeLoc().getBeginLoc()) >=
+ DiagnosticsEngine::Error)
+ TypeErrorFound = true;
}
// C11 6.5.1.1p2 "No two generic associations in the same generic
diff --git a/clang/test/C/C2y/n3409.c b/clang/test/C/C2y/n3409.c
index 01be716..a0b8e2f 100644
--- a/clang/test/C/C2y/n3409.c
+++ b/clang/test/C/C2y/n3409.c
@@ -1,7 +1,6 @@
-// RUN: %clang_cc1 -verify -std=c2y -pedantic %s
-// RUN: %clang_cc1 -verify=pre-c2y -std=c2y -Wpre-c2y-compat %s
-// RUN: %clang_cc1 -verify=ext -std=c23 -pedantic %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -verify -std=c2y -pedantic -Wno-unused %s
+// RUN: %clang_cc1 -verify=expected,pre-c2y -std=c2y -Wpre-c2y-compat -Wno-unused %s
+// RUN: %clang_cc1 -verify=expected,ext -std=c23 -pedantic -Wno-unused %s
/* WG14 N3409: Clang 21
* Slay Some Earthly Demons X
@@ -34,3 +33,25 @@ void foo() {
// C23 and earlier.
return x; // ext-warning {{void function 'foo' should not return void expression}}
}
+
+
+// Ensure we behave correctly with incomplete types. See GH141549.
+static_assert(
+ _Generic(
+ void, /* ext-warning {{passing a type argument as the first operand to '_Generic' is a C2y extension}}
+ pre-c2y-warning {{passing a type argument as the first operand to '_Generic' is incompatible with C standards before C2y}}
+ */
+ void : 1,
+ default : 0
+ )
+);
+
+static_assert(
+ _Generic( // expected-error {{static assertion failed}}
+ 12,
+ void : 1, /* ext-warning {{incomplete type 'void' in a '_Generic' association is a C2y extension}}
+ pre-c2y-warning {{use of incomplete type 'void' in a '_Generic' association is incompatible with C standards before C2y}}
+ */
+ default : 0
+ )
+);
diff --git a/clang/test/SemaCXX/generic-selection.cpp b/clang/test/SemaCXX/generic-selection.cpp
index aa4a4c4..ed9d2b7 100644
--- a/clang/test/SemaCXX/generic-selection.cpp
+++ b/clang/test/SemaCXX/generic-selection.cpp
@@ -81,7 +81,7 @@ void func(struct S s) {
// is an elaborated type specifier followed by the association's value and
// it should work the same as in C.
(void)_Generic(s, struct S : 1);
- (void)_Generic(s, struct T : 1);
+ (void)_Generic(s, struct T : 1); // expected-error {{controlling expression type 'struct S' not compatible with any generic association type}}
// The rest of these cases test that we still produce a reasonable diagnostic
// when referencing an unknown type or trying to define a type in other ways.