clang-tools 20.0.0git
CollectMacros.cpp
Go to the documentation of this file.
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
21Range MacroOccurrence::toRange(const SourceManager &SM) const {
22 auto MainFile = SM.getMainFileID();
23 return halfOpenToRange(
24 SM, syntax::FileRange(MainFile, StartOffset, EndOffset).toCharRange(SM));
25}
26
27void CollectMainFileMacros::add(const Token &MacroNameTok, const MacroInfo *MI,
28 bool IsDefinition, bool InIfCondition) {
29 if (!InMainFile)
30 return;
31 auto Loc = MacroNameTok.getLocation();
32 if (Loc.isInvalid() || Loc.isMacroID())
33 return;
34
35 assert(isInsideMainFile(Loc, SM));
36 auto Name = MacroNameTok.getIdentifierInfo()->getName();
37 Out.Names.insert(Name);
38 size_t Start = SM.getFileOffset(Loc);
39 size_t End = SM.getFileOffset(MacroNameTok.getEndLoc());
40 if (auto SID = getSymbolID(Name, MI, SM))
41 Out.MacroRefs[SID].push_back({Start, End, IsDefinition, InIfCondition});
42 else
43 Out.UnknownMacros.push_back({Start, End, IsDefinition, InIfCondition});
44}
45
46void CollectMainFileMacros::FileChanged(SourceLocation Loc, FileChangeReason,
47 SrcMgr::CharacteristicKind, FileID) {
48 InMainFile = isInsideMainFile(Loc, SM);
49}
50
52 const MacroDefinition &MD,
53 SourceRange Range,
54 const MacroArgs *Args) {
55 add(MacroName, MD.getMacroInfo());
56}
57
59 const clang::MacroDefinition &MD,
60 const clang::MacroDirective *Undef) {
61 add(MacroName, MD.getMacroInfo());
62}
63
64void CollectMainFileMacros::Ifdef(SourceLocation Loc, const Token &MacroName,
65 const MacroDefinition &MD) {
66 add(MacroName, MD.getMacroInfo(), /*IsDefinition=*/false,
67 /*InConditionalDirective=*/true);
68}
69
71 const MacroDefinition &MD) {
72 add(MacroName, MD.getMacroInfo(), /*IsDefinition=*/false,
73 /*InConditionalDirective=*/true);
74}
75
77 const MacroDefinition &MD) {
78 add(MacroName, MD.getMacroInfo(), /*IsDefinition=*/false,
79 /*InConditionalDirective=*/true);
80}
81
83 const MacroDefinition &MD) {
84 add(MacroName, MD.getMacroInfo(), /*IsDefinition=*/false,
85 /*InConditionalDirective=*/true);
86}
87
89 const MacroDefinition &MD,
90 SourceRange Range) {
91 add(MacroName, MD.getMacroInfo(), /*IsDefinition=*/false,
92 /*InConditionalDirective=*/true);
93}
94
96 SourceLocation EndifLoc) {
97 if (!InMainFile)
98 return;
99 Position Begin = sourceLocToPosition(SM, R.getBegin());
100 Position End = sourceLocToPosition(SM, R.getEnd());
101 Out.SkippedRanges.push_back(Range{Begin, End});
102}
103
105public:
106 explicit CollectPragmaMarks(const SourceManager &SM,
107 std::vector<clangd::PragmaMark> &Out)
108 : SM(SM), Out(Out) {}
109
110 void PragmaMark(SourceLocation Loc, StringRef Trivia) override {
111 if (isInsideMainFile(Loc, SM)) {
112 // FIXME: This range should just cover `XX` in `#pragma mark XX` and
113 // `- XX` in `#pragma mark - XX`.
114 Position Start = sourceLocToPosition(SM, Loc);
115 Position End = {Start.line + 1, 0};
116 Out.emplace_back(clangd::PragmaMark{{Start, End}, Trivia.str()});
117 }
118 }
119
120private:
121 const SourceManager &SM;
122 std::vector<clangd::PragmaMark> &Out;
123};
124
125std::unique_ptr<PPCallbacks>
126collectPragmaMarksCallback(const SourceManager &SM,
127 std::vector<PragmaMark> &Out) {
128 return std::make_unique<CollectPragmaMarks>(SM, Out);
129}
130
132 const MacroDirective *MD) {
133
134 if (!InMainFile)
135 return;
136 const auto *MI = MD->getMacroInfo();
137 add(MacroName, MD->getMacroInfo(), true);
138 if (MI)
139 for (const auto &Tok : MI->tokens()) {
140 auto *II = Tok.getIdentifierInfo();
141 // Could this token be a reference to a macro? (Not param to this macro).
142 if (!II || !II->hadMacroDefinition() ||
143 llvm::is_contained(MI->params(), II))
144 continue;
145 if (const MacroInfo *MI = PP.getMacroInfo(II))
146 add(Tok, MI);
147 }
148}
149
150} // namespace clangd
151} // namespace clang
llvm::SmallString< 256U > Name
CompiledFragmentImpl & Out
std::string MainFile
SourceLocation Loc
std::string MacroName
Definition: Preamble.cpp:240
llvm::json::Object Args
Definition: Trace.cpp:138
void MacroDefined(const Token &MacroName, const MacroDirective *MD) override
void FileChanged(SourceLocation Loc, FileChangeReason, SrcMgr::CharacteristicKind, FileID) override
void MacroExpands(const Token &MacroName, const MacroDefinition &MD, SourceRange Range, const MacroArgs *Args) override
void Elifndef(SourceLocation Loc, const Token &MacroNameTok, const MacroDefinition &MD) override
void Defined(const Token &MacroName, const MacroDefinition &MD, SourceRange Range) override
void MacroUndefined(const clang::Token &MacroName, const clang::MacroDefinition &MD, const clang::MacroDirective *Undef) override
void Ifndef(SourceLocation Loc, const Token &MacroName, const MacroDefinition &MD) override
void SourceRangeSkipped(SourceRange R, SourceLocation EndifLoc) override
void Ifdef(SourceLocation Loc, const Token &MacroName, const MacroDefinition &MD) override
void Elifdef(SourceLocation Loc, const Token &MacroNameTok, const MacroDefinition &MD) override
CollectPragmaMarks(const SourceManager &SM, std::vector< clangd::PragmaMark > &Out)
void PragmaMark(SourceLocation Loc, StringRef Trivia) override
SymbolID getSymbolID(const Decl *D)
Gets the symbol ID for a declaration. Returned SymbolID might be null.
Definition: AST.cpp:331
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R)
Definition: SourceCode.cpp:472
bool isInsideMainFile(SourceLocation Loc, const SourceManager &SM)
Returns true iff Loc is inside the main file.
Definition: SourceCode.cpp:423
std::unique_ptr< PPCallbacks > collectPragmaMarksCallback(const SourceManager &SM, std::vector< PragmaMark > &Out)
Collect all pragma marks from the main file.
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
Definition: SourceCode.cpp:214
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Range toRange(const SourceManager &SM) const
std::vector< MacroOccurrence > UnknownMacros
Definition: CollectMacros.h:43
llvm::DenseMap< SymbolID, std::vector< MacroOccurrence > > MacroRefs
Definition: CollectMacros.h:39
std::vector< Range > SkippedRanges
Definition: CollectMacros.h:45
Represents a #pragma mark in the main file.
A single C++ or preprocessor token.
Definition: support/Token.h:50