123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- //===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- ///
- /// \file
- /// \brief Polymorphic value type.
- ///
- //===----------------------------------------------------------------------===//
- #include "clang/ASTMatchers/Dynamic/VariantValue.h"
- #include "clang/Basic/LLVM.h"
- #include "llvm/ADT/STLExtras.h"
- namespace clang {
- namespace ast_matchers {
- namespace dynamic {
- std::string ArgKind::asString() const {
- switch (getArgKind()) {
- case AK_Matcher:
- return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str();
- case AK_Unsigned:
- return "unsigned";
- case AK_String:
- return "string";
- }
- llvm_unreachable("unhandled ArgKind");
- }
- bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
- if (K != To.K)
- return false;
- if (K != AK_Matcher) {
- if (Specificity)
- *Specificity = 1;
- return true;
- }
- unsigned Distance;
- if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance))
- return false;
- if (Specificity)
- *Specificity = 100 - Distance;
- return true;
- }
- bool
- VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,
- bool &IsExactMatch) const {
- IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);
- return Matcher.canConvertTo(NodeKind);
- }
- llvm::Optional<DynTypedMatcher>
- VariantMatcher::MatcherOps::constructVariadicOperator(
- DynTypedMatcher::VariadicOperator Op,
- ArrayRef<VariantMatcher> InnerMatchers) const {
- std::vector<DynTypedMatcher> DynMatchers;
- for (const auto &InnerMatcher : InnerMatchers) {
- // Abort if any of the inner matchers can't be converted to
- // Matcher<T>.
- if (!InnerMatcher.Value)
- return llvm::None;
- llvm::Optional<DynTypedMatcher> Inner =
- InnerMatcher.Value->getTypedMatcher(*this);
- if (!Inner)
- return llvm::None;
- DynMatchers.push_back(*Inner);
- }
- return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);
- }
- VariantMatcher::Payload::~Payload() {}
- class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
- public:
- SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}
- llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
- return Matcher;
- }
- std::string getTypeAsString() const override {
- return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")
- .str();
- }
- llvm::Optional<DynTypedMatcher>
- getTypedMatcher(const MatcherOps &Ops) const override {
- bool Ignore;
- if (Ops.canConstructFrom(Matcher, Ignore))
- return Matcher;
- return llvm::None;
- }
- bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
- unsigned *Specificity) const override {
- return ArgKind(Matcher.getSupportedKind())
- .isConvertibleTo(Kind, Specificity);
- }
- private:
- const DynTypedMatcher Matcher;
- };
- class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {
- public:
- PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)
- : Matchers(std::move(MatchersIn)) {}
- ~PolymorphicPayload() override {}
- llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
- if (Matchers.size() != 1)
- return llvm::Optional<DynTypedMatcher>();
- return Matchers[0];
- }
- std::string getTypeAsString() const override {
- std::string Inner;
- for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
- if (i != 0)
- Inner += "|";
- Inner += Matchers[i].getSupportedKind().asStringRef();
- }
- return (Twine("Matcher<") + Inner + ">").str();
- }
- llvm::Optional<DynTypedMatcher>
- getTypedMatcher(const MatcherOps &Ops) const override {
- bool FoundIsExact = false;
- const DynTypedMatcher *Found = nullptr;
- int NumFound = 0;
- for (size_t i = 0, e = Matchers.size(); i != e; ++i) {
- bool IsExactMatch;
- if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {
- if (Found) {
- if (FoundIsExact) {
- assert(!IsExactMatch && "We should not have two exact matches.");
- continue;
- }
- }
- Found = &Matchers[i];
- FoundIsExact = IsExactMatch;
- ++NumFound;
- }
- }
- // We only succeed if we found exactly one, or if we found an exact match.
- if (Found && (FoundIsExact || NumFound == 1))
- return *Found;
- return llvm::None;
- }
- bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
- unsigned *Specificity) const override {
- unsigned MaxSpecificity = 0;
- for (const DynTypedMatcher &Matcher : Matchers) {
- unsigned ThisSpecificity;
- if (ArgKind(Matcher.getSupportedKind())
- .isConvertibleTo(Kind, &ThisSpecificity)) {
- MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
- }
- }
- if (Specificity)
- *Specificity = MaxSpecificity;
- return MaxSpecificity > 0;
- }
- const std::vector<DynTypedMatcher> Matchers;
- };
- class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
- public:
- VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,
- std::vector<VariantMatcher> Args)
- : Op(Op), Args(std::move(Args)) {}
- llvm::Optional<DynTypedMatcher> getSingleMatcher() const override {
- return llvm::Optional<DynTypedMatcher>();
- }
- std::string getTypeAsString() const override {
- std::string Inner;
- for (size_t i = 0, e = Args.size(); i != e; ++i) {
- if (i != 0)
- Inner += "&";
- Inner += Args[i].getTypeAsString();
- }
- return Inner;
- }
- llvm::Optional<DynTypedMatcher>
- getTypedMatcher(const MatcherOps &Ops) const override {
- return Ops.constructVariadicOperator(Op, Args);
- }
- bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
- unsigned *Specificity) const override {
- for (const VariantMatcher &Matcher : Args) {
- if (!Matcher.isConvertibleTo(Kind, Specificity))
- return false;
- }
- return true;
- }
- private:
- const DynTypedMatcher::VariadicOperator Op;
- const std::vector<VariantMatcher> Args;
- };
- VariantMatcher::VariantMatcher() {}
- VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {
- return VariantMatcher(new SinglePayload(Matcher));
- }
- VariantMatcher
- VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {
- return VariantMatcher(new PolymorphicPayload(std::move(Matchers)));
- }
- VariantMatcher VariantMatcher::VariadicOperatorMatcher(
- DynTypedMatcher::VariadicOperator Op,
- std::vector<VariantMatcher> Args) {
- return VariantMatcher(new VariadicOpPayload(Op, std::move(Args)));
- }
- llvm::Optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {
- return Value ? Value->getSingleMatcher() : llvm::Optional<DynTypedMatcher>();
- }
- void VariantMatcher::reset() { Value.reset(); }
- std::string VariantMatcher::getTypeAsString() const {
- if (Value) return Value->getTypeAsString();
- return "<Nothing>";
- }
- VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {
- *this = Other;
- }
- VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {
- setUnsigned(Unsigned);
- }
- VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {
- setString(String);
- }
- VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {
- setMatcher(Matcher);
- }
- VariantValue::~VariantValue() { reset(); }
- VariantValue &VariantValue::operator=(const VariantValue &Other) {
- if (this == &Other) return *this;
- reset();
- switch (Other.Type) {
- case VT_Unsigned:
- setUnsigned(Other.getUnsigned());
- break;
- case VT_String:
- setString(Other.getString());
- break;
- case VT_Matcher:
- setMatcher(Other.getMatcher());
- break;
- case VT_Nothing:
- Type = VT_Nothing;
- break;
- }
- return *this;
- }
- void VariantValue::reset() {
- switch (Type) {
- case VT_String:
- delete Value.String;
- break;
- case VT_Matcher:
- delete Value.Matcher;
- break;
- // Cases that do nothing.
- case VT_Unsigned:
- case VT_Nothing:
- break;
- }
- Type = VT_Nothing;
- }
- bool VariantValue::isUnsigned() const {
- return Type == VT_Unsigned;
- }
- unsigned VariantValue::getUnsigned() const {
- assert(isUnsigned());
- return Value.Unsigned;
- }
- void VariantValue::setUnsigned(unsigned NewValue) {
- reset();
- Type = VT_Unsigned;
- Value.Unsigned = NewValue;
- }
- bool VariantValue::isString() const {
- return Type == VT_String;
- }
- const std::string &VariantValue::getString() const {
- assert(isString());
- return *Value.String;
- }
- void VariantValue::setString(StringRef NewValue) {
- reset();
- Type = VT_String;
- Value.String = new std::string(NewValue);
- }
- bool VariantValue::isMatcher() const {
- return Type == VT_Matcher;
- }
- const VariantMatcher &VariantValue::getMatcher() const {
- assert(isMatcher());
- return *Value.Matcher;
- }
- void VariantValue::setMatcher(const VariantMatcher &NewValue) {
- reset();
- Type = VT_Matcher;
- Value.Matcher = new VariantMatcher(NewValue);
- }
- bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {
- switch (Kind.getArgKind()) {
- case ArgKind::AK_Unsigned:
- if (!isUnsigned())
- return false;
- *Specificity = 1;
- return true;
- case ArgKind::AK_String:
- if (!isString())
- return false;
- *Specificity = 1;
- return true;
- case ArgKind::AK_Matcher:
- if (!isMatcher())
- return false;
- return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);
- }
- llvm_unreachable("Invalid Type");
- }
- bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,
- unsigned *Specificity) const {
- unsigned MaxSpecificity = 0;
- for (const ArgKind& Kind : Kinds) {
- unsigned ThisSpecificity;
- if (!isConvertibleTo(Kind, &ThisSpecificity))
- continue;
- MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
- }
- if (Specificity && MaxSpecificity > 0) {
- *Specificity = MaxSpecificity;
- }
- return MaxSpecificity > 0;
- }
- std::string VariantValue::getTypeAsString() const {
- switch (Type) {
- case VT_String: return "String";
- case VT_Matcher: return getMatcher().getTypeAsString();
- case VT_Unsigned: return "Unsigned";
- case VT_Nothing: return "Nothing";
- }
- llvm_unreachable("Invalid Type");
- }
- } // end namespace dynamic
- } // end namespace ast_matchers
- } // end namespace clang
|