summaryrefslogtreecommitdiffstats
path: root/include/clang/Lex/MacroArgs.h
blob: 8806f2d8c6567fec787b0fc3fa390b217ad1ed2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//===--- MacroArgs.h - Formal argument info for Macros ----------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file defines the MacroArgs interface.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LEX_MACROARGS_H
#define LLVM_CLANG_LEX_MACROARGS_H

#include "clang/Basic/LLVM.h"
#include "clang/Lex/Token.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/TrailingObjects.h"
#include <vector>

namespace clang {
  class MacroInfo;
  class Preprocessor;
  class SourceLocation;

/// MacroArgs - An instance of this class captures information about
/// the formal arguments specified to a function-like macro invocation.
class MacroArgs final
    : private llvm::TrailingObjects<MacroArgs, Token> {

  friend TrailingObjects;
  /// NumUnexpArgTokens - The number of raw, unexpanded tokens for the
  /// arguments.  All of the actual argument tokens are allocated immediately
  /// after the MacroArgs object in memory.  This is all of the arguments
  /// concatenated together, with 'EOF' markers at the end of each argument.
  unsigned NumUnexpArgTokens;

  /// VarargsElided - True if this is a C99 style varargs macro invocation and
  /// there was no argument specified for the "..." argument.  If the argument
  /// was specified (even empty) or this isn't a C99 style varargs function, or
  /// if in strict mode and the C99 varargs macro had only a ... argument, this
  /// is false.
  bool VarargsElided;

  /// PreExpArgTokens - Pre-expanded tokens for arguments that need them.  Empty
  /// if not yet computed.  This includes the EOF marker at the end of the
  /// stream.
  std::vector<std::vector<Token> > PreExpArgTokens;

  /// StringifiedArgs - This contains arguments in 'stringified' form.  If the
  /// stringified form of an argument has not yet been computed, this is empty.
  std::vector<Token> StringifiedArgs;

  /// ArgCache - This is a linked list of MacroArgs objects that the
  /// Preprocessor owns which we use to avoid thrashing malloc/free.
  MacroArgs *ArgCache;

  /// MacroArgs - The number of arguments the invoked macro expects.
  unsigned NumMacroArgs;

  MacroArgs(unsigned NumToks, bool varargsElided, unsigned MacroArgs)
      : NumUnexpArgTokens(NumToks), VarargsElided(varargsElided),
        ArgCache(nullptr), NumMacroArgs(MacroArgs) {}
  ~MacroArgs() = default;

public:
  /// MacroArgs ctor function - Create a new MacroArgs object with the specified
  /// macro and argument info.
  static MacroArgs *create(const MacroInfo *MI,
                           ArrayRef<Token> UnexpArgTokens,
                           bool VarargsElided, Preprocessor &PP);

  /// destroy - Destroy and deallocate the memory for this object.
  ///
  void destroy(Preprocessor &PP);

  /// ArgNeedsPreexpansion - If we can prove that the argument won't be affected
  /// by pre-expansion, return false.  Otherwise, conservatively return true.
  bool ArgNeedsPreexpansion(const Token *ArgTok, Preprocessor &PP) const;

  /// getUnexpArgument - Return a pointer to the first token of the unexpanded
  /// token list for the specified formal.
  ///
  const Token *getUnexpArgument(unsigned Arg) const;

  /// getArgLength - Given a pointer to an expanded or unexpanded argument,
  /// return the number of tokens, not counting the EOF, that make up the
  /// argument.
  static unsigned getArgLength(const Token *ArgPtr);

  /// getPreExpArgument - Return the pre-expanded form of the specified
  /// argument.
  const std::vector<Token> &
    getPreExpArgument(unsigned Arg, Preprocessor &PP);

  /// getStringifiedArgument - Compute, cache, and return the specified argument
  /// that has been 'stringified' as required by the # operator.
  const Token &getStringifiedArgument(unsigned ArgNo, Preprocessor &PP,
                                      SourceLocation ExpansionLocStart,
                                      SourceLocation ExpansionLocEnd);

  /// getNumMacroArguments - Return the number of arguments the invoked macro
  /// expects.
  unsigned getNumMacroArguments() const { return NumMacroArgs; }

  /// isVarargsElidedUse - Return true if this is a C99 style varargs macro
  /// invocation and there was no argument specified for the "..." argument.  If
  /// the argument was specified (even empty) or this isn't a C99 style varargs
  /// function, or if in strict mode and the C99 varargs macro had only a ...
  /// argument, this returns false.
  bool isVarargsElidedUse() const { return VarargsElided; }

  /// Returns true if the macro was defined with a variadic (ellipsis) parameter
  /// AND was invoked with at least one token supplied as a variadic argument
  /// (after pre-expansion).
  ///
  /// \code
  ///   #define F(a)  a
  ///   #define V(a, ...) __VA_OPT__(a)
  ///   F()     <-- returns false on this invocation.
  ///   V(,a)   <-- returns true on this invocation.
  ///   V(,)    <-- returns false on this invocation.
  ///   V(,F()) <-- returns false on this invocation.
  /// \endcode
  ///
  bool invokedWithVariadicArgument(const MacroInfo *const MI, Preprocessor &PP);

  /// StringifyArgument - Implement C99 6.10.3.2p2, converting a sequence of
  /// tokens into the literal string token that should be produced by the C #
  /// preprocessor operator.  If Charify is true, then it should be turned into
  /// a character literal for the Microsoft charize (#@) extension.
  ///
  static Token StringifyArgument(const Token *ArgToks,
                                 Preprocessor &PP, bool Charify,
                                 SourceLocation ExpansionLocStart,
                                 SourceLocation ExpansionLocEnd);


  /// deallocate - This should only be called by the Preprocessor when managing
  /// its freelist.
  MacroArgs *deallocate();
};

}  // end namespace clang

#endif