1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
//===--- CollectMacros.cpp ---------------------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "CollectMacros.h"
#include "AST.h"
#include "Protocol.h"
#include "SourceCode.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Tooling/Syntax/Tokens.h"
#include "llvm/ADT/STLExtras.h"
#include <cstddef>
namespace clang {
namespace clangd {
Range MacroOccurrence::toRange(const SourceManager &SM) const {
auto MainFile = SM.getMainFileID();
return halfOpenToRange(
SM, syntax::FileRange(MainFile, StartOffset, EndOffset).toCharRange(SM));
}
void CollectMainFileMacros::add(const Token &MacroNameTok, const MacroInfo *MI,
bool IsDefinition, bool InIfCondition) {
if (!InMainFile)
return;
auto Loc = MacroNameTok.getLocation();
if (Loc.isInvalid() || Loc.isMacroID())
return;
auto Name = MacroNameTok.getIdentifierInfo()->getName();
Out.Names.insert(Name);
size_t Start = SM.getFileOffset(Loc);
size_t End = SM.getFileOffset(MacroNameTok.getEndLoc());
if (auto SID = getSymbolID(Name, MI, SM))
Out.MacroRefs[SID].push_back({Start, End, IsDefinition, InIfCondition});
else
Out.UnknownMacros.push_back({Start, End, IsDefinition, InIfCondition});
}
void CollectMainFileMacros::FileChanged(SourceLocation Loc, FileChangeReason,
SrcMgr::CharacteristicKind, FileID) {
InMainFile = isInsideMainFile(Loc, SM);
}
void CollectMainFileMacros::MacroExpands(const Token &MacroName,
const MacroDefinition &MD,
SourceRange Range,
const MacroArgs *Args) {
add(MacroName, MD.getMacroInfo());
}
void CollectMainFileMacros::MacroUndefined(const clang::Token &MacroName,
const clang::MacroDefinition &MD,
const clang::MacroDirective *Undef) {
add(MacroName, MD.getMacroInfo());
}
void CollectMainFileMacros::Ifdef(SourceLocation Loc, const Token &MacroName,
const MacroDefinition &MD) {
add(MacroName, MD.getMacroInfo(), /*IsDefinition=*/false,
/*InConditionalDirective=*/true);
}
void CollectMainFileMacros::Ifndef(SourceLocation Loc, const Token &MacroName,
const MacroDefinition &MD) {
add(MacroName, MD.getMacroInfo(), /*IsDefinition=*/false,
/*InConditionalDirective=*/true);
}
void CollectMainFileMacros::Elifdef(SourceLocation Loc, const Token &MacroName,
const MacroDefinition &MD) {
add(MacroName, MD.getMacroInfo(), /*IsDefinition=*/false,
/*InConditionalDirective=*/true);
}
void CollectMainFileMacros::Elifndef(SourceLocation Loc, const Token &MacroName,
const MacroDefinition &MD) {
add(MacroName, MD.getMacroInfo(), /*IsDefinition=*/false,
/*InConditionalDirective=*/true);
}
void CollectMainFileMacros::Defined(const Token &MacroName,
const MacroDefinition &MD,
SourceRange Range) {
add(MacroName, MD.getMacroInfo(), /*IsDefinition=*/false,
/*InConditionalDirective=*/true);
}
void CollectMainFileMacros::SourceRangeSkipped(SourceRange R,
SourceLocation EndifLoc) {
if (!InMainFile)
return;
Position Begin = sourceLocToPosition(SM, R.getBegin());
Position End = sourceLocToPosition(SM, R.getEnd());
Out.SkippedRanges.push_back(Range{Begin, End});
}
class CollectPragmaMarks : public PPCallbacks {
public:
explicit CollectPragmaMarks(const SourceManager &SM,
std::vector<clangd::PragmaMark> &Out)
: SM(SM), Out(Out) {}
void PragmaMark(SourceLocation Loc, StringRef Trivia) override {
if (isInsideMainFile(Loc, SM)) {
// FIXME: This range should just cover `XX` in `#pragma mark XX` and
// `- XX` in `#pragma mark - XX`.
Position Start = sourceLocToPosition(SM, Loc);
Position End = {Start.line + 1, 0};
Out.emplace_back(clangd::PragmaMark{{Start, End}, Trivia.str()});
}
}
private:
const SourceManager &SM;
std::vector<clangd::PragmaMark> &Out;
};
std::unique_ptr<PPCallbacks>
collectPragmaMarksCallback(const SourceManager &SM,
std::vector<PragmaMark> &Out) {
return std::make_unique<CollectPragmaMarks>(SM, Out);
}
void CollectMainFileMacros::MacroDefined(const Token &MacroName,
const MacroDirective *MD) {
if (!InMainFile)
return;
const auto *MI = MD->getMacroInfo();
add(MacroName, MD->getMacroInfo(), true);
if (MI)
for (const auto &Tok : MI->tokens()) {
auto *II = Tok.getIdentifierInfo();
// Could this token be a reference to a macro? (Not param to this macro).
if (!II || !II->hadMacroDefinition() ||
llvm::is_contained(MI->params(), II))
continue;
if (const MacroInfo *MI = PP.getMacroInfo(II))
add(Tok, MI);
}
}
} // namespace clangd
} // namespace clang
|