
An uninitialized variable that caused a crash (https://lab.llvm.org/buildbot/#/builders/164/builds/11004) was identified using the memory analyzer, leading to the reversion of https://github.com/llvm/llvm-project/pull/141423. This pull request reapplies the previously reverted changes and includes the fix, which has been tested locally following the steps at https://github.com/google/sanitizers/wiki/SanitizerBotReproduceBuild. Note: the fix is included as part of the second commit
225 lines
6.1 KiB
C++
225 lines
6.1 KiB
C++
//===--- Variantvalue.cpp -------------------------------------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "mlir/Query/Matcher/VariantValue.h"
|
|
|
|
namespace mlir::query::matcher {
|
|
|
|
VariantMatcher::Payload::~Payload() = default;
|
|
|
|
class VariantMatcher::SinglePayload : public VariantMatcher::Payload {
|
|
public:
|
|
explicit SinglePayload(DynMatcher matcher) : matcher(std::move(matcher)) {}
|
|
|
|
std::optional<DynMatcher> getDynMatcher() const override { return matcher; }
|
|
|
|
std::string getTypeAsString() const override { return "Matcher"; }
|
|
|
|
private:
|
|
DynMatcher matcher;
|
|
};
|
|
|
|
class VariantMatcher::VariadicOpPayload : public VariantMatcher::Payload {
|
|
public:
|
|
VariadicOpPayload(DynMatcher::VariadicOperator varOp,
|
|
std::vector<VariantMatcher> args)
|
|
: varOp(varOp), args(std::move(args)) {}
|
|
|
|
std::optional<DynMatcher> getDynMatcher() const override {
|
|
std::vector<DynMatcher> dynMatchers;
|
|
for (auto variantMatcher : args) {
|
|
std::optional<DynMatcher> dynMatcher = variantMatcher.getDynMatcher();
|
|
if (dynMatcher)
|
|
dynMatchers.push_back(dynMatcher.value());
|
|
}
|
|
auto result = DynMatcher::constructVariadic(varOp, dynMatchers);
|
|
return *result;
|
|
}
|
|
|
|
std::string getTypeAsString() const override {
|
|
std::string inner;
|
|
llvm::interleave(
|
|
args, [&](auto const &arg) { inner += arg.getTypeAsString(); },
|
|
[&] { inner += " & "; });
|
|
return inner;
|
|
}
|
|
|
|
private:
|
|
const DynMatcher::VariadicOperator varOp;
|
|
const std::vector<VariantMatcher> args;
|
|
};
|
|
|
|
VariantMatcher::VariantMatcher() = default;
|
|
|
|
VariantMatcher VariantMatcher::SingleMatcher(DynMatcher matcher) {
|
|
return VariantMatcher(std::make_shared<SinglePayload>(std::move(matcher)));
|
|
}
|
|
|
|
VariantMatcher
|
|
VariantMatcher::VariadicOperatorMatcher(DynMatcher::VariadicOperator varOp,
|
|
ArrayRef<VariantMatcher> args) {
|
|
return VariantMatcher(
|
|
std::make_shared<VariadicOpPayload>(varOp, std::move(args)));
|
|
}
|
|
|
|
std::optional<DynMatcher> VariantMatcher::MatcherOps::constructVariadicOperator(
|
|
DynMatcher::VariadicOperator varOp,
|
|
ArrayRef<VariantMatcher> innerMatchers) const {
|
|
std::vector<DynMatcher> dynMatchers;
|
|
for (const auto &innerMatcher : innerMatchers) {
|
|
if (!innerMatcher.value)
|
|
return std::nullopt;
|
|
std::optional<DynMatcher> inner = innerMatcher.value->getDynMatcher();
|
|
if (!inner)
|
|
return std::nullopt;
|
|
dynMatchers.push_back(*inner);
|
|
}
|
|
return *DynMatcher::constructVariadic(varOp, dynMatchers);
|
|
}
|
|
|
|
std::optional<DynMatcher> VariantMatcher::getDynMatcher() const {
|
|
return value ? value->getDynMatcher() : std::nullopt;
|
|
}
|
|
|
|
void VariantMatcher::reset() { value.reset(); }
|
|
|
|
std::string VariantMatcher::getTypeAsString() const { return "<Nothing>"; }
|
|
|
|
VariantValue::VariantValue(const VariantValue &other)
|
|
: type(ValueType::Nothing) {
|
|
*this = other;
|
|
}
|
|
|
|
VariantValue::VariantValue(const llvm::StringRef string)
|
|
: type(ValueType::String) {
|
|
value.String = new llvm::StringRef(string);
|
|
}
|
|
|
|
VariantValue::VariantValue(const VariantMatcher &matcher)
|
|
: type(ValueType::Matcher) {
|
|
value.Matcher = new VariantMatcher(matcher);
|
|
}
|
|
|
|
VariantValue::VariantValue(int64_t signedValue) : type(ValueType::Signed) {
|
|
value.Signed = signedValue;
|
|
}
|
|
|
|
VariantValue::VariantValue(bool setBoolean) : type(ValueType::Boolean) {
|
|
value.Boolean = setBoolean;
|
|
}
|
|
|
|
VariantValue::~VariantValue() { reset(); }
|
|
|
|
VariantValue &VariantValue::operator=(const VariantValue &other) {
|
|
if (this == &other)
|
|
return *this;
|
|
reset();
|
|
switch (other.type) {
|
|
case ValueType::String:
|
|
setString(other.getString());
|
|
break;
|
|
case ValueType::Matcher:
|
|
setMatcher(other.getMatcher());
|
|
break;
|
|
case ValueType::Signed:
|
|
setSigned(other.getSigned());
|
|
break;
|
|
case ValueType::Boolean:
|
|
setBoolean(other.getBoolean());
|
|
break;
|
|
case ValueType::Nothing:
|
|
type = ValueType::Nothing;
|
|
break;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
void VariantValue::reset() {
|
|
switch (type) {
|
|
case ValueType::String:
|
|
delete value.String;
|
|
break;
|
|
case ValueType::Matcher:
|
|
delete value.Matcher;
|
|
break;
|
|
// Cases that do nothing.
|
|
case ValueType::Signed:
|
|
case ValueType::Boolean:
|
|
case ValueType::Nothing:
|
|
break;
|
|
}
|
|
type = ValueType::Nothing;
|
|
}
|
|
|
|
// Signed
|
|
bool VariantValue::isSigned() const { return type == ValueType::Signed; }
|
|
|
|
int64_t VariantValue::getSigned() const { return value.Signed; }
|
|
|
|
void VariantValue::setSigned(int64_t newValue) {
|
|
type = ValueType::Signed;
|
|
value.Signed = newValue;
|
|
}
|
|
|
|
// Boolean
|
|
bool VariantValue::isBoolean() const { return type == ValueType::Boolean; }
|
|
|
|
bool VariantValue::getBoolean() const { return value.Boolean; }
|
|
|
|
void VariantValue::setBoolean(bool newValue) {
|
|
type = ValueType::Boolean;
|
|
value.Boolean = newValue;
|
|
}
|
|
|
|
bool VariantValue::isString() const { return type == ValueType::String; }
|
|
|
|
const llvm::StringRef &VariantValue::getString() const {
|
|
assert(isString());
|
|
return *value.String;
|
|
}
|
|
|
|
void VariantValue::setString(const llvm::StringRef &newValue) {
|
|
reset();
|
|
type = ValueType::String;
|
|
value.String = new llvm::StringRef(newValue);
|
|
}
|
|
|
|
bool VariantValue::isMatcher() const { return type == ValueType::Matcher; }
|
|
|
|
const VariantMatcher &VariantValue::getMatcher() const {
|
|
assert(isMatcher());
|
|
return *value.Matcher;
|
|
}
|
|
|
|
void VariantValue::setMatcher(const VariantMatcher &newValue) {
|
|
reset();
|
|
type = ValueType::Matcher;
|
|
value.Matcher = new VariantMatcher(newValue);
|
|
}
|
|
|
|
std::string VariantValue::getTypeAsString() const {
|
|
switch (type) {
|
|
case ValueType::String:
|
|
return "String";
|
|
case ValueType::Matcher:
|
|
return "Matcher";
|
|
case ValueType::Signed:
|
|
return "Signed";
|
|
case ValueType::Boolean:
|
|
return "Boolean";
|
|
case ValueType::Nothing:
|
|
return "Nothing";
|
|
}
|
|
llvm_unreachable("Invalid Type");
|
|
}
|
|
|
|
} // namespace mlir::query::matcher
|