clang  14.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/Optional.h"
17 #include "llvm/ADT/SmallString.h"
18 #include "llvm/ADT/SmallVector.h"
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 llvm::None.
89  Optional<StringRef> getExpandedText(SourceLocation MacroExpansionLoc) const;
90 
91  /// \param MacroExpansionLoc Must be the expansion location of a macro.
92  /// \return The text from the original source code which were substituted by
93  /// the macro expansion chain from the given location.
94  /// If no macro was expanded at that location, returns llvm::None.
95  Optional<StringRef> getOriginalText(SourceLocation MacroExpansionLoc) const;
96 
97  LLVM_DUMP_METHOD void dumpExpansionRangesToStream(raw_ostream &OS) const;
98  LLVM_DUMP_METHOD void dumpExpandedTextsToStream(raw_ostream &OS) const;
99  LLVM_DUMP_METHOD void dumpExpansionRanges() const;
100  LLVM_DUMP_METHOD void dumpExpandedTexts() const;
101 
102 private:
105  using ExpansionMap = llvm::DenseMap<SourceLocation, MacroExpansionText>;
106  using ExpansionRangeMap = llvm::DenseMap<SourceLocation, SourceLocation>;
107 
108  /// Associates the textual representation of the expanded tokens at the given
109  /// macro expansion location.
110  ExpansionMap ExpandedTokens;
111 
112  /// Tracks which source location was the last affected by any macro
113  /// substitution starting from a given macro expansion location.
114  ExpansionRangeMap ExpansionRanges;
115 
116  Preprocessor *PP = nullptr;
117  SourceManager *SM = nullptr;
118  const LangOptions &LangOpts;
119 
120  /// This callback is called by the preprocessor.
121  /// It stores the textual representation of the expanded token sequence for a
122  /// macro expansion location.
123  void onTokenLexed(const Token &Tok);
124 };
125 } // end namespace clang
126 
127 #endif // LLVM_CLANG_ANALYSIS_MACROEXPANSIONCONTEXT_H
clang::MacroExpansionContext::dumpExpandedTextsToStream
LLVM_DUMP_METHOD void dumpExpandedTextsToStream(raw_ostream &OS) const
Definition: MacroExpansionContext.cpp:159
clang::MacroExpansionContext::getOriginalText
Optional< StringRef > getOriginalText(SourceLocation MacroExpansionLoc) const
Definition: MacroExpansionContext.cpp:118
clang::MacroExpansionContext::dumpExpansionRangesToStream
LLVM_DUMP_METHOD void dumpExpansionRangesToStream(raw_ostream &OS) const
Definition: MacroExpansionContext.cpp:141
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:86
llvm::Optional
Definition: LLVM.h:40
clang::MacroExpansionContext::getExpandedText
Optional< StringRef > getExpandedText(SourceLocation MacroExpansionLoc) const
Definition: MacroExpansionContext.cpp:100
clang::Token
Token - This structure provides full information about a lexed token.
Definition: Token.h:34
clang::SourceManager
This class handles loading and caching of source files into memory.
Definition: SourceManager.h:626
Preprocessor.h
LangOptions.h
llvm::SmallString
Definition: LLVM.h:37
clang::detail::MacroExpansionRangeRecorder
Definition: MacroExpansionContext.cpp:19
clang::MacroExpansionContext::dumpExpandedTexts
LLVM_DUMP_METHOD void dumpExpandedTexts() const
Definition: MacroExpansionContext.cpp:137
clang::MacroExpansionContext::dumpExpansionRanges
LLVM_DUMP_METHOD void dumpExpansionRanges() const
Definition: MacroExpansionContext.cpp:134
SourceLocation.h
clang::MacroExpansionContext::registerForPreprocessor
void registerForPreprocessor(Preprocessor &PP)
Register the necessary callbacks to the Preprocessor to record the expansion events and the generated...
Definition: MacroExpansionContext.cpp:88
clang::MacroExpansionContext
MacroExpansionContext tracks the macro expansions processed by the Preprocessor.
Definition: MacroExpansionContext.h:73
clang::LangOptions
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:58
clang
Definition: CalledOnceCheck.h:17
clang::MacroExpansionContext::MacroExpansionContext
MacroExpansionContext(const LangOptions &LangOpts)
Creates a MacroExpansionContext.
Definition: MacroExpansionContext.cpp:85
clang::Preprocessor
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:130
SM
#define SM(sm)
Definition: Cuda.cpp:81