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 1/4] [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}} >From ef569e0d6506eb929f7b36e6d1c4e66525ce771a Mon Sep 17 00:00:00 2001 From: Karl Friebel <[email protected]> Date: Mon, 9 Feb 2026 18:21:18 +0100 Subject: [PATCH 2/4] Merged release notes. Co-authored-by: Sirraide <[email protected]> --- clang/docs/ReleaseNotes.rst | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d955eeebf5131..a75e159732d0b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -227,11 +227,8 @@ 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. +- Added a missing space to the FixIt for the ``implicit-int`` group of diagnostics and + made sure that only one such diagnostic and FixIt is emitted per declaration group. (#GH179354) Improvements to Clang's time-trace ---------------------------------- >From 7b9f2017207df3a544c9e76e23f89ec8eb397ee9 Mon Sep 17 00:00:00 2001 From: Karl Friebel <[email protected]> Date: Tue, 10 Feb 2026 00:56:43 +0100 Subject: [PATCH 3/4] Added missing-type-spec test suite and C90 FixIt. This commit moves the implicit-int fixit checks from fixit.c into fixit-missing-type-spec.c and adds the appropriate tests for C90, C99 and C23. In addition, this commit adds a FixIt for the warning emitted on function declarations without a type specifier in C90 mode for consistency. --- clang/lib/Parse/Parser.cpp | 3 +- clang/test/FixIt/fixit-missing-type-spec.c | 57 ++++++++++++++++++++++ clang/test/FixIt/fixit.c | 21 -------- 3 files changed, 59 insertions(+), 22 deletions(-) create mode 100644 clang/test/FixIt/fixit-missing-type-spec.c diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index be9e0a39a3781..5d18414b1a746 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1188,7 +1188,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // declaration-specifiers are completely optional in the grammar. if (getLangOpts().isImplicitIntRequired() && D.getDeclSpec().isEmpty()) { Diag(D.getIdentifierLoc(), diag::warn_missing_type_specifier) - << D.getDeclSpec().getSourceRange(); + << D.getDeclSpec().getSourceRange() + << FixItHint::CreateInsertion(D.getDeclSpec().getBeginLoc(), "int "); const char *PrevSpec; unsigned DiagID; const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); diff --git a/clang/test/FixIt/fixit-missing-type-spec.c b/clang/test/FixIt/fixit-missing-type-spec.c new file mode 100644 index 0000000000000..5d1eecfcb1f7a --- /dev/null +++ b/clang/test/FixIt/fixit-missing-type-spec.c @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -std=c90 -pedantic -Wno-comment -Wno-deprecated-non-prototype -Wimplicit-int -verify=c90 -x c %s +// RUN: cp %s %t +// RUN: %clang_cc1 -std=c90 -pedantic -Wno-comment -Wno-deprecated-non-prototype -Wimplicit-int -fixit %t +// RUN: %clang_cc1 -std=c90 -pedantic -Wno-comment -Wno-deprecated-non-prototype -Wimplicit-int -Werror -x c %t +// RUN: cat %t | FileCheck %s +// RUN: %clang_cc1 -std=c99 -pedantic -Wno-deprecated-non-prototype -verify=c99 -x c %s +// RUN: cp %s %t +// RUN: not %clang_cc1 -std=c99 -pedantic -Wno-deprecated-non-prototype -fixit %t +// RUN: %clang_cc1 -std=c99 -pedantic -Wno-deprecated-non-prototype -Werror -x c %t +// RUN: cat %t | FileCheck %s +// RUN: %clang_cc1 -std=c23 -pedantic -verify=c23 -x c %s + +// CHECK: int imp0[4],imp1,imp2=5; +imp0[4],imp1,imp2=5; +// c90-warning@-1 {{type specifier missing, defaults to 'int'}} +// c99-error@-2 {{type specifier missing, defaults to 'int'}} +// c23-error@-3 {{a type specifier is required for all declarations}} +// c23-error@-4 {{expected ';' after top level declarator}} + +// CHECK: int const imp3; +const imp3; +// c90-warning@-1 {{type specifier missing, defaults to 'int'}} +// c99-error@-2 {{type specifier missing, defaults to 'int'}} +// c23-error@-3 {{a type specifier is required for all declarations}} + +// CHECK: int static imp4; +static imp4; +// c90-warning@-1 {{type specifier missing, defaults to 'int'}} +// c99-error@-2 {{type specifier missing, defaults to 'int'}} +// c23-error@-3 {{a type specifier is required for all declarations}} + +// CHECK: int static const imp5; +static const imp5; +// c90-warning@-1 {{type specifier missing, defaults to 'int'}} +// c99-error@-2 {{type specifier missing, defaults to 'int'}} +// c23-error@-3 {{a type specifier is required for all declarations}} + +// CHECK: int volatile __attribute__ ((aligned (16))) imp6; +volatile __attribute__ ((aligned (16))) imp6; +// c90-warning@-1 {{type specifier missing, defaults to 'int'}} +// c99-error@-2 {{type specifier missing, defaults to 'int'}} +// c23-error@-3 {{a type specifier is required for all declarations}} + +// CHECK-LABEL: int f2(void) +f2(void) +// c90-warning@-1 {{type specifier missing, defaults to 'int'}} +// c99-error@-2 {{type specifier missing, defaults to 'int'}} +// c23-error@-3 {{a type specifier is required for all declarations}} +{ + // CHECK: int register __attribute__ ((uninitialized)) i; + register __attribute__ ((uninitialized)) i; + // c90-warning@-1 {{type specifier missing, defaults to 'int'}} + // c99-error@-2 {{type specifier missing, defaults to 'int'}} + // c23-error@-3 {{a type specifier is required for all declarations}} + + return 0; +} diff --git a/clang/test/FixIt/fixit.c b/clang/test/FixIt/fixit.c index 2cd5b7ae020ba..0e86d454a0e10 100644 --- a/clang/test/FixIt/fixit.c +++ b/clang/test/FixIt/fixit.c @@ -27,27 +27,6 @@ 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}} >From 9267ec4a7430cf80422705dc6b7dd7d9d09e8496 Mon Sep 17 00:00:00 2001 From: Karl Friebel <[email protected]> Date: Tue, 10 Feb 2026 19:25:50 +0100 Subject: [PATCH 4/4] Applied suggestions to fixit-missing-type-spec.c - Added an empty line between every lang standard - Added -fsyntax-only where appropriate - Made C90 exfail using -Werror for consistency --- clang/test/FixIt/fixit-missing-type-spec.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/clang/test/FixIt/fixit-missing-type-spec.c b/clang/test/FixIt/fixit-missing-type-spec.c index 5d1eecfcb1f7a..a8804593bc496 100644 --- a/clang/test/FixIt/fixit-missing-type-spec.c +++ b/clang/test/FixIt/fixit-missing-type-spec.c @@ -1,14 +1,18 @@ -// RUN: %clang_cc1 -std=c90 -pedantic -Wno-comment -Wno-deprecated-non-prototype -Wimplicit-int -verify=c90 -x c %s +// RUN: %clang_cc1 -std=c90 -pedantic -Wno-comment -Wno-deprecated-non-prototype -Wimplicit-int -fsyntax-only -verify=c90 -x c %s // RUN: cp %s %t -// RUN: %clang_cc1 -std=c90 -pedantic -Wno-comment -Wno-deprecated-non-prototype -Wimplicit-int -fixit %t -// RUN: %clang_cc1 -std=c90 -pedantic -Wno-comment -Wno-deprecated-non-prototype -Wimplicit-int -Werror -x c %t +// RUN: not %clang_cc1 -std=c90 -pedantic -Wno-comment -Wno-deprecated-non-prototype -Wimplicit-int -Werror -fixit %t +// RUN: %clang_cc1 -std=c90 -pedantic -Wno-comment -Wno-deprecated-non-prototype -Wimplicit-int -fsyntax-only -verify -x c %t // RUN: cat %t | FileCheck %s -// RUN: %clang_cc1 -std=c99 -pedantic -Wno-deprecated-non-prototype -verify=c99 -x c %s +// +// RUN: %clang_cc1 -std=c99 -pedantic -Wno-deprecated-non-prototype -fsyntax-only -verify=c99 -x c %s // RUN: cp %s %t // RUN: not %clang_cc1 -std=c99 -pedantic -Wno-deprecated-non-prototype -fixit %t -// RUN: %clang_cc1 -std=c99 -pedantic -Wno-deprecated-non-prototype -Werror -x c %t +// RUN: %clang_cc1 -std=c99 -pedantic -Wno-deprecated-non-prototype -fsyntax-only -verify -x c %t // RUN: cat %t | FileCheck %s -// RUN: %clang_cc1 -std=c23 -pedantic -verify=c23 -x c %s +// +// RUN: %clang_cc1 -std=c23 -pedantic -fsyntax-only -verify=c23 -x c %s + +// expected-no-diagnostics // CHECK: int imp0[4],imp1,imp2=5; imp0[4],imp1,imp2=5; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
