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
//===--- VariantValue.h - Polymorphic value type ----------------*- 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
/// \file
10
/// Polymorphic value type.
11
///
12
/// Supports all the types required for dynamic Matcher construction.
13
///  Used by the registry to construct matchers in a generic way.
14
///
15
//===----------------------------------------------------------------------===//
16
 
17
#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
18
#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
19
 
20
#include "clang/ASTMatchers/ASTMatchers.h"
21
#include "clang/ASTMatchers/ASTMatchersInternal.h"
22
#include "llvm/ADT/IntrusiveRefCntPtr.h"
23
#include <memory>
24
#include <optional>
25
#include <vector>
26
 
27
namespace clang {
28
namespace ast_matchers {
29
namespace dynamic {
30
 
31
/// Kind identifier.
32
///
33
/// It supports all types that VariantValue can contain.
34
class ArgKind {
35
 public:
36
  enum Kind {
37
    AK_Matcher,
38
    AK_Node,
39
    AK_Boolean,
40
    AK_Double,
41
    AK_Unsigned,
42
    AK_String
43
  };
44
  /// Constructor for non-matcher types.
45
  ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
46
 
47
  /// Constructor for matcher types.
48
  static ArgKind MakeMatcherArg(ASTNodeKind MatcherKind) {
49
    return ArgKind{AK_Matcher, MatcherKind};
50
  }
51
 
52
  static ArgKind MakeNodeArg(ASTNodeKind MatcherKind) {
53
    return ArgKind{AK_Node, MatcherKind};
54
  }
55
 
56
  Kind getArgKind() const { return K; }
57
  ASTNodeKind getMatcherKind() const {
58
    assert(K == AK_Matcher);
59
    return NodeKind;
60
  }
61
  ASTNodeKind getNodeKind() const {
62
    assert(K == AK_Node);
63
    return NodeKind;
64
  }
65
 
66
  /// Determines if this type can be converted to \p To.
67
  ///
68
  /// \param To the requested destination type.
69
  ///
70
  /// \param Specificity value corresponding to the "specificity" of the
71
  ///   conversion.
72
  bool isConvertibleTo(ArgKind To, unsigned *Specificity) const;
73
 
74
  bool operator<(const ArgKind &Other) const {
75
    if ((K == AK_Matcher && Other.K == AK_Matcher) ||
76
        (K == AK_Node && Other.K == AK_Node))
77
      return NodeKind < Other.NodeKind;
78
    return K < Other.K;
79
  }
80
 
81
  /// String representation of the type.
82
  std::string asString() const;
83
 
84
private:
85
  ArgKind(Kind K, ASTNodeKind NK) : K(K), NodeKind(NK) {}
86
  Kind K;
87
  ASTNodeKind NodeKind;
88
};
89
 
90
using ast_matchers::internal::DynTypedMatcher;
91
 
92
/// A variant matcher object.
93
///
94
/// The purpose of this object is to abstract simple and polymorphic matchers
95
/// into a single object type.
96
/// Polymorphic matchers might be implemented as a list of all the possible
97
/// overloads of the matcher. \c VariantMatcher knows how to select the
98
/// appropriate overload when needed.
99
/// To get a real matcher object out of a \c VariantMatcher you can do:
100
///  - getSingleMatcher() which returns a matcher, only if it is not ambiguous
101
///    to decide which matcher to return. Eg. it contains only a single
102
///    matcher, or a polymorphic one with only one overload.
103
///  - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if
104
///    the underlying matcher(s) can unambiguously return a Matcher<T>.
105
class VariantMatcher {
106
  /// Methods that depend on T from hasTypedMatcher/getTypedMatcher.
107
  class MatcherOps {
108
  public:
109
    MatcherOps(ASTNodeKind NodeKind) : NodeKind(NodeKind) {}
110
 
111
    bool canConstructFrom(const DynTypedMatcher &Matcher,
112
                          bool &IsExactMatch) const;
113
 
114
    /// Convert \p Matcher the destination type and return it as a new
115
    /// DynTypedMatcher.
116
    DynTypedMatcher convertMatcher(const DynTypedMatcher &Matcher) const;
117
 
118
    /// Constructs a variadic typed matcher from \p InnerMatchers.
119
    /// Will try to convert each inner matcher to the destination type and
120
    /// return std::nullopt if it fails to do so.
121
    std::optional<DynTypedMatcher>
122
    constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,
123
                              ArrayRef<VariantMatcher> InnerMatchers) const;
124
 
125
  private:
126
    ASTNodeKind NodeKind;
127
  };
128
 
129
  /// Payload interface to be specialized by each matcher type.
130
  ///
131
  /// It follows a similar interface as VariantMatcher itself.
132
  class Payload {
133
  public:
134
    virtual ~Payload();
135
    virtual std::optional<DynTypedMatcher> getSingleMatcher() const = 0;
136
    virtual std::string getTypeAsString() const = 0;
137
    virtual std::optional<DynTypedMatcher>
138
    getTypedMatcher(const MatcherOps &Ops) const = 0;
139
    virtual bool isConvertibleTo(ASTNodeKind Kind,
140
                                 unsigned *Specificity) const = 0;
141
  };
142
 
143
public:
144
  /// A null matcher.
145
  VariantMatcher();
146
 
147
  /// Clones the provided matcher.
148
  static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
149
 
150
  /// Clones the provided matchers.
151
  ///
152
  /// They should be the result of a polymorphic matcher.
153
  static VariantMatcher
154
  PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers);
155
 
156
  /// Creates a 'variadic' operator matcher.
157
  ///
158
  /// It will bind to the appropriate type on getTypedMatcher<T>().
159
  static VariantMatcher
160
  VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
161
                          std::vector<VariantMatcher> Args);
162
 
163
  /// Makes the matcher the "null" matcher.
164
  void reset();
165
 
166
  /// Whether the matcher is null.
167
  bool isNull() const { return !Value; }
168
 
169
  /// Return a single matcher, if there is no ambiguity.
170
  ///
171
  /// \returns the matcher, if there is only one matcher. An empty Optional, if
172
  /// the underlying matcher is a polymorphic matcher with more than one
173
  /// representation.
174
  std::optional<DynTypedMatcher> getSingleMatcher() const;
175
 
176
  /// Determines if the contained matcher can be converted to
177
  ///   \c Matcher<T>.
178
  ///
179
  /// For the Single case, it returns true if it can be converted to
180
  /// \c Matcher<T>.
181
  /// For the Polymorphic case, it returns true if one, and only one, of the
182
  /// overloads can be converted to \c Matcher<T>. If there are more than one
183
  /// that can, the result would be ambiguous and false is returned.
184
  template <class T>
185
  bool hasTypedMatcher() const {
186
    return hasTypedMatcher(ASTNodeKind::getFromNodeKind<T>());
187
  }
188
 
189
  bool hasTypedMatcher(ASTNodeKind NK) const {
190
    if (!Value) return false;
191
    return Value->getTypedMatcher(MatcherOps(NK)).has_value();
192
  }
193
 
194
  /// Determines if the contained matcher can be converted to \p Kind.
195
  ///
196
  /// \param Kind the requested destination type.
197
  ///
198
  /// \param Specificity value corresponding to the "specificity" of the
199
  ///   conversion.
200
  bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const {
201
    if (Value)
202
      return Value->isConvertibleTo(Kind, Specificity);
203
    return false;
204
  }
205
 
206
  /// Return this matcher as a \c Matcher<T>.
207
  ///
208
  /// Handles the different types (Single, Polymorphic) accordingly.
209
  /// Asserts that \c hasTypedMatcher<T>() is true.
210
  template <class T>
211
  ast_matchers::internal::Matcher<T> getTypedMatcher() const {
212
    assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false");
213
    return Value->getTypedMatcher(MatcherOps(ASTNodeKind::getFromNodeKind<T>()))
214
        ->template convertTo<T>();
215
  }
216
 
217
  DynTypedMatcher getTypedMatcher(ASTNodeKind NK) const {
218
    assert(hasTypedMatcher(NK) && "hasTypedMatcher(NK) == false");
219
    return *Value->getTypedMatcher(MatcherOps(NK));
220
  }
221
 
222
  /// String representation of the type of the value.
223
  ///
224
  /// If the underlying matcher is a polymorphic one, the string will show all
225
  /// the types.
226
  std::string getTypeAsString() const;
227
 
228
private:
229
  explicit VariantMatcher(std::shared_ptr<Payload> Value)
230
      : Value(std::move(Value)) {}
231
 
232
 
233
  class SinglePayload;
234
  class PolymorphicPayload;
235
  class VariadicOpPayload;
236
 
237
  std::shared_ptr<const Payload> Value;
238
};
239
 
240
/// Variant value class.
241
///
242
/// Basically, a tagged union with value type semantics.
243
/// It is used by the registry as the return value and argument type for the
244
/// matcher factory methods.
245
/// It can be constructed from any of the supported types. It supports
246
/// copy/assignment.
247
///
248
/// Supported types:
249
///  - \c bool
250
//   - \c double
251
///  - \c unsigned
252
///  - \c llvm::StringRef
253
///  - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
254
class VariantValue {
255
public:
256
  VariantValue() : Type(VT_Nothing) {}
257
 
258
  VariantValue(const VariantValue &Other);
259
  ~VariantValue();
260
  VariantValue &operator=(const VariantValue &Other);
261
 
262
  /// Specific constructors for each supported type.
263
  VariantValue(bool Boolean);
264
  VariantValue(double Double);
265
  VariantValue(unsigned Unsigned);
266
  VariantValue(StringRef String);
267
  VariantValue(ASTNodeKind NodeKind);
268
  VariantValue(const VariantMatcher &Matchers);
269
 
270
  /// Constructs an \c unsigned value (disambiguation from bool).
271
  VariantValue(int Signed) : VariantValue(static_cast<unsigned>(Signed)) {}
272
 
273
  /// Returns true iff this is not an empty value.
274
  explicit operator bool() const { return hasValue(); }
275
  bool hasValue() const { return Type != VT_Nothing; }
276
 
277
  /// Boolean value functions.
278
  bool isBoolean() const;
279
  bool getBoolean() const;
280
  void setBoolean(bool Boolean);
281
 
282
  /// Double value functions.
283
  bool isDouble() const;
284
  double getDouble() const;
285
  void setDouble(double Double);
286
 
287
  /// Unsigned value functions.
288
  bool isUnsigned() const;
289
  unsigned getUnsigned() const;
290
  void setUnsigned(unsigned Unsigned);
291
 
292
  /// String value functions.
293
  bool isString() const;
294
  const std::string &getString() const;
295
  void setString(StringRef String);
296
 
297
  bool isNodeKind() const;
298
  const ASTNodeKind &getNodeKind() const;
299
  void setNodeKind(ASTNodeKind NodeKind);
300
 
301
  /// Matcher value functions.
302
  bool isMatcher() const;
303
  const VariantMatcher &getMatcher() const;
304
  void setMatcher(const VariantMatcher &Matcher);
305
 
306
  /// Determines if the contained value can be converted to \p Kind.
307
  ///
308
  /// \param Kind the requested destination type.
309
  ///
310
  /// \param Specificity value corresponding to the "specificity" of the
311
  ///   conversion.
312
  bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const;
313
 
314
  /// Determines if the contained value can be converted to any kind
315
  /// in \p Kinds.
316
  ///
317
  /// \param Kinds the requested destination types.
318
  ///
319
  /// \param Specificity value corresponding to the "specificity" of the
320
  ///   conversion. It is the maximum specificity of all the possible
321
  ///   conversions.
322
  bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const;
323
 
324
  /// String representation of the type of the value.
325
  std::string getTypeAsString() const;
326
 
327
private:
328
  void reset();
329
 
330
  /// All supported value types.
331
  enum ValueType {
332
    VT_Nothing,
333
    VT_Boolean,
334
    VT_Double,
335
    VT_Unsigned,
336
    VT_String,
337
    VT_Matcher,
338
    VT_NodeKind
339
  };
340
 
341
  /// All supported value types.
342
  union AllValues {
343
    unsigned Unsigned;
344
    double Double;
345
    bool Boolean;
346
    std::string *String;
347
    VariantMatcher *Matcher;
348
    ASTNodeKind *NodeKind;
349
  };
350
 
351
  ValueType Type;
352
  AllValues Value;
353
};
354
 
355
} // end namespace dynamic
356
} // end namespace ast_matchers
357
} // end namespace clang
358
 
359
#endif // LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H