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 VariantMatcher::MatcherOps::~MatcherOps() {}
     24 VariantMatcher::Payload::~Payload() {}
     25 
     26 class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
     27 public:
     28   SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
     29 
     30   virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
     31     return Matcher;
     32   }
     33 
     34   virtual std::string getTypeAsString() const {
     35     return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
     36         .str();
     37   }
     38 
     39   virtual void makeTypedMatcher(MatcherOps &Ops) const {
     40     bool Ignore;
     41     if (Ops.canConstructFrom(Matcher, Ignore))
     42       Ops.constructFrom(Matcher);
     43   }
     44 
     45 private:
     46   const DynTypedMatcher Matcher;
     47 };
     48 
     49 class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
     50 public:
     51   PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
     52       : Matchers(std::move(MatchersIn)) {}
     53 
     54   virtual ~PolymorphicPayload() {}
     55 
     56   virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
     57     if (Matchers.size() != 1)
     58       return llvm::Optional<DynTypedMatcher>();
     59     return Matchers[0];
     60   }
     61 
     62   virtual std::string getTypeAsString() const {
     63     std::string Inner;
     64     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
     65       if (i != 0)
     66         Inner += "|";
     67       Inner += Matchers[i].getSupportedKind().asStringRef();
     68     }
     69     return (Twine("Matcher<") + Inner + ">").str();
     70   }
     71 
     72   virtual void makeTypedMatcher(MatcherOps &Ops) const {
     73     bool FoundIsExact = false;
     74     const DynTypedMatcher *Found = nullptr;
     75     int NumFound = 0;
     76     for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
     77       bool IsExactMatch;
     78       if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
     79         if (Found) {
     80           if (FoundIsExact) {
     81             assert(!IsExactMatch && "We should not have two exact matches.");
     82             continue;
     83           }
     84         }
     85         Found = &Matchers[i];
     86         FoundIsExact = IsExactMatch;
     87         ++NumFound;
     88       }
     89     }
     90     // We only succeed if we found exactly one, or if we found an exact match.
     91     if (Found && (FoundIsExact || NumFound == 1))
     92       Ops.constructFrom(*Found);
     93   }
     94 
     95   const std::vector<DynTypedMatcher> Matchers;
     96 };
     97 
     98 class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
     99 public:
    100   VariadicOpPayload(ast_matchers::internal::VariadicOperatorFunction Func,
    101                     std::vector<VariantMatcher> Args)
    102       : Func(Func), Args(std::move(Args)) {}
    103 
    104   virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const {
    105     return llvm::Optional<DynTypedMatcher>();
    106   }
    107 
    108   virtual std::string getTypeAsString() const {
    109     std::string Inner;
    110     for (size_t i = 0, e = Args.size(); i != e; ++i) {
    111       if (i != 0)
    112         Inner += "&";
    113       Inner += Args[i].getTypeAsString();
    114     }
    115     return Inner;
    116   }
    117 
    118   virtual void makeTypedMatcher(MatcherOps &Ops) const {
    119     Ops.constructVariadicOperator(Func, Args);
    120   }
    121 
    122 private:
    123   const ast_matchers::internal::VariadicOperatorFunction Func;
    124   const std::vector<VariantMatcher> Args;
    125 };
    126 
    127 VariantMatcher::VariantMatcher() {}
    128 
    129 VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
    130   return VariantMatcher(new SinglePayload(Matcher));
    131 }
    132 
    133 VariantMatcher
    134 VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
    135   return VariantMatcher(new PolymorphicPayload(std::move(Matchers)));
    136 }
    137 
    138 VariantMatcher VariantMatcher::VariadicOperatorMatcher(
    139     ast_matchers::internal::VariadicOperatorFunction Func,
    140     std::vector<VariantMatcher> Args) {
    141   return VariantMatcher(new VariadicOpPayload(Func, std::move(Args)));
    142 }
    143 
    144 llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
    145   return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
    146 }
    147 
    148 void VariantMatcher::reset() { Value.reset(); }
    149 
    150 std::string VariantMatcher::getTypeAsString() const {
    151   if (Value) return Value->getTypeAsString();
    152   return "<Nothing>";
    153 }
    154 
    155 VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
    156   *this = Other;
    157 }
    158 
    159 VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
    160   setUnsigned(Unsigned);
    161 }
    162 
    163 VariantValue::VariantValue(const std::string &String) : Type(VT_Nothing) {
    164   setString(String);
    165 }
    166 
    167 VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
    168   setMatcher(Matcher);
    169 }
    170 
    171 VariantValue::~VariantValue() { reset(); }
    172 
    173 VariantValue &VariantValue::operator=(const VariantValue &Other) {
    174   if (this == &Other) return *this;
    175   reset();
    176   switch (Other.Type) {
    177   case VT_Unsigned:
    178     setUnsigned(Other.getUnsigned());
    179     break;
    180   case VT_String:
    181     setString(Other.getString());
    182     break;
    183   case VT_Matcher:
    184     setMatcher(Other.getMatcher());
    185     break;
    186   case VT_Nothing:
    187     Type = VT_Nothing;
    188     break;
    189   }
    190   return *this;
    191 }
    192 
    193 void VariantValue::reset() {
    194   switch (Type) {
    195   case VT_String:
    196     delete Value.String;
    197     break;
    198   case VT_Matcher:
    199     delete Value.Matcher;
    200     break;
    201   // Cases that do nothing.
    202   case VT_Unsigned:
    203   case VT_Nothing:
    204     break;
    205   }
    206   Type = VT_Nothing;
    207 }
    208 
    209 bool VariantValue::isUnsigned() const {
    210   return Type == VT_Unsigned;
    211 }
    212 
    213 unsigned VariantValue::getUnsigned() const {
    214   assert(isUnsigned());
    215   return Value.Unsigned;
    216 }
    217 
    218 void VariantValue::setUnsigned(unsigned NewValue) {
    219   reset();
    220   Type = VT_Unsigned;
    221   Value.Unsigned = NewValue;
    222 }
    223 
    224 bool VariantValue::isString() const {
    225   return Type == VT_String;
    226 }
    227 
    228 const std::string &VariantValue::getString() const {
    229   assert(isString());
    230   return *Value.String;
    231 }
    232 
    233 void VariantValue::setString(const std::string &NewValue) {
    234   reset();
    235   Type = VT_String;
    236   Value.String = new std::string(NewValue);
    237 }
    238 
    239 bool VariantValue::isMatcher() const {
    240   return Type == VT_Matcher;
    241 }
    242 
    243 const VariantMatcher &VariantValue::getMatcher() const {
    244   assert(isMatcher());
    245   return *Value.Matcher;
    246 }
    247 
    248 void VariantValue::setMatcher(const VariantMatcher &NewValue) {
    249   reset();
    250   Type = VT_Matcher;
    251   Value.Matcher = new VariantMatcher(NewValue);
    252 }
    253 
    254 std::string VariantValue::getTypeAsString() const {
    255   switch (Type) {
    256   case VT_String: return "String";
    257   case VT_Matcher: return getMatcher().getTypeAsString();
    258   case VT_Unsigned: return "Unsigned";
    259   case VT_Nothing: return "Nothing";
    260   }
    261   llvm_unreachable("Invalid Type");
    262 }
    263 
    264 } // end namespace dynamic
    265 } // end namespace ast_matchers
    266 } // end namespace clang
    267