diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 4f62a679b8b21..8b4246880e927 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -271,6 +271,8 @@ Non-comprehensive list of changes in this release allocation functions with a token ID can be enabled via the ``-fsanitize=alloc-token`` flag. +- Clang now rejects the invalid use of ``constexpr`` with ``auto`` and an explicit type in C. (#GH163090) + New Compiler Flags ------------------ - New option ``-fno-sanitize-debug-trap-reasons`` added to disable emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``). diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 184d31ecd1e40..9da3d0d2ef599 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -1369,7 +1369,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { if (S.getLangOpts().C23 && getConstexprSpecifier() == ConstexprSpecKind::Constexpr && - StorageClassSpec == SCS_extern) { + getTypeSpecType() != TST_unspecified && + (StorageClassSpec == SCS_extern || StorageClassSpec == SCS_auto)) { S.Diag(ConstexprLoc, diag::err_invalid_decl_spec_combination) << DeclSpec::getSpecifierName(getStorageClassSpec()) << SourceRange(getStorageClassSpecLoc()); diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c index b878a5b7c42d4..7f80b0717ab25 100644 --- a/clang/test/Parser/c2x-auto.c +++ b/clang/test/Parser/c2x-auto.c @@ -130,3 +130,30 @@ void atomic(void) { void attributes(void) { auto ident [[clang::annotate("this works")]] = 12; // c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} } + +/** GH163090 */ +constexpr auto int a1 = 0; // c23-error {{illegal storage class on file-scoped variable}} \ + c23-error {{cannot combine with previous 'auto' declaration specifier}} \ + c17-error {{illegal storage class on file-scoped variable}} \ + c17-error {{unknown type name 'constexpr'}} + +constexpr int auto a2 = 0; // c23-error {{cannot combine with previous 'int' declaration specifier}} \ + c17-error {{illegal storage class on file-scoped variable}} \ + c17-error {{unknown type name 'constexpr'}} + +auto int b1 = 0; // c23-error {{illegal storage class on file-scoped variable}} \ + c17-error {{illegal storage class on file-scoped variable}} + +int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration specifier}} \ + c17-error {{illegal storage class on file-scoped variable}} + +void f() { + constexpr auto int c1 = 0; // c23-error {{cannot combine with previous 'auto' declaration specifier}} \ + c17-error {{use of undeclared identifier 'constexpr'}} + + constexpr int auto c2 = 0; // c23-error {{cannot combine with previous 'int' declaration specifier}} \ + c17-error {{use of undeclared identifier 'constexpr'}} + + auto int d1 = 0; + int auto d2 = 0; // c23-error {{cannot combine with previous 'int' declaration specifier}} +}