1ec727ea7Spatrick //===--- VariantValue.cpp - Polymorphic value type --------------*- C++ -*-===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick ///
9e5dd7070Spatrick /// \file
10e5dd7070Spatrick /// Polymorphic value type.
11e5dd7070Spatrick ///
12e5dd7070Spatrick //===----------------------------------------------------------------------===//
13e5dd7070Spatrick
14e5dd7070Spatrick #include "clang/ASTMatchers/Dynamic/VariantValue.h"
15e5dd7070Spatrick #include "clang/Basic/LLVM.h"
16e5dd7070Spatrick #include "llvm/ADT/STLExtras.h"
17*12c85518Srobert #include <optional>
18e5dd7070Spatrick
19e5dd7070Spatrick namespace clang {
20e5dd7070Spatrick namespace ast_matchers {
21e5dd7070Spatrick namespace dynamic {
22e5dd7070Spatrick
asString() const23e5dd7070Spatrick std::string ArgKind::asString() const {
24e5dd7070Spatrick switch (getArgKind()) {
25e5dd7070Spatrick case AK_Matcher:
26a9ac8606Spatrick return (Twine("Matcher<") + NodeKind.asStringRef() + ">").str();
27a9ac8606Spatrick case AK_Node:
28a9ac8606Spatrick return NodeKind.asStringRef().str();
29e5dd7070Spatrick case AK_Boolean:
30e5dd7070Spatrick return "boolean";
31e5dd7070Spatrick case AK_Double:
32e5dd7070Spatrick return "double";
33e5dd7070Spatrick case AK_Unsigned:
34e5dd7070Spatrick return "unsigned";
35e5dd7070Spatrick case AK_String:
36e5dd7070Spatrick return "string";
37e5dd7070Spatrick }
38e5dd7070Spatrick llvm_unreachable("unhandled ArgKind");
39e5dd7070Spatrick }
40e5dd7070Spatrick
isConvertibleTo(ArgKind To,unsigned * Specificity) const41e5dd7070Spatrick bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
42e5dd7070Spatrick if (K != To.K)
43e5dd7070Spatrick return false;
44a9ac8606Spatrick if (K != AK_Matcher && K != AK_Node) {
45e5dd7070Spatrick if (Specificity)
46e5dd7070Spatrick *Specificity = 1;
47e5dd7070Spatrick return true;
48e5dd7070Spatrick }
49e5dd7070Spatrick unsigned Distance;
50a9ac8606Spatrick if (!NodeKind.isBaseOf(To.NodeKind, &Distance))
51e5dd7070Spatrick return false;
52e5dd7070Spatrick
53e5dd7070Spatrick if (Specificity)
54e5dd7070Spatrick *Specificity = 100 - Distance;
55e5dd7070Spatrick return true;
56e5dd7070Spatrick }
57e5dd7070Spatrick
58e5dd7070Spatrick bool
canConstructFrom(const DynTypedMatcher & Matcher,bool & IsExactMatch) const59e5dd7070Spatrick VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
60e5dd7070Spatrick bool &IsExactMatch) const {
61e5dd7070Spatrick IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
62e5dd7070Spatrick return Matcher.canConvertTo(NodeKind);
63e5dd7070Spatrick }
64e5dd7070Spatrick
convertMatcher(const DynTypedMatcher & Matcher) const65a9ac8606Spatrick DynTypedMatcher VariantMatcher::MatcherOps::convertMatcher(
66a9ac8606Spatrick const DynTypedMatcher &Matcher) const {
67a9ac8606Spatrick return Matcher.dynCastTo(NodeKind);
68a9ac8606Spatrick }
69a9ac8606Spatrick
70*12c85518Srobert std::optional<DynTypedMatcher>
constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,ArrayRef<VariantMatcher> InnerMatchers) const71e5dd7070Spatrick VariantMatcher::MatcherOps::constructVariadicOperator(
72e5dd7070Spatrick DynTypedMatcher::VariadicOperator Op,
73e5dd7070Spatrick ArrayRef<VariantMatcher> InnerMatchers) const {
74e5dd7070Spatrick std::vector<DynTypedMatcher> DynMatchers;
75e5dd7070Spatrick for (const auto &InnerMatcher : InnerMatchers) {
76e5dd7070Spatrick // Abort if any of the inner matchers can't be converted to
77e5dd7070Spatrick // Matcher<T>.
78e5dd7070Spatrick if (!InnerMatcher.Value)
79*12c85518Srobert return std::nullopt;
80*12c85518Srobert std::optional<DynTypedMatcher> Inner =
81e5dd7070Spatrick InnerMatcher.Value->getTypedMatcher(*this);
82e5dd7070Spatrick if (!Inner)
83*12c85518Srobert return std::nullopt;
84e5dd7070Spatrick DynMatchers.push_back(*Inner);
85e5dd7070Spatrick }
86e5dd7070Spatrick return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
87e5dd7070Spatrick }
88e5dd7070Spatrick
~Payload()89e5dd7070Spatrick VariantMatcher::Payload::~Payload() {}
90e5dd7070Spatrick
91e5dd7070Spatrick class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
92e5dd7070Spatrick public:
SinglePayload(const DynTypedMatcher & Matcher)93e5dd7070Spatrick SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
94e5dd7070Spatrick
getSingleMatcher() const95*12c85518Srobert std::optional<DynTypedMatcher> getSingleMatcher() const override {
96e5dd7070Spatrick return Matcher;
97e5dd7070Spatrick }
98e5dd7070Spatrick
getTypeAsString() const99e5dd7070Spatrick std::string getTypeAsString() const override {
100e5dd7070Spatrick return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
101e5dd7070Spatrick .str();
102e5dd7070Spatrick }
103e5dd7070Spatrick
104*12c85518Srobert std::optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const105e5dd7070Spatrick getTypedMatcher(const MatcherOps &Ops) const override {
106e5dd7070Spatrick bool Ignore;
107e5dd7070Spatrick if (Ops.canConstructFrom(Matcher, Ignore))
108e5dd7070Spatrick return Matcher;
109*12c85518Srobert return std::nullopt;
110e5dd7070Spatrick }
111e5dd7070Spatrick
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const112ec727ea7Spatrick bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
113a9ac8606Spatrick return ArgKind::MakeMatcherArg(Matcher.getSupportedKind())
114a9ac8606Spatrick .isConvertibleTo(ArgKind::MakeMatcherArg(Kind), Specificity);
115e5dd7070Spatrick }
116e5dd7070Spatrick
117e5dd7070Spatrick private:
118e5dd7070Spatrick const DynTypedMatcher Matcher;
119e5dd7070Spatrick };
120e5dd7070Spatrick
121e5dd7070Spatrick class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
122e5dd7070Spatrick public:
PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)123e5dd7070Spatrick PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
124e5dd7070Spatrick : Matchers(std::move(MatchersIn)) {}
125e5dd7070Spatrick
~PolymorphicPayload()126e5dd7070Spatrick ~PolymorphicPayload() override {}
127e5dd7070Spatrick
getSingleMatcher() const128*12c85518Srobert std::optional<DynTypedMatcher> getSingleMatcher() const override {
129e5dd7070Spatrick if (Matchers.size() != 1)
130*12c85518Srobert return std::nullopt;
131e5dd7070Spatrick return Matchers[0];
132e5dd7070Spatrick }
133e5dd7070Spatrick
getTypeAsString() const134e5dd7070Spatrick std::string getTypeAsString() const override {
135e5dd7070Spatrick std::string Inner;
136e5dd7070Spatrick for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
137e5dd7070Spatrick if (i != 0)
138e5dd7070Spatrick Inner += "|";
139e5dd7070Spatrick Inner += Matchers[i].getSupportedKind().asStringRef();
140e5dd7070Spatrick }
141e5dd7070Spatrick return (Twine("Matcher<") + Inner + ">").str();
142e5dd7070Spatrick }
143e5dd7070Spatrick
144*12c85518Srobert std::optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const145e5dd7070Spatrick getTypedMatcher(const MatcherOps &Ops) const override {
146e5dd7070Spatrick bool FoundIsExact = false;
147e5dd7070Spatrick const DynTypedMatcher *Found = nullptr;
148e5dd7070Spatrick int NumFound = 0;
149e5dd7070Spatrick for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
150e5dd7070Spatrick bool IsExactMatch;
151e5dd7070Spatrick if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
152e5dd7070Spatrick if (Found) {
153e5dd7070Spatrick if (FoundIsExact) {
154e5dd7070Spatrick assert(!IsExactMatch && "We should not have two exact matches.");
155e5dd7070Spatrick continue;
156e5dd7070Spatrick }
157e5dd7070Spatrick }
158e5dd7070Spatrick Found = &Matchers[i];
159e5dd7070Spatrick FoundIsExact = IsExactMatch;
160e5dd7070Spatrick ++NumFound;
161e5dd7070Spatrick }
162e5dd7070Spatrick }
163e5dd7070Spatrick // We only succeed if we found exactly one, or if we found an exact match.
164e5dd7070Spatrick if (Found && (FoundIsExact || NumFound == 1))
165e5dd7070Spatrick return *Found;
166*12c85518Srobert return std::nullopt;
167e5dd7070Spatrick }
168e5dd7070Spatrick
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const169ec727ea7Spatrick bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
170e5dd7070Spatrick unsigned MaxSpecificity = 0;
171e5dd7070Spatrick for (const DynTypedMatcher &Matcher : Matchers) {
172e5dd7070Spatrick unsigned ThisSpecificity;
173a9ac8606Spatrick if (ArgKind::MakeMatcherArg(Matcher.getSupportedKind())
174a9ac8606Spatrick .isConvertibleTo(ArgKind::MakeMatcherArg(Kind),
175a9ac8606Spatrick &ThisSpecificity)) {
176e5dd7070Spatrick MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
177e5dd7070Spatrick }
178e5dd7070Spatrick }
179e5dd7070Spatrick if (Specificity)
180e5dd7070Spatrick *Specificity = MaxSpecificity;
181e5dd7070Spatrick return MaxSpecificity > 0;
182e5dd7070Spatrick }
183e5dd7070Spatrick
184e5dd7070Spatrick const std::vector<DynTypedMatcher> Matchers;
185e5dd7070Spatrick };
186e5dd7070Spatrick
187e5dd7070Spatrick class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
188e5dd7070Spatrick public:
VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)189e5dd7070Spatrick VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
190e5dd7070Spatrick std::vector<VariantMatcher> Args)
191e5dd7070Spatrick : Op(Op), Args(std::move(Args)) {}
192e5dd7070Spatrick
getSingleMatcher() const193*12c85518Srobert std::optional<DynTypedMatcher> getSingleMatcher() const override {
194*12c85518Srobert return std::nullopt;
195e5dd7070Spatrick }
196e5dd7070Spatrick
getTypeAsString() const197e5dd7070Spatrick std::string getTypeAsString() const override {
198e5dd7070Spatrick std::string Inner;
199e5dd7070Spatrick for (size_t i = 0, e = Args.size(); i != e; ++i) {
200e5dd7070Spatrick if (i != 0)
201e5dd7070Spatrick Inner += "&";
202e5dd7070Spatrick Inner += Args[i].getTypeAsString();
203e5dd7070Spatrick }
204e5dd7070Spatrick return Inner;
205e5dd7070Spatrick }
206e5dd7070Spatrick
207*12c85518Srobert std::optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const208e5dd7070Spatrick getTypedMatcher(const MatcherOps &Ops) const override {
209e5dd7070Spatrick return Ops.constructVariadicOperator(Op, Args);
210e5dd7070Spatrick }
211e5dd7070Spatrick
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const212ec727ea7Spatrick bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
213e5dd7070Spatrick for (const VariantMatcher &Matcher : Args) {
214e5dd7070Spatrick if (!Matcher.isConvertibleTo(Kind, Specificity))
215e5dd7070Spatrick return false;
216e5dd7070Spatrick }
217e5dd7070Spatrick return true;
218e5dd7070Spatrick }
219e5dd7070Spatrick
220e5dd7070Spatrick private:
221e5dd7070Spatrick const DynTypedMatcher::VariadicOperator Op;
222e5dd7070Spatrick const std::vector<VariantMatcher> Args;
223e5dd7070Spatrick };
224e5dd7070Spatrick
VariantMatcher()225e5dd7070Spatrick VariantMatcher::VariantMatcher() {}
226e5dd7070Spatrick
SingleMatcher(const DynTypedMatcher & Matcher)227e5dd7070Spatrick VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
228e5dd7070Spatrick return VariantMatcher(std::make_shared<SinglePayload>(Matcher));
229e5dd7070Spatrick }
230e5dd7070Spatrick
231e5dd7070Spatrick VariantMatcher
PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers)232e5dd7070Spatrick VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
233e5dd7070Spatrick return VariantMatcher(
234e5dd7070Spatrick std::make_shared<PolymorphicPayload>(std::move(Matchers)));
235e5dd7070Spatrick }
236e5dd7070Spatrick
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)237e5dd7070Spatrick VariantMatcher VariantMatcher::VariadicOperatorMatcher(
238e5dd7070Spatrick DynTypedMatcher::VariadicOperator Op,
239e5dd7070Spatrick std::vector<VariantMatcher> Args) {
240e5dd7070Spatrick return VariantMatcher(
241e5dd7070Spatrick std::make_shared<VariadicOpPayload>(Op, std::move(Args)));
242e5dd7070Spatrick }
243e5dd7070Spatrick
getSingleMatcher() const244*12c85518Srobert std::optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
245*12c85518Srobert return Value ? Value->getSingleMatcher() : std::optional<DynTypedMatcher>();
246e5dd7070Spatrick }
247e5dd7070Spatrick
reset()248e5dd7070Spatrick void VariantMatcher::reset() { Value.reset(); }
249e5dd7070Spatrick
getTypeAsString() const250e5dd7070Spatrick std::string VariantMatcher::getTypeAsString() const {
251e5dd7070Spatrick if (Value) return Value->getTypeAsString();
252e5dd7070Spatrick return "<Nothing>";
253e5dd7070Spatrick }
254e5dd7070Spatrick
VariantValue(const VariantValue & Other)255e5dd7070Spatrick VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
256e5dd7070Spatrick *this = Other;
257e5dd7070Spatrick }
258e5dd7070Spatrick
VariantValue(bool Boolean)259e5dd7070Spatrick VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
260e5dd7070Spatrick setBoolean(Boolean);
261e5dd7070Spatrick }
262e5dd7070Spatrick
VariantValue(double Double)263e5dd7070Spatrick VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
264e5dd7070Spatrick setDouble(Double);
265e5dd7070Spatrick }
266e5dd7070Spatrick
VariantValue(unsigned Unsigned)267e5dd7070Spatrick VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
268e5dd7070Spatrick setUnsigned(Unsigned);
269e5dd7070Spatrick }
270e5dd7070Spatrick
VariantValue(StringRef String)271e5dd7070Spatrick VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
272e5dd7070Spatrick setString(String);
273e5dd7070Spatrick }
274e5dd7070Spatrick
VariantValue(ASTNodeKind NodeKind)275a9ac8606Spatrick VariantValue::VariantValue(ASTNodeKind NodeKind) : Type(VT_Nothing) {
276a9ac8606Spatrick setNodeKind(NodeKind);
277a9ac8606Spatrick }
278a9ac8606Spatrick
VariantValue(const VariantMatcher & Matcher)279e5dd7070Spatrick VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
280e5dd7070Spatrick setMatcher(Matcher);
281e5dd7070Spatrick }
282e5dd7070Spatrick
~VariantValue()283e5dd7070Spatrick VariantValue::~VariantValue() { reset(); }
284e5dd7070Spatrick
operator =(const VariantValue & Other)285e5dd7070Spatrick VariantValue &VariantValue::operator=(const VariantValue &Other) {
286e5dd7070Spatrick if (this == &Other) return *this;
287e5dd7070Spatrick reset();
288e5dd7070Spatrick switch (Other.Type) {
289e5dd7070Spatrick case VT_Boolean:
290e5dd7070Spatrick setBoolean(Other.getBoolean());
291e5dd7070Spatrick break;
292e5dd7070Spatrick case VT_Double:
293e5dd7070Spatrick setDouble(Other.getDouble());
294e5dd7070Spatrick break;
295e5dd7070Spatrick case VT_Unsigned:
296e5dd7070Spatrick setUnsigned(Other.getUnsigned());
297e5dd7070Spatrick break;
298e5dd7070Spatrick case VT_String:
299e5dd7070Spatrick setString(Other.getString());
300e5dd7070Spatrick break;
301a9ac8606Spatrick case VT_NodeKind:
302a9ac8606Spatrick setNodeKind(Other.getNodeKind());
303a9ac8606Spatrick break;
304e5dd7070Spatrick case VT_Matcher:
305e5dd7070Spatrick setMatcher(Other.getMatcher());
306e5dd7070Spatrick break;
307e5dd7070Spatrick case VT_Nothing:
308e5dd7070Spatrick Type = VT_Nothing;
309e5dd7070Spatrick break;
310e5dd7070Spatrick }
311e5dd7070Spatrick return *this;
312e5dd7070Spatrick }
313e5dd7070Spatrick
reset()314e5dd7070Spatrick void VariantValue::reset() {
315e5dd7070Spatrick switch (Type) {
316e5dd7070Spatrick case VT_String:
317e5dd7070Spatrick delete Value.String;
318e5dd7070Spatrick break;
319e5dd7070Spatrick case VT_Matcher:
320e5dd7070Spatrick delete Value.Matcher;
321e5dd7070Spatrick break;
322a9ac8606Spatrick case VT_NodeKind:
323a9ac8606Spatrick delete Value.NodeKind;
324a9ac8606Spatrick break;
325e5dd7070Spatrick // Cases that do nothing.
326e5dd7070Spatrick case VT_Boolean:
327e5dd7070Spatrick case VT_Double:
328e5dd7070Spatrick case VT_Unsigned:
329e5dd7070Spatrick case VT_Nothing:
330e5dd7070Spatrick break;
331e5dd7070Spatrick }
332e5dd7070Spatrick Type = VT_Nothing;
333e5dd7070Spatrick }
334e5dd7070Spatrick
isBoolean() const335e5dd7070Spatrick bool VariantValue::isBoolean() const {
336e5dd7070Spatrick return Type == VT_Boolean;
337e5dd7070Spatrick }
338e5dd7070Spatrick
getBoolean() const339e5dd7070Spatrick bool VariantValue::getBoolean() const {
340e5dd7070Spatrick assert(isBoolean());
341e5dd7070Spatrick return Value.Boolean;
342e5dd7070Spatrick }
343e5dd7070Spatrick
setBoolean(bool NewValue)344e5dd7070Spatrick void VariantValue::setBoolean(bool NewValue) {
345e5dd7070Spatrick reset();
346e5dd7070Spatrick Type = VT_Boolean;
347e5dd7070Spatrick Value.Boolean = NewValue;
348e5dd7070Spatrick }
349e5dd7070Spatrick
isDouble() const350e5dd7070Spatrick bool VariantValue::isDouble() const {
351e5dd7070Spatrick return Type == VT_Double;
352e5dd7070Spatrick }
353e5dd7070Spatrick
getDouble() const354e5dd7070Spatrick double VariantValue::getDouble() const {
355e5dd7070Spatrick assert(isDouble());
356e5dd7070Spatrick return Value.Double;
357e5dd7070Spatrick }
358e5dd7070Spatrick
setDouble(double NewValue)359e5dd7070Spatrick void VariantValue::setDouble(double NewValue) {
360e5dd7070Spatrick reset();
361e5dd7070Spatrick Type = VT_Double;
362e5dd7070Spatrick Value.Double = NewValue;
363e5dd7070Spatrick }
364e5dd7070Spatrick
isUnsigned() const365e5dd7070Spatrick bool VariantValue::isUnsigned() const {
366e5dd7070Spatrick return Type == VT_Unsigned;
367e5dd7070Spatrick }
368e5dd7070Spatrick
getUnsigned() const369e5dd7070Spatrick unsigned VariantValue::getUnsigned() const {
370e5dd7070Spatrick assert(isUnsigned());
371e5dd7070Spatrick return Value.Unsigned;
372e5dd7070Spatrick }
373e5dd7070Spatrick
setUnsigned(unsigned NewValue)374e5dd7070Spatrick void VariantValue::setUnsigned(unsigned NewValue) {
375e5dd7070Spatrick reset();
376e5dd7070Spatrick Type = VT_Unsigned;
377e5dd7070Spatrick Value.Unsigned = NewValue;
378e5dd7070Spatrick }
379e5dd7070Spatrick
isString() const380e5dd7070Spatrick bool VariantValue::isString() const {
381e5dd7070Spatrick return Type == VT_String;
382e5dd7070Spatrick }
383e5dd7070Spatrick
getString() const384e5dd7070Spatrick const std::string &VariantValue::getString() const {
385e5dd7070Spatrick assert(isString());
386e5dd7070Spatrick return *Value.String;
387e5dd7070Spatrick }
388e5dd7070Spatrick
setString(StringRef NewValue)389e5dd7070Spatrick void VariantValue::setString(StringRef NewValue) {
390e5dd7070Spatrick reset();
391e5dd7070Spatrick Type = VT_String;
392e5dd7070Spatrick Value.String = new std::string(NewValue);
393e5dd7070Spatrick }
394e5dd7070Spatrick
isNodeKind() const395a9ac8606Spatrick bool VariantValue::isNodeKind() const { return Type == VT_NodeKind; }
396a9ac8606Spatrick
getNodeKind() const397a9ac8606Spatrick const ASTNodeKind &VariantValue::getNodeKind() const {
398a9ac8606Spatrick assert(isNodeKind());
399a9ac8606Spatrick return *Value.NodeKind;
400a9ac8606Spatrick }
401a9ac8606Spatrick
setNodeKind(ASTNodeKind NewValue)402a9ac8606Spatrick void VariantValue::setNodeKind(ASTNodeKind NewValue) {
403a9ac8606Spatrick reset();
404a9ac8606Spatrick Type = VT_NodeKind;
405a9ac8606Spatrick Value.NodeKind = new ASTNodeKind(NewValue);
406a9ac8606Spatrick }
407a9ac8606Spatrick
isMatcher() const408e5dd7070Spatrick bool VariantValue::isMatcher() const {
409e5dd7070Spatrick return Type == VT_Matcher;
410e5dd7070Spatrick }
411e5dd7070Spatrick
getMatcher() const412e5dd7070Spatrick const VariantMatcher &VariantValue::getMatcher() const {
413e5dd7070Spatrick assert(isMatcher());
414e5dd7070Spatrick return *Value.Matcher;
415e5dd7070Spatrick }
416e5dd7070Spatrick
setMatcher(const VariantMatcher & NewValue)417e5dd7070Spatrick void VariantValue::setMatcher(const VariantMatcher &NewValue) {
418e5dd7070Spatrick reset();
419e5dd7070Spatrick Type = VT_Matcher;
420e5dd7070Spatrick Value.Matcher = new VariantMatcher(NewValue);
421e5dd7070Spatrick }
422e5dd7070Spatrick
isConvertibleTo(ArgKind Kind,unsigned * Specificity) const423e5dd7070Spatrick bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
424e5dd7070Spatrick switch (Kind.getArgKind()) {
425e5dd7070Spatrick case ArgKind::AK_Boolean:
426e5dd7070Spatrick if (!isBoolean())
427e5dd7070Spatrick return false;
428e5dd7070Spatrick *Specificity = 1;
429e5dd7070Spatrick return true;
430e5dd7070Spatrick
431e5dd7070Spatrick case ArgKind::AK_Double:
432e5dd7070Spatrick if (!isDouble())
433e5dd7070Spatrick return false;
434e5dd7070Spatrick *Specificity = 1;
435e5dd7070Spatrick return true;
436e5dd7070Spatrick
437e5dd7070Spatrick case ArgKind::AK_Unsigned:
438e5dd7070Spatrick if (!isUnsigned())
439e5dd7070Spatrick return false;
440e5dd7070Spatrick *Specificity = 1;
441e5dd7070Spatrick return true;
442e5dd7070Spatrick
443e5dd7070Spatrick case ArgKind::AK_String:
444e5dd7070Spatrick if (!isString())
445e5dd7070Spatrick return false;
446e5dd7070Spatrick *Specificity = 1;
447e5dd7070Spatrick return true;
448e5dd7070Spatrick
449a9ac8606Spatrick case ArgKind::AK_Node:
450a9ac8606Spatrick if (!isNodeKind())
451a9ac8606Spatrick return false;
452a9ac8606Spatrick return getMatcher().isConvertibleTo(Kind.getNodeKind(), Specificity);
453a9ac8606Spatrick
454e5dd7070Spatrick case ArgKind::AK_Matcher:
455e5dd7070Spatrick if (!isMatcher())
456e5dd7070Spatrick return false;
457e5dd7070Spatrick return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
458e5dd7070Spatrick }
459e5dd7070Spatrick llvm_unreachable("Invalid Type");
460e5dd7070Spatrick }
461e5dd7070Spatrick
isConvertibleTo(ArrayRef<ArgKind> Kinds,unsigned * Specificity) const462e5dd7070Spatrick bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
463e5dd7070Spatrick unsigned *Specificity) const {
464e5dd7070Spatrick unsigned MaxSpecificity = 0;
465e5dd7070Spatrick for (const ArgKind& Kind : Kinds) {
466e5dd7070Spatrick unsigned ThisSpecificity;
467e5dd7070Spatrick if (!isConvertibleTo(Kind, &ThisSpecificity))
468e5dd7070Spatrick continue;
469e5dd7070Spatrick MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
470e5dd7070Spatrick }
471e5dd7070Spatrick if (Specificity && MaxSpecificity > 0) {
472e5dd7070Spatrick *Specificity = MaxSpecificity;
473e5dd7070Spatrick }
474e5dd7070Spatrick return MaxSpecificity > 0;
475e5dd7070Spatrick }
476e5dd7070Spatrick
getTypeAsString() const477e5dd7070Spatrick std::string VariantValue::getTypeAsString() const {
478e5dd7070Spatrick switch (Type) {
479e5dd7070Spatrick case VT_String: return "String";
480e5dd7070Spatrick case VT_Matcher: return getMatcher().getTypeAsString();
481e5dd7070Spatrick case VT_Boolean: return "Boolean";
482e5dd7070Spatrick case VT_Double: return "Double";
483e5dd7070Spatrick case VT_Unsigned: return "Unsigned";
484a9ac8606Spatrick case VT_NodeKind:
485a9ac8606Spatrick return getNodeKind().asStringRef().str();
486e5dd7070Spatrick case VT_Nothing: return "Nothing";
487e5dd7070Spatrick }
488e5dd7070Spatrick llvm_unreachable("Invalid Type");
489e5dd7070Spatrick }
490e5dd7070Spatrick
491e5dd7070Spatrick } // end namespace dynamic
492e5dd7070Spatrick } // end namespace ast_matchers
493e5dd7070Spatrick } // end namespace clang
494