|
|
|||
File indexing completed on 2026-05-10 08:36:26
0001 //===- MacroExpansionContext.h - Macro expansion information ----*- C++ -*-===// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 0009 #ifndef LLVM_CLANG_ANALYSIS_MACROEXPANSIONCONTEXT_H 0010 #define LLVM_CLANG_ANALYSIS_MACROEXPANSIONCONTEXT_H 0011 0012 #include "clang/Basic/LangOptions.h" 0013 #include "clang/Basic/SourceLocation.h" 0014 #include "clang/Lex/Preprocessor.h" 0015 #include "llvm/ADT/DenseMap.h" 0016 #include "llvm/ADT/SmallString.h" 0017 #include "llvm/ADT/SmallVector.h" 0018 #include <optional> 0019 0020 namespace clang { 0021 0022 namespace detail { 0023 class MacroExpansionRangeRecorder; 0024 } // namespace detail 0025 0026 /// MacroExpansionContext tracks the macro expansions processed by the 0027 /// Preprocessor. It means that it can track source locations from a single 0028 /// translation unit. For every macro expansion it can tell you what text will 0029 /// be substituted. 0030 /// 0031 /// It was designed to deal with: 0032 /// - regular macros 0033 /// - macro functions 0034 /// - variadic macros 0035 /// - transitive macro expansions 0036 /// - macro redefinition 0037 /// - unbalanced parenthesis 0038 /// 0039 /// \code{.c} 0040 /// void bar(); 0041 /// #define retArg(x) x 0042 /// #define retArgUnclosed retArg(bar() 0043 /// #define BB CC 0044 /// #define applyInt BB(int) 0045 /// #define CC(x) retArgUnclosed 0046 /// 0047 /// void unbalancedMacros() { 0048 /// applyInt ); 0049 /// //^~~~~~~~~~^ is the substituted range 0050 /// // Substituted text is "applyInt )" 0051 /// // Expanded text is "bar()" 0052 /// } 0053 /// 0054 /// #define expandArgUnclosedCommaExpr(x) (x, bar(), 1 0055 /// #define f expandArgUnclosedCommaExpr 0056 /// 0057 /// void unbalancedMacros2() { 0058 /// int x = f(f(1)) )); // Look at the parenthesis! 0059 /// // ^~~~~~^ is the substituted range 0060 /// // Substituted text is "f(f(1))" 0061 /// // Expanded text is "((1,bar(),1,bar(),1" 0062 /// } 0063 /// \endcode 0064 /// \remark Currently we don't respect the whitespaces between expanded tokens, 0065 /// so the output for this example might differ from the -E compiler 0066 /// invocation. 0067 /// \remark All whitespaces are consumed while constructing the expansion. 0068 /// After all identifier a single space inserted to produce a valid C 0069 /// code even if identifier follows an other identifiers such as 0070 /// variable declarations. 0071 /// \remark MacroExpansionContext object must outlive the Preprocessor 0072 /// parameter. 0073 class MacroExpansionContext { 0074 public: 0075 /// Creates a MacroExpansionContext. 0076 /// \remark You must call registerForPreprocessor to set the required 0077 /// onTokenLexed callback and the PPCallbacks. 0078 explicit MacroExpansionContext(const LangOptions &LangOpts); 0079 0080 /// Register the necessary callbacks to the Preprocessor to record the 0081 /// expansion events and the generated tokens. Must ensure that this object 0082 /// outlives the given Preprocessor. 0083 void registerForPreprocessor(Preprocessor &PP); 0084 0085 /// \param MacroExpansionLoc Must be the expansion location of a macro. 0086 /// \return The textual representation of the token sequence which was 0087 /// substituted in place of the macro after the preprocessing. 0088 /// If no macro was expanded at that location, returns std::nullopt. 0089 std::optional<StringRef> 0090 getExpandedText(SourceLocation MacroExpansionLoc) const; 0091 0092 /// \param MacroExpansionLoc Must be the expansion location of a macro. 0093 /// \return The text from the original source code which were substituted by 0094 /// the macro expansion chain from the given location. 0095 /// If no macro was expanded at that location, returns std::nullopt. 0096 std::optional<StringRef> 0097 getOriginalText(SourceLocation MacroExpansionLoc) const; 0098 0099 LLVM_DUMP_METHOD void dumpExpansionRangesToStream(raw_ostream &OS) const; 0100 LLVM_DUMP_METHOD void dumpExpandedTextsToStream(raw_ostream &OS) const; 0101 LLVM_DUMP_METHOD void dumpExpansionRanges() const; 0102 LLVM_DUMP_METHOD void dumpExpandedTexts() const; 0103 0104 private: 0105 friend class detail::MacroExpansionRangeRecorder; 0106 using MacroExpansionText = SmallString<40>; 0107 using ExpansionMap = llvm::DenseMap<SourceLocation, MacroExpansionText>; 0108 using ExpansionRangeMap = llvm::DenseMap<SourceLocation, SourceLocation>; 0109 0110 /// Associates the textual representation of the expanded tokens at the given 0111 /// macro expansion location. 0112 ExpansionMap ExpandedTokens; 0113 0114 /// Tracks which source location was the last affected by any macro 0115 /// substitution starting from a given macro expansion location. 0116 ExpansionRangeMap ExpansionRanges; 0117 0118 Preprocessor *PP = nullptr; 0119 SourceManager *SM = nullptr; 0120 const LangOptions &LangOpts; 0121 0122 /// This callback is called by the preprocessor. 0123 /// It stores the textual representation of the expanded token sequence for a 0124 /// macro expansion location. 0125 void onTokenLexed(const Token &Tok); 0126 }; 0127 } // end namespace clang 0128 0129 #endif // LLVM_CLANG_ANALYSIS_MACROEXPANSIONCONTEXT_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|