- //===- MacroExpansionContext.h - Macro expansion information ----*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_CLANG_ANALYSIS_MACROEXPANSIONCONTEXT_H 
- #define LLVM_CLANG_ANALYSIS_MACROEXPANSIONCONTEXT_H 
-   
- #include "clang/Basic/LangOptions.h" 
- #include "clang/Basic/SourceLocation.h" 
- #include "clang/Lex/Preprocessor.h" 
- #include "llvm/ADT/DenseMap.h" 
- #include "llvm/ADT/SmallString.h" 
- #include "llvm/ADT/SmallVector.h" 
- #include <optional> 
-   
- namespace clang { 
-   
- namespace detail { 
- class MacroExpansionRangeRecorder; 
- } // namespace detail 
-   
- /// MacroExpansionContext tracks the macro expansions processed by the 
- /// Preprocessor. It means that it can track source locations from a single 
- /// translation unit. For every macro expansion it can tell you what text will 
- /// be substituted. 
- /// 
- /// It was designed to deal with: 
- ///  - regular macros 
- ///  - macro functions 
- ///  - variadic macros 
- ///  - transitive macro expansions 
- ///  - macro redefinition 
- ///  - unbalanced parenthesis 
- /// 
- /// \code{.c} 
- ///   void bar(); 
- ///   #define retArg(x) x 
- ///   #define retArgUnclosed retArg(bar() 
- ///   #define BB CC 
- ///   #define applyInt BB(int) 
- ///   #define CC(x) retArgUnclosed 
- /// 
- ///   void unbalancedMacros() { 
- ///     applyInt  ); 
- ///   //^~~~~~~~~~^ is the substituted range 
- ///   // Substituted text is "applyInt  )" 
- ///   // Expanded text is "bar()" 
- ///   } 
- /// 
- ///   #define expandArgUnclosedCommaExpr(x) (x, bar(), 1 
- ///   #define f expandArgUnclosedCommaExpr 
- /// 
- ///   void unbalancedMacros2() { 
- ///     int x =  f(f(1))  ));  // Look at the parenthesis! 
- ///   //         ^~~~~~^ is the substituted range 
- ///   // Substituted text is "f(f(1))" 
- ///   // Expanded text is "((1,bar(),1,bar(),1" 
- ///   } 
- /// \endcode 
- /// \remark Currently we don't respect the whitespaces between expanded tokens, 
- ///         so the output for this example might differ from the -E compiler 
- ///         invocation. 
- /// \remark All whitespaces are consumed while constructing the expansion. 
- ///         After all identifier a single space inserted to produce a valid C 
- ///         code even if identifier follows an other identifiers such as 
- ///         variable declarations. 
- /// \remark MacroExpansionContext object must outlive the Preprocessor 
- ///         parameter. 
- class MacroExpansionContext { 
- public: 
-   /// Creates a MacroExpansionContext. 
-   /// \remark You must call registerForPreprocessor to set the required 
-   ///         onTokenLexed callback and the PPCallbacks. 
-   explicit MacroExpansionContext(const LangOptions &LangOpts); 
-   
-   /// Register the necessary callbacks to the Preprocessor to record the 
-   /// expansion events and the generated tokens. Must ensure that this object 
-   /// outlives the given Preprocessor. 
-   void registerForPreprocessor(Preprocessor &PP); 
-   
-   /// \param MacroExpansionLoc Must be the expansion location of a macro. 
-   /// \return The textual representation of the token sequence which was 
-   ///         substituted in place of the macro after the preprocessing. 
-   ///         If no macro was expanded at that location, returns std::nullopt. 
-   std::optional<StringRef> 
-   getExpandedText(SourceLocation MacroExpansionLoc) const; 
-   
-   /// \param MacroExpansionLoc Must be the expansion location of a macro. 
-   /// \return The text from the original source code which were substituted by 
-   ///         the macro expansion chain from the given location. 
-   ///         If no macro was expanded at that location, returns std::nullopt. 
-   std::optional<StringRef> 
-   getOriginalText(SourceLocation MacroExpansionLoc) const; 
-   
-   LLVM_DUMP_METHOD void dumpExpansionRangesToStream(raw_ostream &OS) const; 
-   LLVM_DUMP_METHOD void dumpExpandedTextsToStream(raw_ostream &OS) const; 
-   LLVM_DUMP_METHOD void dumpExpansionRanges() const; 
-   LLVM_DUMP_METHOD void dumpExpandedTexts() const; 
-   
- private: 
-   friend class detail::MacroExpansionRangeRecorder; 
-   using MacroExpansionText = SmallString<40>; 
-   using ExpansionMap = llvm::DenseMap<SourceLocation, MacroExpansionText>; 
-   using ExpansionRangeMap = llvm::DenseMap<SourceLocation, SourceLocation>; 
-   
-   /// Associates the textual representation of the expanded tokens at the given 
-   /// macro expansion location. 
-   ExpansionMap ExpandedTokens; 
-   
-   /// Tracks which source location was the last affected by any macro 
-   /// substitution starting from a given macro expansion location. 
-   ExpansionRangeMap ExpansionRanges; 
-   
-   Preprocessor *PP = nullptr; 
-   SourceManager *SM = nullptr; 
-   const LangOptions &LangOpts; 
-   
-   /// This callback is called by the preprocessor. 
-   /// It stores the textual representation of the expanded token sequence for a 
-   /// macro expansion location. 
-   void onTokenLexed(const Token &Tok); 
- }; 
- } // end namespace clang 
-   
- #endif // LLVM_CLANG_ANALYSIS_MACROEXPANSIONCONTEXT_H 
-