15ffd83dbSDimitry Andric //===--- VariantValue.cpp - Polymorphic value type --------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// Polymorphic value type.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "clang/ASTMatchers/Dynamic/VariantValue.h"
150b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
160b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
17*bdd1243dSDimitry Andric #include <optional>
180b57cec5SDimitry Andric
190b57cec5SDimitry Andric namespace clang {
200b57cec5SDimitry Andric namespace ast_matchers {
210b57cec5SDimitry Andric namespace dynamic {
220b57cec5SDimitry Andric
asString() const230b57cec5SDimitry Andric std::string ArgKind::asString() const {
240b57cec5SDimitry Andric switch (getArgKind()) {
250b57cec5SDimitry Andric case AK_Matcher:
26fe6060f1SDimitry Andric return (Twine("Matcher<") + NodeKind.asStringRef() + ">").str();
27fe6060f1SDimitry Andric case AK_Node:
28fe6060f1SDimitry Andric return NodeKind.asStringRef().str();
290b57cec5SDimitry Andric case AK_Boolean:
300b57cec5SDimitry Andric return "boolean";
310b57cec5SDimitry Andric case AK_Double:
320b57cec5SDimitry Andric return "double";
330b57cec5SDimitry Andric case AK_Unsigned:
340b57cec5SDimitry Andric return "unsigned";
350b57cec5SDimitry Andric case AK_String:
360b57cec5SDimitry Andric return "string";
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric llvm_unreachable("unhandled ArgKind");
390b57cec5SDimitry Andric }
400b57cec5SDimitry Andric
isConvertibleTo(ArgKind To,unsigned * Specificity) const410b57cec5SDimitry Andric bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
420b57cec5SDimitry Andric if (K != To.K)
430b57cec5SDimitry Andric return false;
44fe6060f1SDimitry Andric if (K != AK_Matcher && K != AK_Node) {
450b57cec5SDimitry Andric if (Specificity)
460b57cec5SDimitry Andric *Specificity = 1;
470b57cec5SDimitry Andric return true;
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric unsigned Distance;
50fe6060f1SDimitry Andric if (!NodeKind.isBaseOf(To.NodeKind, &Distance))
510b57cec5SDimitry Andric return false;
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric if (Specificity)
540b57cec5SDimitry Andric *Specificity = 100 - Distance;
550b57cec5SDimitry Andric return true;
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric
580b57cec5SDimitry Andric bool
canConstructFrom(const DynTypedMatcher & Matcher,bool & IsExactMatch) const590b57cec5SDimitry Andric VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
600b57cec5SDimitry Andric bool &IsExactMatch) const {
610b57cec5SDimitry Andric IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
620b57cec5SDimitry Andric return Matcher.canConvertTo(NodeKind);
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric
convertMatcher(const DynTypedMatcher & Matcher) const65e8d8bef9SDimitry Andric DynTypedMatcher VariantMatcher::MatcherOps::convertMatcher(
66e8d8bef9SDimitry Andric const DynTypedMatcher &Matcher) const {
67e8d8bef9SDimitry Andric return Matcher.dynCastTo(NodeKind);
68e8d8bef9SDimitry Andric }
69e8d8bef9SDimitry Andric
70*bdd1243dSDimitry Andric std::optional<DynTypedMatcher>
constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,ArrayRef<VariantMatcher> InnerMatchers) const710b57cec5SDimitry Andric VariantMatcher::MatcherOps::constructVariadicOperator(
720b57cec5SDimitry Andric DynTypedMatcher::VariadicOperator Op,
730b57cec5SDimitry Andric ArrayRef<VariantMatcher> InnerMatchers) const {
740b57cec5SDimitry Andric std::vector<DynTypedMatcher> DynMatchers;
750b57cec5SDimitry Andric for (const auto &InnerMatcher : InnerMatchers) {
760b57cec5SDimitry Andric // Abort if any of the inner matchers can't be converted to
770b57cec5SDimitry Andric // Matcher<T>.
780b57cec5SDimitry Andric if (!InnerMatcher.Value)
79*bdd1243dSDimitry Andric return std::nullopt;
80*bdd1243dSDimitry Andric std::optional<DynTypedMatcher> Inner =
810b57cec5SDimitry Andric InnerMatcher.Value->getTypedMatcher(*this);
820b57cec5SDimitry Andric if (!Inner)
83*bdd1243dSDimitry Andric return std::nullopt;
840b57cec5SDimitry Andric DynMatchers.push_back(*Inner);
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric
~Payload()890b57cec5SDimitry Andric VariantMatcher::Payload::~Payload() {}
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
920b57cec5SDimitry Andric public:
SinglePayload(const DynTypedMatcher & Matcher)930b57cec5SDimitry Andric SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
940b57cec5SDimitry Andric
getSingleMatcher() const95*bdd1243dSDimitry Andric std::optional<DynTypedMatcher> getSingleMatcher() const override {
960b57cec5SDimitry Andric return Matcher;
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric
getTypeAsString() const990b57cec5SDimitry Andric std::string getTypeAsString() const override {
1000b57cec5SDimitry Andric return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
1010b57cec5SDimitry Andric .str();
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric
104*bdd1243dSDimitry Andric std::optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const1050b57cec5SDimitry Andric getTypedMatcher(const MatcherOps &Ops) const override {
1060b57cec5SDimitry Andric bool Ignore;
1070b57cec5SDimitry Andric if (Ops.canConstructFrom(Matcher, Ignore))
1080b57cec5SDimitry Andric return Matcher;
109*bdd1243dSDimitry Andric return std::nullopt;
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const1125ffd83dbSDimitry Andric bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
113fe6060f1SDimitry Andric return ArgKind::MakeMatcherArg(Matcher.getSupportedKind())
114fe6060f1SDimitry Andric .isConvertibleTo(ArgKind::MakeMatcherArg(Kind), Specificity);
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric
1170b57cec5SDimitry Andric private:
1180b57cec5SDimitry Andric const DynTypedMatcher Matcher;
1190b57cec5SDimitry Andric };
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
1220b57cec5SDimitry Andric public:
PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)1230b57cec5SDimitry Andric PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
1240b57cec5SDimitry Andric : Matchers(std::move(MatchersIn)) {}
1250b57cec5SDimitry Andric
~PolymorphicPayload()1260b57cec5SDimitry Andric ~PolymorphicPayload() override {}
1270b57cec5SDimitry Andric
getSingleMatcher() const128*bdd1243dSDimitry Andric std::optional<DynTypedMatcher> getSingleMatcher() const override {
1290b57cec5SDimitry Andric if (Matchers.size() != 1)
130*bdd1243dSDimitry Andric return std::nullopt;
1310b57cec5SDimitry Andric return Matchers[0];
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric
getTypeAsString() const1340b57cec5SDimitry Andric std::string getTypeAsString() const override {
1350b57cec5SDimitry Andric std::string Inner;
1360b57cec5SDimitry Andric for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
1370b57cec5SDimitry Andric if (i != 0)
1380b57cec5SDimitry Andric Inner += "|";
1390b57cec5SDimitry Andric Inner += Matchers[i].getSupportedKind().asStringRef();
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric return (Twine("Matcher<") + Inner + ">").str();
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric
144*bdd1243dSDimitry Andric std::optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const1450b57cec5SDimitry Andric getTypedMatcher(const MatcherOps &Ops) const override {
1460b57cec5SDimitry Andric bool FoundIsExact = false;
1470b57cec5SDimitry Andric const DynTypedMatcher *Found = nullptr;
1480b57cec5SDimitry Andric int NumFound = 0;
1490b57cec5SDimitry Andric for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
1500b57cec5SDimitry Andric bool IsExactMatch;
1510b57cec5SDimitry Andric if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
1520b57cec5SDimitry Andric if (Found) {
1530b57cec5SDimitry Andric if (FoundIsExact) {
1540b57cec5SDimitry Andric assert(!IsExactMatch && "We should not have two exact matches.");
1550b57cec5SDimitry Andric continue;
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric Found = &Matchers[i];
1590b57cec5SDimitry Andric FoundIsExact = IsExactMatch;
1600b57cec5SDimitry Andric ++NumFound;
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric // We only succeed if we found exactly one, or if we found an exact match.
1640b57cec5SDimitry Andric if (Found && (FoundIsExact || NumFound == 1))
1650b57cec5SDimitry Andric return *Found;
166*bdd1243dSDimitry Andric return std::nullopt;
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const1695ffd83dbSDimitry Andric bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
1700b57cec5SDimitry Andric unsigned MaxSpecificity = 0;
1710b57cec5SDimitry Andric for (const DynTypedMatcher &Matcher : Matchers) {
1720b57cec5SDimitry Andric unsigned ThisSpecificity;
173fe6060f1SDimitry Andric if (ArgKind::MakeMatcherArg(Matcher.getSupportedKind())
174fe6060f1SDimitry Andric .isConvertibleTo(ArgKind::MakeMatcherArg(Kind),
175fe6060f1SDimitry Andric &ThisSpecificity)) {
1760b57cec5SDimitry Andric MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric if (Specificity)
1800b57cec5SDimitry Andric *Specificity = MaxSpecificity;
1810b57cec5SDimitry Andric return MaxSpecificity > 0;
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric
1840b57cec5SDimitry Andric const std::vector<DynTypedMatcher> Matchers;
1850b57cec5SDimitry Andric };
1860b57cec5SDimitry Andric
1870b57cec5SDimitry Andric class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
1880b57cec5SDimitry Andric public:
VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)1890b57cec5SDimitry Andric VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
1900b57cec5SDimitry Andric std::vector<VariantMatcher> Args)
1910b57cec5SDimitry Andric : Op(Op), Args(std::move(Args)) {}
1920b57cec5SDimitry Andric
getSingleMatcher() const193*bdd1243dSDimitry Andric std::optional<DynTypedMatcher> getSingleMatcher() const override {
194*bdd1243dSDimitry Andric return std::nullopt;
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric
getTypeAsString() const1970b57cec5SDimitry Andric std::string getTypeAsString() const override {
1980b57cec5SDimitry Andric std::string Inner;
1990b57cec5SDimitry Andric for (size_t i = 0, e = Args.size(); i != e; ++i) {
2000b57cec5SDimitry Andric if (i != 0)
2010b57cec5SDimitry Andric Inner += "&";
2020b57cec5SDimitry Andric Inner += Args[i].getTypeAsString();
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric return Inner;
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric
207*bdd1243dSDimitry Andric std::optional<DynTypedMatcher>
getTypedMatcher(const MatcherOps & Ops) const2080b57cec5SDimitry Andric getTypedMatcher(const MatcherOps &Ops) const override {
2090b57cec5SDimitry Andric return Ops.constructVariadicOperator(Op, Args);
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric
isConvertibleTo(ASTNodeKind Kind,unsigned * Specificity) const2125ffd83dbSDimitry Andric bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
2130b57cec5SDimitry Andric for (const VariantMatcher &Matcher : Args) {
2140b57cec5SDimitry Andric if (!Matcher.isConvertibleTo(Kind, Specificity))
2150b57cec5SDimitry Andric return false;
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric return true;
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric
2200b57cec5SDimitry Andric private:
2210b57cec5SDimitry Andric const DynTypedMatcher::VariadicOperator Op;
2220b57cec5SDimitry Andric const std::vector<VariantMatcher> Args;
2230b57cec5SDimitry Andric };
2240b57cec5SDimitry Andric
VariantMatcher()2250b57cec5SDimitry Andric VariantMatcher::VariantMatcher() {}
2260b57cec5SDimitry Andric
SingleMatcher(const DynTypedMatcher & Matcher)2270b57cec5SDimitry Andric VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
2280b57cec5SDimitry Andric return VariantMatcher(std::make_shared<SinglePayload>(Matcher));
2290b57cec5SDimitry Andric }
2300b57cec5SDimitry Andric
2310b57cec5SDimitry Andric VariantMatcher
PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers)2320b57cec5SDimitry Andric VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
2330b57cec5SDimitry Andric return VariantMatcher(
2340b57cec5SDimitry Andric std::make_shared<PolymorphicPayload>(std::move(Matchers)));
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,std::vector<VariantMatcher> Args)2370b57cec5SDimitry Andric VariantMatcher VariantMatcher::VariadicOperatorMatcher(
2380b57cec5SDimitry Andric DynTypedMatcher::VariadicOperator Op,
2390b57cec5SDimitry Andric std::vector<VariantMatcher> Args) {
2400b57cec5SDimitry Andric return VariantMatcher(
2410b57cec5SDimitry Andric std::make_shared<VariadicOpPayload>(Op, std::move(Args)));
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric
getSingleMatcher() const244*bdd1243dSDimitry Andric std::optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
245*bdd1243dSDimitry Andric return Value ? Value->getSingleMatcher() : std::optional<DynTypedMatcher>();
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric
reset()2480b57cec5SDimitry Andric void VariantMatcher::reset() { Value.reset(); }
2490b57cec5SDimitry Andric
getTypeAsString() const2500b57cec5SDimitry Andric std::string VariantMatcher::getTypeAsString() const {
2510b57cec5SDimitry Andric if (Value) return Value->getTypeAsString();
2520b57cec5SDimitry Andric return "<Nothing>";
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric
VariantValue(const VariantValue & Other)2550b57cec5SDimitry Andric VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
2560b57cec5SDimitry Andric *this = Other;
2570b57cec5SDimitry Andric }
2580b57cec5SDimitry Andric
VariantValue(bool Boolean)2590b57cec5SDimitry Andric VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {
2600b57cec5SDimitry Andric setBoolean(Boolean);
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric
VariantValue(double Double)2630b57cec5SDimitry Andric VariantValue::VariantValue(double Double) : Type(VT_Nothing) {
2640b57cec5SDimitry Andric setDouble(Double);
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric
VariantValue(unsigned Unsigned)2670b57cec5SDimitry Andric VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
2680b57cec5SDimitry Andric setUnsigned(Unsigned);
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric
VariantValue(StringRef String)2710b57cec5SDimitry Andric VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
2720b57cec5SDimitry Andric setString(String);
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric
VariantValue(ASTNodeKind NodeKind)275e8d8bef9SDimitry Andric VariantValue::VariantValue(ASTNodeKind NodeKind) : Type(VT_Nothing) {
276e8d8bef9SDimitry Andric setNodeKind(NodeKind);
277e8d8bef9SDimitry Andric }
278e8d8bef9SDimitry Andric
VariantValue(const VariantMatcher & Matcher)2790b57cec5SDimitry Andric VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
2800b57cec5SDimitry Andric setMatcher(Matcher);
2810b57cec5SDimitry Andric }
2820b57cec5SDimitry Andric
~VariantValue()2830b57cec5SDimitry Andric VariantValue::~VariantValue() { reset(); }
2840b57cec5SDimitry Andric
operator =(const VariantValue & Other)2850b57cec5SDimitry Andric VariantValue &VariantValue::operator=(const VariantValue &Other) {
2860b57cec5SDimitry Andric if (this == &Other) return *this;
2870b57cec5SDimitry Andric reset();
2880b57cec5SDimitry Andric switch (Other.Type) {
2890b57cec5SDimitry Andric case VT_Boolean:
2900b57cec5SDimitry Andric setBoolean(Other.getBoolean());
2910b57cec5SDimitry Andric break;
2920b57cec5SDimitry Andric case VT_Double:
2930b57cec5SDimitry Andric setDouble(Other.getDouble());
2940b57cec5SDimitry Andric break;
2950b57cec5SDimitry Andric case VT_Unsigned:
2960b57cec5SDimitry Andric setUnsigned(Other.getUnsigned());
2970b57cec5SDimitry Andric break;
2980b57cec5SDimitry Andric case VT_String:
2990b57cec5SDimitry Andric setString(Other.getString());
3000b57cec5SDimitry Andric break;
301e8d8bef9SDimitry Andric case VT_NodeKind:
302e8d8bef9SDimitry Andric setNodeKind(Other.getNodeKind());
303e8d8bef9SDimitry Andric break;
3040b57cec5SDimitry Andric case VT_Matcher:
3050b57cec5SDimitry Andric setMatcher(Other.getMatcher());
3060b57cec5SDimitry Andric break;
3070b57cec5SDimitry Andric case VT_Nothing:
3080b57cec5SDimitry Andric Type = VT_Nothing;
3090b57cec5SDimitry Andric break;
3100b57cec5SDimitry Andric }
3110b57cec5SDimitry Andric return *this;
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric
reset()3140b57cec5SDimitry Andric void VariantValue::reset() {
3150b57cec5SDimitry Andric switch (Type) {
3160b57cec5SDimitry Andric case VT_String:
3170b57cec5SDimitry Andric delete Value.String;
3180b57cec5SDimitry Andric break;
3190b57cec5SDimitry Andric case VT_Matcher:
3200b57cec5SDimitry Andric delete Value.Matcher;
3210b57cec5SDimitry Andric break;
322e8d8bef9SDimitry Andric case VT_NodeKind:
323e8d8bef9SDimitry Andric delete Value.NodeKind;
324e8d8bef9SDimitry Andric break;
3250b57cec5SDimitry Andric // Cases that do nothing.
3260b57cec5SDimitry Andric case VT_Boolean:
3270b57cec5SDimitry Andric case VT_Double:
3280b57cec5SDimitry Andric case VT_Unsigned:
3290b57cec5SDimitry Andric case VT_Nothing:
3300b57cec5SDimitry Andric break;
3310b57cec5SDimitry Andric }
3320b57cec5SDimitry Andric Type = VT_Nothing;
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric
isBoolean() const3350b57cec5SDimitry Andric bool VariantValue::isBoolean() const {
3360b57cec5SDimitry Andric return Type == VT_Boolean;
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric
getBoolean() const3390b57cec5SDimitry Andric bool VariantValue::getBoolean() const {
3400b57cec5SDimitry Andric assert(isBoolean());
3410b57cec5SDimitry Andric return Value.Boolean;
3420b57cec5SDimitry Andric }
3430b57cec5SDimitry Andric
setBoolean(bool NewValue)3440b57cec5SDimitry Andric void VariantValue::setBoolean(bool NewValue) {
3450b57cec5SDimitry Andric reset();
3460b57cec5SDimitry Andric Type = VT_Boolean;
3470b57cec5SDimitry Andric Value.Boolean = NewValue;
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric
isDouble() const3500b57cec5SDimitry Andric bool VariantValue::isDouble() const {
3510b57cec5SDimitry Andric return Type == VT_Double;
3520b57cec5SDimitry Andric }
3530b57cec5SDimitry Andric
getDouble() const3540b57cec5SDimitry Andric double VariantValue::getDouble() const {
3550b57cec5SDimitry Andric assert(isDouble());
3560b57cec5SDimitry Andric return Value.Double;
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric
setDouble(double NewValue)3590b57cec5SDimitry Andric void VariantValue::setDouble(double NewValue) {
3600b57cec5SDimitry Andric reset();
3610b57cec5SDimitry Andric Type = VT_Double;
3620b57cec5SDimitry Andric Value.Double = NewValue;
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric
isUnsigned() const3650b57cec5SDimitry Andric bool VariantValue::isUnsigned() const {
3660b57cec5SDimitry Andric return Type == VT_Unsigned;
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric
getUnsigned() const3690b57cec5SDimitry Andric unsigned VariantValue::getUnsigned() const {
3700b57cec5SDimitry Andric assert(isUnsigned());
3710b57cec5SDimitry Andric return Value.Unsigned;
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric
setUnsigned(unsigned NewValue)3740b57cec5SDimitry Andric void VariantValue::setUnsigned(unsigned NewValue) {
3750b57cec5SDimitry Andric reset();
3760b57cec5SDimitry Andric Type = VT_Unsigned;
3770b57cec5SDimitry Andric Value.Unsigned = NewValue;
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric
isString() const3800b57cec5SDimitry Andric bool VariantValue::isString() const {
3810b57cec5SDimitry Andric return Type == VT_String;
3820b57cec5SDimitry Andric }
3830b57cec5SDimitry Andric
getString() const3840b57cec5SDimitry Andric const std::string &VariantValue::getString() const {
3850b57cec5SDimitry Andric assert(isString());
3860b57cec5SDimitry Andric return *Value.String;
3870b57cec5SDimitry Andric }
3880b57cec5SDimitry Andric
setString(StringRef NewValue)3890b57cec5SDimitry Andric void VariantValue::setString(StringRef NewValue) {
3900b57cec5SDimitry Andric reset();
3910b57cec5SDimitry Andric Type = VT_String;
3920b57cec5SDimitry Andric Value.String = new std::string(NewValue);
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric
isNodeKind() const395e8d8bef9SDimitry Andric bool VariantValue::isNodeKind() const { return Type == VT_NodeKind; }
396e8d8bef9SDimitry Andric
getNodeKind() const397e8d8bef9SDimitry Andric const ASTNodeKind &VariantValue::getNodeKind() const {
398e8d8bef9SDimitry Andric assert(isNodeKind());
399e8d8bef9SDimitry Andric return *Value.NodeKind;
400e8d8bef9SDimitry Andric }
401e8d8bef9SDimitry Andric
setNodeKind(ASTNodeKind NewValue)402e8d8bef9SDimitry Andric void VariantValue::setNodeKind(ASTNodeKind NewValue) {
403e8d8bef9SDimitry Andric reset();
404e8d8bef9SDimitry Andric Type = VT_NodeKind;
405e8d8bef9SDimitry Andric Value.NodeKind = new ASTNodeKind(NewValue);
406e8d8bef9SDimitry Andric }
407e8d8bef9SDimitry Andric
isMatcher() const4080b57cec5SDimitry Andric bool VariantValue::isMatcher() const {
4090b57cec5SDimitry Andric return Type == VT_Matcher;
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric
getMatcher() const4120b57cec5SDimitry Andric const VariantMatcher &VariantValue::getMatcher() const {
4130b57cec5SDimitry Andric assert(isMatcher());
4140b57cec5SDimitry Andric return *Value.Matcher;
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric
setMatcher(const VariantMatcher & NewValue)4170b57cec5SDimitry Andric void VariantValue::setMatcher(const VariantMatcher &NewValue) {
4180b57cec5SDimitry Andric reset();
4190b57cec5SDimitry Andric Type = VT_Matcher;
4200b57cec5SDimitry Andric Value.Matcher = new VariantMatcher(NewValue);
4210b57cec5SDimitry Andric }
4220b57cec5SDimitry Andric
isConvertibleTo(ArgKind Kind,unsigned * Specificity) const4230b57cec5SDimitry Andric bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
4240b57cec5SDimitry Andric switch (Kind.getArgKind()) {
4250b57cec5SDimitry Andric case ArgKind::AK_Boolean:
4260b57cec5SDimitry Andric if (!isBoolean())
4270b57cec5SDimitry Andric return false;
4280b57cec5SDimitry Andric *Specificity = 1;
4290b57cec5SDimitry Andric return true;
4300b57cec5SDimitry Andric
4310b57cec5SDimitry Andric case ArgKind::AK_Double:
4320b57cec5SDimitry Andric if (!isDouble())
4330b57cec5SDimitry Andric return false;
4340b57cec5SDimitry Andric *Specificity = 1;
4350b57cec5SDimitry Andric return true;
4360b57cec5SDimitry Andric
4370b57cec5SDimitry Andric case ArgKind::AK_Unsigned:
4380b57cec5SDimitry Andric if (!isUnsigned())
4390b57cec5SDimitry Andric return false;
4400b57cec5SDimitry Andric *Specificity = 1;
4410b57cec5SDimitry Andric return true;
4420b57cec5SDimitry Andric
4430b57cec5SDimitry Andric case ArgKind::AK_String:
4440b57cec5SDimitry Andric if (!isString())
4450b57cec5SDimitry Andric return false;
4460b57cec5SDimitry Andric *Specificity = 1;
4470b57cec5SDimitry Andric return true;
4480b57cec5SDimitry Andric
449fe6060f1SDimitry Andric case ArgKind::AK_Node:
450fe6060f1SDimitry Andric if (!isNodeKind())
451fe6060f1SDimitry Andric return false;
452fe6060f1SDimitry Andric return getMatcher().isConvertibleTo(Kind.getNodeKind(), Specificity);
453fe6060f1SDimitry Andric
4540b57cec5SDimitry Andric case ArgKind::AK_Matcher:
4550b57cec5SDimitry Andric if (!isMatcher())
4560b57cec5SDimitry Andric return false;
4570b57cec5SDimitry Andric return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
4580b57cec5SDimitry Andric }
4590b57cec5SDimitry Andric llvm_unreachable("Invalid Type");
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric
isConvertibleTo(ArrayRef<ArgKind> Kinds,unsigned * Specificity) const4620b57cec5SDimitry Andric bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
4630b57cec5SDimitry Andric unsigned *Specificity) const {
4640b57cec5SDimitry Andric unsigned MaxSpecificity = 0;
4650b57cec5SDimitry Andric for (const ArgKind& Kind : Kinds) {
4660b57cec5SDimitry Andric unsigned ThisSpecificity;
4670b57cec5SDimitry Andric if (!isConvertibleTo(Kind, &ThisSpecificity))
4680b57cec5SDimitry Andric continue;
4690b57cec5SDimitry Andric MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
4700b57cec5SDimitry Andric }
4710b57cec5SDimitry Andric if (Specificity && MaxSpecificity > 0) {
4720b57cec5SDimitry Andric *Specificity = MaxSpecificity;
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric return MaxSpecificity > 0;
4750b57cec5SDimitry Andric }
4760b57cec5SDimitry Andric
getTypeAsString() const4770b57cec5SDimitry Andric std::string VariantValue::getTypeAsString() const {
4780b57cec5SDimitry Andric switch (Type) {
4790b57cec5SDimitry Andric case VT_String: return "String";
4800b57cec5SDimitry Andric case VT_Matcher: return getMatcher().getTypeAsString();
4810b57cec5SDimitry Andric case VT_Boolean: return "Boolean";
4820b57cec5SDimitry Andric case VT_Double: return "Double";
4830b57cec5SDimitry Andric case VT_Unsigned: return "Unsigned";
484e8d8bef9SDimitry Andric case VT_NodeKind:
485e8d8bef9SDimitry Andric return getNodeKind().asStringRef().str();
4860b57cec5SDimitry Andric case VT_Nothing: return "Nothing";
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric llvm_unreachable("Invalid Type");
4890b57cec5SDimitry Andric }
4900b57cec5SDimitry Andric
4910b57cec5SDimitry Andric } // end namespace dynamic
4920b57cec5SDimitry Andric } // end namespace ast_matchers
4930b57cec5SDimitry Andric } // end namespace clang
494