https://github.com/kleinesfilmroellchen created https://github.com/llvm/llvm-project/pull/67749
Projects can now add config fragments like this to their .clangd: ```yaml Style: QuotedHeaders: "src/.*" AngledHeaders: ["path/sdk/.*", "third-party/.*"] ``` to force headers inserted via the --header-insertion=iwyu mode matching at least one of the regexes to have <> (AngledHeaders) or "" (QuotedHeaders) around them, respectively. For other headers (and in conflicting cases where both styles have a matching regex), the current system header detection remains. Ref https://github.com/clangd/clangd/issues/1247 Based on https://reviews.llvm.org/D145843 This solution does not affect other clang tools like clang-format. CC @HighCommander4 @adkaster. I have no merge rights so someone else needs to commit this. From d2bb8241dfd396c1c77413918f1983b1afe16517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kleines=20Filmr=C3=B6llchen?= <filmroellc...@serenityos.org> Date: Fri, 29 Sep 2023 00:22:12 +0200 Subject: [PATCH] [clangd] Allow specifying what headers are always included via "" or <> Projects can now add config fragments like this to their .clangd: ```yaml Style: QuotedHeaders: "src/.*" AngledHeaders: ["path/sdk/.*", "third-party/.*"] ``` to force headers inserted via the --header-insertion=iwyu mode matching at least one of the regexes to have <> (AngledHeaders) or "" (QuotedHeaders) around them, respectively. For other headers (and in conflicting cases where both styles have a matching regex), the current system header detection remains. Ref https://github.com/clangd/clangd/issues/1247 Based on https://reviews.llvm.org/D145843 This solution does not affect other clang tools like clang-format. --- clang-tools-extra/clangd/CodeComplete.cpp | 15 +++-- clang-tools-extra/clangd/Config.h | 4 ++ clang-tools-extra/clangd/ConfigCompile.cpp | 66 +++++++++++++++++++ clang-tools-extra/clangd/ConfigFragment.h | 13 ++++ clang-tools-extra/clangd/ConfigYAML.cpp | 8 +++ clang-tools-extra/clangd/Headers.cpp | 34 ++++++++-- clang-tools-extra/clangd/Headers.h | 11 +++- clang-tools-extra/clangd/IncludeCleaner.h | 1 - clang-tools-extra/clangd/ParsedAST.cpp | 3 +- .../clangd/unittests/ConfigCompileTests.cpp | 34 ++++++++++ .../clangd/unittests/ConfigYAMLTests.cpp | 8 ++- .../clangd/unittests/HeadersTests.cpp | 29 +++++++- 12 files changed, 208 insertions(+), 18 deletions(-) diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 70c4d7e65b76db3..388e032e160474a 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -21,6 +21,7 @@ #include "AST.h" #include "CodeCompletionStrings.h" #include "Compiler.h" +#include "Config.h" #include "ExpectedTypes.h" #include "Feature.h" #include "FileDistance.h" @@ -786,8 +787,8 @@ SpecifiedScope getQueryScopes(CodeCompletionContext &CCContext, llvm::StringRef SpelledSpecifier = Lexer::getSourceText( CharSourceRange::getCharRange(SemaSpecifier->getRange()), CCSema.SourceMgr, clang::LangOptions()); - if (SpelledSpecifier.consume_front("::")) - Scopes.QueryScopes = {""}; + if (SpelledSpecifier.consume_front("::")) + Scopes.QueryScopes = {""}; Scopes.UnresolvedQualifier = std::string(SpelledSpecifier); // Sema excludes the trailing "::". if (!Scopes.UnresolvedQualifier->empty()) @@ -1540,7 +1541,7 @@ class CodeCompleteFlow { CompletionPrefix HeuristicPrefix; std::optional<FuzzyMatcher> Filter; // Initialized once Sema runs. Range ReplacedRange; - std::vector<std::string> QueryScopes; // Initialized once Sema runs. + std::vector<std::string> QueryScopes; // Initialized once Sema runs. std::vector<std::string> AccessibleScopes; // Initialized once Sema runs. // Initialized once QueryScopes is initialized, if there are scopes. std::optional<ScopeDistance> ScopeProximity; @@ -1599,7 +1600,9 @@ class CodeCompleteFlow { Inserter.emplace( SemaCCInput.FileName, SemaCCInput.ParseInput.Contents, Style, SemaCCInput.ParseInput.CompileCommand.Directory, - &Recorder->CCSema->getPreprocessor().getHeaderSearchInfo()); + &Recorder->CCSema->getPreprocessor().getHeaderSearchInfo(), + Config::current().Style.QuotedHeaders, + Config::current().Style.AngledHeaders); for (const auto &Inc : Includes.MainFileIncludes) Inserter->addExisting(Inc); @@ -1682,7 +1685,9 @@ class CodeCompleteFlow { auto Style = getFormatStyleForFile(FileName, Content, TFS); // This will only insert verbatim headers. Inserter.emplace(FileName, Content, Style, - /*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr); + /*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr, + Config::current().Style.QuotedHeaders, + Config::current().Style.AngledHeaders); auto Identifiers = collectIdentifiers(Content, Style); std::vector<RawIdentifier> IdentifierResults; diff --git a/clang-tools-extra/clangd/Config.h b/clang-tools-extra/clangd/Config.h index daae8d1c0c833eb..5d70ed3376715e5 100644 --- a/clang-tools-extra/clangd/Config.h +++ b/clang-tools-extra/clangd/Config.h @@ -121,6 +121,10 @@ struct Config { // declarations, always spell out the whole name (with or without leading // ::). All nested namespaces are affected as well. std::vector<std::string> FullyQualifiedNamespaces; + + // List of regexes for inserting certain headers with <> or "". + std::vector<std::function<bool(llvm::StringRef)>> QuotedHeaders; + std::vector<std::function<bool(llvm::StringRef)>> AngledHeaders; } Style; /// Configures code completion feature. diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp b/clang-tools-extra/clangd/ConfigCompile.cpp index d4ff7ae3181bc3d..b41c8cde15dbf9a 100644 --- a/clang-tools-extra/clangd/ConfigCompile.cpp +++ b/clang-tools-extra/clangd/ConfigCompile.cpp @@ -483,6 +483,72 @@ struct FragmentCompiler { FullyQualifiedNamespaces.begin(), FullyQualifiedNamespaces.end()); }); } + +// TODO: Share this code with Diagnostics.Includes.IgnoreHeader +#ifdef CLANGD_PATH_CASE_INSENSITIVE + static llvm::Regex::RegexFlags Flags = llvm::Regex::IgnoreCase; +#else + static llvm::Regex::RegexFlags Flags = llvm::Regex::NoFlags; +#endif + { + auto Filters = std::make_shared<std::vector<llvm::Regex>>(); + for (auto &HeaderPattern : F.AngledHeaders) { + // Anchor on the right. + std::string AnchoredPattern = "(" + *HeaderPattern + ")$"; + llvm::Regex CompiledRegex(AnchoredPattern, Flags); + std::string RegexError; + if (!CompiledRegex.isValid(RegexError)) { + diag(Warning, + llvm::formatv("Invalid regular expression '{0}': {1}", + *HeaderPattern, RegexError) + .str(), + HeaderPattern.Range); + continue; + } + Filters->push_back(std::move(CompiledRegex)); + } + if (Filters->empty()) + return; + auto Filter = [Filters](llvm::StringRef Path) { + for (auto &Regex : *Filters) + if (Regex.match(Path)) + return true; + return false; + }; + Out.Apply.push_back([Filter](const Params &, Config &C) { + C.Style.AngledHeaders.emplace_back(Filter); + }); + } + + { + auto Filters = std::make_shared<std::vector<llvm::Regex>>(); + for (auto &HeaderPattern : F.QuotedHeaders) { + // Anchor on the right. + std::string AnchoredPattern = "(" + *HeaderPattern + ")$"; + llvm::Regex CompiledRegex(AnchoredPattern, Flags); + std::string RegexError; + if (!CompiledRegex.isValid(RegexError)) { + diag(Warning, + llvm::formatv("Invalid regular expression '{0}': {1}", + *HeaderPattern, RegexError) + .str(), + HeaderPattern.Range); + continue; + } + Filters->push_back(std::move(CompiledRegex)); + } + if (Filters->empty()) + return; + auto Filter = [Filters](llvm::StringRef Path) { + for (auto &Regex : *Filters) + if (Regex.match(Path)) + return true; + return false; + }; + Out.Apply.push_back([Filter](const Params &, Config &C) { + C.Style.QuotedHeaders.emplace_back(Filter); + }); + } } void appendTidyCheckSpec(std::string &CurSpec, diff --git a/clang-tools-extra/clangd/ConfigFragment.h b/clang-tools-extra/clangd/ConfigFragment.h index a59d4124b0828ac..02ef30949629f7a 100644 --- a/clang-tools-extra/clangd/ConfigFragment.h +++ b/clang-tools-extra/clangd/ConfigFragment.h @@ -289,6 +289,19 @@ struct Fragment { // ::). All nested namespaces are affected as well. // Affects availability of the AddUsing tweak. std::vector<Located<std::string>> FullyQualifiedNamespaces; + + /// List of regexes for headers that should always be included with a + /// ""-style include. By default, and in case of a conflict with + /// AngledHeaders (i.e. a header matches a regex in both QuotedHeaders and + /// AngledHeaders), system headers use <> and non-system headers use "". + /// These can match any suffix of the header file in question. + std::vector<Located<std::string>> QuotedHeaders; + /// List of regexes for headers that should always be included with a + /// <>-style include. By default, and in case of a conflict with + /// AngledHeaders (i.e. a header matches a regex in both QuotedHeaders and + /// AngledHeaders), system headers use <> and non-system headers use "". + /// These can match any suffix of the header file in question. + std::vector<Located<std::string>> AngledHeaders; }; StyleBlock Style; diff --git a/clang-tools-extra/clangd/ConfigYAML.cpp b/clang-tools-extra/clangd/ConfigYAML.cpp index cf3cec472bf8a31..141a897b8ec82ee 100644 --- a/clang-tools-extra/clangd/ConfigYAML.cpp +++ b/clang-tools-extra/clangd/ConfigYAML.cpp @@ -117,6 +117,14 @@ class Parser { if (auto Values = scalarValues(N)) F.FullyQualifiedNamespaces = std::move(*Values); }); + Dict.handle("QuotedHeaders", [&](Node &N) { + if (auto Values = scalarValues(N)) + F.QuotedHeaders = std::move(*Values); + }); + Dict.handle("AngledHeaders", [&](Node &N) { + if (auto Values = scalarValues(N)) + F.AngledHeaders = std::move(*Values); + }); Dict.parse(N); } diff --git a/clang-tools-extra/clangd/Headers.cpp b/clang-tools-extra/clangd/Headers.cpp index 6005069be01160d..bec6aed5bfd6fd2 100644 --- a/clang-tools-extra/clangd/Headers.cpp +++ b/clang-tools-extra/clangd/Headers.cpp @@ -9,6 +9,7 @@ #include "Headers.h" #include "Preamble.h" #include "SourceCode.h" +#include "support/Logger.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/CompilerInstance.h" @@ -30,8 +31,7 @@ namespace clangd { class IncludeStructure::RecordHeaders : public PPCallbacks { public: RecordHeaders(const CompilerInstance &CI, IncludeStructure *Out) - : SM(CI.getSourceManager()), - Out(Out) {} + : SM(CI.getSourceManager()), Out(Out) {} // Record existing #includes - both written and resolved paths. Only #includes // in the main file are collected. @@ -286,11 +286,11 @@ IncludeInserter::calculateIncludePath(const HeaderFile &InsertedHeader, assert(InsertedHeader.valid()); if (InsertedHeader.Verbatim) return InsertedHeader.File; - bool IsAngled = false; + bool IsAngledByDefault = false; std::string Suggested; if (HeaderSearchInfo) { Suggested = HeaderSearchInfo->suggestPathToFileForDiagnostics( - InsertedHeader.File, BuildDir, IncludingFile, &IsAngled); + InsertedHeader.File, BuildDir, IncludingFile, &IsAngledByDefault); } else { // Calculate include relative to including file only. StringRef IncludingDir = llvm::sys::path::parent_path(IncludingFile); @@ -303,9 +303,33 @@ IncludeInserter::calculateIncludePath(const HeaderFile &InsertedHeader, // FIXME: should we allow (some limited number of) "../header.h"? if (llvm::sys::path::is_absolute(Suggested)) return std::nullopt; + bool IsAngled = false; + for (auto Filter : AngledHeaders) { + if (Filter(Suggested)) { + IsAngled = true; + break; + } + } + bool IsQuoted = false; + for (auto Filter : QuotedHeaders) { + if (Filter(Suggested)) { + IsQuoted = true; + break; + } + } + // No filters apply, or both filters apply (a bug), use system default. + if (IsAngled == IsQuoted) { + // Probably a bug in the config regex. + if (IsAngled && IsQuoted) { + elog("Header '{0}' matches both quoted and angled regexes, default will " + "be used.", + Suggested); + } + IsAngled = IsAngledByDefault; + } if (IsAngled) Suggested = "<" + Suggested + ">"; - else + else // if (IsQuoted) Suggested = "\"" + Suggested + "\""; return Suggested; } diff --git a/clang-tools-extra/clangd/Headers.h b/clang-tools-extra/clangd/Headers.h index 41cf3de6bba350b..f1ec44422775f9c 100644 --- a/clang-tools-extra/clangd/Headers.h +++ b/clang-tools-extra/clangd/Headers.h @@ -9,6 +9,7 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEADERS_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEADERS_H +#include "Config.h" #include "Protocol.h" #include "SourceCode.h" #include "index/Symbol.h" @@ -32,6 +33,8 @@ namespace clang { namespace clangd { + +using HeaderFilter = llvm::ArrayRef<std::function<bool(llvm::StringRef)>>; /// Returns true if \p Include is literal include like "path" or <path>. bool isLiteralInclude(llvm::StringRef Include); @@ -211,10 +214,12 @@ class IncludeInserter { // include path of non-verbatim header will not be shortened. IncludeInserter(StringRef FileName, StringRef Code, const format::FormatStyle &Style, StringRef BuildDir, - HeaderSearch *HeaderSearchInfo) + HeaderSearch *HeaderSearchInfo, HeaderFilter QuotedHeaders, + HeaderFilter AngledHeaders) : FileName(FileName), Code(Code), BuildDir(BuildDir), HeaderSearchInfo(HeaderSearchInfo), - Inserter(FileName, Code, Style.IncludeStyle) {} + Inserter(FileName, Code, Style.IncludeStyle), + QuotedHeaders(QuotedHeaders), AngledHeaders(AngledHeaders) {} void addExisting(const Inclusion &Inc); @@ -258,6 +263,8 @@ class IncludeInserter { HeaderSearch *HeaderSearchInfo = nullptr; llvm::StringSet<> IncludedHeaders; // Both written and resolved. tooling::HeaderIncludes Inserter; // Computers insertion replacement. + HeaderFilter QuotedHeaders; + HeaderFilter AngledHeaders; }; } // namespace clangd diff --git a/clang-tools-extra/clangd/IncludeCleaner.h b/clang-tools-extra/clangd/IncludeCleaner.h index b3ba3a716083e88..7e289ef4c13532e 100644 --- a/clang-tools-extra/clangd/IncludeCleaner.h +++ b/clang-tools-extra/clangd/IncludeCleaner.h @@ -55,7 +55,6 @@ struct IncludeCleanerFindings { IncludeCleanerFindings computeIncludeCleanerFindings(ParsedAST &AST); -using HeaderFilter = llvm::ArrayRef<std::function<bool(llvm::StringRef)>>; std::vector<Diag> issueIncludeCleanerDiagnostics(ParsedAST &AST, llvm::StringRef Code, const IncludeCleanerFindings &Findings, diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp index 3f6c0eaebac6c41..90684d36f152c7e 100644 --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -612,7 +612,8 @@ ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs, getFormatStyleForFile(Filename, Inputs.Contents, *Inputs.TFS); auto Inserter = std::make_shared<IncludeInserter>( Filename, Inputs.Contents, Style, BuildDir.get(), - &Clang->getPreprocessor().getHeaderSearchInfo()); + &Clang->getPreprocessor().getHeaderSearchInfo(), + Cfg.Style.QuotedHeaders, Cfg.Style.AngledHeaders); ArrayRef<Inclusion> MainFileIncludes; if (Preamble) { MainFileIncludes = Preamble->Includes.MainFileIncludes; diff --git a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp index f0ffc429c0ca909..780a23fc1348841 100644 --- a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp +++ b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp @@ -539,6 +539,40 @@ TEST_F(ConfigCompileTests, Style) { Frag.Style.FullyQualifiedNamespaces.push_back(std::string("bar")); EXPECT_TRUE(compileAndApply()); EXPECT_THAT(Conf.Style.FullyQualifiedNamespaces, ElementsAre("foo", "bar")); + + { + EXPECT_TRUE(Conf.Style.QuotedHeaders.empty()) + << Conf.Style.QuotedHeaders.size(); + Frag.Style.QuotedHeaders.push_back(Located<std::string>("foo.h")); + Frag.Style.QuotedHeaders.push_back(Located<std::string>(".*inc")); + EXPECT_TRUE(compileAndApply()); + auto HeaderFilter = [this](llvm::StringRef Path) { + for (auto &Filter : Conf.Style.QuotedHeaders) { + if (Filter(Path)) + return true; + } + return false; + }; + EXPECT_TRUE(HeaderFilter("foo.h")); + EXPECT_FALSE(HeaderFilter("bar.h")); + } + + { + EXPECT_TRUE(Conf.Style.AngledHeaders.empty()) + << Conf.Style.AngledHeaders.size(); + Frag.Style.AngledHeaders.push_back(Located<std::string>("foo.h")); + Frag.Style.AngledHeaders.push_back(Located<std::string>(".*inc")); + EXPECT_TRUE(compileAndApply()); + auto HeaderFilter = [this](llvm::StringRef Path) { + for (auto &Filter : Conf.Style.AngledHeaders) { + if (Filter(Path)) + return true; + } + return false; + }; + EXPECT_TRUE(HeaderFilter("foo.h")); + EXPECT_FALSE(HeaderFilter("bar.h")); + } } } // namespace } // namespace config diff --git a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp index 44a6647d4c0a818..8f8ecc52b4034a8 100644 --- a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp +++ b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp @@ -282,13 +282,19 @@ TEST(ParseYAML, Style) { CapturedDiags Diags; Annotations YAML(R"yaml( Style: - FullyQualifiedNamespaces: [foo, bar])yaml"); + FullyQualifiedNamespaces: [foo, bar] + AngledHeaders: ["foo", "bar"] + QuotedHeaders: ["baz", "baar"])yaml"); auto Results = Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback()); ASSERT_THAT(Diags.Diagnostics, IsEmpty()); ASSERT_EQ(Results.size(), 1u); EXPECT_THAT(Results[0].Style.FullyQualifiedNamespaces, ElementsAre(val("foo"), val("bar"))); + EXPECT_THAT(Results[0].Style.AngledHeaders, + ElementsAre(val("foo"), val("bar"))); + EXPECT_THAT(Results[0].Style.QuotedHeaders, + ElementsAre(val("baz"), val("baar"))); } } // namespace } // namespace config diff --git a/clang-tools-extra/clangd/unittests/HeadersTests.cpp b/clang-tools-extra/clangd/unittests/HeadersTests.cpp index dc6adaee1125718..751383e3b4650a4 100644 --- a/clang-tools-extra/clangd/unittests/HeadersTests.cpp +++ b/clang-tools-extra/clangd/unittests/HeadersTests.cpp @@ -107,7 +107,8 @@ class HeadersTest : public ::testing::Test { IncludeInserter Inserter(MainFile, /*Code=*/"", format::getLLVMStyle(), CDB.getCompileCommand(MainFile)->Directory, - &Clang->getPreprocessor().getHeaderSearchInfo()); + &Clang->getPreprocessor().getHeaderSearchInfo(), + QuotedHeaders, AngledHeaders); for (const auto &Inc : Inclusions) Inserter.addExisting(Inc); auto Inserted = ToHeaderFile(Preferred); @@ -127,7 +128,8 @@ class HeadersTest : public ::testing::Test { IncludeInserter Inserter(MainFile, /*Code=*/"", format::getLLVMStyle(), CDB.getCompileCommand(MainFile)->Directory, - &Clang->getPreprocessor().getHeaderSearchInfo()); + &Clang->getPreprocessor().getHeaderSearchInfo(), + QuotedHeaders, AngledHeaders); auto Edit = Inserter.insert(VerbatimHeader, Directive); Action.EndSourceFile(); return Edit; @@ -139,6 +141,8 @@ class HeadersTest : public ::testing::Test { std::string Subdir = testPath("sub"); std::string SearchDirArg = (llvm::Twine("-I") + Subdir).str(); IgnoringDiagConsumer IgnoreDiags; + std::vector<std::function<bool(llvm::StringRef)>> QuotedHeaders; + std::vector<std::function<bool(llvm::StringRef)>> AngledHeaders; std::unique_ptr<CompilerInstance> Clang; }; @@ -304,6 +308,9 @@ TEST_F(HeadersTest, InsertInclude) { std::string Path = testPath("sub/bar.h"); FS.Files[Path] = ""; EXPECT_EQ(calculate(Path), "\"bar.h\""); + + AngledHeaders.push_back([](auto Path) { return true; }); + EXPECT_EQ(calculate(Path), "<bar.h>"); } TEST_F(HeadersTest, DoNotInsertIfInSameFile) { @@ -326,6 +333,17 @@ TEST_F(HeadersTest, ShortenIncludesInSearchPath) { EXPECT_EQ(calculate(BarHeader), "\"sub/bar.h\""); } +TEST_F(HeadersTest, ShortenIncludesInSearchPathBracketed) { + AngledHeaders.push_back([](auto Path) { return true; }); + std::string BarHeader = testPath("sub/bar.h"); + EXPECT_EQ(calculate(BarHeader), "<bar.h>"); + + SearchDirArg = (llvm::Twine("-I") + Subdir + "/..").str(); + CDB.ExtraClangFlags = {SearchDirArg.c_str()}; + BarHeader = testPath("sub/bar.h"); + EXPECT_EQ(calculate(BarHeader), "<sub/bar.h>"); +} + TEST_F(HeadersTest, ShortenedIncludeNotInSearchPath) { std::string BarHeader = llvm::sys::path::convert_to_slash(testPath("sub-2/bar.h")); @@ -338,6 +356,10 @@ TEST_F(HeadersTest, PreferredHeader) { std::string BazHeader = testPath("sub/baz.h"); EXPECT_EQ(calculate(BarHeader, BazHeader), "\"baz.h\""); + + AngledHeaders.push_back([](auto Path) { return true; }); + std::string BiffHeader = testPath("sub/biff.h"); + EXPECT_EQ(calculate(BarHeader, BiffHeader), "<biff.h>"); } TEST_F(HeadersTest, DontInsertDuplicatePreferred) { @@ -370,7 +392,8 @@ TEST_F(HeadersTest, PreferInserted) { TEST(Headers, NoHeaderSearchInfo) { std::string MainFile = testPath("main.cpp"); IncludeInserter Inserter(MainFile, /*Code=*/"", format::getLLVMStyle(), - /*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr); + /*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr, + /*QuotedHeaders=*/{}, /*AngledHeaders=*/{}); auto HeaderPath = testPath("sub/bar.h"); auto Inserting = HeaderFile{HeaderPath, /*Verbatim=*/false}; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits