diff options
author | 2020-08-03 14:31:31 +0000 | |
---|---|---|
committer | 2020-08-03 14:31:31 +0000 | |
commit | e5dd70708596ae51455a0ffa086a00c5b29f8583 (patch) | |
tree | 5d676f27b570bacf71e786c3b5cff3e6f6679b59 /gnu/llvm/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp | |
parent | Import LLVM 10.0.0 release including clang, lld and lldb. (diff) | |
download | wireguard-openbsd-e5dd70708596ae51455a0ffa086a00c5b29f8583.tar.xz wireguard-openbsd-e5dd70708596ae51455a0ffa086a00c5b29f8583.zip |
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom
tested by plenty
Diffstat (limited to 'gnu/llvm/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp')
-rw-r--r-- | gnu/llvm/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp | 457 |
1 files changed, 457 insertions, 0 deletions
diff --git a/gnu/llvm/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp b/gnu/llvm/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp new file mode 100644 index 00000000000..118ca2a41cb --- /dev/null +++ b/gnu/llvm/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp @@ -0,0 +1,457 @@ +//===--- VariantValue.cpp - Polymorphic value type -*- C++ -*-===/ +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// 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_Boolean: + return "boolean"; + case AK_Double: + return "double"; + 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(std::make_shared<SinglePayload>(Matcher)); +} + +VariantMatcher +VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) { + return VariantMatcher( + std::make_shared<PolymorphicPayload>(std::move(Matchers))); +} + +VariantMatcher VariantMatcher::VariadicOperatorMatcher( + DynTypedMatcher::VariadicOperator Op, + std::vector<VariantMatcher> Args) { + return VariantMatcher( + std::make_shared<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(bool Boolean) : Type(VT_Nothing) { + setBoolean(Boolean); +} + +VariantValue::VariantValue(double Double) : Type(VT_Nothing) { + setDouble(Double); +} + +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_Boolean: + setBoolean(Other.getBoolean()); + break; + case VT_Double: + setDouble(Other.getDouble()); + break; + 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_Boolean: + case VT_Double: + case VT_Unsigned: + case VT_Nothing: + break; + } + Type = VT_Nothing; +} + +bool VariantValue::isBoolean() const { + return Type == VT_Boolean; +} + +bool VariantValue::getBoolean() const { + assert(isBoolean()); + return Value.Boolean; +} + +void VariantValue::setBoolean(bool NewValue) { + reset(); + Type = VT_Boolean; + Value.Boolean = NewValue; +} + +bool VariantValue::isDouble() const { + return Type == VT_Double; +} + +double VariantValue::getDouble() const { + assert(isDouble()); + return Value.Double; +} + +void VariantValue::setDouble(double NewValue) { + reset(); + Type = VT_Double; + Value.Double = NewValue; +} + +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_Boolean: + if (!isBoolean()) + return false; + *Specificity = 1; + return true; + + case ArgKind::AK_Double: + if (!isDouble()) + return false; + *Specificity = 1; + return true; + + 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_Boolean: return "Boolean"; + case VT_Double: return "Double"; + case VT_Unsigned: return "Unsigned"; + case VT_Nothing: return "Nothing"; + } + llvm_unreachable("Invalid Type"); +} + +} // end namespace dynamic +} // end namespace ast_matchers +} // end namespace clang |