https://github.com/rahulana-quic updated https://github.com/llvm/llvm-project/pull/210141
>From 62c7c85e99e7551ade93e3b6173e00b47d5019a6 Mon Sep 17 00:00:00 2001 From: Rahul Anand Radhakrishnan <[email protected]> Date: Thu, 16 Jul 2026 11:43:59 -0700 Subject: [PATCH 1/2] [clang] Add test for typedef+auto diagnostic in C++98/pre-C23 C --- clang/test/SemaCXX/auto-cxx98.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/clang/test/SemaCXX/auto-cxx98.cpp b/clang/test/SemaCXX/auto-cxx98.cpp index 1e28d0635a48d..db2036d462532 100644 --- a/clang/test/SemaCXX/auto-cxx98.cpp +++ b/clang/test/SemaCXX/auto-cxx98.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wc++11-compat +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wc++11-compat void f() { auto int a; // expected-warning {{'auto' storage class specifier is redundant and incompatible with C++11}} int auto b; // expected-warning {{'auto' storage class specifier is redundant and incompatible with C++11}} @@ -6,3 +6,11 @@ void f() { static auto d = 0; // expected-warning {{C++11 extension}} auto static e = 0; // expected-warning {{C++11 extension}} } + +// typedef and auto storage-class-specifier cannot appear in the same +// decl-specifier-seq ([dcl.stc] p1). This must be diagnosed in C++98 even +// though 'auto int' (without typedef) is valid there. +void g() { + typedef auto int t1; // expected-error {{cannot combine with previous 'typedef' declaration specifier}} + auto typedef int t2; // expected-error {{cannot combine with previous 'typedef' declaration specifier}} +} >From f27d290caa8bd53e6fdf77000faf113fb02b4199 Mon Sep 17 00:00:00 2001 From: Rahul Anand Radhakrishnan <[email protected]> Date: Thu, 16 Jul 2026 11:43:59 -0700 Subject: [PATCH 2/2] [clang] Emit diagnostic for typedef+auto missed case in C++98/C23 CheckTypeSpec() converted 'auto' to a storage-class specifier without checking whether 'typedef' was already set. [dcl.stc]p1 unconditionally forbids typedef alongside any storage-class specifier regardless of C++ version. This change adds the check for tydef in the code handling auto in the C++98/C23 paths. --- clang/lib/Sema/DeclSpec.cpp | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 4d20657d5e517..8751aab1c9b8d 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -1244,11 +1244,19 @@ void DeclSpec::CheckTypeSpec(Sema &S, const PrintingPolicy &Policy) { (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11)) { // In C23 or C++98, convert 'auto' to storage class specifier if (TypeSpecType == TST_auto) { - // "auto int" case: Convert 'auto' to storage class specifier - StorageClassSpec = SCS_auto; - StorageClassSpecLoc = TSTLoc; - TypeSpecType = ConflictingTypeSpecifier; - TSTLoc = ConflictingTypeSpecifierLoc; + // "auto int" case: Convert 'auto' to storage class specifier. + // But typedef + any storage-class-specifier is unconditionally invalid + // per [dcl.stc]p1, regardless of C++ version. + if (StorageClassSpec == SCS_typedef) { + S.Diag(TSTLoc, diag::err_invalid_decl_spec_combination) + << "typedef" << FixItHint::CreateRemoval(TSTLoc); + TypeSpecType = TST_error; + } else { + StorageClassSpec = SCS_auto; + StorageClassSpecLoc = TSTLoc; + TypeSpecType = ConflictingTypeSpecifier; + TSTLoc = ConflictingTypeSpecifierLoc; + } // Clear the conflict tracking ConflictingTypeSpecifier = TST_unspecified; ConflictingTypeSpecifierLoc = SourceLocation(); @@ -1273,11 +1281,19 @@ void DeclSpec::CheckTypeSpec(Sema &S, const PrintingPolicy &Policy) { return; } // int auto (without constexpr): Convert 'auto' to storage class - // specifier. No type conflict error - auto is treated as storage class, - // not type specifier. - StorageClassSpec = SCS_auto; - StorageClassSpecLoc = ConflictingTypeSpecifierLoc; - // TypeSpecType already has the correct type (e.g., TST_int) + // specifier. But typedef + any storage-class-specifier is + // unconditionally invalid per [dcl.stc]p1. + if (StorageClassSpec == SCS_typedef) { + S.Diag(ConflictingTypeSpecifierLoc, + diag::err_invalid_decl_spec_combination) + << "typedef" + << FixItHint::CreateRemoval(ConflictingTypeSpecifierLoc); + TypeSpecType = TST_error; + } else { + StorageClassSpec = SCS_auto; + StorageClassSpecLoc = ConflictingTypeSpecifierLoc; + // TypeSpecType already has the correct type (e.g., TST_int) + } // Clear the conflict tracking ConflictingTypeSpecifier = TST_unspecified; ConflictingTypeSpecifierLoc = SourceLocation(); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
