release/23.x: [clang] Emit diagnostic for typedef+auto missed case in C++98/C23 (#210141) - #211391
Merged
Merged
Conversation
Member
Author
|
@AaronBallman What do you think about merging this PR to the release branch? |
|
@llvm/pr-subscribers-clang Author: llvmbot ChangesBackport 34436db Requested by: @efriedma-quic Full diff: https://github.com/llvm/llvm-project/pull/211391.diff 2 Files Affected:
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();
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}}
+}
|
cor3ntin
approved these changes
Jul 23, 2026
cor3ntin
left a comment
Contributor
There was a problem hiding this comment.
We need a release note, otherwise LGTM
Contributor
I don't think we need a release note -- 22.x was in good shape, so this restores the good shape of things. |
…vm#210141) 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 add the check for tydef in the code handling auto. (cherry picked from commit 34436db)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Backport 34436db
Requested by: @efriedma-quic