diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 5cc1a36fac1e8..3becd3e3e4603 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -188,6 +188,9 @@ C Language Changes ``-Wunterminated-string-initialization``. However, this diagnostic is not silenced by the ``nonstring`` attribute as these initializations are always incompatible with C++. +- Added the existing ``-Wduplicate-decl-specifier`` diagnostic, which is on by + default, to ``-Wc++-compat`` because duplicated declaration specifiers are + not valid in C++. C2y Feature Support ^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 75e8fc541305b..de3374962c6b0 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -156,6 +156,8 @@ def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">; def C99Compat : DiagGroup<"c99-compat">; def C23Compat : DiagGroup<"c23-compat">; def : DiagGroup<"c2x-compat", [C23Compat]>; + +def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">; def InitStringTooLongMissingNonString : DiagGroup<"unterminated-string-initialization">; def InitStringTooLongForCpp : @@ -168,7 +170,8 @@ def ImplicitIntToEnumCast : DiagGroup<"implicit-int-enum-cast", [ImplicitEnumEnumCast]>; def CXXCompat: DiagGroup<"c++-compat", [ImplicitVoidPtrCast, DefaultConstInit, ImplicitIntToEnumCast, HiddenCppDecl, - InitStringTooLongForCpp]>; + InitStringTooLongForCpp, + DuplicateDeclSpecifier]>; def ExternCCompat : DiagGroup<"extern-c-compat">; def KeywordCompat : DiagGroup<"keyword-compat">; @@ -814,7 +817,6 @@ def TautologicalCompare : DiagGroup<"tautological-compare", TautologicalObjCBoolCompare, TautologicalNegationCompare]>; def HeaderHygiene : DiagGroup<"header-hygiene">; -def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">; def CompareDistinctPointerType : DiagGroup<"compare-distinct-pointer-types">; def GNUUnionCast : DiagGroup<"gnu-union-cast">; def GNUVariableSizedTypeNotAtEnd : DiagGroup<"gnu-variable-sized-type-not-at-end">; diff --git a/clang/test/Sema/warn-duplicate-decl-specifier.c b/clang/test/Sema/warn-duplicate-decl-specifier.c new file mode 100644 index 0000000000000..d57bb867f66f1 --- /dev/null +++ b/clang/test/Sema/warn-duplicate-decl-specifier.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wduplicate-decl-specifier %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wc++-compat %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-duplicate-decl-specifier -Wc++-compat %s +// RUN: %clang_cc1 -fsyntax-only -verify=good -Wc++-compat -Wno-duplicate-decl-specifier %s +// RUN: %clang_cc1 -fsyntax-only -verify=good -Wno-duplicate-decl-specifier %s +// RUN: %clang_cc1 -fsyntax-only -verify -x c++ %s +// good-no-diagnostics + +// Note: we treat this as a warning in C++, so you get the same diagnostics in +// either language mode. However, GCC diagnoses this as an error, so the +// compatibility warning has value. +const const int i = 12; // expected-warning {{duplicate 'const' declaration specifier}} + +__attribute__((address_space(1))) +__attribute__((address_space(1))) // expected-warning {{multiple identical address spaces specified for type}} +int j = 12; +