Skip to content

Commit ec6c344

Browse files
authored
[include-cleaner] Respect langopts when analyzing macro names (#123634)
Fixes #113926. Fixes #63976.
1 parent 67a412f commit ec6c344

File tree

11 files changed

+77
-40
lines changed

11 files changed

+77
-40
lines changed

clang-tools-extra/clangd/Hover.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,12 +1193,13 @@ void maybeAddSymbolProviders(ParsedAST &AST, HoverInfo &HI,
11931193
include_cleaner::Symbol Sym) {
11941194
trace::Span Tracer("Hover::maybeAddSymbolProviders");
11951195

1196-
const SourceManager &SM = AST.getSourceManager();
11971196
llvm::SmallVector<include_cleaner::Header> RankedProviders =
1198-
include_cleaner::headersForSymbol(Sym, SM, &AST.getPragmaIncludes());
1197+
include_cleaner::headersForSymbol(Sym, AST.getPreprocessor(),
1198+
&AST.getPragmaIncludes());
11991199
if (RankedProviders.empty())
12001200
return;
12011201

1202+
const SourceManager &SM = AST.getSourceManager();
12021203
std::string Result;
12031204
include_cleaner::Includes ConvertedIncludes = convertIncludes(AST);
12041205
for (const auto &P : RankedProviders) {

clang-tools-extra/clangd/index/SymbolCollector.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,7 @@ void SymbolCollector::setIncludeLocation(const Symbol &S, SourceLocation DefLoc,
888888
// might run while parsing, rather than at the end of a translation unit.
889889
// Hence we see more and more redecls over time.
890890
SymbolProviders[S.ID] =
891-
include_cleaner::headersForSymbol(Sym, SM, Opts.PragmaIncludes);
891+
include_cleaner::headersForSymbol(Sym, *PP, Opts.PragmaIncludes);
892892
}
893893

894894
llvm::StringRef getStdHeader(const Symbol *S, const LangOptions &LangOpts) {

clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ std::string fixIncludes(const AnalysisResults &Results,
9090
/// Returned headers are sorted by relevance, first element is the most
9191
/// likely provider for the symbol.
9292
llvm::SmallVector<Header> headersForSymbol(const Symbol &S,
93-
const SourceManager &SM,
93+
const Preprocessor &PP,
9494
const PragmaIncludes *PI);
9595
} // namespace include_cleaner
9696
} // namespace clang

clang-tools-extra/include-cleaner/lib/Analysis.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,15 @@ void walkUsed(llvm::ArrayRef<Decl *> ASTRoots,
6464
// FIXME: Most of the work done here is repetitive. It might be useful to
6565
// have a cache/batching.
6666
SymbolReference SymRef{ND, Loc, RT};
67-
return CB(SymRef, headersForSymbol(ND, SM, PI));
67+
return CB(SymRef, headersForSymbol(ND, PP, PI));
6868
});
6969
}
7070
for (const SymbolReference &MacroRef : MacroRefs) {
7171
assert(MacroRef.Target.kind() == Symbol::Macro);
7272
if (!SM.isWrittenInMainFile(SM.getSpellingLoc(MacroRef.RefLocation)) ||
7373
shouldIgnoreMacroReference(PP, MacroRef.Target.macro()))
7474
continue;
75-
CB(MacroRef, headersForSymbol(MacroRef.Target, SM, PI));
75+
CB(MacroRef, headersForSymbol(MacroRef.Target, PP, PI));
7676
}
7777
}
7878

clang-tools-extra/include-cleaner/lib/AnalysisInternal.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "clang-include-cleaner/Analysis.h"
2626
#include "clang-include-cleaner/Record.h"
2727
#include "clang-include-cleaner/Types.h"
28+
#include "clang/Basic/LangOptions.h"
29+
#include "clang/Lex/Preprocessor.h"
2830
#include "llvm/ADT/STLFunctionalExtras.h"
2931
#include <vector>
3032

@@ -57,13 +59,14 @@ llvm::SmallVector<Hinted<Header>> findHeaders(const SymbolLocation &Loc,
5759
const PragmaIncludes *PI);
5860

5961
/// A set of locations that provides the declaration.
60-
std::vector<Hinted<SymbolLocation>> locateSymbol(const Symbol &S);
62+
std::vector<Hinted<SymbolLocation>> locateSymbol(const Symbol &S,
63+
const LangOptions &LO);
6164

6265
/// Write an HTML summary of the analysis to the given stream.
6366
void writeHTMLReport(FileID File, const Includes &,
6467
llvm::ArrayRef<Decl *> Roots,
6568
llvm::ArrayRef<SymbolReference> MacroRefs, ASTContext &Ctx,
66-
const HeaderSearch &HS, PragmaIncludes *PI,
69+
const Preprocessor &PP, PragmaIncludes *PI,
6770
llvm::raw_ostream &OS);
6871

6972
} // namespace include_cleaner

clang-tools-extra/include-cleaner/lib/FindHeaders.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "clang/Basic/FileEntry.h"
1919
#include "clang/Basic/SourceLocation.h"
2020
#include "clang/Basic/SourceManager.h"
21+
#include "clang/Lex/Preprocessor.h"
2122
#include "clang/Tooling/Inclusions/StandardLibrary.h"
2223
#include "llvm/ADT/ArrayRef.h"
2324
#include "llvm/ADT/STLExtras.h"
@@ -239,16 +240,17 @@ llvm::SmallVector<Hinted<Header>> findHeaders(const SymbolLocation &Loc,
239240
}
240241

241242
llvm::SmallVector<Header> headersForSymbol(const Symbol &S,
242-
const SourceManager &SM,
243+
const Preprocessor &PP,
243244
const PragmaIncludes *PI) {
245+
const auto &SM = PP.getSourceManager();
244246
// Get headers for all the locations providing Symbol. Same header can be
245247
// reached through different traversals, deduplicate those into a single
246248
// Header by merging their hints.
247249
llvm::SmallVector<Hinted<Header>> Headers;
248250
if (auto SpecialHeaders = headersForSpecialSymbol(S, SM, PI)) {
249251
Headers = std::move(*SpecialHeaders);
250252
} else {
251-
for (auto &Loc : locateSymbol(S))
253+
for (auto &Loc : locateSymbol(S, PP.getLangOpts()))
252254
Headers.append(applyHints(findHeaders(Loc, SM, PI), Loc.Hint));
253255
}
254256
// If two Headers probably refer to the same file (e.g. Verbatim(foo.h) and

clang-tools-extra/include-cleaner/lib/HTMLReport.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "clang/Basic/SourceManager.h"
2222
#include "clang/Lex/HeaderSearch.h"
2323
#include "clang/Lex/Lexer.h"
24+
#include "clang/Lex/Preprocessor.h"
2425
#include "clang/Tooling/Inclusions/StandardLibrary.h"
2526
#include "llvm/Support/ScopedPrinter.h"
2627
#include "llvm/Support/raw_ostream.h"
@@ -135,7 +136,7 @@ class Reporter {
135136
llvm::raw_ostream &OS;
136137
const ASTContext &Ctx;
137138
const SourceManager &SM;
138-
const HeaderSearch &HS;
139+
const Preprocessor &PP;
139140
const include_cleaner::Includes &Includes;
140141
const PragmaIncludes *PI;
141142
FileID MainFile;
@@ -170,9 +171,9 @@ class Reporter {
170171

171172
void fillTarget(Ref &R) {
172173
// Duplicates logic from walkUsed(), which doesn't expose SymbolLocations.
173-
for (auto &Loc : locateSymbol(R.Sym))
174+
for (auto &Loc : locateSymbol(R.Sym, Ctx.getLangOpts()))
174175
R.Locations.push_back(Loc);
175-
R.Headers = headersForSymbol(R.Sym, SM, PI);
176+
R.Headers = headersForSymbol(R.Sym, PP, PI);
176177

177178
for (const auto &H : R.Headers) {
178179
R.Includes.append(Includes.match(H));
@@ -189,14 +190,15 @@ class Reporter {
189190
R.Includes.end());
190191

191192
if (!R.Headers.empty())
192-
R.Insert = spellHeader({R.Headers.front(), HS, MainFE});
193+
R.Insert =
194+
spellHeader({R.Headers.front(), PP.getHeaderSearchInfo(), MainFE});
193195
}
194196

195197
public:
196-
Reporter(llvm::raw_ostream &OS, ASTContext &Ctx, const HeaderSearch &HS,
198+
Reporter(llvm::raw_ostream &OS, ASTContext &Ctx, const Preprocessor &PP,
197199
const include_cleaner::Includes &Includes, const PragmaIncludes *PI,
198200
FileID MainFile)
199-
: OS(OS), Ctx(Ctx), SM(Ctx.getSourceManager()), HS(HS),
201+
: OS(OS), Ctx(Ctx), SM(Ctx.getSourceManager()), PP(PP),
200202
Includes(Includes), PI(PI), MainFile(MainFile),
201203
MainFE(SM.getFileEntryForID(MainFile)) {}
202204

@@ -498,9 +500,9 @@ class Reporter {
498500
void writeHTMLReport(FileID File, const include_cleaner::Includes &Includes,
499501
llvm::ArrayRef<Decl *> Roots,
500502
llvm::ArrayRef<SymbolReference> MacroRefs, ASTContext &Ctx,
501-
const HeaderSearch &HS, PragmaIncludes *PI,
503+
const Preprocessor &PP, PragmaIncludes *PI,
502504
llvm::raw_ostream &OS) {
503-
Reporter R(OS, Ctx, HS, Includes, PI, File);
505+
Reporter R(OS, Ctx, PP, Includes, PI, File);
504506
const auto& SM = Ctx.getSourceManager();
505507
for (Decl *Root : Roots)
506508
walkAST(*Root, [&](SourceLocation Loc, const NamedDecl &D, RefType T) {

clang-tools-extra/include-cleaner/lib/LocateSymbol.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,24 @@ std::vector<Hinted<SymbolLocation>> locateDecl(const Decl &D) {
5454
return Result;
5555
}
5656

57-
std::vector<Hinted<SymbolLocation>> locateMacro(const Macro &M) {
57+
std::vector<Hinted<SymbolLocation>> locateMacro(const Macro &M,
58+
const tooling::stdlib::Lang L) {
5859
// FIXME: Should we also provide physical locations?
59-
if (auto SS = tooling::stdlib::Symbol::named("", M.Name->getName()))
60+
if (auto SS = tooling::stdlib::Symbol::named("", M.Name->getName(), L))
6061
return {{*SS, Hints::CompleteSymbol}};
6162
return {{M.Definition, Hints::CompleteSymbol}};
6263
}
6364
} // namespace
6465

65-
std::vector<Hinted<SymbolLocation>> locateSymbol(const Symbol &S) {
66+
std::vector<Hinted<SymbolLocation>> locateSymbol(const Symbol &S,
67+
const LangOptions &LO) {
68+
const auto L = !LO.CPlusPlus && LO.C99 ? tooling::stdlib::Lang::C
69+
: tooling::stdlib::Lang::CXX;
6670
switch (S.kind()) {
6771
case Symbol::Declaration:
6872
return locateDecl(S.declaration());
6973
case Symbol::Macro:
70-
return locateMacro(S.macro());
74+
return locateMacro(S.macro(), L);
7175
}
7276
llvm_unreachable("Unknown Symbol::Kind enum");
7377
}

clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,9 @@ class Action : public clang::ASTFrontendAction {
216216
++Errors;
217217
return;
218218
}
219-
writeHTMLReport(
220-
AST.Ctx->getSourceManager().getMainFileID(), PP.Includes, AST.Roots,
221-
PP.MacroReferences, *AST.Ctx,
222-
getCompilerInstance().getPreprocessor().getHeaderSearchInfo(), &PI, OS);
219+
writeHTMLReport(AST.Ctx->getSourceManager().getMainFileID(), PP.Includes,
220+
AST.Roots, PP.MacroReferences, *AST.Ctx,
221+
getCompilerInstance().getPreprocessor(), &PI, OS);
223222
}
224223
};
225224
class ActionFactory : public tooling::FrontendActionFactory {

clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ class HeadersForSymbolTest : public FindHeadersTest {
306306
if (!V.Out)
307307
ADD_FAILURE() << "Couldn't find any decls named " << Name << ".";
308308
assert(V.Out);
309-
return headersForSymbol(*V.Out, AST->sourceManager(), &PI);
309+
return headersForSymbol(*V.Out, AST->preprocessor(), &PI);
310310
}
311311
llvm::SmallVector<Header> headersForFoo() { return headersFor("foo"); }
312312
};
@@ -611,13 +611,12 @@ TEST_F(HeadersForSymbolTest, AmbiguousStdSymbolsUsingShadow) {
611611
Visitor V;
612612
V.TraverseDecl(AST->context().getTranslationUnitDecl());
613613
ASSERT_TRUE(V.Out) << "Couldn't find a DeclRefExpr!";
614-
EXPECT_THAT(headersForSymbol(*(V.Out->getFoundDecl()),
615-
AST->sourceManager(), &PI),
616-
UnorderedElementsAre(
617-
Header(*tooling::stdlib::Header::named("<cstdio>"))));
614+
EXPECT_THAT(
615+
headersForSymbol(*(V.Out->getFoundDecl()), AST->preprocessor(), &PI),
616+
UnorderedElementsAre(
617+
Header(*tooling::stdlib::Header::named("<cstdio>"))));
618618
}
619619

620-
621620
TEST_F(HeadersForSymbolTest, StandardHeaders) {
622621
Inputs.Code = R"cpp(
623622
#include "stdlib_internal.h"
@@ -636,6 +635,30 @@ TEST_F(HeadersForSymbolTest, StandardHeaders) {
636635
tooling::stdlib::Header::named("<assert.h>")));
637636
}
638637

638+
TEST_F(HeadersForSymbolTest, StdlibLangForMacros) {
639+
Inputs.Code = R"cpp(
640+
#define EOF 0
641+
void foo() { EOF; }
642+
)cpp";
643+
{
644+
buildAST();
645+
const Macro Eof{AST->preprocessor().getIdentifierInfo("EOF"), {}};
646+
EXPECT_THAT(
647+
headersForSymbol(Eof, AST->preprocessor(), nullptr),
648+
UnorderedElementsAre(tooling::stdlib::Header::named("<cstdio>"),
649+
tooling::stdlib::Header::named("<stdio.h>")));
650+
}
651+
652+
{
653+
Inputs.ExtraArgs.push_back("-xc");
654+
buildAST();
655+
const Macro Eof{AST->preprocessor().getIdentifierInfo("EOF"), {}};
656+
EXPECT_THAT(headersForSymbol(Eof, AST->preprocessor(), nullptr),
657+
UnorderedElementsAre(tooling::stdlib::Header::named(
658+
"<stdio.h>", tooling::stdlib::Lang::C)));
659+
}
660+
}
661+
639662
TEST_F(HeadersForSymbolTest, ExporterNoNameMatch) {
640663
Inputs.Code = R"cpp(
641664
#include "exporter/foo.h"

clang-tools-extra/include-cleaner/unittests/LocateSymbolTest.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "clang/AST/Decl.h"
1212
#include "clang/AST/DeclBase.h"
1313
#include "clang/AST/RecursiveASTVisitor.h"
14+
#include "clang/Basic/LangOptions.h"
1415
#include "clang/Basic/SourceLocation.h"
1516
#include "clang/Lex/Preprocessor.h"
1617
#include "clang/Testing/TestAST.h"
@@ -96,6 +97,8 @@ struct LocateExample {
9697
Results.emplace_back(SM.getComposedLoc(FID, Offset));
9798
return Results;
9899
}
100+
101+
const LangOptions &langOpts() { return AST.preprocessor().getLangOpts(); }
99102
};
100103

101104
TEST(LocateSymbol, Decl) {
@@ -110,7 +113,7 @@ TEST(LocateSymbol, Decl) {
110113
for (auto &Case : Cases) {
111114
SCOPED_TRACE(Case);
112115
LocateExample Test(Case);
113-
EXPECT_THAT(locateSymbol(Test.findDecl("foo")),
116+
EXPECT_THAT(locateSymbol(Test.findDecl("foo"), Test.langOpts()),
114117
ElementsAreArray(Test.points()));
115118
}
116119
}
@@ -119,20 +122,20 @@ TEST(LocateSymbol, Stdlib) {
119122
{
120123
LocateExample Test("namespace std { struct vector; }");
121124
EXPECT_THAT(
122-
locateSymbol(Test.findDecl("vector")),
125+
locateSymbol(Test.findDecl("vector"), Test.langOpts()),
123126
ElementsAre(*tooling::stdlib::Symbol::named("std::", "vector")));
124127
}
125128
{
126129
LocateExample Test("#define assert(x)\nvoid foo() { assert(true); }");
127-
EXPECT_THAT(locateSymbol(Test.findMacro("assert")),
130+
EXPECT_THAT(locateSymbol(Test.findMacro("assert"), Test.langOpts()),
128131
ElementsAre(*tooling::stdlib::Symbol::named("", "assert")));
129132
}
130133
}
131134

132135
TEST(LocateSymbol, Macros) {
133136
// Make sure we preserve the last one.
134137
LocateExample Test("#define FOO\n#undef FOO\n#define ^FOO");
135-
EXPECT_THAT(locateSymbol(Test.findMacro("FOO")),
138+
EXPECT_THAT(locateSymbol(Test.findMacro("FOO"), Test.langOpts()),
136139
ElementsAreArray(Test.points()));
137140
}
138141

@@ -143,15 +146,15 @@ TEST(LocateSymbol, CompleteSymbolHint) {
143146
{
144147
// stdlib symbols are always complete.
145148
LocateExample Test("namespace std { struct vector; }");
146-
EXPECT_THAT(locateSymbol(Test.findDecl("vector")),
149+
EXPECT_THAT(locateSymbol(Test.findDecl("vector"), Test.langOpts()),
147150
ElementsAre(HintedSymbol(
148151
*tooling::stdlib::Symbol::named("std::", "vector"),
149152
Hints::CompleteSymbol)));
150153
}
151154
{
152155
// macros are always complete.
153156
LocateExample Test("#define ^FOO");
154-
EXPECT_THAT(locateSymbol(Test.findMacro("FOO")),
157+
EXPECT_THAT(locateSymbol(Test.findMacro("FOO"), Test.langOpts()),
155158
ElementsAre(HintedSymbol(Test.points().front(),
156159
Hints::CompleteSymbol)));
157160
}
@@ -165,7 +168,7 @@ TEST(LocateSymbol, CompleteSymbolHint) {
165168
for (auto &Case : Cases) {
166169
SCOPED_TRACE(Case);
167170
LocateExample Test(Case);
168-
EXPECT_THAT(locateSymbol(Test.findDecl("foo")),
171+
EXPECT_THAT(locateSymbol(Test.findDecl("foo"), Test.langOpts()),
169172
ElementsAre(HintedSymbol(Test.points().front(), Hints::None),
170173
HintedSymbol(Test.points().back(),
171174
Hints::CompleteSymbol)));
@@ -181,7 +184,7 @@ TEST(LocateSymbol, CompleteSymbolHint) {
181184
for (auto &Case : Cases) {
182185
SCOPED_TRACE(Case);
183186
LocateExample Test(Case);
184-
EXPECT_THAT(locateSymbol(Test.findDecl("foo")),
187+
EXPECT_THAT(locateSymbol(Test.findDecl("foo"), Test.langOpts()),
185188
Each(Field(&Hinted<SymbolLocation>::Hint,
186189
Eq(Hints::CompleteSymbol))));
187190
}

0 commit comments

Comments
 (0)