Skip to content

Commit

Permalink
[clang-tidy] introduce modernize-deprecated-headers check
Browse files Browse the repository at this point in the history
Summary:
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.

Reviewers: Eugene.Zelenko, LegalizeAdulthood, alexfh

Subscribers: cfe-commits

Patch by Kirill Bobyrev!

Differential Revision: http://reviews.llvm.org/D17484

llvm-svn: 261738
  • Loading branch information
alexfh committed Feb 24, 2016
1 parent ea9fd99 commit e4a75fd
Show file tree
Hide file tree
Showing 8 changed files with 512 additions and 0 deletions.
1 change: 1 addition & 0 deletions clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
set(LLVM_LINK_COMPONENTS support)

add_clang_library(clangTidyModernizeModule
DeprecatedHeadersCheck.cpp
LoopConvertCheck.cpp
LoopConvertUtils.cpp
MakeUniqueCheck.cpp
Expand Down
110 changes: 110 additions & 0 deletions clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
//===--- 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 "llvm/ADT/StringMap.h"

#include <vector>

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:
ClangTidyCheck &Check;
LangOptions LangOpts;
llvm::StringMap<std::string> CStyledHeaderToCxx;
};
} // 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"},
{"complex.h", "ccomplex"},
{"ctype.h", "cctype"},
{"errno.h", "cerrno"},
{"float.h", "cfloat"},
{"inttypes.h", "cinttypes"},
{"iso646.h", "ciso646"},
{"limits.h", "climits"},
{"locale.h", "clocale"},
{"math.h", "cmath"},
{"setjmp.h", "csetjmp"},
{"signal.h", "csignal"},
{"stdarg.h", "cstdarg"},
{"stddef.h", "cstddef"},
{"stdint.h", "cstdint"},
{"stdio.h", "cstdio"},
{"stdlib.h", "cstdlib"},
{"string.h", "cstring"},
{"time.h", "ctime"},
{"wchar.h", "cwchar"},
{"wctype.h", "cwctype"}}) {
// Add C++ 11 headers.
if (LangOpts.CPlusPlus11) {
for (const auto &it : std::vector<std::pair<std::string, std::string>>(
{{"fenv.h", "cfenv"},
{"stdalign.h", "cstdalign"},
{"stdbool.h", "cstdbool"},
{"tgmath.h", "ctgmath"},
{"uchar.h", "cuchar"}})) {
CStyledHeaderToCxx.insert(it);
}
}
}

void IncludeModernizePPCallbacks::InclusionDirective(
SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath, const Module *Imported) {
// FIXME: Take care of library symbols from the global namespace.
//
// Reasonable options for the check:
//
// 1. Insert std prefix for every such symbol occurance.
// 2. Insert `using namespace std;` to the beginning of TU.
// 3. Do nothing and let the user deal with the migration himself.
if (CStyledHeaderToCxx.count(FileName) != 0) {
std::string Replacement =
(llvm::Twine("<") + CStyledHeaderToCxx[FileName] + ">").str();
Check.diag(FilenameRange.getBegin(),
"inclusion of deprecated C++ header '%0'; consider using '%1' instead")
<< FileName << CStyledHeaderToCxx[FileName]
<< FixItHint::CreateReplacement(FilenameRange.getAsRange(),
Replacement);
}
}

} // namespace modernize
} // namespace tidy
} // namespace clang
42 changes: 42 additions & 0 deletions clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//===--- 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
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -30,6 +31,8 @@ namespace modernize {
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");
Expand Down
1 change: 1 addition & 0 deletions clang-tools-extra/docs/clang-tidy/checks/list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Clang-Tidy Checks
misc-unused-parameters
misc-unused-raii
misc-virtual-near-miss
modernize-deprecated-headers
modernize-loop-convert
modernize-make-unique
modernize-pass-by-value
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
.. title:: clang-tidy - modernize-deprecated-headers

modernize-deprecated-headers
==========================

Some headers from C library were deprecated in C++ and are no longer welcome in
C++ codebases. For more details refer to the C++ 14 Standard [depr.c.headers]
section.

This check replaces C standard library headers with their C++ alternatives.

Improtant 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.

* `<assert.h>`
* `<complex.h>`
* `<ctype.h>`
* `<errno.h>`
* `<fenv.h>` // deprecated since C++11
* `<float.h>`
* `<inttypes.h>`
* `<iso646.h>`
* `<limits.h>`
* `<locale.h>`
* `<math.h>`
* `<setjmp.h>`
* `<signal.h>`
* `<stdalign.h>` // deprecated since C++11
* `<stdarg.h>`
* `<stdbool.h>` // deprecated since C++11
* `<stddef.h>`
* `<stdint.h>`
* `<stdio.h>`
* `<stdlib.h>`
* `<string.h>`
* `<tgmath.h>` // deprecated since C++11
* `<time.h>`
* `<uchar.h>` // deprecated since C++11
* `<wchar.h>`
* `<wctype.h>`

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 list.
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// RUN: %check_clang_tidy %s modernize-deprecated-headers %t -- -- -std=c++03 -isystem %S/Inputs/Headers

#include <assert.h>
#include <complex.h>
#include <ctype.h>
#include <errno.h>
#include <float.h>
#include <inttypes.h>
#include <iso646.h>
#include <limits.h>
#include <locale.h>
#include <math.h>
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
#include <wctype.h>

// Headers deprecated since C++11: expect no diagnostics.
#include <fenv.h>
#include <stdalign.h>
#include <stdbool.h>
#include <tgmath.h>
#include <uchar.h>

// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'assert.h'; consider using 'cassert' instead [modernize-deprecated-headers]
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'complex.h'; consider using 'ccomplex' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'ctype.h'; consider using 'cctype' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'errno.h'; consider using 'cerrno' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'float.h'; consider using 'cfloat' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'inttypes.h'; consider using 'cinttypes' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'iso646.h'; consider using 'ciso646' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'limits.h'; consider using 'climits' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'locale.h'; consider using 'clocale' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'math.h'; consider using 'cmath' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'setjmp.h'; consider using 'csetjmp' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'signal.h'; consider using 'csignal' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'stdarg.h'; consider using 'cstdarg' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'stddef.h'; consider using 'cstddef' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'stdint.h'; consider using 'cstdint' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'stdio.h'; consider using 'cstdio' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'stdlib.h'; consider using 'cstdlib' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'string.h'; consider using 'cstring' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'time.h'; consider using 'ctime' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'wchar.h'; consider using 'cwchar' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'wctype.h'; consider using 'cwctype' instead

// CHECK-FIXES: #include <cassert>
// CHECK-FIXES: #include <ccomplex>
// CHECK-FIXES: #include <cctype>
// CHECK-FIXES: #include <cerrno>
// CHECK-FIXES: #include <cfloat>
// CHECK-FIXES: #include <cinttypes>
// CHECK-FIXES: #include <ciso646>
// CHECK-FIXES: #include <climits>
// CHECK-FIXES: #include <clocale>
// CHECK-FIXES: #include <cmath>
// CHECK-FIXES: #include <csetjmp>
// CHECK-FIXES: #include <csignal>
// CHECK-FIXES: #include <cstdarg>
// CHECK-FIXES: #include <cstddef>
// CHECK-FIXES: #include <cstdint>
// CHECK-FIXES: #include <cstdio>
// CHECK-FIXES: #include <cstdlib>
// CHECK-FIXES: #include <cstring>
// CHECK-FIXES: #include <ctime>
// CHECK-FIXES: #include <cwchar>
// CHECK-FIXES: #include <cwctype>

#include "assert.h"
#include "complex.h"
#include "ctype.h"
#include "errno.h"
#include "float.h"
#include "inttypes.h"
#include "iso646.h"
#include "limits.h"
#include "locale.h"
#include "math.h"
#include "setjmp.h"
#include "signal.h"
#include "stdarg.h"
#include "stddef.h"
#include "stdint.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "time.h"
#include "wchar.h"
#include "wctype.h"

// Headers deprecated since C++11; expect no diagnostics
#include "fenv.h"
#include "stdalign.h"
#include "stdbool.h"
#include "tgmath.h"
#include "uchar.h"

// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'assert.h'; consider using 'cassert' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'complex.h'; consider using 'ccomplex' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'ctype.h'; consider using 'cctype' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'errno.h'; consider using 'cerrno' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'float.h'; consider using 'cfloat' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'inttypes.h'; consider using 'cinttypes' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'iso646.h'; consider using 'ciso646' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'limits.h'; consider using 'climits' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'locale.h'; consider using 'clocale' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'math.h'; consider using 'cmath' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'setjmp.h'; consider using 'csetjmp' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'signal.h'; consider using 'csignal' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'stdarg.h'; consider using 'cstdarg' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'stddef.h'; consider using 'cstddef' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'stdint.h'; consider using 'cstdint' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'stdio.h'; consider using 'cstdio' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'stdlib.h'; consider using 'cstdlib' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'string.h'; consider using 'cstring' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'time.h'; consider using 'ctime' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'wchar.h'; consider using 'cwchar' instead
// CHECK-MESSAGES: :[[@LINE-29]]:10: warning: inclusion of deprecated C++ header 'wctype.h'; consider using 'cwctype' instead

// CHECK-FIXES: #include <cassert>
// CHECK-FIXES: #include <ccomplex>
// CHECK-FIXES: #include <cctype>
// CHECK-FIXES: #include <cerrno>
// CHECK-FIXES: #include <cfloat>
// CHECK-FIXES: #include <cinttypes>
// CHECK-FIXES: #include <ciso646>
// CHECK-FIXES: #include <climits>
// CHECK-FIXES: #include <clocale>
// CHECK-FIXES: #include <cmath>
// CHECK-FIXES: #include <csetjmp>
// CHECK-FIXES: #include <csignal>
// CHECK-FIXES: #include <cstdarg>
// CHECK-FIXES: #include <cstddef>
// CHECK-FIXES: #include <cstdint>
// CHECK-FIXES: #include <cstdio>
// CHECK-FIXES: #include <cstdlib>
// CHECK-FIXES: #include <cstring>
// CHECK-FIXES: #include <ctime>
// CHECK-FIXES: #include <cwchar>
// CHECK-FIXES: #include <cwctype>
Loading

0 comments on commit e4a75fd

Please sign in to comment.