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

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang-tools-extra/clangd/CollectMacros.cpp