Home | History | Annotate | Download | only in Dynamic
      1 //===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// \brief Polymorphic value type.
     12 ///
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "clang/ASTMatchers/Dynamic/VariantValue.h"
     16 #include "clang/Basic/LLVM.h"
     17 #include "llvm/ADT/STLExtras.h"
     18 
     19 namespace clang {
     20 namespace ast_matchers {
     21 namespace dynamic {
     22 
     23 std::string ArgKind::asString() const {
     24   switch (getArgKind()) {
     25   case AK_Matcher:
     26     return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str();
     27   case AK_Unsigned:
     28     return "unsigned";
     29   case AK_String:
     30     return "string";
     31   }
     32   llvm_unreachable("unhandled ArgKind");
     33 }
     34 
     35 bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
     36   if (K != To.K)
     37     return false;
     38   if (K != AK_Matcher) {
     39     if (Specificity)
     40       *Specificity = 1;
     41     return true;
     42   }
     43   unsigned Distance;
     44   if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance))
     45     return false;
     46 
     47   if (Specificity)
     48     *Specificity = 100 - Distance;
     49   return true;
     50 }
     51 
     52 bool
     53 VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
     54                                              bool &IsExactMatch) const {
     55   IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
     56   return Matcher.canConvertTo(NodeKind);
     57 }
     58 
     59 llvm::Optional<DynTypedMatcher>
     60 VariantMatcher::MatcherOps::constructVariadicOperator(
     61     DynTypedMatcher::VariadicOperator Op,
     62     ArrayRef<VariantMatcher> InnerMatchers) const {
     63   std::vector<DynTypedMatcher> DynMatchers;
     64   for (const auto &InnerMatcher : InnerMatchers) {
     65     // Abort if any of the inner matchers can't be converted to
     66     // Matcher<T>.
     67     if (!InnerMatcher.Value)
     68       return llvm::None;
     69     llvm::Optional<DynTypedMatcher> Inner =
     70         InnerMatcher.Value->getTypedMatcher(*this);
     71     if (!Inner)
     72       return llvm::None;
     73     DynMatchers.push_back(*Inner);
     74   }
     75   return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
     76 }
     77 
     78 VariantMatcher::Payload::~Payload() {}
     79 
     80 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
     81 public:
     82   SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
     83 
     84   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
     85     return Matcher;
     86   }
     87 
     88   std::string getTypeAsString() const override {
     89     return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
     90         .str();
     91   }
     92 
     93   llvm::Optional<DynTypedMatcher>
     94   getTypedMatcher(const MatcherOps &Ops) const override {
     95     bool Ignore;
     96     if (Ops.canConstructFrom(Matcher, Ignore))
     97       return Matcher;
     98     return llvm::None;
     99   }
    100 
    101   bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
    102                        unsigned *Specificity) const override {
    103     return ArgKind(Matcher.getSupportedKind())
    104         .isConvertibleTo(Kind, Specificity);
    105   }
    106 
    107 private:
    108   const DynTypedMatcher Matcher;
    109 };
    110 
    111 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
    112 public:
    113   PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
    114       : Matchers(std::move(MatchersIn)) {}
    115 
    116   ~PolymorphicPayload() override {}
    117 
    118   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
    119     if (Matchers.size() != 1)
    120       return llvm::Optional<DynTypedMatcher>();
    121     return Matchers[0];
    122   }
    123 
    124   std::string getTypeAsString() const override {
    125     std::string Inner;
    126     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
    127       if (i != 0)
    128         Inner += "|";
    129       Inner += Matchers[i].getSupportedKind().asStringRef();
    130     }
    131     return (Twine("Matcher<") + Inner + ">").str();
    132   }
    133 
    134   llvm::Optional<DynTypedMatcher>
    135   getTypedMatcher(const MatcherOps &Ops) const override {
    136     bool FoundIsExact = false;
    137     const DynTypedMatcher *Found = nullptr;
    138     int NumFound = 0;
    139     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
    140       bool IsExactMatch;
    141       if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
    142         if (Found) {
    143           if (FoundIsExact) {
    144             assert(!IsExactMatch && "We should not have two exact matches.");
    145             continue;
    146           }
    147         }
    148         Found = &Matchers[i];
    149         FoundIsExact = IsExactMatch;
    150         ++NumFound;
    151       }
    152     }
    153     // We only succeed if we found exactly one, or if we found an exact match.
    154     if (Found && (FoundIsExact || NumFound == 1))
    155       return *Found;
    156     return llvm::None;
    157   }
    158 
    159   bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
    160                        unsigned *Specificity) const override {
    161     unsigned MaxSpecificity = 0;
    162     for (const DynTypedMatcher &Matcher : Matchers) {
    163       unsigned ThisSpecificity;
    164       if (ArgKind(Matcher.getSupportedKind())
    165               .isConvertibleTo(Kind, &ThisSpecificity)) {
    166         MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
    167       }
    168     }
    169     if (Specificity)
    170       *Specificity = MaxSpecificity;
    171     return MaxSpecificity > 0;
    172   }
    173 
    174   const std::vector<DynTypedMatcher> Matchers;
    175 };
    176 
    177 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
    178 public:
    179   VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
    180                     std::vector<VariantMatcher> Args)
    181       : Op(Op), Args(std::move(Args)) {}
    182 
    183   llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
    184     return llvm::Optional<DynTypedMatcher>();
    185   }
    186 
    187   std::string getTypeAsString() const override {
    188     std::string Inner;
    189     for (size_t i = 0, e = Args.size(); i != e; ++i) {
    190       if (i != 0)
    191         Inner += "&";
    192       Inner += Args[i].getTypeAsString();
    193     }
    194     return Inner;
    195   }
    196 
    197   llvm::Optional<DynTypedMatcher>
    198   getTypedMatcher(const MatcherOps &Ops) const override {
    199     return Ops.constructVariadicOperator(Op, Args);
    200   }
    201 
    202   bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
    203                        unsigned *Specificity) const override {
    204     for (const VariantMatcher &Matcher : Args) {
    205       if (!Matcher.isConvertibleTo(Kind, Specificity))
    206         return false;
    207     }
    208     return true;
    209   }
    210 
    211 private:
    212   const DynTypedMatcher::VariadicOperator Op;
    213   const std::vector<VariantMatcher> Args;
    214 };
    215 
    216 VariantMatcher::VariantMatcher() {}
    217 
    218 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
    219   return VariantMatcher(new SinglePayload(Matcher));
    220 }
    221 
    222 VariantMatcher
    223 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
    224   return VariantMatcher(new PolymorphicPayload(std::move(Matchers)));
    225 }
    226 
    227 VariantMatcher VariantMatcher::VariadicOperatorMatcher(
    228     DynTypedMatcher::VariadicOperator Op,
    229     std::vector<VariantMatcher> Args) {
    230   return VariantMatcher(new VariadicOpPayload(Op, std::move(Args)));
    231 }
    232 
    233 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
    234   return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
    235 }
    236 
    237 void VariantMatcher::reset() { Value.reset(); }
    238 
    239 std::string VariantMatcher::getTypeAsString() const {
    240   if (Value) return Value->getTypeAsString();
    241   return "<Nothing>";
    242 }
    243 
    244 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
    245   *this = Other;
    246 }
    247 
    248 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
    249   setUnsigned(Unsigned);
    250 }
    251 
    252 VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
    253   setString(String);
    254 }
    255 
    256 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
    257   setMatcher(Matcher);
    258 }
    259 
    260 VariantValue::~VariantValue() { reset(); }
    261 
    262 VariantValue &VariantValue::operator=(const VariantValue &Other) {
    263   if (this == &Other) return *this;
    264   reset();
    265   switch (Other.Type) {
    266   case VT_Unsigned:
    267     setUnsigned(Other.getUnsigned());
    268     break;
    269   case VT_String:
    270     setString(Other.getString());
    271     break;
    272   case VT_Matcher:
    273     setMatcher(Other.getMatcher());
    274     break;
    275   case VT_Nothing:
    276     Type = VT_Nothing;
    277     break;
    278   }
    279   return *this;
    280 }
    281 
    282 void VariantValue::reset() {
    283   switch (Type) {
    284   case VT_String:
    285     delete Value.String;
    286     break;
    287   case VT_Matcher:
    288     delete Value.Matcher;
    289     break;
    290   // Cases that do nothing.
    291   case VT_Unsigned:
    292   case VT_Nothing:
    293     break;
    294   }
    295   Type = VT_Nothing;
    296 }
    297 
    298 bool VariantValue::isUnsigned() const {
    299   return Type == VT_Unsigned;
    300 }
    301 
    302 unsigned VariantValue::getUnsigned() const {
    303   assert(isUnsigned());
    304   return Value.Unsigned;
    305 }
    306 
    307 void VariantValue::setUnsigned(unsigned NewValue) {
    308   reset();
    309   Type = VT_Unsigned;
    310   Value.Unsigned = NewValue;
    311 }
    312 
    313 bool VariantValue::isString() const {
    314   return Type == VT_String;
    315 }
    316 
    317 const std::string &VariantValue::getString() const {
    318   assert(isString());
    319   return *Value.String;
    320 }
    321 
    322 void VariantValue::setString(StringRef NewValue) {
    323   reset();
    324   Type = VT_String;
    325   Value.String = new std::string(NewValue);
    326 }
    327 
    328 bool VariantValue::isMatcher() const {
    329   return Type == VT_Matcher;
    330 }
    331 
    332 const VariantMatcher &VariantValue::getMatcher() const {
    333   assert(isMatcher());
    334   return *Value.Matcher;
    335 }
    336 
    337 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
    338   reset();
    339   Type = VT_Matcher;
    340   Value.Matcher = new VariantMatcher(NewValue);
    341 }
    342 
    343 bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
    344   switch (Kind.getArgKind()) {
    345   case ArgKind::AK_Unsigned:
    346     if (!isUnsigned())
    347       return false;
    348     *Specificity = 1;
    349     return true;
    350 
    351   case ArgKind::AK_String:
    352     if (!isString())
    353       return false;
    354     *Specificity = 1;
    355     return true;
    356 
    357   case ArgKind::AK_Matcher:
    358     if (!isMatcher())
    359       return false;
    360     return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
    361   }
    362   llvm_unreachable("Invalid Type");
    363 }
    364 
    365 bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
    366                                    unsigned *Specificity) const {
    367   unsigned MaxSpecificity = 0;
    368   for (const ArgKind& Kind : Kinds) {
    369     unsigned ThisSpecificity;
    370     if (!isConvertibleTo(Kind, &ThisSpecificity))
    371       continue;
    372     MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
    373   }
    374   if (Specificity && MaxSpecificity > 0) {
    375     *Specificity = MaxSpecificity;
    376   }
    377   return MaxSpecificity > 0;
    378 }
    379 
    380 std::string VariantValue::getTypeAsString() const {
    381   switch (Type) {
    382   case VT_String: return "String";
    383   case VT_Matcher: return getMatcher().getTypeAsString();
    384   case VT_Unsigned: return "Unsigned";
    385   case VT_Nothing: return "Nothing";
    386   }
    387   llvm_unreachable("Invalid Type");
    388 }
    389 
    390 } // end namespace dynamic
    391 } // end namespace ast_matchers
    392 } // end namespace clang
    393