1//===--- CollectMacros.h -----------------------------------------*- 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#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTMACROS_H
10#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTMACROS_H
11
12#include "Protocol.h"
13#include "SourceCode.h"
14#include "index/SymbolID.h"
15#include "clang/Basic/SourceLocation.h"
16#include "clang/Lex/PPCallbacks.h"
17#include "clang/Lex/Preprocessor.h"
18#include "llvm/ADT/DenseMap.h"
19#include <cstddef>
20#include <string>
21
22namespace clang {
23namespace clangd {
24
25struct MacroOccurrence {
26 // Half-open range (end offset is exclusive) inside the main file.
27 size_t StartOffset;
28 size_t EndOffset;
29
30 bool IsDefinition;
31 // True if the occurence is used in a conditional directive, e.g. #ifdef MACRO
32 bool InConditionalDirective;
33
34 Range toRange(const SourceManager &SM) const;
35};
36
37struct MainFileMacros {
38 llvm::StringSet<> Names;
39 llvm::DenseMap<SymbolID, std::vector<MacroOccurrence>> MacroRefs;
40 // Somtimes it is not possible to compute the SymbolID for the Macro, e.g. a
41 // reference to an undefined macro. Store them separately, e.g. for semantic
42 // highlighting.
43 std::vector<MacroOccurrence> UnknownMacros;
44 // Ranges skipped by the preprocessor due to being inactive.
45 std::vector<Range> SkippedRanges;
46};
47
48/// Collects macro references (e.g. definitions, expansions) in the main file.
49/// It is used to:
50/// - collect macros in the preamble section of the main file (in Preamble.cpp)
51/// - collect macros after the preamble of the main file (in ParsedAST.cpp)
52class CollectMainFileMacros : public PPCallbacks {
53public:
54 explicit CollectMainFileMacros(const Preprocessor &PP, MainFileMacros &Out)
55 : SM(PP.getSourceManager()), PP(PP), Out(Out) {}
56
57 void FileChanged(SourceLocation Loc, FileChangeReason,
58 SrcMgr::CharacteristicKind, FileID) override;
59
60 void MacroDefined(const Token &MacroName, const MacroDirective *MD) override;
61
62 void MacroExpands(const Token &MacroName, const MacroDefinition &MD,
63 SourceRange Range, const MacroArgs *Args) override;
64
65 void MacroUndefined(const clang::Token &MacroName,
66 const clang::MacroDefinition &MD,
67 const clang::MacroDirective *Undef) override;
68
69 void Ifdef(SourceLocation Loc, const Token &MacroName,
70 const MacroDefinition &MD) override;
71 void Ifndef(SourceLocation Loc, const Token &MacroName,
72 const MacroDefinition &MD) override;
73 using PPCallbacks::Elifdef;
74 using PPCallbacks::Elifndef;
75 void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
76 const MacroDefinition &MD) override;
77 void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
78 const MacroDefinition &MD) override;
79
80 void Defined(const Token &MacroName, const MacroDefinition &MD,
81 SourceRange Range) override;
82
83 void SourceRangeSkipped(SourceRange R, SourceLocation EndifLoc) override;
84
85private:
86 void add(const Token &MacroNameTok, const MacroInfo *MI,
87 bool IsDefinition = false, bool InConditionalDirective = false);
88 const SourceManager &SM;
89 const Preprocessor &PP;
90 bool InMainFile = true;
91 MainFileMacros &Out;
92};
93
94/// Represents a `#pragma mark` in the main file.
95///
96/// There can be at most one pragma mark per line.
97struct PragmaMark {
98 Range Rng;
99 std::string Trivia;
100};
101
102/// Collect all pragma marks from the main file.
103std::unique_ptr<PPCallbacks>
104collectPragmaMarksCallback(const SourceManager &, std::vector<PragmaMark> &Out);
105
106} // namespace clangd
107} // namespace clang
108
109#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTMACROS_H
110

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