diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index f131ac17c11bb..5275b86a57a47 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -2062,12 +2062,16 @@ bool Compiler::visitArrayElemInit(unsigned ElemIndex, const Expr *Init, template bool Compiler::visitCallArgs(ArrayRef Args, const FunctionDecl *FuncDecl, - bool Activate) { + bool Activate, bool IsOperatorCall) { assert(VarScope->getKind() == ScopeKind::Call); llvm::BitVector NonNullArgs; if (FuncDecl && FuncDecl->hasAttr()) NonNullArgs = collectNonNullArgs(FuncDecl, Args); + bool ExplicitMemberFn = false; + if (const auto *MD = dyn_cast_if_present(FuncDecl)) + ExplicitMemberFn = MD->isExplicitObjectMemberFunction(); + unsigned ArgIndex = 0; for (const Expr *Arg : Args) { if (canClassify(Arg)) { @@ -2075,8 +2079,19 @@ bool Compiler::visitCallArgs(ArrayRef Args, return false; } else { - std::optional LocalIndex = allocateLocal( - Arg, Arg->getType(), /*ExtendingDecl=*/nullptr, ScopeKind::Call); + DeclTy Source = Arg; + if (FuncDecl) { + // Try to use the parameter declaration instead of the argument + // expression as a source. + unsigned DeclIndex = ArgIndex - IsOperatorCall + ExplicitMemberFn; + if (DeclIndex < FuncDecl->getNumParams()) + Source = FuncDecl->getParamDecl(ArgIndex - IsOperatorCall + + ExplicitMemberFn); + } + + std::optional LocalIndex = + allocateLocal(std::move(Source), Arg->getType(), + /*ExtendingDecl=*/nullptr, ScopeKind::Call); if (!LocalIndex) return false; @@ -4489,14 +4504,6 @@ template unsigned Compiler::allocateLocalPrimitive( DeclTy &&Src, PrimType Ty, bool IsConst, const ValueDecl *ExtendingDecl, ScopeKind SC, bool IsConstexprUnknown) { - // Make sure we don't accidentally register the same decl twice. - if (const auto *VD = - dyn_cast_if_present(Src.dyn_cast())) { - assert(!P.getGlobal(VD)); - assert(!Locals.contains(VD)); - (void)VD; - } - // FIXME: There are cases where Src.is() is wrong, e.g. // (int){12} in C. Consider using Expr::isTemporaryObject() instead // or isa(). @@ -4518,19 +4525,11 @@ std::optional Compiler::allocateLocal(DeclTy &&Src, QualType Ty, const ValueDecl *ExtendingDecl, ScopeKind SC, bool IsConstexprUnknown) { - // Make sure we don't accidentally register the same decl twice. - if ([[maybe_unused]] const auto *VD = - dyn_cast_if_present(Src.dyn_cast())) { - assert(!P.getGlobal(VD)); - assert(!Locals.contains(VD)); - } - const ValueDecl *Key = nullptr; const Expr *Init = nullptr; bool IsTemporary = false; if (auto *VD = dyn_cast_if_present(Src.dyn_cast())) { Key = VD; - Ty = VD->getType(); if (const auto *VarD = dyn_cast(VD)) Init = VarD->getInit(); @@ -5167,7 +5166,8 @@ bool Compiler::VisitCallExpr(const CallExpr *E) { return false; } - if (!this->visitCallArgs(Args, FuncDecl, IsAssignmentOperatorCall)) + if (!this->visitCallArgs(Args, FuncDecl, IsAssignmentOperatorCall, + isa(E))) return false; // Undo the argument reversal we did earlier. diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h index d72ffa13f6b9d..901934e530ade 100644 --- a/clang/lib/AST/ByteCode/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -306,7 +306,7 @@ class Compiler : public ConstStmtVisitor, bool>, bool visitArrayElemInit(unsigned ElemIndex, const Expr *Init, OptPrimType InitT); bool visitCallArgs(ArrayRef Args, const FunctionDecl *FuncDecl, - bool Activate); + bool Activate, bool IsOperatorCall); /// Creates a local primitive value. unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst, diff --git a/clang/test/AST/ByteCode/cxx23.cpp b/clang/test/AST/ByteCode/cxx23.cpp index 45dd4f528aefb..2182d7c4e4325 100644 --- a/clang/test/AST/ByteCode/cxx23.cpp +++ b/clang/test/AST/ByteCode/cxx23.cpp @@ -309,15 +309,14 @@ namespace NonLiteralDtorInParam { ~NonLiteral() {} // all23-note {{declared here}} }; constexpr int F2(NonLiteral N) { // all20-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} \ - // ref23-note {{non-constexpr function '~NonLiteral' cannot be used in a constant expression}} + // all23-note {{non-constexpr function '~NonLiteral' cannot be used in a constant expression}} return 8; } void test() { NonLiteral L; - constexpr auto D = F2(L); // all23-error {{must be initialized by a constant expression}} \ - // expected23-note {{non-constexpr function '~NonLiteral' cannot be used in a constant expression}} + constexpr auto D = F2(L); // all23-error {{must be initialized by a constant expression}} } } diff --git a/clang/test/AST/ByteCode/lifetimes.cpp b/clang/test/AST/ByteCode/lifetimes.cpp index 5c8d56291f079..c8bf02c228481 100644 --- a/clang/test/AST/ByteCode/lifetimes.cpp +++ b/clang/test/AST/ByteCode/lifetimes.cpp @@ -94,14 +94,13 @@ namespace CallScope { int n = 0; constexpr int f() const { return 0; } }; - constexpr Q *out_of_lifetime(Q q) { return &q; } // both-warning {{address of stack}} + constexpr Q *out_of_lifetime(Q q) { return &q; } // both-warning {{address of stack}} \ + // expected-note 2{{declared here}} constexpr int k3 = out_of_lifetime({})->n; // both-error {{must be initialized by a constant expression}} \ - // expected-note {{read of temporary whose lifetime has ended}} \ - // expected-note {{temporary created here}} \ + // expected-note {{read of variable whose lifetime has ended}} \ // ref-note {{read of object outside its lifetime}} constexpr int k4 = out_of_lifetime({})->f(); // both-error {{must be initialized by a constant expression}} \ - // expected-note {{member call on temporary whose lifetime has ended}} \ - // expected-note {{temporary created here}} \ + // expected-note {{member call on variable whose lifetime has ended}} \ // ref-note {{member call on object outside its lifetime}} } diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp index 3229a91fbcefb..1c832e51c2cbc 100644 --- a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp +++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify=expected -std=c++23 %s +// RUN: %clang_cc1 -fsyntax-only -verify=expected -std=c++23 %s -fexperimental-new-constant-interpreter // This test covers modifications made by P2448R2.