llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> I forgot to call this here as well. It was only used in the EvalEmitter implementation of the function. Also fix a problem where we didn't diagnose out-of-lifetime reads here. --- Full diff: https://github.com/llvm/llvm-project/pull/152090.diff 3 Files Affected: - (modified) clang/lib/AST/ByteCode/Interp.cpp (+2) - (modified) clang/lib/AST/ByteCode/Interp.h (+1-1) - (modified) clang/test/AST/ByteCode/cxx2a.cpp (+38) ``````````diff diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index f2366f674f45b..eb4e4800d44ae 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -752,6 +752,8 @@ bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { // Similarly, for local loads. bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { + if (!CheckLifetime(S, OpPC, Ptr, AK_Read)) + return false; if (!CheckInitialized(S, OpPC, Ptr, AK_Read)) return false; if (!CheckVolatile(S, OpPC, Ptr, AK_Read)) diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 61e776965a006..8a28106c0583a 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -1352,7 +1352,7 @@ inline bool ConstFloat(InterpState &S, CodePtr OpPC, const Floating &F) { template <PrimType Name, class T = typename PrimConv<Name>::T> bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I) { const Pointer &Ptr = S.Current->getLocalPointer(I); - if (!CheckLoad(S, OpPC, Ptr)) + if (!CheckLocalLoad(S, OpPC, Ptr)) return false; S.Stk.push<T>(Ptr.deref<T>()); return true; diff --git a/clang/test/AST/ByteCode/cxx2a.cpp b/clang/test/AST/ByteCode/cxx2a.cpp index d9541aca225b9..ac2f9883d49b6 100644 --- a/clang/test/AST/ByteCode/cxx2a.cpp +++ b/clang/test/AST/ByteCode/cxx2a.cpp @@ -1,6 +1,25 @@ // RUN: %clang_cc1 -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both %s // RUN: %clang_cc1 -std=c++2a -fsyntax-only -fcxx-exceptions -verify=expected,both %s -fexperimental-new-constant-interpreter + +namespace std { + struct type_info; + struct destroying_delete_t { + explicit destroying_delete_t() = default; + } inline constexpr destroying_delete{}; + struct nothrow_t { + explicit nothrow_t() = default; + } inline constexpr nothrow{}; + using size_t = decltype(sizeof(0)); + enum class align_val_t : size_t {}; +}; + +constexpr void *operator new(std::size_t, void *p) { return p; } +namespace std { + template<typename T> constexpr T *construct(T *p) { return new (p) T; } + template<typename T> constexpr void destroy(T *p) { p->~T(); } +} + template <unsigned N> struct S { S() requires (N==1) = default; @@ -187,3 +206,22 @@ namespace PureVirtual { struct PureVirtualCall : Abstract { void f(); }; // both-note {{in call to 'Abstract}} constexpr PureVirtualCall pure_virtual_call; // both-error {{constant expression}} both-note {{in call to 'PureVirtualCall}} } + +namespace Dtor { + constexpr bool pseudo(bool read, bool recreate) { + using T = bool; + bool b = false; // both-note {{lifetime has already ended}} + // This evaluates the store to 'b'... + (b = true).~T(); + // ... and ends the lifetime of the object. + return (read + ? b // both-note {{read of object outside its lifetime}} + : true) + + (recreate + ? (std::construct(&b), true) + : true); + } + static_assert(pseudo(false, false)); // both-error {{constant expression}} both-note {{in call}} + static_assert(pseudo(true, false)); // both-error {{constant expression}} both-note {{in call}} + static_assert(pseudo(false, true)); +} `````````` </details> https://github.com/llvm/llvm-project/pull/152090 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits