clang  19.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 
14 #include "clang/Lex/Preprocessor.h"
15 #include "llvm/ADT/DenseMap.h"
16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include <optional>
19 
20 namespace clang {
21 
22 namespace 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.
74 public:
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  LLVM_DUMP_METHOD void dumpExpansionRangesToStream(raw_ostream &OS) const;
100  LLVM_DUMP_METHOD void dumpExpandedTextsToStream(raw_ostream &OS) const;
101  LLVM_DUMP_METHOD void dumpExpansionRanges() const;
102  LLVM_DUMP_METHOD void dumpExpandedTexts() const;
103 
104 private:
107  using ExpansionMap = llvm::DenseMap<SourceLocation, MacroExpansionText>;
108  using ExpansionRangeMap = llvm::DenseMap<SourceLocation, SourceLocation>;
109 
110  /// Associates the textual representation of the expanded tokens at the given
111  /// macro expansion location.
112  ExpansionMap ExpandedTokens;
113 
114  /// Tracks which source location was the last affected by any macro
115  /// substitution starting from a given macro expansion location.
116  ExpansionRangeMap ExpansionRanges;
117 
118  Preprocessor *PP = nullptr;
119  SourceManager *SM = nullptr;
120  const LangOptions &LangOpts;
121 
122  /// This callback is called by the preprocessor.
123  /// It stores the textual representation of the expanded token sequence for a
124  /// macro expansion location.
125  void onTokenLexed(const Token &Tok);
126 };
127 } // end namespace clang
128 
129 #endif // LLVM_CLANG_ANALYSIS_MACROEXPANSIONCONTEXT_H
#define SM(sm)
Definition: Cuda.cpp:83
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...
Definition: LangOptions.h:482
MacroExpansionContext tracks the macro expansions processed by the Preprocessor.
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.
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.
Definition: Preprocessor.h:128
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.