fbl/unique_ptr.h --> std <memory>
Change-Id: Ieb4150ffecfd86e30045bef8aaa4e05e33933df0
diff --git a/clang-tools-extra/clang-tidy/zircon/CMakeLists.txt b/clang-tools-extra/clang-tidy/zircon/CMakeLists.txt
index 56b6278..3ebc5db 100644
--- a/clang-tools-extra/clang-tidy/zircon/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/zircon/CMakeLists.txt
@@ -2,6 +2,7 @@
add_clang_library(clangTidyZirconModule
FblAtomicCheck.cpp
+ FblMemoryCheck.cpp
FblMoveCheck.cpp
FblLimitsCheck.cpp
FblOptionalCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/zircon/FblMemoryCheck.cpp b/clang-tools-extra/clang-tidy/zircon/FblMemoryCheck.cpp
new file mode 100644
index 0000000..493f616
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/zircon/FblMemoryCheck.cpp
@@ -0,0 +1,152 @@
+//===--- FblMemoryCheck.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 "FblMemoryCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/Optional.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace zircon {
+
+class FblMemoryPPCallbacks : public PPCallbacks {
+public:
+ explicit FblMemoryPPCallbacks(FblMemoryCheck &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:
+ bool found = false;
+ CharSourceRange IncludeRange;
+
+ FblMemoryCheck &Check;
+ SourceManager &SM;
+};
+
+void FblMemoryPPCallbacks::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/unique_ptr.h") {
+ unsigned End = std::strcspn(SM.getCharacterData(HashLoc), "\n") + 1;
+ IncludeRange =
+ CharSourceRange::getCharRange(HashLoc, HashLoc.getLocWithOffset(End));
+ found = true;
+ }
+}
+
+void FblMemoryPPCallbacks::EndOfMainFile() {
+ // Any instance of <fbl/unique_ptr.h> should be removed, since the decls in it
+ // will be replaced in this check and <memory> added.
+ if (found) {
+ if (!SM.isInMainFile(IncludeRange.getBegin())) {
+ Check.diag(IncludeRange.getBegin(),
+ "including fbl/unique_ptr.h is deprecated, transitively "
+ "included from %0")
+ << SM.getFilename(IncludeRange.getBegin())
+ << FixItHint::CreateRemoval(IncludeRange);
+ return;
+ }
+ Check.diag(IncludeRange.getBegin(),
+ "including fbl/unique_ptr.h is deprecated")
+ << FixItHint::CreateRemoval(IncludeRange);
+ }
+}
+
+void FblMemoryCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(
+ valueDecl(hasType(cxxRecordDecl(
+ allOf(hasDeclContext(namespaceDecl(hasName("::fbl"))),
+ hasName("unique_ptr")))))
+ .bind("unique_ptr"),
+ this);
+ Finder->addMatcher(
+ declRefExpr(hasDeclaration(functionDecl(
+ allOf(hasDeclContext(namespaceDecl(hasName("::fbl"))),
+ hasName("make_unique")))))
+ .bind("make_unique"),
+ this);
+}
+
+void FblMemoryCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+ Inserter = llvm::make_unique<utils::IncludeInserter>(
+ Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle);
+ Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+ Compiler.getPreprocessor().addPPCallbacks(
+ llvm::make_unique<FblMemoryPPCallbacks>(*this,
+ Compiler.getSourceManager()));
+}
+
+void FblMemoryCheck::check(const MatchFinder::MatchResult &Result) {
+ SourceManager &SM = *Result.SourceManager;
+ SourceLocation Start;
+ SourceLocation End;
+ std::string Name;
+ if (const auto *V = Result.Nodes.getNodeAs<ValueDecl>("unique_ptr")) {
+ Start = V->getBeginLoc();
+ End = V->getEndLoc();
+ Name = "unique_ptr";
+ } else if (const auto *V =
+ Result.Nodes.getNodeAs<DeclRefExpr>("make_unique")) {
+ Start = V->getBeginLoc();
+ End = V->getEndLoc();
+ Name = "make_unique";
+ }
+
+ // If it's a macro, we want to extract information about the macro instead of
+ // the expr.
+ if (Start.isMacroID()) {
+ Start = SM.getSpellingLoc(Start);
+ End = SM.getSpellingLoc(End);
+ }
+
+ bool Invalid = false;
+ StringRef Statement = Lexer::getSourceText(
+ CharSourceRange::getCharRange(Start, End), SM, getLangOpts(), &Invalid);
+ if (Invalid || !Statement.startswith("fbl"))
+ return;
+
+ size_t LAngle = Statement.find("<");
+ if (LAngle != std::string::npos)
+ End = Start.getLocWithOffset(LAngle - 1);
+
+ DiagnosticBuilder Diag =
+ diag(Start, "use of fbl::%0 is deprecated, use "
+ "std::%1 instead")
+ << Name << Name
+ << FixItHint::CreateReplacement(SourceRange(Start, End), "std::" + Name);
+
+ // Add in the <unique_ptr> header, since we know this file uses it.
+ if (llvm::Optional<FixItHint> IncludeFixit =
+ Inserter->CreateIncludeInsertion(SM.getFileID(Start), "memory",
+ /*IsAngled=*/true)) {
+ Diag << *IncludeFixit;
+ }
+}
+
+void FblMemoryCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "IncludeStyle", IncludeStyle);
+}
+
+} // namespace zircon
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/zircon/FblMemoryCheck.h b/clang-tools-extra/clang-tidy/zircon/FblMemoryCheck.h
new file mode 100644
index 0000000..cc16c42
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/zircon/FblMemoryCheck.h
@@ -0,0 +1,46 @@
+//===--- FblMemoryCheck.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_FBLMEMORYCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ZIRCON_FBLMEMORYCHECK_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
+/// <fbl/limits.h> includes and adds <limits> 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 FblMemoryCheck : public ClangTidyCheck {
+public:
+ FblMemoryCheck(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<utils::IncludeInserter> Inserter;
+ const utils::IncludeSorter::IncludeStyle IncludeStyle;
+};
+
+} // namespace zircon
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ZIRCON_FBLMEMORYCHECK_H
diff --git a/clang-tools-extra/clang-tidy/zircon/ZirconTidyModule.cpp b/clang-tools-extra/clang-tidy/zircon/ZirconTidyModule.cpp
index c89774e..4e5c845 100644
--- a/clang-tools-extra/clang-tidy/zircon/ZirconTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/zircon/ZirconTidyModule.cpp
@@ -11,6 +11,7 @@
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
#include "FblAtomicCheck.h"
+#include "FblMemoryCheck.h"
#include "FblMoveCheck.h"
#include "FblLimitsCheck.h"
#include "FblOptionalCheck.h"
@@ -29,6 +30,8 @@
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
CheckFactories.registerCheck<FblAtomicCheck>(
"zircon-fbl-atomic");
+ CheckFactories.registerCheck<FblMemoryCheck>(
+ "zircon-fbl-memory");
CheckFactories.registerCheck<FblMoveCheck>(
"zircon-fbl-move");
CheckFactories.registerCheck<FblLimitsCheck>(
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 7b6b1e1..91cd062 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -67,6 +67,11 @@
Improvements to clang-tidy
--------------------------
+- New :doc:`zircon-fbl-memory
+ <clang-tidy/checks/zircon-fbl-memory>` check.
+
+ FIXME: add release notes.
+
- New :doc:`zircon-fbl-atomic
<clang-tidy/checks/zircon-fbl-atomic>` check.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index ad1c59f..3328779 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -260,6 +260,7 @@
readability-uppercase-literal-suffix
zircon-fbl-atomic
zircon-fbl-limits
+ zircon-fbl-memory
zircon-fbl-move
zircon-fbl-optional
zircon-fbl-type-traits
diff --git a/clang-tools-extra/docs/clang-tidy/checks/zircon-fbl-memory.rst b/clang-tools-extra/docs/clang-tidy/checks/zircon-fbl-memory.rst
new file mode 100644
index 0000000..9fdeb3b
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/zircon-fbl-memory.rst
@@ -0,0 +1,6 @@
+.. title:: clang-tidy - zircon-fbl-memory
+
+zircon-fbl-memory
+=================
+
+FIXME: Describe what patterns does the check detect and why. Give examples.
diff --git a/clang-tools-extra/test/clang-tidy/Inputs/zircon/fbl/unique_ptr.h b/clang-tools-extra/test/clang-tidy/Inputs/zircon/fbl/unique_ptr.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/Inputs/zircon/fbl/unique_ptr.h
diff --git a/clang-tools-extra/test/clang-tidy/Inputs/zircon/transitive.h b/clang-tools-extra/test/clang-tidy/Inputs/zircon/transitive.h
index fe6529d..cf3ca62 100644
--- a/clang-tools-extra/test/clang-tidy/Inputs/zircon/transitive.h
+++ b/clang-tools-extra/test/clang-tidy/Inputs/zircon/transitive.h
@@ -3,3 +3,4 @@
#include <fbl/optional.h>
#include <fbl/type_support.h>
#include <fbl/atomic.h>
+#include <fbl/unique_ptr.h>
diff --git a/clang-tools-extra/test/clang-tidy/zircon-fbl-memory-transitive.cpp b/clang-tools-extra/test/clang-tidy/zircon-fbl-memory-transitive.cpp
new file mode 100644
index 0000000..c41afd8
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/zircon-fbl-memory-transitive.cpp
@@ -0,0 +1,11 @@
+// RUN: rm -rf %T/Unique
+// RUN: mkdir %T/Unique
+// RUN: cp -r %S/Inputs/zircon %T/Unique/zircon
+// RUN: %check_clang_tidy %s zircon-fbl-memory %t -- -header-filter=.* -- -std=c++11 -I %T/Unique/zircon
+// RUN: FileCheck -input-file=%T/Unique/zircon/transitive.h %s -check-prefix=CHECK-FIXES
+// RUN: rm -rf %T/Unique
+
+// transitive.h includes <fbl/unique_ptr.h>
+#include "transitive.h"
+// CHECK-NOTES: :6:1: warning: including fbl/unique_ptr.h is deprecated, transitively included from {{.*}}.
+// CHECK-FIXES-NOT: #include <fbl/unique_ptr.h>
diff --git a/clang-tools-extra/test/clang-tidy/zircon-fbl-memory.cpp b/clang-tools-extra/test/clang-tidy/zircon-fbl-memory.cpp
new file mode 100644
index 0000000..f6b9d1e
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/zircon-fbl-memory.cpp
@@ -0,0 +1,115 @@
+// RUN: %check_clang_tidy %s zircon-fbl-memory %t -- -- -isystem %S/Inputs/zircon
+
+#include <fbl/unique_ptr.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: including fbl/unique_ptr.h is deprecated
+// CHECK-FIXES-NOT: #include <fbl/unique_ptr.h>
+// CHECK-FIXES: #include <memory>
+
+namespace fbl {
+
+template <typename T>
+class unique_ptr {
+public:
+ explicit unique_ptr(T* t) { }
+};
+
+template <typename T>
+class unique_ptr<T[]> {
+public:
+ explicit unique_ptr(T* t) { }
+};
+
+template <typename T>
+struct unique_type {
+ using single = unique_ptr<T>;
+};
+
+template <typename T>
+struct unique_type<T[]> {
+ using incomplete_array = unique_ptr<T[]>;
+};
+
+template <typename T> struct remove_extent { using type = T; };
+
+template <typename T> struct remove_extent<T[]> { using type = T; };
+
+// Constructs a new object and assigns it to a unique_ptr.
+template <typename T, typename... Args>
+typename unique_type<T>::single make_unique(Args &&... args) {
+ return unique_ptr<T>(new T());
+}
+
+template <typename T, typename... Args>
+typename unique_type<T>::incomplete_array make_unique(int size) {
+ using single_type = typename remove_extent<T>::type;
+ return unique_ptr<single_type[]>(new single_type[size]());
+}
+
+} // namespace fbl
+
+namespace std {
+template <class T>
+struct default_delete {};
+
+template <class T> struct default_delete<T[]> {};
+
+template <class T, class D = default_delete<T> > class unique_ptr {
+public:
+ explicit unique_ptr(T *t) {}
+};
+
+template <class T, class D> class unique_ptr<T[], D> {
+public:
+ explicit unique_ptr(T *t) {}
+};
+
+template <class _Tp> struct __unique_if {
+ typedef unique_ptr<_Tp> __unique_single;
+};
+
+template <class _Tp> struct __unique_if<_Tp[]> {
+ typedef unique_ptr<_Tp[]> __unique_array_unknown_bound;
+};
+
+template<class _Tp, int _Np>
+struct __unique_if<_Tp[_Np]>
+{
+ typedef void __unique_array_known_bound;
+};
+
+template <class _Tp> struct remove_extent
+ {typedef _Tp type;};
+template <class _Tp> struct remove_extent<_Tp[]>
+ {typedef _Tp type;};
+template <class _Tp, int _Np> struct remove_extent<_Tp[_Np]>
+ {typedef _Tp type;};
+
+template<class _Tp, class... _Args>
+typename __unique_if<_Tp>::__unique_single
+make_unique(_Args&&... __args)
+{
+ return unique_ptr<_Tp>(new _Tp());
+}
+
+template<class _Tp>
+typename __unique_if<_Tp>::__unique_array_unknown_bound
+make_unique(int __n)
+{
+ typedef typename remove_extent<_Tp>::type _Up;
+ return unique_ptr<_Tp>(new _Up[__n]());
+}
+
+} // namespace std
+
+int main() {
+ fbl::unique_ptr<int> a = fbl::make_unique<int>();
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of fbl::unique_ptr is deprecated, use std::unique_ptr instead
+ // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use of fbl::make_unique is deprecated, use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<int> a = std::make_unique<int>();
+ std::unique_ptr<int> b = std::make_unique<int>();
+
+ auto c = fbl::make_unique<int>();
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of fbl::make_unique is deprecated, use std::make_unique instead
+ // CHECK-FIXES: auto d = std::make_unique<int>();
+ auto d = std::make_unique<int>();
+}