diff --git a/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp index 1de9e136c5719..aa27cfd5ce81d 100644 --- a/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp @@ -115,9 +115,9 @@ void DeprecatedHeadersCheck::check( // Emit all the remaining reports. for (const IncludeMarker &Marker : IncludesToBeProcessed) { if (Marker.Replacement.empty()) { - diag(Marker.DiagLoc, - "including '%0' has no effect in C++; consider removing it") - << Marker.FileName + diag(Marker.DiagLoc, "including '%0' has no effect %select{since C23|in " + "C++}1; consider removing it") + << Marker.FileName << getLangOpts().CPlusPlus << FixItHint::CreateRemoval(Marker.ReplacementRange); } else { diag(Marker.DiagLoc, "inclusion of deprecated C++ header " @@ -147,7 +147,9 @@ IncludeModernizePPCallbacks::IncludeModernizePPCallbacks( {"string.h", "cstring"}, {"time.h", "ctime"}, {"wchar.h", "cwchar"}, {"wctype.h", "cwctype"}, }; - CStyledHeaderToCxx.insert(std::begin(CXX98Headers), std::end(CXX98Headers)); + + if (LangOpts.CPlusPlus) + CStyledHeaderToCxx.insert(std::begin(CXX98Headers), std::end(CXX98Headers)); static constexpr std::pair CXX11Headers[] = { {"fenv.h", "cfenv"}, {"stdint.h", "cstdint"}, @@ -157,9 +159,16 @@ IncludeModernizePPCallbacks::IncludeModernizePPCallbacks( if (LangOpts.CPlusPlus11) CStyledHeaderToCxx.insert(std::begin(CXX11Headers), std::end(CXX11Headers)); - static constexpr StringRef HeadersToDelete[] = {"stdalign.h", "stdbool.h", - "iso646.h"}; - DeleteHeaders.insert_range(HeadersToDelete); + static constexpr StringRef CXXHeadersToDelete[] = {"stdalign.h", "cstdalign", + "stdbool.h", "cstdbool", + "iso646.h", "ciso646"}; + if (LangOpts.CPlusPlus) + DeleteHeaders.insert_range(CXXHeadersToDelete); + + static constexpr StringRef C23HeadersToDelete[] = {"stdalign.h", "stdbool.h", + "stdnoreturn.h"}; + if (LangOpts.C23) + DeleteHeaders.insert_range(C23HeadersToDelete); } void IncludeModernizePPCallbacks::InclusionDirective( diff --git a/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.h b/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.h index badb2b41f164f..1b7c1821fb19c 100644 --- a/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.h +++ b/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.h @@ -34,7 +34,7 @@ class DeprecatedHeadersCheck : public ClangTidyCheck { public: DeprecatedHeadersCheck(StringRef Name, ClangTidyContext *Context); bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { - return LangOpts.CPlusPlus; + return LangOpts.CPlusPlus || LangOpts.C23; } void storeOptions(ClangTidyOptions::OptionMap &Opts) override; void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 33cc401bcb78f..c2ed8b643c590 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -346,6 +346,10 @@ Changes in existing checks ` to not diagnose array types which are part of an implicit instantiation of a template. +- Improved :doc:`modernize-deprecated-headers + ` to diagnose more + deprecated headers, in both C++ and (for the first time) in C. + - Improved :doc:`modernize-use-constraints ` check by fixing a crash on uses of non-standard ``enable_if`` with a signature different from diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/deprecated-headers.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/deprecated-headers.rst index 6c35cd4e53d87..8dcc8580b2ccc 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/deprecated-headers.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/deprecated-headers.rst @@ -3,12 +3,55 @@ modernize-deprecated-headers ============================ -Some headers from C library were deprecated in C++ and are no longer welcome in -C++ codebases. Some have no effect in C++. For more details refer to the C++14 -Standard [depr.c.headers] section. - -This check replaces C standard library headers with their C++ alternatives and -removes redundant ones. +There exist headers that produce no effect when included, which are there +solely to ease migrating code. The check will suggest removing them. +In C++, they are: + +* ``stdalign.h`` / ``cstdalign`` +* ``stdbool.h`` / ``cstdbool`` +* ``iso646.h`` / ``ciso646`` + +And in C they are: + +* ``stdalign.h`` // No-op since C23 +* ``stdbool.h`` // No-op since C23 +* ``stdnoreturn.h`` // No-op since C23 + +In C++, there is additionally a number of headers intended for +interoperability with C, which should not be used in pure C++ code. +The check will suggest replacing them with their C++ counterparts +(e.g. replacing ```` with ````). These headers are: + +* ```` +* ```` +* ```` +* ```` +* ```` // deprecated since C++11 +* ```` +* ```` +* ```` +* ```` +* ```` +* ```` +* ```` +* ```` +* ```` +* ```` +* ```` +* ```` +* ```` +* ```` // deprecated since C++11 +* ```` +* ```` // deprecated since C++11 +* ```` +* ```` + +Important note: the C++ headers are not identical to their C counterparts. +The C headers provide names in the global namespace (e.g. ```` +provides ``printf``), but the C++ headers might provide them only in the +``std`` namespace (e.g. ```` provides ``std::printf``, but not +necessarily ``printf``). The check can break code that uses the unqualified +names. .. code-block:: c++ @@ -21,46 +64,9 @@ removes redundant ones. #include // No 'stdbool.h' here. -Important note: the Standard doesn't guarantee that the C++ headers declare all -the same functions in the global namespace. The check in its current form can -break the code that uses library symbols from the global namespace. - -* `` -* `` -* `` -* `` -* `` // deprecated since C++11 -* `` -* `` -* `` -* `` -* `` -* `` -* `` -* `` -* `` -* `` -* `` -* `` -* `` -* `` // deprecated since C++11 -* `` -* `` // deprecated since C++11 -* `` -* `` - -If the specified standard is older than C++11 the check will only replace -headers deprecated before C++11, otherwise -- every header that appeared in -the previous list. - -These headers don't have effect in C++: - -* `` -* `` -* `` - -The checker ignores `include` directives within `extern "C" { ... }` blocks, -since a library might want to expose some API for C and C++ libraries. +The check will ignore `include` directives within `extern "C" { ... }` +blocks, under the assumption that such code is an API meant to compile as +both C and C++: .. code-block:: c++ diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/deprecated-headers/ciso646 b/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/deprecated-headers/ciso646 new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/deprecated-headers/cstdalign b/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/deprecated-headers/cstdalign new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/deprecated-headers/cstdbool b/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/deprecated-headers/cstdbool new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/deprecated-headers/stdnoreturn.h b/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/deprecated-headers/stdnoreturn.h new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/deprecated-headers-c23.c b/clang-tools-extra/test/clang-tidy/checkers/modernize/deprecated-headers-c23.c new file mode 100644 index 0000000000000..f81f9981abaa6 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/deprecated-headers-c23.c @@ -0,0 +1,25 @@ +// RUN: %check_clang_tidy -std=c23-or-later %s modernize-deprecated-headers %t -- -extra-arg-before=-isystem%S/Inputs/deprecated-headers + +#include // +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdalign.h' has no effect since C23; consider removing it +// CHECK-FIXES: // +#include // +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdbool.h' has no effect since C23; consider removing it +// CHECK-FIXES: // +#include // +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdnoreturn.h' has no effect since C23; consider removing it +// CHECK-FIXES: // + +#include // OK, not deprecated + +#include "stdalign.h" // "stdalign.h" +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdalign.h' has no effect since C23; consider removing it +// CHECK-FIXES: // "stdalign.h" +#include "stdbool.h" // "stdbool.h" +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdbool.h' has no effect since C23; consider removing it +// CHECK-FIXES: // "stdbool.h" +#include "stdnoreturn.h" // "stdnoreturn.h" +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdnoreturn.h' has no effect since C23; consider removing it +// CHECK-FIXES: // "stdnoreturn.h" + +#include "stdio.h" // OK, not deprecated diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/deprecated-headers-cxx03.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/deprecated-headers-cxx03.cpp index b02dfd1ce976f..01bb62e99f16f 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/deprecated-headers-cxx03.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/deprecated-headers-cxx03.cpp @@ -59,12 +59,21 @@ #include // // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdalign.h' has no effect in C++; consider removing it // CHECK-FIXES: // +#include // +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'cstdalign' has no effect in C++; consider removing it +// CHECK-FIXES: // #include // // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdbool.h' has no effect in C++; consider removing it // CHECK-FIXES: // +#include // +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'cstdbool' has no effect in C++; consider removing it +// CHECK-FIXES: // #include // // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'iso646.h' has no effect in C++; consider removing it // CHECK-FIXES: // +#include // +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'ciso646' has no effect in C++; consider removing it +// CHECK-FIXES: // // Headers deprecated since C++11: expect no diagnostics. #include @@ -133,12 +142,21 @@ #include "stdalign.h" // "stdalign.h" // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdalign.h' has no effect in C++; consider removing it // CHECK-FIXES: // "stdalign.h" +#include "cstdalign" // "cstdalign" +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'cstdalign' has no effect in C++; consider removing it +// CHECK-FIXES: // "cstdalign" #include "stdbool.h" // "stdbool.h" // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdbool.h' has no effect in C++; consider removing it // CHECK-FIXES: // "stdbool.h" +#include "cstdbool" // "cstdbool" +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'cstdbool' has no effect in C++; consider removing it +// CHECK-FIXES: // "cstdbool" #include "iso646.h" // "iso646.h" // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'iso646.h' has no effect in C++; consider removing it // CHECK-FIXES: // "iso646.h" +#include "ciso646" // "ciso646" +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'ciso646' has no effect in C++; consider removing it +// CHECK-FIXES: // "ciso646" // Headers deprecated since C++11; expect no diagnostics #include "fenv.h" diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/deprecated-headers-cxx11.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/deprecated-headers-cxx11.cpp index 99ef506276a66..d4af364f0a844 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/deprecated-headers-cxx11.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/deprecated-headers-cxx11.cpp @@ -74,12 +74,21 @@ #include // // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdalign.h' has no effect in C++; consider removing it // CHECK-FIXES: // +#include // +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'cstdalign' has no effect in C++; consider removing it +// CHECK-FIXES: // #include // // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdbool.h' has no effect in C++; consider removing it // CHECK-FIXES: // +#include // +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'cstdbool' has no effect in C++; consider removing it +// CHECK-FIXES: // #include // // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'iso646.h' has no effect in C++; consider removing it // CHECK-FIXES: // +#include // +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'ciso646' has no effect in C++; consider removing it +// CHECK-FIXES: // #include "assert.h" // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'assert.h'; consider using 'cassert' instead @@ -155,9 +164,18 @@ #include "stdalign.h" // "stdalign.h" // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdalign.h' has no effect in C++; consider removing it // CHECK-FIXES: // "stdalign.h" +#include "cstdalign" // "cstdalign" +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'cstdalign' has no effect in C++; consider removing it +// CHECK-FIXES: // "cstdalign" #include "stdbool.h" // "stdbool.h" // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'stdbool.h' has no effect in C++; consider removing it // CHECK-FIXES: // "stdbool.h" +#include "cstdbool" // "cstdbool" +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'cstdbool' has no effect in C++; consider removing it +// CHECK-FIXES: // "cstdbool" #include "iso646.h" // "iso646.h" // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'iso646.h' has no effect in C++; consider removing it // CHECK-FIXES: // "iso646.h" +#include "ciso646" // "ciso646" +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: including 'ciso646' has no effect in C++; consider removing it +// CHECK-FIXES: // "ciso646"