Index: clang-tools-extra/clang-tidy/zircon/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/zircon/CMakeLists.txt +++ clang-tools-extra/clang-tidy/zircon/CMakeLists.txt @@ -1,6 +1,7 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangTidyZirconModule + FblLimitsCheck.cpp TemporaryObjectsCheck.cpp ZirconTidyModule.cpp Index: clang-tools-extra/clang-tidy/zircon/FblLimitsCheck.h =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/zircon/FblLimitsCheck.h @@ -0,0 +1,46 @@ +//===--- FblLimitsCheck.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_ZIRCON_FBLLIMITSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ZIRCON_FBLLIMITSCHECK_H + +#include "../ClangTidy.h" +#include "../utils/IncludeInserter.h" + +namespace clang { +namespace tidy { +namespace zircon { + +/// Replace instances of fbl::numeric_limits with std::numeric_limits, removes +/// includes and adds include if std::numeric_limits is +/// used. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/zircon-fbl-limits.html +class FblLimitsCheck : public ClangTidyCheck { +public: + FblLimitsCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + IncludeStyle(utils::IncludeSorter::parseIncludeStyle( + Options.getLocalOrGlobal("IncludeStyle", "google"))) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void registerPPCallbacks(clang::CompilerInstance &Compiler) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + +private: + std::unique_ptr Inserter; + const utils::IncludeSorter::IncludeStyle IncludeStyle; +}; + +} // namespace zircon +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ZIRCON_FBLLIMITSCHECK_H Index: clang-tools-extra/clang-tidy/zircon/FblLimitsCheck.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/zircon/FblLimitsCheck.cpp @@ -0,0 +1,124 @@ +//===--- FblLimitsCheck.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 "FblLimitsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace zircon { + +class FblLimitsPPCallbacks : public PPCallbacks { +public: + explicit FblLimitsPPCallbacks(FblLimitsCheck &Check, SourceManager &SM) + : Check(Check), SM(SM) {} + + void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, + StringRef FileName, bool IsAngled, + CharSourceRange FilenameRange, const FileEntry *File, + StringRef SearchPath, StringRef RelativePath, + const Module *Imported, + SrcMgr::CharacteristicKind FileType) override; + void EndOfMainFile() override; + +private: + CharSourceRange IncludeRange; + + FblLimitsCheck &Check; + SourceManager &SM; +}; + +void FblLimitsPPCallbacks::InclusionDirective( + SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, + bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, + StringRef SearchPath, StringRef RelativePath, const Module *Imported, + SrcMgr::CharacteristicKind FileType) { + if (FileName == "fbl/limits.h") { + unsigned End = std::strcspn(SM.getCharacterData(HashLoc), "\n") + 1; + IncludeRange = + CharSourceRange::getCharRange(HashLoc, HashLoc.getLocWithOffset(End)); + } +} + +void FblLimitsPPCallbacks::EndOfMainFile() { + // Any instance of should be removed, since the decls in it + // will be replaced in this check and added. + if (!SM.isInMainFile(IncludeRange.getBegin())) { + Check.diag(IncludeRange.getBegin(), + "including fbl/limits.h is deprecated, transitively " + "included from %0") + << SM.getFilename(IncludeRange.getBegin()) + << FixItHint::CreateRemoval(IncludeRange); + return; + } + Check.diag(IncludeRange.getBegin(), "including fbl/limits.h is deprecated") + << FixItHint::CreateRemoval(IncludeRange); +} + +void FblLimitsCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(varDecl(hasType(cxxRecordDecl(allOf( + hasDeclContext(namespaceDecl(hasName("fbl"))), + hasName("numeric_limits"))))) + .bind("limits"), + this); +} + +void FblLimitsCheck::registerPPCallbacks(CompilerInstance &Compiler) { + Inserter = llvm::make_unique( + Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle); + Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks()); + Compiler.getPreprocessor().addPPCallbacks( + llvm::make_unique(*this, + Compiler.getSourceManager())); +} + +void FblLimitsCheck::check(const MatchFinder::MatchResult &Result) { + SourceManager &SM = *Result.SourceManager; + const auto *V = Result.Nodes.getNodeAs("limits"); + + bool Invalid = false; + StringRef ExprStr = Lexer::getSourceText( + CharSourceRange::getCharRange(V->getBeginLoc(), V->getEndLoc()), SM, + getLangOpts(), &Invalid); + if (Invalid) + return; + + size_t LAngle = ExprStr.find("<"); + SourceLocation End; + if (LAngle == std::string::npos) + End = V->getEndLoc(); + else + End = V->getBeginLoc().getLocWithOffset(LAngle - 1); + + auto Diag = + diag(V->getBeginLoc(), "use of fbl::numeric_limits is deprecated, use " + "std::numeric_limits instead") + << FixItHint::CreateReplacement(SourceRange(V->getBeginLoc(), End), + "std::numeric_limits"); + + // Add in the header, since we know this file uses it. + if (auto IncludeFixit = Inserter->CreateIncludeInsertion( + SM.getFileID(V->getLocation()), "limits", + /*IsAngled=*/true)) { + Diag << *IncludeFixit; + } +} + +void FblLimitsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "IncludeStyle", IncludeStyle); +} + +} // namespace zircon +} // namespace tidy +} // namespace clang Index: clang-tools-extra/clang-tidy/zircon/ZirconTidyModule.cpp =================================================================== --- clang-tools-extra/clang-tidy/zircon/ZirconTidyModule.cpp +++ clang-tools-extra/clang-tidy/zircon/ZirconTidyModule.cpp @@ -10,6 +10,7 @@ #include "../ClangTidy.h" #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" +#include "FblLimitsCheck.h" #include "TemporaryObjectsCheck.h" using namespace clang::ast_matchers; @@ -22,6 +23,8 @@ class ZirconModule : public ClangTidyModule { public: void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { + CheckFactories.registerCheck( + "zircon-fbl-limits"); CheckFactories.registerCheck( "zircon-temporary-objects"); } Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -182,6 +182,13 @@ ` check does not warn about calls inside macros anymore by default. +- New :doc:`zircon-fbl-limits + ` check. + + This check is part of the migration checks for moving Zircon user code to use + the C++ standard library. It suggests converting uses of declarations in the + ```` header to their std counterparts in ````. + Improvements to include-fixer ----------------------------- Index: clang-tools-extra/docs/clang-tidy/checks/list.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/checks/list.rst +++ clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -254,4 +254,5 @@ readability-string-compare readability-uniqueptr-delete-release readability-uppercase-literal-suffix + zircon-fbl-limits zircon-temporary-objects Index: clang-tools-extra/docs/clang-tidy/checks/zircon-fbl-limits.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/zircon-fbl-limits.rst @@ -0,0 +1,13 @@ +.. title:: clang-tidy - zircon-fbl-limits + +zircon-fbl-limits +================= + +This check is part of the migration checks for moving Zircon user code to use +the C++ standard library. + +It suggests converting uses of ``fbl::numeric_limits`` to +``std::numeric_limits``, and suggests inserting the ```` header. It +also suggests the removal of all uses of the ```` header, as all +declarations therein will be replaced by the check and the appropriate +```` replacement header recommended. Index: clang-tools-extra/test/clang-tidy/Inputs/zircon/transitive.h =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/Inputs/zircon/transitive.h @@ -0,0 +1,2 @@ +// Transitively included headers. +#include Index: clang-tools-extra/test/clang-tidy/zircon-fbl-limits-transitive.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/zircon-fbl-limits-transitive.cpp @@ -0,0 +1,11 @@ +// RUN: rm -rf %T/Headers +// RUN: mkdir %T/Headers +// RUN: cp -r %S/Inputs/zircon %T/Headers/zircon +// RUN: %check_clang_tidy %s zircon-fbl-limits %t -- -header-filter=.* -- -std=c++11 -I %T/Headers/zircon +// RUN: FileCheck -input-file=%T/Headers/zircon/transitive.h %s -check-prefix=CHECK-FIXES +// RUN: rm -rf %T/Headers + +// transitive.h includes +#include "transitive.h" +// CHECK-NOTES: :2:1: warning: including fbl/limits.h is deprecated, transitively included from {{.*}}. +// CHECK-FIXES-NOT: #include Index: clang-tools-extra/test/clang-tidy/zircon-fbl-limits.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/zircon-fbl-limits.cpp @@ -0,0 +1,45 @@ +// RUN: %check_clang_tidy %s zircon-fbl-limits %t -- -- -isystem %S/Inputs/zircon + +#include +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: including fbl/limits.h is deprecated +// CHECK-FIXES-NOT: #include +// CHECK-FIXES: #include + +namespace fbl { + +template +class numeric_limits {}; + +#define SPECIALIZE_INT_FBL(type) \ + template <> \ + class numeric_limits {}; + +SPECIALIZE_INT_FBL(short) + +numeric_limits lim; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use of fbl::numeric_limits is deprecated, use std::numeric_limits instead +// CHECK-FIXES: std::numeric_limits lim; + +} // namespace fbl + +namespace std { + +template +class numeric_limits {}; + +#define SPECIALIZE_INT_STD(type) \ + template <> \ + class numeric_limits {}; + +SPECIALIZE_INT_STD(short) + +numeric_limits lim; + +} // namespace std + +int main() { + fbl::numeric_limits fbllim; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of fbl::numeric_limits is deprecated, use std::numeric_limits instead + // CHECK-FIXES: std::numeric_limits fbllim; + std::numeric_limits stdlim; +}