Skip to content

[C] Add -Wtentative-definition-compat #137967

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.,
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Sema/warn-default-const-init.c
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
23 changes: 23 additions & 0 deletions clang/test/Sema/warn-tentative-defn-compat.c
Original file line number Diff line number Diff line change
@@ -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++.