diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -99,6 +99,9 @@ Bug Fixes --------- +- Correct ``_Static_assert`` to accept the same set of extended integer + constant expressions as is accpted in other contexts that accept them. + This fixes `Issue 57687 `_. - Fixes an accepts-invalid bug in C when using a ``_Noreturn`` function specifier on something other than a function declaration. This fixes `Issue 56800 `_. diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -16736,10 +16736,21 @@ AssertExpr = FullAssertExpr.get(); llvm::APSInt Cond; + Expr *BaseExpr = AssertExpr; + AllowFoldKind FoldKind = NoFold; + + if (!getLangOpts().CPlusPlus) { + // In C mode only allow folding and strip the implicit conversion + // to the type of the first _Static_assert argument that would + // otherwise suppress diagnostics for arguments that convert to int. + FoldKind = AllowFold; + BaseExpr = BaseExpr->IgnoreImpCasts(); + } + if (!Failed && VerifyIntegerConstantExpression( - AssertExpr, &Cond, - diag::err_static_assert_expression_is_not_constant) - .isInvalid()) + BaseExpr, &Cond, + diag::err_static_assert_expression_is_not_constant, + FoldKind).isInvalid()) Failed = true; if (!Failed && !Cond) { diff --git a/clang/test/Sema/static-assert.c b/clang/test/Sema/static-assert.c --- a/clang/test/Sema/static-assert.c +++ b/clang/test/Sema/static-assert.c @@ -74,3 +74,23 @@ _Static_assert(1 , "") // expected-error {{expected ';' after '_Static_assert'}} \ // ext-warning {{'_Static_assert' is a C11 extension}} + +static int static_var; +_Static_assert(&static_var != 0, ""); // ext-warning {{'_Static_assert' is a C11 extension}} \ + // expected-warning {{comparison of address of 'static_var' not equal to a null pointer is always true}} +_Static_assert("" != 0, ""); // ext-warning {{'_Static_assert' is a C11 extension}} +_Static_assert(("" != 0), ""); // ext-warning {{'_Static_assert' is a C11 extension}} +_Static_assert(*"1", ""); // ext-warning {{'_Static_assert' is a C11 extension}} +_Static_assert("1"[0], ""); // ext-warning {{'_Static_assert' is a C11 extension}} +_Static_assert(1.0 != 0, ""); // ext-warning {{'_Static_assert' is a C11 extension}} +_Static_assert(__builtin_strlen("1"), ""); // ext-warning {{'_Static_assert' is a C11 extension}} +#ifndef __cplusplus +// ext-warning@-9 {{expression is not an integer constant expression; folding it to a constant is a GNU extension}} +// ext-warning@-8 {{expression is not an integer constant expression; folding it to a constant is a GNU extension}} +// ext-warning@-8 {{expression is not an integer constant expression; folding it to a constant is a GNU extension}} +// ext-warning@-8 {{expression is not an integer constant expression; folding it to a constant is a GNU extension}} +// ext-warning@-8 {{expression is not an integer constant expression; folding it to a constant is a GNU extension}} +// ext-warning@-8 {{expression is not an integer constant expression; folding it to a constant is a GNU extension}} +// __builtin_strlen(literal) is considered an integer constant expression +// and doesn't cause a pedantic warning +#endif