Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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.  
  12. #include "clang/Basic/LangOptions.h"
  13. #include "clang/Basic/SourceLocation.h"
  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 {
  23. class MacroExpansionRangeRecorder;
  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.
  73. class MacroExpansionContext {
  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.
  83.   void registerForPreprocessor(Preprocessor &PP);
  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:
  105.   friend class detail::MacroExpansionRangeRecorder;
  106.   using MacroExpansionText = SmallString<40>;
  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
  130.