xref: /freebsd-src/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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