[include-cleaner] Report refs from macro-concat'd tokens as ambigious (#175532)
Previously we completely ignored these references as we couldn't detect whether some pieces of concat'd token originated from main file and we wanted to prevent false positives. Unfortunately these are resulting in false negatives in certain cases and are breaking builds. After this change, include-cleaner will treat such references as ambigious to prevent deletion of likely-used headers (if they're already directly included), while still giving user the opportunity to explicitly delete them.
This commit is contained in:
parent
8380b57b7e
commit
51ee583b1a
@ -58,7 +58,19 @@ void walkUsed(llvm::ArrayRef<Decl *> ASTRoots,
|
||||
tooling::stdlib::Recognizer Recognizer;
|
||||
for (auto *Root : ASTRoots) {
|
||||
walkAST(*Root, [&](SourceLocation Loc, NamedDecl &ND, RefType RT) {
|
||||
auto FID = SM.getFileID(SM.getSpellingLoc(Loc));
|
||||
auto SpellLoc = SM.getSpellingLoc(Loc);
|
||||
// Tokens resulting from macro concatenation ends up in scratch space and
|
||||
// clang currently doesn't have a good/simple APIs for tracking where
|
||||
// pieces of a concataned token originated from.
|
||||
// So we use the macro expansion location instead, and downgrade reference
|
||||
// type to ambigious to prevent false negatives.
|
||||
if (SM.isWrittenInScratchSpace(SpellLoc)) {
|
||||
Loc = SM.getExpansionLoc(Loc);
|
||||
if (RT == RefType::Explicit)
|
||||
RT = RefType::Ambiguous;
|
||||
SpellLoc = SM.getSpellingLoc(Loc);
|
||||
}
|
||||
auto FID = SM.getFileID(SpellLoc);
|
||||
if (FID != SM.getMainFileID() && FID != SM.getPreambleFileID())
|
||||
return;
|
||||
// FIXME: Most of the work done here is repetitive. It might be useful to
|
||||
|
||||
@ -680,5 +680,31 @@ TEST_F(WalkUsedTest, IgnoresIdentityMacros) {
|
||||
// FIXME: we should have a reference from stdin to header.h
|
||||
Pair(Code.point("bar"), UnorderedElementsAre(MainFile))));
|
||||
}
|
||||
|
||||
TEST_F(WalkUsedTest, MacroConcat) {
|
||||
llvm::Annotations Code(R"cpp(
|
||||
#include "header.h"
|
||||
void f() {
|
||||
$xyz^FOO(xyz) = 1;
|
||||
$bar^BAR = 2;
|
||||
}
|
||||
)cpp");
|
||||
Inputs.Code = Code.code();
|
||||
Inputs.ExtraFiles["header.h"] = guard(R"cpp(
|
||||
#define FOO(x) FLAGS_##x
|
||||
#define BAR FOO(bb)
|
||||
|
||||
int FLAGS_xyz;
|
||||
int FLAGS_bb;
|
||||
)cpp");
|
||||
|
||||
TestAST AST(Inputs);
|
||||
auto &SM = AST.sourceManager();
|
||||
auto Header = *SM.getFileManager().getOptionalFileRef("header.h");
|
||||
EXPECT_THAT(
|
||||
offsetToProviders(AST),
|
||||
AllOf(Contains(Pair(Code.point("bar"), UnorderedElementsAre(Header))),
|
||||
Contains(Pair(Code.point("xyz"), UnorderedElementsAre(Header)))));
|
||||
}
|
||||
} // namespace
|
||||
} // namespace clang::include_cleaner
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user