diff options
author | Aaron Ballman <aaron@aaronballman.com> | 2025-05-27 11:29:30 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-27 11:29:30 -0400 |
commit | cc5237c7af6417139fb32f3e312b9489a6e0bf62 (patch) | |
tree | eb88386f2a9def74f9f151fc7f77d9cffda606ce | |
parent | 97f6076dedc6ba78ccdb36f53a6953a66abfd395 (diff) | |
download | llvm-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.cpp | 8 | ||||
-rw-r--r-- | clang/test/C/C2y/n3409.c | 29 | ||||
-rw-r--r-- | clang/test/SemaCXX/generic-selection.cpp | 2 |
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. |