Skip to content

Commit

Permalink
[clangd] Fix locateMacroAt() for macro definition outside preamble
Browse files Browse the repository at this point in the history
  • Loading branch information
HighCommander4 committed Dec 13, 2020
1 parent 5ad202c commit fef242c
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 11 deletions.
35 changes: 24 additions & 11 deletions clang-tools-extra/clangd/SourceCode.cpp
Expand Up @@ -975,17 +975,30 @@ llvm::Optional<DefinedMacro> locateMacroAt(const syntax::Token &SpelledTok,
if (!IdentifierInfo || !IdentifierInfo->hadMacroDefinition())
return None;

// Get the definition just before the searched location so that a macro
// referenced in a '#undef MACRO' can still be found. Note that we only do
// that if Loc is not pointing at start of file.
if (SM.getLocForStartOfFile(SM.getFileID(Loc)) != Loc)
Loc = Loc.getLocWithOffset(-1);
MacroDefinition MacroDef = PP.getMacroDefinitionAtLoc(IdentifierInfo, Loc);
if (auto *MI = MacroDef.getMacroInfo())
return DefinedMacro{
IdentifierInfo->getName(), MI,
translatePreamblePatchLocation(MI->getDefinitionLoc(), SM)};
return None;
// We need to take special case to handle #define and #undef.
// Preprocessor::getMacroDefinitionAtLoc() only considers a macro
// definition to be in scope *after* the location of the macro name in a
// #define that introduces it, and *before* the location of the macro name
// in an #undef that undefines it. To handle these cases, we check for
// the macro being in scope either just after or just before the location
// of the token. In getting the location before, we also take care to check
// for start-of-file.
FileID FID = SM.getFileID(Loc);
assert(Loc != SM.getLocForEndOfFile(FID));
SourceLocation JustAfterToken = Loc.getLocWithOffset(1);
auto *MacroInfo =
PP.getMacroDefinitionAtLoc(IdentifierInfo, JustAfterToken).getMacroInfo();
if (!MacroInfo && SM.getLocForStartOfFile(FID) != Loc) {
SourceLocation JustBeforeToken = Loc.getLocWithOffset(-1);
MacroInfo = PP.getMacroDefinitionAtLoc(IdentifierInfo, JustBeforeToken)
.getMacroInfo();
}
if (!MacroInfo) {
return None;
}
return DefinedMacro{
IdentifierInfo->getName(), MacroInfo,
translatePreamblePatchLocation(MacroInfo->getDefinitionLoc(), SM)};
}

llvm::Expected<std::string> Edit::apply() const {
Expand Down
8 changes: 8 additions & 0 deletions clang-tools-extra/clangd/unittests/XRefsTests.cpp
Expand Up @@ -1624,6 +1624,14 @@ TEST(FindReferences, WithinAST) {
}
)cpp",

R"cpp(// Macro outside preamble
int breakPreamble;
#define [[MA^CRO]](X) (X+1)
void test() {
int x = [[MACRO]]([[MACRO]](1));
}
)cpp",

R"cpp(
int [[v^ar]] = 0;
void foo(int s = [[var]]);
Expand Down

0 comments on commit fef242c

Please sign in to comment.