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
24 changes: 16 additions & 8 deletions clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4293,7 +4293,8 @@ bool Compiler<Emitter>::emitConst(const APSInt &Value, const Expr *E) {

template <class Emitter>
unsigned Compiler<Emitter>::allocateLocalPrimitive(
DeclTy &&Src, PrimType Ty, bool IsConst, const ValueDecl *ExtendingDecl) {
DeclTy &&Src, PrimType Ty, bool IsConst, const ValueDecl *ExtendingDecl,
bool IsConstexprUnknown) {
// Make sure we don't accidentally register the same decl twice.
if (const auto *VD =
dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
Expand All @@ -4307,6 +4308,7 @@ unsigned Compiler<Emitter>::allocateLocalPrimitive(
// or isa<MaterializeTemporaryExpr>().
Descriptor *D = P.createDescriptor(Src, Ty, nullptr, Descriptor::InlineDescMD,
IsConst, isa<const Expr *>(Src));
D->IsConstexprUnknown = IsConstexprUnknown;
Scope::Local Local = this->createLocal(D);
if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>()))
Locals.insert({VD, Local});
Expand All @@ -4320,7 +4322,8 @@ unsigned Compiler<Emitter>::allocateLocalPrimitive(
template <class Emitter>
std::optional<unsigned>
Compiler<Emitter>::allocateLocal(DeclTy &&Src, QualType Ty,
const ValueDecl *ExtendingDecl) {
const ValueDecl *ExtendingDecl,
bool IsConstexprUnknown) {
// Make sure we don't accidentally register the same decl twice.
if ([[maybe_unused]] const auto *VD =
dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
Expand Down Expand Up @@ -4349,6 +4352,7 @@ Compiler<Emitter>::allocateLocal(DeclTy &&Src, QualType Ty,
IsTemporary, /*IsMutable=*/false, Init);
if (!D)
return std::nullopt;
D->IsConstexprUnknown = IsConstexprUnknown;

Scope::Local Local = this->createLocal(D);
if (Key)
Expand Down Expand Up @@ -4460,9 +4464,10 @@ bool Compiler<Emitter>::visitExpr(const Expr *E, bool DestroyToplevelScope) {
}

template <class Emitter>
VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD) {
VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD,
bool IsConstexprUnknown) {

auto R = this->visitVarDecl(VD, /*Toplevel=*/true);
auto R = this->visitVarDecl(VD, /*Toplevel=*/true, IsConstexprUnknown);

if (R.notCreated())
return R;
Expand Down Expand Up @@ -4550,7 +4555,8 @@ bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD,

template <class Emitter>
VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
bool Toplevel) {
bool Toplevel,
bool IsConstexprUnknown) {
// We don't know what to do with these, so just return false.
if (VD->getType().isNull())
return false;
Expand Down Expand Up @@ -4620,7 +4626,8 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,

if (VarT) {
unsigned Offset = this->allocateLocalPrimitive(
VD, *VarT, VD->getType().isConstQualified());
VD, *VarT, VD->getType().isConstQualified(), nullptr,
IsConstexprUnknown);
if (Init) {
// If this is a toplevel declaration, create a scope for the
// initializer.
Expand All @@ -4636,7 +4643,8 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
}
}
} else {
if (std::optional<unsigned> Offset = this->allocateLocal(VD)) {
if (std::optional<unsigned> Offset = this->allocateLocal(
VD, VD->getType(), nullptr, IsConstexprUnknown)) {
if (!Init)
return true;

Expand Down Expand Up @@ -6461,7 +6469,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {

// In case we need to re-visit a declaration.
auto revisit = [&](const VarDecl *VD) -> bool {
auto VarState = this->visitDecl(VD);
auto VarState = this->visitDecl(VD, /*IsConstexprUnknown=*/true);

if (VarState.notCreated())
return true;
Expand Down
12 changes: 8 additions & 4 deletions clang/lib/AST/ByteCode/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,10 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
/// intact.
bool delegate(const Expr *E);
/// Creates and initializes a variable from the given decl.
VarCreationState visitVarDecl(const VarDecl *VD, bool Toplevel = false);
VarCreationState visitDecl(const VarDecl *VD);
VarCreationState visitVarDecl(const VarDecl *VD, bool Toplevel = false,
bool IsConstexprUnknown = false);
VarCreationState visitDecl(const VarDecl *VD,
bool IsConstexprUnknown = false);
/// Visit an APValue.
bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E);
bool visitAPValueInitializer(const APValue &Val, const Expr *E, QualType T);
Expand All @@ -303,12 +305,14 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,

/// Creates a local primitive value.
unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst,
const ValueDecl *ExtendingDecl = nullptr);
const ValueDecl *ExtendingDecl = nullptr,
bool IsConstexprUnknown = false);

/// Allocates a space storing a local given its type.
std::optional<unsigned>
allocateLocal(DeclTy &&Decl, QualType Ty = QualType(),
const ValueDecl *ExtendingDecl = nullptr);
const ValueDecl *ExtendingDecl = nullptr,
bool IsConstexprUnknown = false);
std::optional<unsigned> allocateTemporary(const Expr *E);

private:
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/ByteCode/Descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ struct Descriptor final {
const bool IsArray = false;
/// Flag indicating if this is a dummy descriptor.
bool IsDummy = false;
bool IsConstexprUnknown = false;

/// Storage management methods.
const BlockCtorFn CtorFn = nullptr;
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/ByteCode/Disasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,8 @@ LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const {

if (isDummy())
OS << " dummy";
if (IsConstexprUnknown)
OS << " constexpr-unknown";
}

/// Dump descriptor, including all valid offsets.
Expand Down
9 changes: 4 additions & 5 deletions clang/lib/AST/ByteCode/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,15 +299,14 @@ void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC,
TYPE_SWITCH(Ty, S.Stk.discard<T>());
}

// FIXME: Instead of using this fairly expensive test, we should
// just mark constexpr-unknown values when creating them.
bool isConstexprUnknown(const Pointer &P) {
if (!P.isBlockPointer())
return false;

if (P.isDummy())
return false;
const VarDecl *VD = P.block()->getDescriptor()->asVarDecl();
return VD && VD->hasLocalStorage() && !isa<ParmVarDecl>(VD);
return isa_and_nonnull<ParmVarDecl>(P.getDeclDesc()->asValueDecl());

return P.getDeclDesc()->IsConstexprUnknown;
}

bool CheckBCPResult(InterpState &S, const Pointer &Ptr) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ unsigned Program::getOrCreateDummy(const DeclTy &D) {
if (const auto *E = dyn_cast<const Expr *>(D)) {
QT = E->getType();
} else {
const ValueDecl *VD = cast<ValueDecl>(cast<const Decl *>(D));
const auto *VD = cast<ValueDecl>(cast<const Decl *>(D));
IsWeak = VD->isWeak();
QT = VD->getType();
if (const auto *RT = QT->getAs<ReferenceType>())
Expand Down
35 changes: 33 additions & 2 deletions clang/test/AST/ByteCode/codegen.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s -fexperimental-new-constant-interpreter | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s -fcxx-exceptions | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s -fcxx-exceptions -fexperimental-new-constant-interpreter | FileCheck %s

#ifdef __SIZEOF_INT128__
// CHECK: @PR11705 = global i128 0
Expand Down Expand Up @@ -104,3 +104,34 @@ int notdead() {
}
// CHECK: _ZZ7notdeadvEN3$_0clEv
// CHECK: ret i32 %cond

/// The conmparison of those two parameters should NOT work.
bool paramcmp(const int& lhs, const int& rhs) {
if (&lhs == &rhs)
return true;
return false;
}
// CHECK: _Z8paramcmpRKiS0_
// CHECK: if.then
// CHECK: if.end

/// &x == &OuterX should work and return 0.
class X {
public:
X();
X(const X&);
X(const volatile X &);
~X();
};

extern X OuterX;

X test24() {
X x;
if (&x == &OuterX)
throw 0;
return x;
}
// CHECK: _Z6test24v
// CHECK-NOT: eh.resume
// CHECK-NOT: unreachable
Loading