Author: Timm Baeder Date: 2025-04-25T13:03:58+02:00 New Revision: d775b911c90e631f5cc332c07474f7121564e25b
URL: https://github.com/llvm/llvm-project/commit/d775b911c90e631f5cc332c07474f7121564e25b DIFF: https://github.com/llvm/llvm-project/commit/d775b911c90e631f5cc332c07474f7121564e25b.diff LOG: [clang][bytecode] Diagnose pseudo dtor calls before C++20 (#137303) Added: Modified: clang/lib/AST/ByteCode/Compiler.cpp clang/lib/AST/ByteCode/Interp.h clang/lib/AST/ByteCode/Opcodes.td clang/test/AST/ByteCode/cxx11.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 3c774c16696dc..fd306c0669d6c 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -4933,6 +4933,8 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) { } } else if (const auto *PD = dyn_cast<CXXPseudoDestructorExpr>(E->getCallee())) { + if (!this->emitCheckPseudoDtor(E)) + return false; const Expr *Base = PD->getBase(); if (!Base->isGLValue()) return this->discard(Base); diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 0cfeed86f0b51..ac5e095ffa1f1 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -2947,6 +2947,13 @@ inline bool SizelessVectorElementSize(InterpState &S, CodePtr OpPC) { return false; } +inline bool CheckPseudoDtor(InterpState &S, CodePtr OpPC) { + if (!S.getLangOpts().CPlusPlus20) + S.CCEDiag(S.Current->getSource(OpPC), + diag::note_constexpr_pseudo_destructor); + return true; +} + inline bool Assume(InterpState &S, CodePtr OpPC) { const auto Val = S.Stk.pop<Boolean>(); diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index 8451e54ad0c41..7a1cc4e8c408a 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -783,6 +783,7 @@ def SideEffect : Opcode {} def InvalidCast : Opcode { let Args = [ArgCastKind, ArgBool]; } +def CheckPseudoDtor : Opcode {} def InvalidDeclRef : Opcode { let Args = [ArgDeclRef, ArgBool]; diff --git a/clang/test/AST/ByteCode/cxx11.cpp b/clang/test/AST/ByteCode/cxx11.cpp index cb05f26d11206..18806801bdd33 100644 --- a/clang/test/AST/ByteCode/cxx11.cpp +++ b/clang/test/AST/ByteCode/cxx11.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-linux -fexperimental-new-constant-interpreter -verify=both,expected -std=c++11 %s -// RUN: %clang_cc1 -triple x86_64-linux -verify=both,ref -std=c++11 %s +// RUN: %clang_cc1 -triple x86_64-linux -verify=both,expected -std=c++11 %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -triple x86_64-linux -verify=both,ref -std=c++11 %s namespace IntOrEnum { const int k = 0; @@ -208,3 +208,16 @@ namespace ExternPointer { extern const S pu; constexpr const int *pua = &pu.a; // Ok. } + +namespace PseudoDtor { + typedef int I; + constexpr int f(int a = 1) { // both-error {{never produces a constant expression}} \ + // ref-note {{destroying object 'a' whose lifetime has already ended}} + return ( + a.~I(), // both-note {{pseudo-destructor call is not permitted}} \ + // expected-note {{pseudo-destructor call is not permitted}} + 0); + } + static_assert(f() == 0, ""); // both-error {{constant expression}} \ + // expected-note {{in call to}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits