Path: blob/main/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
35291 views
//===--- VariantValue.cpp - Polymorphic value type --------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// Polymorphic value type.10///11//===----------------------------------------------------------------------===//1213#include "clang/ASTMatchers/Dynamic/VariantValue.h"14#include "clang/Basic/LLVM.h"15#include "llvm/ADT/STLExtras.h"16#include <optional>1718namespace clang {19namespace ast_matchers {20namespace dynamic {2122std::string ArgKind::asString() const {23switch (getArgKind()) {24case AK_Matcher:25return (Twine("Matcher<") + NodeKind.asStringRef() + ">").str();26case AK_Node:27return NodeKind.asStringRef().str();28case AK_Boolean:29return "boolean";30case AK_Double:31return "double";32case AK_Unsigned:33return "unsigned";34case AK_String:35return "string";36}37llvm_unreachable("unhandled ArgKind");38}3940bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {41if (K != To.K)42return false;43if (K != AK_Matcher && K != AK_Node) {44if (Specificity)45*Specificity = 1;46return true;47}48unsigned Distance;49if (!NodeKind.isBaseOf(To.NodeKind, &Distance))50return false;5152if (Specificity)53*Specificity = 100 - Distance;54return true;55}5657bool58VariantMatcher::MatcherOps::canConstructFrom(const DynTypedMatcher &Matcher,59bool &IsExactMatch) const {60IsExactMatch = Matcher.getSupportedKind().isSame(NodeKind);61return Matcher.canConvertTo(NodeKind);62}6364DynTypedMatcher VariantMatcher::MatcherOps::convertMatcher(65const DynTypedMatcher &Matcher) const {66return Matcher.dynCastTo(NodeKind);67}6869std::optional<DynTypedMatcher>70VariantMatcher::MatcherOps::constructVariadicOperator(71DynTypedMatcher::VariadicOperator Op,72ArrayRef<VariantMatcher> InnerMatchers) const {73std::vector<DynTypedMatcher> DynMatchers;74for (const auto &InnerMatcher : InnerMatchers) {75// Abort if any of the inner matchers can't be converted to76// Matcher<T>.77if (!InnerMatcher.Value)78return std::nullopt;79std::optional<DynTypedMatcher> Inner =80InnerMatcher.Value->getTypedMatcher(*this);81if (!Inner)82return std::nullopt;83DynMatchers.push_back(*Inner);84}85return DynTypedMatcher::constructVariadic(Op, NodeKind, DynMatchers);86}8788VariantMatcher::Payload::~Payload() {}8990class VariantMatcher::SinglePayload : public VariantMatcher::Payload {91public:92SinglePayload(const DynTypedMatcher &Matcher) : Matcher(Matcher) {}9394std::optional<DynTypedMatcher> getSingleMatcher() const override {95return Matcher;96}9798std::string getTypeAsString() const override {99return (Twine("Matcher<") + Matcher.getSupportedKind().asStringRef() + ">")100.str();101}102103std::optional<DynTypedMatcher>104getTypedMatcher(const MatcherOps &Ops) const override {105bool Ignore;106if (Ops.canConstructFrom(Matcher, Ignore))107return Matcher;108return std::nullopt;109}110111bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {112return ArgKind::MakeMatcherArg(Matcher.getSupportedKind())113.isConvertibleTo(ArgKind::MakeMatcherArg(Kind), Specificity);114}115116private:117const DynTypedMatcher Matcher;118};119120class VariantMatcher::PolymorphicPayload : public VariantMatcher::Payload {121public:122PolymorphicPayload(std::vector<DynTypedMatcher> MatchersIn)123: Matchers(std::move(MatchersIn)) {}124125~PolymorphicPayload() override {}126127std::optional<DynTypedMatcher> getSingleMatcher() const override {128if (Matchers.size() != 1)129return std::nullopt;130return Matchers[0];131}132133std::string getTypeAsString() const override {134std::string Inner;135for (size_t i = 0, e = Matchers.size(); i != e; ++i) {136if (i != 0)137Inner += "|";138Inner += Matchers[i].getSupportedKind().asStringRef();139}140return (Twine("Matcher<") + Inner + ">").str();141}142143std::optional<DynTypedMatcher>144getTypedMatcher(const MatcherOps &Ops) const override {145bool FoundIsExact = false;146const DynTypedMatcher *Found = nullptr;147int NumFound = 0;148for (size_t i = 0, e = Matchers.size(); i != e; ++i) {149bool IsExactMatch;150if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) {151if (Found) {152if (FoundIsExact) {153assert(!IsExactMatch && "We should not have two exact matches.");154continue;155}156}157Found = &Matchers[i];158FoundIsExact = IsExactMatch;159++NumFound;160}161}162// We only succeed if we found exactly one, or if we found an exact match.163if (Found && (FoundIsExact || NumFound == 1))164return *Found;165return std::nullopt;166}167168bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {169unsigned MaxSpecificity = 0;170for (const DynTypedMatcher &Matcher : Matchers) {171unsigned ThisSpecificity;172if (ArgKind::MakeMatcherArg(Matcher.getSupportedKind())173.isConvertibleTo(ArgKind::MakeMatcherArg(Kind),174&ThisSpecificity)) {175MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);176}177}178if (Specificity)179*Specificity = MaxSpecificity;180return MaxSpecificity > 0;181}182183const std::vector<DynTypedMatcher> Matchers;184};185186class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {187public:188VariadicOpPayload(DynTypedMatcher::VariadicOperator Op,189std::vector<VariantMatcher> Args)190: Op(Op), Args(std::move(Args)) {}191192std::optional<DynTypedMatcher> getSingleMatcher() const override {193return std::nullopt;194}195196std::string getTypeAsString() const override {197std::string Inner;198for (size_t i = 0, e = Args.size(); i != e; ++i) {199if (i != 0)200Inner += "&";201Inner += Args[i].getTypeAsString();202}203return Inner;204}205206std::optional<DynTypedMatcher>207getTypedMatcher(const MatcherOps &Ops) const override {208return Ops.constructVariadicOperator(Op, Args);209}210211bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {212for (const VariantMatcher &Matcher : Args) {213if (!Matcher.isConvertibleTo(Kind, Specificity))214return false;215}216return true;217}218219private:220const DynTypedMatcher::VariadicOperator Op;221const std::vector<VariantMatcher> Args;222};223224VariantMatcher::VariantMatcher() {}225226VariantMatcher VariantMatcher::SingleMatcher(const DynTypedMatcher &Matcher) {227return VariantMatcher(std::make_shared<SinglePayload>(Matcher));228}229230VariantMatcher231VariantMatcher::PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers) {232return VariantMatcher(233std::make_shared<PolymorphicPayload>(std::move(Matchers)));234}235236VariantMatcher VariantMatcher::VariadicOperatorMatcher(237DynTypedMatcher::VariadicOperator Op,238std::vector<VariantMatcher> Args) {239return VariantMatcher(240std::make_shared<VariadicOpPayload>(Op, std::move(Args)));241}242243std::optional<DynTypedMatcher> VariantMatcher::getSingleMatcher() const {244return Value ? Value->getSingleMatcher() : std::optional<DynTypedMatcher>();245}246247void VariantMatcher::reset() { Value.reset(); }248249std::string VariantMatcher::getTypeAsString() const {250if (Value) return Value->getTypeAsString();251return "<Nothing>";252}253254VariantValue::VariantValue(const VariantValue &Other) : Type(VT_Nothing) {255*this = Other;256}257258VariantValue::VariantValue(bool Boolean) : Type(VT_Nothing) {259setBoolean(Boolean);260}261262VariantValue::VariantValue(double Double) : Type(VT_Nothing) {263setDouble(Double);264}265266VariantValue::VariantValue(unsigned Unsigned) : Type(VT_Nothing) {267setUnsigned(Unsigned);268}269270VariantValue::VariantValue(StringRef String) : Type(VT_Nothing) {271setString(String);272}273274VariantValue::VariantValue(ASTNodeKind NodeKind) : Type(VT_Nothing) {275setNodeKind(NodeKind);276}277278VariantValue::VariantValue(const VariantMatcher &Matcher) : Type(VT_Nothing) {279setMatcher(Matcher);280}281282VariantValue::~VariantValue() { reset(); }283284VariantValue &VariantValue::operator=(const VariantValue &Other) {285if (this == &Other) return *this;286reset();287switch (Other.Type) {288case VT_Boolean:289setBoolean(Other.getBoolean());290break;291case VT_Double:292setDouble(Other.getDouble());293break;294case VT_Unsigned:295setUnsigned(Other.getUnsigned());296break;297case VT_String:298setString(Other.getString());299break;300case VT_NodeKind:301setNodeKind(Other.getNodeKind());302break;303case VT_Matcher:304setMatcher(Other.getMatcher());305break;306case VT_Nothing:307Type = VT_Nothing;308break;309}310return *this;311}312313void VariantValue::reset() {314switch (Type) {315case VT_String:316delete Value.String;317break;318case VT_Matcher:319delete Value.Matcher;320break;321case VT_NodeKind:322delete Value.NodeKind;323break;324// Cases that do nothing.325case VT_Boolean:326case VT_Double:327case VT_Unsigned:328case VT_Nothing:329break;330}331Type = VT_Nothing;332}333334bool VariantValue::isBoolean() const {335return Type == VT_Boolean;336}337338bool VariantValue::getBoolean() const {339assert(isBoolean());340return Value.Boolean;341}342343void VariantValue::setBoolean(bool NewValue) {344reset();345Type = VT_Boolean;346Value.Boolean = NewValue;347}348349bool VariantValue::isDouble() const {350return Type == VT_Double;351}352353double VariantValue::getDouble() const {354assert(isDouble());355return Value.Double;356}357358void VariantValue::setDouble(double NewValue) {359reset();360Type = VT_Double;361Value.Double = NewValue;362}363364bool VariantValue::isUnsigned() const {365return Type == VT_Unsigned;366}367368unsigned VariantValue::getUnsigned() const {369assert(isUnsigned());370return Value.Unsigned;371}372373void VariantValue::setUnsigned(unsigned NewValue) {374reset();375Type = VT_Unsigned;376Value.Unsigned = NewValue;377}378379bool VariantValue::isString() const {380return Type == VT_String;381}382383const std::string &VariantValue::getString() const {384assert(isString());385return *Value.String;386}387388void VariantValue::setString(StringRef NewValue) {389reset();390Type = VT_String;391Value.String = new std::string(NewValue);392}393394bool VariantValue::isNodeKind() const { return Type == VT_NodeKind; }395396const ASTNodeKind &VariantValue::getNodeKind() const {397assert(isNodeKind());398return *Value.NodeKind;399}400401void VariantValue::setNodeKind(ASTNodeKind NewValue) {402reset();403Type = VT_NodeKind;404Value.NodeKind = new ASTNodeKind(NewValue);405}406407bool VariantValue::isMatcher() const {408return Type == VT_Matcher;409}410411const VariantMatcher &VariantValue::getMatcher() const {412assert(isMatcher());413return *Value.Matcher;414}415416void VariantValue::setMatcher(const VariantMatcher &NewValue) {417reset();418Type = VT_Matcher;419Value.Matcher = new VariantMatcher(NewValue);420}421422bool VariantValue::isConvertibleTo(ArgKind Kind, unsigned *Specificity) const {423switch (Kind.getArgKind()) {424case ArgKind::AK_Boolean:425if (!isBoolean())426return false;427*Specificity = 1;428return true;429430case ArgKind::AK_Double:431if (!isDouble())432return false;433*Specificity = 1;434return true;435436case ArgKind::AK_Unsigned:437if (!isUnsigned())438return false;439*Specificity = 1;440return true;441442case ArgKind::AK_String:443if (!isString())444return false;445*Specificity = 1;446return true;447448case ArgKind::AK_Node:449if (!isNodeKind())450return false;451return getMatcher().isConvertibleTo(Kind.getNodeKind(), Specificity);452453case ArgKind::AK_Matcher:454if (!isMatcher())455return false;456return getMatcher().isConvertibleTo(Kind.getMatcherKind(), Specificity);457}458llvm_unreachable("Invalid Type");459}460461bool VariantValue::isConvertibleTo(ArrayRef<ArgKind> Kinds,462unsigned *Specificity) const {463unsigned MaxSpecificity = 0;464for (const ArgKind& Kind : Kinds) {465unsigned ThisSpecificity;466if (!isConvertibleTo(Kind, &ThisSpecificity))467continue;468MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);469}470if (Specificity && MaxSpecificity > 0) {471*Specificity = MaxSpecificity;472}473return MaxSpecificity > 0;474}475476std::string VariantValue::getTypeAsString() const {477switch (Type) {478case VT_String: return "String";479case VT_Matcher: return getMatcher().getTypeAsString();480case VT_Boolean: return "Boolean";481case VT_Double: return "Double";482case VT_Unsigned: return "Unsigned";483case VT_NodeKind:484return getNodeKind().asStringRef().str();485case VT_Nothing: return "Nothing";486}487llvm_unreachable("Invalid Type");488}489490} // end namespace dynamic491} // end namespace ast_matchers492} // end namespace clang493494495