Author: Aaron Ballman Date: 2025-05-01T07:31:48-04:00 New Revision: bc9aa0f4c4c6ad9dd6207097478f4e461a8fe5cb
URL: https://github.com/llvm/llvm-project/commit/bc9aa0f4c4c6ad9dd6207097478f4e461a8fe5cb DIFF: https://github.com/llvm/llvm-project/commit/bc9aa0f4c4c6ad9dd6207097478f4e461a8fe5cb.diff LOG: [C] Add -Wtentative-definition-compat (#137967) This adds a new diagnostic to warn about redeclaration of a tentative definition in C. This is incompatible with C++, so the new diagnostic group is under -Wc++-compat. Added: clang/test/Sema/warn-tentative-defn-compat.c Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticGroups.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaDecl.cpp clang/test/Sema/warn-default-const-init.c Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 65ae5945ca27c..1dd97bcc67364 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -175,6 +175,15 @@ C Language Changes ``-Wenum-conversion`` and ``-Wimplicit-int-enum-cast``. This conversion is an int-to-enum conversion because the enumeration on the right-hand side is promoted to ``int`` before the assignment. +- Added ``-Wtentative-definition-compat``, grouped under ``-Wc++-compat``, + which diagnoses tentative definitions in C with multiple declarations as + being incompatible with C++. e.g., + + .. code-block:: c + + // File scope + int i; + int i; // Vaild C, invalid C++, now diagnosed - Added ``-Wunterminated-string-initialization``, grouped under ``-Wextra``, which diagnoses an initialization from a string literal where only the null terminator cannot be stored. e.g., diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 21d5d54e9c8c5..4f235fecf4cf9 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -176,9 +176,11 @@ def DefaultConstInit : DiagGroup<"default-const-init", def ImplicitVoidPtrCast : DiagGroup<"implicit-void-ptr-cast">; def ImplicitIntToEnumCast : DiagGroup<"implicit-int-enum-cast", [ImplicitEnumEnumCast]>; +def TentativeDefnCompat : DiagGroup<"tentative-definition-compat">; def CXXCompat: DiagGroup<"c++-compat", [ImplicitVoidPtrCast, DefaultConstInit, ImplicitIntToEnumCast, HiddenCppDecl, InitStringTooLongForCpp, + TentativeDefnCompat, DuplicateDeclSpecifier]>; def ExternCCompat : DiagGroup<"extern-c-compat">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index c6c52f471479e..bf7017436f38c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7455,6 +7455,9 @@ def err_tentative_def_incomplete_type : Error< def warn_tentative_incomplete_array : Warning< "tentative array definition assumed to have one element">, InGroup<DiagGroup<"tentative-definition-array">>; +def warn_cxx_compat_tentative_definition : Warning< + "duplicate declaration of %0 is invalid in C++">, + InGroup<TentativeDefnCompat>, DefaultIgnore; def err_typecheck_incomplete_array_needs_initializer : Error< "definition of variable with array type needs an explicit size " "or an initializer">; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 25ee19e0ba5f1..517b3067696a0 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4750,6 +4750,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { if (Def && checkVarDeclRedefinition(Def, New)) return; } + } else { + Diag(New->getLocation(), diag::warn_cxx_compat_tentative_definition) << New; + Diag(Old->getLocation(), diag::note_previous_declaration); } if (haveIncompatibleLanguageLinkages(Old, New)) { diff --git a/clang/test/Sema/warn-default-const-init.c b/clang/test/Sema/warn-default-const-init.c index da11f4189047f..ddd4aba2b5de3 100644 --- a/clang/test/Sema/warn-default-const-init.c +++ b/clang/test/Sema/warn-default-const-init.c @@ -1,5 +1,5 @@ // Both of these should enable everything. -// RUN: %clang_cc1 -fsyntax-only -verify=unsafe-var,unsafe-field,zero-init-var,zero-init-field -Wc++-compat %s +// RUN: %clang_cc1 -fsyntax-only -verify=unsafe-var,unsafe-field,zero-init-var,zero-init-field -Wc++-compat -Wno-tentative-definition-compat %s // RUN: %clang_cc1 -fsyntax-only -verify=unsafe-var,unsafe-field,zero-init-var,zero-init-field -Wdefault-const-init %s // This should enable nothing. diff --git a/clang/test/Sema/warn-tentative-defn-compat.c b/clang/test/Sema/warn-tentative-defn-compat.c new file mode 100644 index 0000000000000..02f3db99992f1 --- /dev/null +++ b/clang/test/Sema/warn-tentative-defn-compat.c @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wtentative-definition-compat %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wc++-compat %s +// RUN: %clang_cc1 -fsyntax-only -verify=good %s +// RUN: %clang_cc1 -fsyntax-only -verify=cxx -x c++ %s +// good-no-diagnostics + +int i; // expected-note {{previous declaration is here}} \ + cxx-note {{previous definition is here}} +int i; // expected-warning {{duplicate declaration of 'i' is invalid in C++}} \ + cxx-error {{redefinition of 'i'}} + +int j = 12; // expected-note {{previous declaration is here}} \ + cxx-note {{previous definition is here}} +int j; // expected-warning {{duplicate declaration of 'j' is invalid in C++}} \ + cxx-error {{redefinition of 'j'}} + +int k; // expected-note {{previous declaration is here}} \ + cxx-note {{previous definition is here}} +int k = 12; // expected-warning {{duplicate declaration of 'k' is invalid in C++}} \ + cxx-error {{redefinition of 'k'}} + +// Cannot have two declarations with initializers, that is a redefinition in +// both C and C++. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits