Fix class_value_ptr invariant bug found by fuzzer (#3025)

Invariant is `*class_value_ptr == this` when the static type matches the
dynamic type.
This commit is contained in:
josh11b
2023-07-27 20:39:54 +00:00
committed by GitHub
parent 56a011f356
commit 1006956ed5
3 changed files with 88 additions and 6 deletions
+17 -5
View File
@@ -19,7 +19,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Error.h"
namespace Carbon {
@@ -128,6 +127,7 @@ NominalClassValue::NominalClassValue(
inits_(inits),
base_(base),
class_value_ptr_(class_value_ptr) {
CARBON_CHECK(!base || (*base)->class_value_ptr() == class_value_ptr);
// Update ancestors's class value to point to latest child.
*class_value_ptr_ = this;
}
@@ -375,15 +375,27 @@ static auto SetFieldImpl(
if (auto inits = SetFieldImpl(arena, &object.inits(), path_begin,
path_end, field_value, source_loc);
inits.ok()) {
return arena->New<NominalClassValue>(
&object.type(), *inits, object.base(), object.class_value_ptr());
auto* class_value_ptr = arena->New<const NominalClassValue*>();
std::vector<const NominalClassValue*> base_path;
for (auto base = object.base(); base; base = (*base)->base()) {
base_path.push_back(*base);
}
std::optional<Nonnull<const NominalClassValue*>> base;
for (auto* base_path_elem : llvm::reverse(base_path)) {
base = arena->New<NominalClassValue>(&base_path_elem->type(),
&base_path_elem->inits(), base,
class_value_ptr);
}
return arena->New<NominalClassValue>(&object.type(), *inits, base,
class_value_ptr);
} else if (object.base().has_value()) {
auto new_base = SetFieldImpl(arena, object.base().value(), path_begin,
path_end, field_value, source_loc);
if (new_base.ok()) {
auto as_nominal_class_value = cast<NominalClassValue>(*new_base);
return arena->New<NominalClassValue>(
&object.type(), &object.inits(),
cast<NominalClassValue>(*new_base), object.class_value_ptr());
&object.type(), &object.inits(), as_nominal_class_value,
as_nominal_class_value->class_value_ptr());
}
}
// Failed to match, show full object content