Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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