https://github.com/KFAFSP updated https://github.com/llvm/llvm-project/pull/179356
>From de0a68f7ab3beb5eff5c108f87ab58918a94658d Mon Sep 17 00:00:00 2001 From: Karl Friebel <[email protected]> Date: Mon, 9 Feb 2026 15:47:24 +0100 Subject: [PATCH] [Clang] Fixes for implicit-int diagnostics. When encountering a declaration without a type specifier, in contexts where they could reasonably be assumed to default to int, clang emits a diagnostic with FixIt. This FixIt does not produce working code. This patch corrects the SemaType FixIts inserting an int type specifier (missing whitespace). In addition, the diagnostic is now emitted only on the first declarator of a comma-separated group. The patch also adds test coverage for the FixIts. Fixes #179354 --- clang/docs/ReleaseNotes.rst | 6 ++++++ clang/lib/Sema/SemaType.cpp | 31 ++++++++++++++++++++----------- clang/test/FixIt/fixit.c | 21 +++++++++++++++++++++ 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a1bb1bd2467b7..d955eeebf5131 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -227,6 +227,12 @@ Improvements to Clang's diagnostics when accessing a member function on a past-the-end array element. (#GH179128) +- Fixed the FixIt for the ``implicit-int`` group of diagnostics. (#GH179354) + +- Changed the ``implicit-int`` diagnostics such that only one will be emitted + per comma-separated declaration group. Previously, one was generated for each + declarator in the group. + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 348823ab2e9ca..a6d4b989cae3d 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -978,17 +978,24 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // parser already though by it pretending to have seen an 'int' in this // case. if (S.getLangOpts().isImplicitIntRequired()) { - S.Diag(DeclLoc, diag::warn_missing_type_specifier) - << DS.getSourceRange() - << FixItHint::CreateInsertion(DS.getBeginLoc(), "int"); + // Only emit the diagnostic for the first declarator in a DeclGroup, as + // the warning is always implied for all subsequent declarators, and the + // fix must only be applied exactly once as well. + if (declarator.isFirstDeclarator()) { + S.Diag(DeclLoc, diag::warn_missing_type_specifier) + << DS.getSourceRange() + << FixItHint::CreateInsertion(DS.getBeginLoc(), "int "); + } } else if (!DS.hasTypeSpecifier()) { // C99 and C++ require a type specifier. For example, C99 6.7.2p2 says: // "At least one type specifier shall be given in the declaration - // specifiers in each declaration, and in the specifier-qualifier list in - // each struct declaration and type name." + // specifiers in each declaration, and in the specifier-qualifier list + // in each struct declaration and type name." if (!S.getLangOpts().isImplicitIntAllowed() && !DS.isTypeSpecPipe()) { - S.Diag(DeclLoc, diag::err_missing_type_specifier) - << DS.getSourceRange(); + if (declarator.isFirstDeclarator()) { + S.Diag(DeclLoc, diag::err_missing_type_specifier) + << DS.getSourceRange(); + } // When this occurs, often something is very broken with the value // being declared, poison it as invalid so we don't get chains of @@ -996,15 +1003,17 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { declarator.setInvalidType(true); } else if (S.getLangOpts().getOpenCLCompatibleVersion() >= 200 && DS.isTypeSpecPipe()) { - S.Diag(DeclLoc, diag::err_missing_actual_pipe_type) - << DS.getSourceRange(); + if (declarator.isFirstDeclarator()) { + S.Diag(DeclLoc, diag::err_missing_actual_pipe_type) + << DS.getSourceRange(); + } declarator.setInvalidType(true); - } else { + } else if (declarator.isFirstDeclarator()) { assert(S.getLangOpts().isImplicitIntAllowed() && "implicit int is disabled?"); S.Diag(DeclLoc, diag::ext_missing_type_specifier) << DS.getSourceRange() - << FixItHint::CreateInsertion(DS.getBeginLoc(), "int"); + << FixItHint::CreateInsertion(DS.getBeginLoc(), "int "); } } diff --git a/clang/test/FixIt/fixit.c b/clang/test/FixIt/fixit.c index 0e86d454a0e10..2cd5b7ae020ba 100644 --- a/clang/test/FixIt/fixit.c +++ b/clang/test/FixIt/fixit.c @@ -27,6 +27,27 @@ struct s s0 = { y: 5 }; // expected-warning {{GNU old-style}} // CHECK: int array0[5] = { [3] = 3 }; int array0[5] = { [3] 3 }; // expected-warning {{GNU 'missing ='}} +// CHECK: int imp0[4],imp1,imp2=5; +imp0[4],imp1,imp2=5; // expected-error {{type specifier missing, defaults to 'int'}} + +// CHECK: int const imp3; +const imp3; // expected-error {{type specifier missing, defaults to 'int'}} +// CHECK: int static imp4; +static imp4; // expected-error {{type specifier missing, defaults to 'int'}} +// CHECK: int static const imp5; +static const imp5; // expected-error {{type specifier missing, defaults to 'int'}} +// CHECK: int volatile __attribute__ ((aligned (16))) imp6; +volatile __attribute__ ((aligned (16))) imp6; // expected-error {{type specifier missing, defaults to 'int'}} + +// CHECK-LABEL: int f2(void) +f2(void) // expected-error {{type specifier missing, defaults to 'int'}} +{ + // CHECK: int register __attribute__ ((uninitialized)) i; + register __attribute__ ((uninitialized)) i; // expected-error {{type specifier missing, defaults to 'int'}} + return 0; +} + +// CHECK-LABEL: void f1(x, y) // CHECK: int x // CHECK: int y void f1(x, y) // expected-error 2{{was not declared, defaults to 'int'; ISO C99 and later do not support implicit int}} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
