omtcyf0 created this revision.
omtcyf0 added reviewers: alexfh, LegalizeAdulthood, Eugene.Zelenko.
omtcyf0 added a subscriber: cfe-commits.

This patch introduces the modernize-deprecated-headers check, which is supposed 
to replace deprecated C library headers with the C++ STL-ones.

For information see documentation; for exmaples see the test cases.

http://reviews.llvm.org/D17484

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/DeprecatedHeadersCheck.cpp
  clang-tidy/modernize/DeprecatedHeadersCheck.h
  clang-tidy/modernize/ModernizeTidyModule.cpp
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/modernize-deprecated-headers.rst
  test/clang-tidy/modernize-deprecated-headers-cxx03.cpp
  test/clang-tidy/modernize-deprecated-headers-cxx11.cpp

Index: test/clang-tidy/modernize-deprecated-headers-cxx11.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/modernize-deprecated-headers-cxx11.cpp
@@ -0,0 +1,117 @@
+// RUN: %check_clang_tidy %s modernize-deprecated-headers %t -- -- -std=c++11 -isystem %S/Inputs/Headers
+
+#include "assert.h"
+#include "float.h"
+#include "math.h"
+#include "stddef.h"
+#include "setjmp.h"
+#include "stdio.h"
+#include "time.h"
+#include "ctype.h"
+#include "iso646.h"
+#include "signal.h"
+#include "errno.h"
+#include "limits.h"
+#include "stdarg.h"
+#include "stdlib.h"
+#include "wchar.h"
+#include "locale.h"
+#include "string.h"
+#include "wctype.h"
+#include "complex.h"
+#include "stdint.h"
+#include "inttypes.h"
+
+// C++11 deprecated headers
+#include "stdalign.h"
+#include "stdbool.h"
+#include "fenv.h"
+#include "tgmath.h"
+#include "uchar.h"
+
+// CHECK-FIXES: #include "cassert"
+// CHECK-FIXES-NEXT: #include "cfloat"
+// CHECK-FIXES-NEXT: #include "cmath"
+// CHECK-FIXES-NEXT: #include "cstddef"
+// CHECK-FIXES-NEXT: #include "csetjmp"
+// CHECK-FIXES-NEXT: #include "cstdio"
+// CHECK-FIXES-NEXT: #include "ctime"
+// CHECK-FIXES-NEXT: #include "cctype"
+// CHECK-FIXES-NEXT: #include "ciso646"
+// CHECK-FIXES-NEXT: #include "csignal"
+// CHECK-FIXES-NEXT: #include "cerrno"
+// CHECK-FIXES-NEXT: #include "climits"
+// CHECK-FIXES-NEXT: #include "cstdarg"
+// CHECK-FIXES-NEXT: #include "cstdlib"
+// CHECK-FIXES-NEXT: #include "cwchar"
+// CHECK-FIXES-NEXT: #include "clocale"
+// CHECK-FIXES-NEXT: #include "cstring"
+// CHECK-FIXES-NEXT: #include "cwctype"
+// CHECK-FIXES-NEXT: #include "ccomplex"
+// CHECK-FIXES-NEXT: #include "cstdint"
+// CHECK-FIXES-NEXT: #include "cinttypes"
+
+// C++11 headers
+// CHECK-FIXES: #include "cstdalign"
+// CHECK-FIXES-NEXT: #include "cstdbool"
+// CHECK-FIXES-NEXT: #include "cfenv"
+// CHECK-FIXES-NEXT: #include "ctgmath"
+// CHECK-FIXES-NEXT: #include "cuchar"
+
+#include <assert.h>
+#include <float.h>
+#include <math.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <time.h>
+#include <ctype.h>
+#include <iso646.h>
+#include <signal.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <locale.h>
+#include <string.h>
+#include <wctype.h>
+#include <complex.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+// C++11 deprecated headers
+#include <stdalign.h>
+#include <stdbool.h>
+#include <fenv.h>
+#include <tgmath.h>
+#include <uchar.h>
+
+// CHECK-FIXES: #include <cassert>
+// CHECK-FIXES-NEXT: #include <cfloat>
+// CHECK-FIXES-NEXT: #include <cmath>
+// CHECK-FIXES-NEXT: #include <cstddef>
+// CHECK-FIXES-NEXT: #include <csetjmp>
+// CHECK-FIXES-NEXT: #include <cstdio>
+// CHECK-FIXES-NEXT: #include <ctime>
+// CHECK-FIXES-NEXT: #include <cctype>
+// CHECK-FIXES-NEXT: #include <ciso646>
+// CHECK-FIXES-NEXT: #include <csignal>
+// CHECK-FIXES-NEXT: #include <cerrno>
+// CHECK-FIXES-NEXT: #include <climits>
+// CHECK-FIXES-NEXT: #include <cstdarg>
+// CHECK-FIXES-NEXT: #include <cstdlib>
+// CHECK-FIXES-NEXT: #include <cwchar>
+// CHECK-FIXES-NEXT: #include <clocale>
+// CHECK-FIXES-NEXT: #include <cstring>
+// CHECK-FIXES-NEXT: #include <cwctype>
+// CHECK-FIXES-NEXT: #include <ccomplex>
+// CHECK-FIXES-NEXT: #include <cstdint>
+// CHECK-FIXES-NEXT: #include <cinttypes>
+
+// C++11 headers
+// CHECK-FIXES: #include <cstdalign>
+// CHECK-FIXES-NEXT: #include <cstdbool>
+// CHECK-FIXES-NEXT: #include <cfenv>
+// CHECK-FIXES-NEXT: #include <ctgmath>
+// CHECK-FIXES-NEXT: #include <cuchar>
Index: test/clang-tidy/modernize-deprecated-headers-cxx03.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/modernize-deprecated-headers-cxx03.cpp
@@ -0,0 +1,103 @@
+// RUN: %check_clang_tidy %s modernize-deprecated-headers %t -- -- -std=c++03 -isystem %S/Inputs/Headers
+
+#include "assert.h"
+#include "float.h"
+#include "math.h"
+#include "stddef.h"
+#include "setjmp.h"
+#include "stdio.h"
+#include "time.h"
+#include "ctype.h"
+#include "iso646.h"
+#include "signal.h"
+#include "errno.h"
+#include "limits.h"
+#include "stdarg.h"
+#include "stdlib.h"
+#include "wchar.h"
+#include "locale.h"
+#include "string.h"
+#include "wctype.h"
+#include "complex.h"
+#include "stdint.h"
+#include "inttypes.h"
+
+// C++11 deprecated headers
+#include "stdalign.h"
+#include "stdbool.h"
+#include "fenv.h"
+#include "tgmath.h"
+#include "uchar.h"
+
+// CHECK-FIXES: #include "cassert"
+// CHECK-FIXES-NEXT: #include "cfloat"
+// CHECK-FIXES-NEXT: #include "cmath"
+// CHECK-FIXES-NEXT: #include "cstddef"
+// CHECK-FIXES-NEXT: #include "csetjmp"
+// CHECK-FIXES-NEXT: #include "cstdio"
+// CHECK-FIXES-NEXT: #include "ctime"
+// CHECK-FIXES-NEXT: #include "cctype"
+// CHECK-FIXES-NEXT: #include "ciso646"
+// CHECK-FIXES-NEXT: #include "csignal"
+// CHECK-FIXES-NEXT: #include "cerrno"
+// CHECK-FIXES-NEXT: #include "climits"
+// CHECK-FIXES-NEXT: #include "cstdarg"
+// CHECK-FIXES-NEXT: #include "cstdlib"
+// CHECK-FIXES-NEXT: #include "cwchar"
+// CHECK-FIXES-NEXT: #include "clocale"
+// CHECK-FIXES-NEXT: #include "cstring"
+// CHECK-FIXES-NEXT: #include "cwctype"
+// CHECK-FIXES-NEXT: #include "ccomplex"
+// CHECK-FIXES-NEXT: #include "cstdint"
+// CHECK-FIXES-NEXT: #include "cinttypes"
+
+#include <assert.h>
+#include <float.h>
+#include <math.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <time.h>
+#include <ctype.h>
+#include <iso646.h>
+#include <signal.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <locale.h>
+#include <string.h>
+#include <wctype.h>
+#include <complex.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+// C++11 deprecated headers
+#include <stdalign.h>
+#include <stdbool.h>
+#include <fenv.h>
+#include <tgmath.h>
+#include <uchar.h>
+
+// CHECK-FIXES: #include <cassert>
+// CHECK-FIXES-NEXT: #include <cfloat>
+// CHECK-FIXES-NEXT: #include <cmath>
+// CHECK-FIXES-NEXT: #include <cstddef>
+// CHECK-FIXES-NEXT: #include <csetjmp>
+// CHECK-FIXES-NEXT: #include <cstdio>
+// CHECK-FIXES-NEXT: #include <ctime>
+// CHECK-FIXES-NEXT: #include <cctype>
+// CHECK-FIXES-NEXT: #include <ciso646>
+// CHECK-FIXES-NEXT: #include <csignal>
+// CHECK-FIXES-NEXT: #include <cerrno>
+// CHECK-FIXES-NEXT: #include <climits>
+// CHECK-FIXES-NEXT: #include <cstdarg>
+// CHECK-FIXES-NEXT: #include <cstdlib>
+// CHECK-FIXES-NEXT: #include <cwchar>
+// CHECK-FIXES-NEXT: #include <clocale>
+// CHECK-FIXES-NEXT: #include <cstring>
+// CHECK-FIXES-NEXT: #include <cwctype>
+// CHECK-FIXES-NEXT: #include <ccomplex>
+// CHECK-FIXES-NEXT: #include <cstdint>
+// CHECK-FIXES-NEXT: #include <cinttypes>
Index: docs/clang-tidy/checks/modernize-deprecated-headers.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/modernize-deprecated-headers.rst
@@ -0,0 +1,66 @@
+.. title:: clang-tidy - modernize-deprecated-headers
+
+modernize-deprecated-headers
+==========================
+
+This check replaces C standard library headers with their C++ alternatives.
+
+  Annex D (normative)
+  Compatibility features [depr]
+
+  D.5 C standard library headers [depr.c.headers]
+  1 For compatibility with the C standard library and the C Unicode TR, the C++
+  standard library provides the 26 C headers, as shown in Table 155
+
+  ...
+
+  Every C header, each of which has a name of the form name.h, behaves as if
+  each name placed in the standard library namespace by the corresponding cname
+  header is placed within the global namespace scope. It is unspecified whether
+  these names are first declared or defined within namespace scope (3.3.6) of
+  the namespace std and are then injected into the global namespace scope by
+  explicit using-declarations (7.3.3).
+
+  [ Example: The header <cstdlib> assuredly provides its declarations and
+  definitions within the namespace std. It may also provide these names within
+  the global namespace. The header <stdlib.h> assuredly provides the same
+  declarations and definitions within the global namespace, much as in the C
+  Standard. It may also provide these names within the namespace std.
+  —end example ]
+
+  -- C++ 14 Standard
+
+The following headers were deprecated before C++ 11:
+
+* `<assert.h>`
+* `<inttypes.h>`
+* `<signal.h>`
+* `<stdio.h>`
+* `<wchar.h>`
+* `<complex.h>`
+* `<iso646.h>`
+* `<stdlib.h>`
+* `<wctype.h>`
+* `<ctype.h>`
+* `<limits.h>`
+* `<stdarg.h>`
+* `<string.h>`
+* `<errno.h>`
+* `<locale.h>`
+* `<math.h>`
+* `<stddef.h>`
+* `<time.h>`
+* `<float.h>`
+* `<setjmp.h>`
+* `<stdint.h>`
+
+The following headers were deprecated in C++ 11:
+
+* `<stdbool.h>`
+* `<tgmath.h>`
+* `<fenv.h>`
+* `<uchar.h>`
+* `<stdalign.h>`
+
+If the specified standard is older than C++11 the check will only replace
+headers from the first list, otherwise -- every header that appeared before.
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -72,6 +72,7 @@
    misc-unused-parameters
    misc-unused-raii
    misc-virtual-near-miss
+   modernize-deprecated-headers
    modernize-loop-convert
    modernize-make-unique
    modernize-pass-by-value
Index: clang-tidy/modernize/ModernizeTidyModule.cpp
===================================================================
--- clang-tidy/modernize/ModernizeTidyModule.cpp
+++ clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -10,6 +10,7 @@
 #include "../ClangTidy.h"
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
+#include "DeprecatedHeadersCheck.h"
 #include "LoopConvertCheck.h"
 #include "MakeUniqueCheck.h"
 #include "PassByValueCheck.h"
@@ -30,6 +31,8 @@
 class ModernizeModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<DeprecatedHeadersCheck>(
+        "modernize-deprecated-headers");
     CheckFactories.registerCheck<LoopConvertCheck>("modernize-loop-convert");
     CheckFactories.registerCheck<MakeUniqueCheck>("modernize-make-unique");
     CheckFactories.registerCheck<PassByValueCheck>("modernize-pass-by-value");
Index: clang-tidy/modernize/DeprecatedHeadersCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/modernize/DeprecatedHeadersCheck.h
@@ -0,0 +1,43 @@
+//===--- DeprecatedHeadersCheck.h - clang-tidy-----------------------*- C++
+//-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_C_HEADERS_TO_CXX_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_C_HEADERS_TO_CXX_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// This check replaces deprecated C library headers with their C++ STL
+/// alternatives.
+///
+/// Before:
+///   #include <header.h>
+/// After:
+///   #include <cheader>
+///
+/// Example: <stdio.h> => <cstdio>
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-deprecated-headers.html
+class DeprecatedHeadersCheck : public ClangTidyCheck {
+public:
+  DeprecatedHeadersCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_C_HEADERS_TO_CXX_H
Index: clang-tidy/modernize/DeprecatedHeadersCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/modernize/DeprecatedHeadersCheck.cpp
@@ -0,0 +1,102 @@
+//===--- DeprecatedHeadersCheck.cpp - clang-tidy---------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DeprecatedHeadersCheck.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+
+#include <iostream>
+#include <vector>
+#include <map>
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+namespace {
+class IncludeModernizePPCallbacks : public PPCallbacks {
+public:
+  explicit IncludeModernizePPCallbacks(ClangTidyCheck &Check,
+                                       LangOptions LangOpts);
+
+  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+                          StringRef FileName, bool IsAngled,
+                          CharSourceRange FilenameRange, const FileEntry *File,
+                          StringRef SearchPath, StringRef RelativePath,
+                          const Module *Imported) override;
+
+private:
+  std::map<std::string, std::string> CStyledHeaderToCxx;
+
+  ClangTidyCheck &Check;
+  LangOptions LangOpts;
+};
+} // namespace
+
+void DeprecatedHeadersCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  if (this->getLangOpts().CPlusPlus) {
+    Compiler.getPreprocessor().addPPCallbacks(
+        ::llvm::make_unique<IncludeModernizePPCallbacks>(*this,
+                                                         this->getLangOpts()));
+  }
+}
+
+IncludeModernizePPCallbacks::IncludeModernizePPCallbacks(ClangTidyCheck &Check,
+                                                         LangOptions LangOpts)
+    : Check(Check), LangOpts(LangOpts) {
+  CStyledHeaderToCxx["assert.h"] = "cassert";
+  CStyledHeaderToCxx["float.h"] = "cfloat";
+  CStyledHeaderToCxx["math.h"] = "cmath";
+  CStyledHeaderToCxx["stddef.h"] = "cstddef";
+  CStyledHeaderToCxx["setjmp.h"] = "csetjmp";
+  CStyledHeaderToCxx["stdio.h"] = "cstdio";
+  CStyledHeaderToCxx["time.h"] = "ctime";
+  CStyledHeaderToCxx["ctype.h"] = "cctype";
+  CStyledHeaderToCxx["iso646.h"] = "ciso646";
+  CStyledHeaderToCxx["signal.h"] = "csignal";
+  CStyledHeaderToCxx["errno.h"] = "cerrno";
+  CStyledHeaderToCxx["limits.h"] = "climits";
+  CStyledHeaderToCxx["stdarg.h"] = "cstdarg";
+  CStyledHeaderToCxx["stdlib.h"] = "cstdlib";
+  CStyledHeaderToCxx["wchar.h"] = "cwchar";
+  CStyledHeaderToCxx["locale.h"] = "clocale";
+  CStyledHeaderToCxx["string.h"] = "cstring";
+  CStyledHeaderToCxx["wctype.h"] = "cwctype";
+  CStyledHeaderToCxx["complex.h"] = "ccomplex";
+  CStyledHeaderToCxx["stdint.h"] = "cstdint";
+  CStyledHeaderToCxx["inttypes.h"] = "cinttypes";
+
+  // C++ 11 headers
+  if (LangOpts.CPlusPlus11) {
+    CStyledHeaderToCxx["stdbool.h"] = "cstdbool";
+    CStyledHeaderToCxx["fenv.h"] = "cfenv";
+    CStyledHeaderToCxx["tgmath.h"] = "ctgmath";
+    CStyledHeaderToCxx["uchar.h"] = "cuchar";
+    CStyledHeaderToCxx["stdalign.h"] = "cstdalign";
+  }
+}
+
+void IncludeModernizePPCallbacks::InclusionDirective(
+    SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
+    bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
+    StringRef SearchPath, StringRef RelativePath, const Module *Imported) {
+  if (CStyledHeaderToCxx.count(std::string(FileName)) != 0) {
+    std::string Replacement =
+        (IsAngled) ? "<" + CStyledHeaderToCxx[std::string(FileName)] + ">"
+                   : "\"" + CStyledHeaderToCxx[std::string(FileName)] + "\"";
+    Check.diag(FilenameRange.getBegin(), "including deprecated C++ header")
+        << FixItHint::CreateReplacement(FilenameRange.getAsRange(),
+                                        Replacement);
+  }
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/modernize/CMakeLists.txt
===================================================================
--- clang-tidy/modernize/CMakeLists.txt
+++ clang-tidy/modernize/CMakeLists.txt
@@ -1,6 +1,7 @@
 set(LLVM_LINK_COMPONENTS support)
 
 add_clang_library(clangTidyModernizeModule
+  DeprecatedHeadersCheck.cpp
   LoopConvertCheck.cpp
   LoopConvertUtils.cpp
   MakeUniqueCheck.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to