Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions clang/lib/AST/ByteCode/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
#endif
}

Result = Res.toAPValue();
Result = Res.stealAPValue();

return true;
}
Expand Down Expand Up @@ -121,7 +121,7 @@ bool Context::evaluate(State &Parent, const Expr *E, APValue &Result,
#endif
}

Result = Res.toAPValue();
Result = Res.stealAPValue();
return true;
}

Expand Down Expand Up @@ -153,7 +153,7 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
#endif
}

Result = Res.toAPValue();
Result = Res.stealAPValue();
return true;
}

Expand Down
34 changes: 5 additions & 29 deletions clang/lib/AST/ByteCode/Disasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -551,37 +551,13 @@ LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const {
LLVM_DUMP_METHOD void EvaluationResult::dump() const {
assert(Ctx);
auto &OS = llvm::errs();
const ASTContext &ASTCtx = Ctx->getASTContext();

switch (Kind) {
case Empty:
if (empty()) {
OS << "Empty\n";
break;
case RValue:
OS << "RValue: ";
std::get<APValue>(Value).dump(OS, ASTCtx);
break;
case LValue: {
assert(Source);
QualType SourceType;
if (const auto *D = dyn_cast<const Decl *>(Source)) {
if (const auto *VD = dyn_cast<ValueDecl>(D))
SourceType = VD->getType();
} else if (const auto *E = dyn_cast<const Expr *>(Source)) {
SourceType = E->getType();
}

OS << "LValue: ";
if (const auto *P = std::get_if<Pointer>(&Value))
P->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);
OS << "\n";
break;
}
case Invalid:
} else if (isInvalid()) {
OS << "Invalid\n";
break;
case Valid:
OS << "Valid\n";
break;
} else {
OS << "Value: ";
Value.dump(OS, Ctx->getASTContext());
}
}
32 changes: 1 addition & 31 deletions clang/lib/AST/ByteCode/EvaluationResult.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "EvaluationResult.h"
#include "InterpState.h"
#include "Pointer.h"
#include "Record.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
Expand All @@ -16,37 +17,6 @@
namespace clang {
namespace interp {

APValue EvaluationResult::toAPValue() const {
assert(!empty());
switch (Kind) {
case LValue:
// Either a pointer or a function pointer.
if (const auto *P = std::get_if<Pointer>(&Value))
return P->toAPValue(Ctx->getASTContext());
else
llvm_unreachable("Unhandled LValue type");
break;
case RValue:
return std::get<APValue>(Value);
case Valid:
return APValue();
default:
llvm_unreachable("Unhandled result kind?");
}
}

std::optional<APValue> EvaluationResult::toRValue() const {
if (Kind == RValue)
return toAPValue();

assert(Kind == LValue);

// We have a pointer and want an RValue.
if (const auto *P = std::get_if<Pointer>(&Value))
return P->toRValue(*Ctx, getSourceType());
llvm_unreachable("Unhandled lvalue kind");
}

static void DiagnoseUninitializedSubobject(InterpState &S, SourceLocation Loc,
const FieldDecl *SubObjDecl) {
assert(SubObjDecl && "Subobject declaration does not exist");
Expand Down
31 changes: 13 additions & 18 deletions clang/lib/AST/ByteCode/EvaluationResult.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#ifndef LLVM_CLANG_AST_INTERP_EVALUATION_RESULT_H
#define LLVM_CLANG_AST_INTERP_EVALUATION_RESULT_H

#include "Pointer.h"
#include "clang/AST/APValue.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
Expand All @@ -20,6 +19,9 @@ namespace clang {
namespace interp {
class EvalEmitter;
class Context;
class Pointer;
class SourceInfo;
class InterpState;

/// Defines the result of an evaluation.
///
Expand All @@ -32,8 +34,6 @@ class EvaluationResult final {
public:
enum ResultKind {
Empty, // Initial state.
LValue, // Result is an lvalue/pointer.
RValue, // Result is an rvalue.
Invalid, // Result is invalid.
Valid, // Result is valid and empty.
};
Expand All @@ -42,7 +42,7 @@ class EvaluationResult final {

private:
const Context *Ctx = nullptr;
std::variant<std::monostate, Pointer, APValue> Value;
APValue Value;
ResultKind Kind = Empty;
DeclTy Source = nullptr; // Currently only needed for dump().

Expand All @@ -55,10 +55,8 @@ class EvaluationResult final {
void setSource(DeclTy D) { Source = D; }

void takeValue(APValue &&V) {
// V could still be an LValue.
assert(empty());
Value = std::move(V);
Kind = RValue;
}
void setInvalid() {
// We are NOT asserting empty() here, since setting it to invalid
Expand All @@ -75,18 +73,15 @@ class EvaluationResult final {

bool empty() const { return Kind == Empty; }
bool isInvalid() const { return Kind == Invalid; }
bool isLValue() const { return Kind == LValue; }
bool isRValue() const { return Kind == RValue; }
bool isPointer() const { return std::holds_alternative<Pointer>(Value); }

/// Returns an APValue for the evaluation result. The returned
/// APValue might be an LValue or RValue.
APValue toAPValue() const;

/// If the result is an LValue, convert that to an RValue
/// and return it. This may fail, e.g. if the result is an
/// LValue and we can't read from it.
std::optional<APValue> toRValue() const;

/// Returns an APValue for the evaluation result.
APValue toAPValue() const {
assert(!empty());
assert(!isInvalid());
return Value;
}

APValue stealAPValue() { return std::move(Value); }

/// Check that all subobjects of the given pointer have been initialized.
bool checkFullyInitialized(InterpState &S, const Pointer &Ptr) const;
Expand Down
Loading