clang 22.0.0git
MacroExpansionContext.h
Go to the documentation of this file.
1//===- MacroExpansionContext.h - Macro expansion information ----*- 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_ANALYSIS_MACROEXPANSIONCONTEXT_H
10#define LLVM_CLANG_ANALYSIS_MACROEXPANSIONCONTEXT_H
11
15#include "llvm/ADT/DenseMap.h"
16#include "llvm/ADT/SmallString.h"
17#include "llvm/ADT/SmallVector.h"
18#include <optional>
19
20namespace clang {
21
22namespace detail {
24} // namespace detail
25
26/// MacroExpansionContext tracks the macro expansions processed by the
27/// Preprocessor. It means that it can track source locations from a single
28/// translation unit. For every macro expansion it can tell you what text will
29/// be substituted.
30///
31/// It was designed to deal with:
32/// - regular macros
33/// - macro functions
34/// - variadic macros
35/// - transitive macro expansions
36/// - macro redefinition
37/// - unbalanced parenthesis
38///
39/// \code{.c}
40/// void bar();
41/// #define retArg(x) x
42/// #define retArgUnclosed retArg(bar()
43/// #define BB CC
44/// #define applyInt BB(int)
45/// #define CC(x) retArgUnclosed
46///
47/// void unbalancedMacros() {
48/// applyInt );
49/// //^~~~~~~~~~^ is the substituted range
50/// // Substituted text is "applyInt )"
51/// // Expanded text is "bar()"
52/// }
53///
54/// #define expandArgUnclosedCommaExpr(x) (x, bar(), 1
55/// #define f expandArgUnclosedCommaExpr
56///
57/// void unbalancedMacros2() {
58/// int x = f(f(1)) )); // Look at the parenthesis!
59/// // ^~~~~~^ is the substituted range
60/// // Substituted text is "f(f(1))"
61/// // Expanded text is "((1,bar(),1,bar(),1"
62/// }
63/// \endcode
64/// \remark Currently we don't respect the whitespaces between expanded tokens,
65/// so the output for this example might differ from the -E compiler
66/// invocation.
67/// \remark All whitespaces are consumed while constructing the expansion.
68/// After all identifier a single space inserted to produce a valid C
69/// code even if identifier follows an other identifiers such as
70/// variable declarations.
71/// \remark MacroExpansionContext object must outlive the Preprocessor
72/// parameter.
74public:
75 /// Creates a MacroExpansionContext.
76 /// \remark You must call registerForPreprocessor to set the required
77 /// onTokenLexed callback and the PPCallbacks.
78 explicit MacroExpansionContext(const LangOptions &LangOpts);
79
80 /// Register the necessary callbacks to the Preprocessor to record the
81 /// expansion events and the generated tokens. Must ensure that this object
82 /// outlives the given Preprocessor.
84
85 /// \param MacroExpansionLoc Must be the expansion location of a macro.
86 /// \return The textual representation of the token sequence which was
87 /// substituted in place of the macro after the preprocessing.
88 /// If no macro was expanded at that location, returns std::nullopt.
89 std::optional<StringRef>
90 getExpandedText(SourceLocation MacroExpansionLoc) const;
91
92 /// \param MacroExpansionLoc Must be the expansion location of a macro.
93 /// \return The text from the original source code which were substituted by
94 /// the macro expansion chain from the given location.
95 /// If no macro was expanded at that location, returns std::nullopt.
96 std::optional<StringRef>
97 getOriginalText(SourceLocation MacroExpansionLoc) const;
98
99 /// \param MacroExpansionLoc Must be the expansion location of a macro.
100 /// \return A formatted representation of the textual representation of the
101 /// token sequence which was substituted in place of the macro.
102 /// If no macro was expanded at that location, returns std::nullopt.
103 std::optional<StringRef>
104 getFormattedExpandedText(SourceLocation MacroExpansionLoc) const;
105
106 LLVM_DUMP_METHOD void dumpExpansionRangesToStream(raw_ostream &OS) const;
107 LLVM_DUMP_METHOD void dumpExpandedTextsToStream(raw_ostream &OS) const;
108 LLVM_DUMP_METHOD void dumpExpansionRanges() const;
109 LLVM_DUMP_METHOD void dumpExpandedTexts() const;
110
111private:
113 using MacroExpansionText = SmallString<40>;
114 using ExpansionMap = llvm::DenseMap<SourceLocation, MacroExpansionText>;
115 using ExpansionRangeMap = llvm::DenseMap<SourceLocation, SourceLocation>;
116 using FormattedExpansionMap = llvm::DenseMap<SourceLocation, std::string>;
117
118 /// Associates the textual representation of the expanded tokens at the given
119 /// macro expansion location.
120 ExpansionMap ExpandedTokens;
121
122 /// Tracks which source location was the last affected by any macro
123 /// substitution starting from a given macro expansion location.
124 ExpansionRangeMap ExpansionRanges;
125
126 /// Caches formatted macro expansions keyed by expansion location.
127 mutable FormattedExpansionMap FormattedExpandedTokens;
128
129 Preprocessor *PP = nullptr;
130 SourceManager *SM = nullptr;
131 const LangOptions &LangOpts;
132
133 /// This callback is called by the preprocessor.
134 /// It stores the textual representation of the expanded token sequence for a
135 /// macro expansion location.
136 void onTokenLexed(const Token &Tok);
137};
138} // end namespace clang
139
140#endif // LLVM_CLANG_ANALYSIS_MACROEXPANSIONCONTEXT_H
Token Tok
The Token.
Defines the clang::LangOptions interface.
Defines the clang::Preprocessor interface.
Defines the clang::SourceLocation class and associated facilities.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
void registerForPreprocessor(Preprocessor &PP)
Register the necessary callbacks to the Preprocessor to record the expansion events and the generated...
LLVM_DUMP_METHOD void dumpExpandedTextsToStream(raw_ostream &OS) const
LLVM_DUMP_METHOD void dumpExpandedTexts() const
LLVM_DUMP_METHOD void dumpExpansionRanges() const
MacroExpansionContext(const LangOptions &LangOpts)
Creates a MacroExpansionContext.
std::optional< StringRef > getFormattedExpandedText(SourceLocation MacroExpansionLoc) const
LLVM_DUMP_METHOD void dumpExpansionRangesToStream(raw_ostream &OS) const
std::optional< StringRef > getExpandedText(SourceLocation MacroExpansionLoc) const
std::optional< StringRef > getOriginalText(SourceLocation MacroExpansionLoc) const
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Encodes a location in the source.
This class handles loading and caching of source files into memory.
Token - This structure provides full information about a lexed token.
Definition Token.h:36
The JSON file list parser is used to communicate input to InstallAPI.