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