diff --git a/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp b/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp --- a/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp @@ -106,8 +106,8 @@ // Create a preprocessor #include FixIt hint (CreateIncludeInsertion checks // whether this already exists). Diagnostic << IncludeInserter.createIncludeInsertion( - Source.getFileID(ComparisonExpr->getBeginLoc()), AbseilStringsMatchHeader, - false); + Source.getFileID(ComparisonExpr->getBeginLoc()), + AbseilStringsMatchHeader); } void StringFindStartswithCheck::registerPPCallbacks( diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp @@ -28,7 +28,7 @@ : ClangTidyCheck(Name, Context), IncludeInserter(Options.getLocalOrGlobal("IncludeStyle", utils::IncludeSorter::IS_LLVM)), - MathHeader(Options.get("MathHeader", "math.h")) {} + MathHeader(Options.get("MathHeader", "")) {} void InitVariablesCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle()); @@ -103,7 +103,7 @@ InitializationString); if (AddMathInclude) { Diagnostic << IncludeInserter.createIncludeInsertion( - Source.getFileID(MatchedDecl->getBeginLoc()), MathHeader, false); + Source.getFileID(MatchedDecl->getBeginLoc()), MathHeader); } } } diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp @@ -85,8 +85,7 @@ IndexRange.getBegin().getLocWithOffset(-1)), ", ") << FixItHint::CreateReplacement(Matched->getEndLoc(), ")") - << Inserter.createMainFileIncludeInsertion(GslHeader, - /*IsAngled=*/false); + << Inserter.createMainFileIncludeInsertion(GslHeader); } return; } diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp @@ -19,7 +19,6 @@ namespace { -constexpr char StdMemoryHeader[] = "memory"; constexpr char ConstructorCall[] = "constructorCall"; constexpr char ResetCall[] = "resetCall"; constexpr char NewExpression[] = "newExpression"; @@ -47,7 +46,7 @@ Inserter(Options.getLocalOrGlobal("IncludeStyle", utils::IncludeSorter::IS_LLVM)), MakeSmartPtrFunctionHeader( - Options.get("MakeSmartPtrFunctionHeader", StdMemoryHeader)), + Options.get("MakeSmartPtrFunctionHeader", "")), MakeSmartPtrFunctionName( Options.get("MakeSmartPtrFunction", MakeSmartPtrFunctionName)), IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {} @@ -430,9 +429,7 @@ if (MakeSmartPtrFunctionHeader.empty()) { return; } - Diag << Inserter.createIncludeInsertion( - FD, MakeSmartPtrFunctionHeader, - /*IsAngled=*/MakeSmartPtrFunctionHeader == StdMemoryHeader); + Diag << Inserter.createIncludeInsertion(FD, MakeSmartPtrFunctionHeader); } } // namespace modernize diff --git a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp @@ -216,8 +216,7 @@ Initializer->getLParenLoc().getLocWithOffset(1), "std::move(") << Inserter.createIncludeInsertion( Result.SourceManager->getFileID(Initializer->getSourceLocation()), - "utility", - /*IsAngled=*/true); + ""); } } // namespace modernize diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp @@ -147,8 +147,7 @@ auto Diag = diag(Range.getBegin(), "use std::move to transfer ownership") << FixItHint::CreateInsertion(Range.getBegin(), "std::move(") << FixItHint::CreateInsertion(Range.getEnd(), ")") - << Inserter.createMainFileIncludeInsertion("utility", - /*IsAngled=*/true); + << Inserter.createMainFileIncludeInsertion(""); return; } diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp @@ -94,7 +94,7 @@ Diag << IncludeInserter.createIncludeInsertion( Result.Context->getSourceManager().getFileID( MatchedCallExpr->getBeginLoc()), - "random", /*IsAngled=*/true); + ""); } } // namespace modernize diff --git a/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp b/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp @@ -192,7 +192,7 @@ if (FnInCmath) Diag << IncludeInserter.createIncludeInsertion( Result.Context->getSourceManager().getFileID(Call->getBeginLoc()), - "cmath", /*IsAngled=*/true); + ""); } } // namespace performance diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp @@ -203,8 +203,7 @@ Diag << FixItHint::CreateInsertion(CopyArgument.getBeginLoc(), "std::move(") << FixItHint::CreateInsertion(EndLoc, ")") << Inserter.createIncludeInsertion( - SM.getFileID(CopyArgument.getBeginLoc()), "utility", - /*IsAngled=*/true); + SM.getFileID(CopyArgument.getBeginLoc()), ""); } } // namespace performance diff --git a/clang-tools-extra/clang-tidy/utils/IncludeInserter.h b/clang-tools-extra/clang-tidy/utils/IncludeInserter.h --- a/clang-tools-extra/clang-tidy/utils/IncludeInserter.h +++ b/clang-tools-extra/clang-tidy/utils/IncludeInserter.h @@ -69,15 +69,35 @@ /// Creates a \p Header inclusion directive fixit in the File \p FileID. /// Returns ``llvm::None`` on error or if the inclusion directive already /// exists. + /// FIXME: This should be removed once the clients are migrated to the + /// overload without the ``IsAngled`` parameter. llvm::Optional createIncludeInsertion(FileID FileID, llvm::StringRef Header, bool IsAngled); + /// Creates a \p Header inclusion directive fixit in the File \p FileID. + /// When \p Header is enclosed in angle brackets, uses angle brackets in the + /// inclusion directive, otherwise uses quotes. + /// Returns ``llvm::None`` on error or if the inclusion directive already + /// exists. + llvm::Optional createIncludeInsertion(FileID FileID, + llvm::StringRef Header); + /// Creates a \p Header inclusion directive fixit in the main file. /// Returns``llvm::None`` on error or if the inclusion directive already /// exists. + /// FIXME: This should be removed once the clients are migrated to the + /// overload without the ``IsAngled`` parameter. llvm::Optional createMainFileIncludeInsertion(llvm::StringRef Header, bool IsAngled); + /// Creates a \p Header inclusion directive fixit in the main file. + /// When \p Header is enclosed in angle brackets, uses angle brackets in the + /// inclusion directive, otherwise uses quotes. + /// Returns``llvm::None`` on error or if the inclusion directive already + /// exists. + llvm::Optional + createMainFileIncludeInsertion(llvm::StringRef Header); + IncludeSorter::IncludeStyle getStyle() const { return Style; } private: diff --git a/clang-tools-extra/clang-tidy/utils/IncludeInserter.cpp b/clang-tools-extra/clang-tidy/utils/IncludeInserter.cpp --- a/clang-tools-extra/clang-tidy/utils/IncludeInserter.cpp +++ b/clang-tools-extra/clang-tidy/utils/IncludeInserter.cpp @@ -77,6 +77,14 @@ return getOrCreate(FileID).CreateIncludeInsertion(Header, IsAngled); } +llvm::Optional +IncludeInserter::createIncludeInsertion(FileID FileID, llvm::StringRef Header) { + bool IsAngled = Header.consume_front("<"); + if (IsAngled != Header.consume_back(">")) + return llvm::None; + return createIncludeInsertion(FileID, Header, IsAngled); +} + llvm::Optional IncludeInserter::createMainFileIncludeInsertion(StringRef Header, bool IsAngled) { @@ -85,6 +93,13 @@ return createIncludeInsertion(SourceMgr->getMainFileID(), Header, IsAngled); } +llvm::Optional +IncludeInserter::createMainFileIncludeInsertion(StringRef Header) { + assert(SourceMgr && "SourceMgr shouldn't be null; did you remember to call " + "registerPreprocessor()?"); + return createIncludeInsertion(SourceMgr->getMainFileID(), Header); +} + void IncludeInserter::addInclude(StringRef FileName, bool IsAngled, SourceLocation HashLocation, SourceLocation EndLocation) { diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -67,6 +67,12 @@ Improvements to clang-tidy -------------------------- +- Checks that allow configuring names of headers to include now support wrapping + the include in angle brackets to create a system include. For example, + :doc:`cppcoreguidelines-init-variables + ` and + :doc:`modernize-make-unique `. + New modules ^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-init-variables.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-init-variables.rst --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-init-variables.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-init-variables.rst @@ -3,13 +3,13 @@ cppcoreguidelines-init-variables ================================ -Checks whether there are local variables that are declared without an -initial value. These may lead to unexpected behaviour if there is a -code path that reads the variable before assigning to it. +Checks whether there are local variables that are declared without an initial +value. These may lead to unexpected behaviour if there is a code path that reads +the variable before assigning to it. -Only integers, booleans, floats, doubles and pointers are checked. The -fix option initializes all detected values with the value of zero. An -exception is float and double types, which are initialized to NaN. +Only integers, booleans, floats, doubles and pointers are checked. The fix +option initializes all detected values with the value of zero. An exception is +float and double types, which are initialized to NaN. As an example a function that looks like this: @@ -42,10 +42,10 @@ .. option:: IncludeStyle - A string specifying which include-style is used, `llvm` or - `google`. Default is `llvm`. + A string specifying which include-style is used, `llvm` or `google`. Default + is `llvm`. .. option:: MathHeader - A string specifying the header to include to get the definition of - `NAN`. Default is `math.h`. + A string specifying the header to include to get the definition of `NAN`. + Default is ``. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-make-unique.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-make-unique.rst --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-make-unique.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-make-unique.rst @@ -37,7 +37,7 @@ .. option:: MakeSmartPtrFunctionHeader A string specifying the corresponding header of make-unique-ptr function. - Default is `memory`. + Default is ``. .. option:: IncludeStyle diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-init-variables.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-init-variables.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-init-variables.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-init-variables.cpp @@ -1,4 +1,5 @@ // RUN: %check_clang_tidy %s cppcoreguidelines-init-variables %t -- -- -fno-delayed-template-parsing -fexceptions +// CHECK-FIXES: {{^}}#include // Ensure that function declarations are not changed. void some_func(int x, double d, bool b, const char *p); diff --git a/clang-tools-extra/unittests/clang-tidy/IncludeInserterTest.cpp b/clang-tools-extra/unittests/clang-tidy/IncludeInserterTest.cpp --- a/clang-tools-extra/unittests/clang-tidy/IncludeInserterTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/IncludeInserterTest.cpp @@ -43,14 +43,12 @@ void check(const ast_matchers::MatchFinder::MatchResult &Result) override { auto Diag = diag(Result.Nodes.getNodeAs("stmt")->getBeginLoc(), "foo, bar"); - for (StringRef Header : HeadersToInclude()) { - Diag << Inserter.createMainFileIncludeInsertion(Header, - IsAngledInclude()); + for (StringRef Header : headersToInclude()) { + Diag << Inserter.createMainFileIncludeInsertion(Header); } } - virtual std::vector HeadersToInclude() const = 0; - virtual bool IsAngledInclude() const = 0; + virtual std::vector headersToInclude() const = 0; utils::IncludeInserter Inserter{utils::IncludeSorter::IS_Google}; }; @@ -60,10 +58,9 @@ NonSystemHeaderInserterCheck(StringRef CheckName, ClangTidyContext *Context) : IncludeInserterCheckBase(CheckName, Context) {} - std::vector HeadersToInclude() const override { + std::vector headersToInclude() const override { return {"path/to/header.h"}; } - bool IsAngledInclude() const override { return false; } }; class EarlyInAlphabetHeaderInserterCheck : public IncludeInserterCheckBase { @@ -71,10 +68,9 @@ EarlyInAlphabetHeaderInserterCheck(StringRef CheckName, ClangTidyContext *Context) : IncludeInserterCheckBase(CheckName, Context) {} - std::vector HeadersToInclude() const override { + std::vector headersToInclude() const override { return {"a/header.h"}; } - bool IsAngledInclude() const override { return false; } }; class MultipleHeaderInserterCheck : public IncludeInserterCheckBase { @@ -82,10 +78,9 @@ MultipleHeaderInserterCheck(StringRef CheckName, ClangTidyContext *Context) : IncludeInserterCheckBase(CheckName, Context) {} - std::vector HeadersToInclude() const override { + std::vector headersToInclude() const override { return {"path/to/header.h", "path/to/header2.h", "path/to/header.h"}; } - bool IsAngledInclude() const override { return false; } }; class CSystemIncludeInserterCheck : public IncludeInserterCheckBase { @@ -93,10 +88,9 @@ CSystemIncludeInserterCheck(StringRef CheckName, ClangTidyContext *Context) : IncludeInserterCheckBase(CheckName, Context) {} - std::vector HeadersToInclude() const override { - return {"stdlib.h"}; + std::vector headersToInclude() const override { + return {""}; } - bool IsAngledInclude() const override { return true; } }; class CXXSystemIncludeInserterCheck : public IncludeInserterCheckBase { @@ -104,8 +98,17 @@ CXXSystemIncludeInserterCheck(StringRef CheckName, ClangTidyContext *Context) : IncludeInserterCheckBase(CheckName, Context) {} - std::vector HeadersToInclude() const override { return {"set"}; } - bool IsAngledInclude() const override { return true; } + std::vector headersToInclude() const override { return {""}; } +}; + +class InvalidIncludeInserterCheck : public IncludeInserterCheckBase { +public: + InvalidIncludeInserterCheck(StringRef CheckName, ClangTidyContext *Context) + : IncludeInserterCheckBase(CheckName, Context) {} + + std::vector headersToInclude() const override { + return {"a.h", "", "b.h", "", ""}; + } }; template @@ -598,6 +601,40 @@ "insert_includes_test_header.cc")); } +TEST(IncludeInserterTest, InvalidHeaderName) { + const char *PreCode = R"( +#include "clang_tidy/tests/insert_includes_test_header.h" + +#include +#include + +#include "path/to/a/header.h" + +void foo() { + int a = 0; +})"; + const char *PostCode = R"( +#include "clang_tidy/tests/insert_includes_test_header.h" + +#include + +#include +#include +#include + +#include "a.h" +#include "b.h" +#include "path/to/a/header.h" + +void foo() { + int a = 0; +})"; + + EXPECT_EQ(PostCode, runCheckOnCode( + PreCode, "clang_tidy/tests/" + "insert_includes_test_header.cc")); +} + } // anonymous namespace } // namespace tidy } // namespace clang