Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2413,7 +2413,7 @@ "cannot take address of consteval function %0 outside" " of an immediate invocation">; def err_invalid_consteval_call : Error< - "call to consteval function '%q0' is not a constant expression">; + "call to consteval function %q0 is not a constant expression">; def err_invalid_consteval_decl_kind : Error< "%0 cannot be declared consteval">; def err_invalid_constexpr : Error< Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -14685,12 +14685,14 @@ if (getLangOpts().CUDA && !CheckCUDACall(ConstructLoc, Constructor)) return ExprError(); - return CXXConstructExpr::Create( - Context, DeclInitType, ConstructLoc, Constructor, Elidable, - ExprArgs, HadMultipleCandidates, IsListInitialization, - IsStdInitListInitialization, RequiresZeroInit, - static_cast(ConstructKind), - ParenRange); + return CheckForImmediateInvocation( + CXXConstructExpr::Create( + Context, DeclInitType, ConstructLoc, Constructor, Elidable, ExprArgs, + HadMultipleCandidates, IsListInitialization, + IsStdInitListInitialization, RequiresZeroInit, + static_cast(ConstructKind), + ParenRange), + Constructor); } ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -15311,6 +15311,8 @@ if (!CE->EvaluateAsConstantExpr(Eval, Expr::EvaluateForCodeGen, SemaRef.getASTContext(), true)) { Expr *InnerExpr = CE->getSubExpr()->IgnoreImplicit(); + if (auto* FunctionalCast = dyn_cast(InnerExpr)) + InnerExpr = FunctionalCast->getSubExpr(); FunctionDecl *FD = nullptr; if (auto *Call = dyn_cast(InnerExpr)) FD = cast(Call->getCalleeDecl()); @@ -15385,6 +15387,36 @@ Rec.ImmediateInvocationCandidates, It); ExprResult Res = Transformer.TransformExpr(It->getPointer()->getSubExpr()); assert(Res.isUsable()); + + /// CXXConstructExpr with a single argument are getting skipped by + /// TreeTransform in some situtation because they could be implicit. This is + /// can only occur for the top-level CXXConstructExpr because it is used + /// nowhere in the expression being transformed therefore will not be rebuild. + /// We need to rebuild it here if this occurred. + if (auto *OldExpr = + dyn_cast(It->getPointer()->IgnoreImplicit())) + if (!isa(Res.get()->IgnoreImplicit()) && + !isa(OldExpr)) { + Expr* Argument = Res.get(); + SmallVector ConstructorArgs; + bool Verify = SemaRef.CompleteConstructorCall( + OldExpr->getConstructor(), llvm::makeMutableArrayRef(&Argument, 1), + OldExpr->getBeginLoc(), ConstructorArgs, + OldExpr->getConstructor()->isExplicit(), + OldExpr->isListInitialization()); + assert(!Verify && "this shouldn't fail"); + (void)Verify; + + Res = SemaRef.BuildCXXConstructExpr( + OldExpr->getBeginLoc(), OldExpr->getType(), OldExpr->getConstructor(), + OldExpr->isElidable(), ConstructorArgs, + OldExpr->hadMultipleCandidates(), OldExpr->isListInitialization(), + OldExpr->isStdInitListInitialization(), + OldExpr->requiresZeroInitialization(), OldExpr->getConstructionKind(), + OldExpr->getParenOrBraceRange()); + Res = SemaRef.MaybeBindToTemporary(Res.get()); + } + Res = SemaRef.MaybeCreateExprWithCleanups(Res); It->getPointer()->setSubExpr(Res.get()); } Index: clang/lib/Sema/SemaInit.cpp =================================================================== --- clang/lib/Sema/SemaInit.cpp +++ clang/lib/Sema/SemaInit.cpp @@ -6416,12 +6416,14 @@ } S.MarkFunctionReferenced(Loc, Constructor); - CurInit = CXXTemporaryObjectExpr::Create( - S.Context, Constructor, - Entity.getType().getNonLValueExprType(S.Context), TSInfo, - ConstructorArgs, ParenOrBraceRange, HadMultipleCandidates, - IsListInitialization, IsStdInitListInitialization, - ConstructorInitRequiresZeroInit); + CurInit = S.CheckForImmediateInvocation( + CXXTemporaryObjectExpr::Create( + S.Context, Constructor, + Entity.getType().getNonLValueExprType(S.Context), TSInfo, + ConstructorArgs, ParenOrBraceRange, HadMultipleCandidates, + IsListInitialization, IsStdInitListInitialization, + ConstructorInitRequiresZeroInit), + Constructor); } else { CXXConstructExpr::ConstructionKind ConstructKind = CXXConstructExpr::CK_Complete; Index: clang/test/SemaCXX/cxx2a-consteval.cpp =================================================================== --- clang/test/SemaCXX/cxx2a-consteval.cpp +++ clang/test/SemaCXX/cxx2a-consteval.cpp @@ -260,6 +260,19 @@ } +namespace std { + +template struct remove_reference { using type = T; }; +template struct remove_reference { using type = T; }; +template struct remove_reference { using type = T; }; + +template +constexpr typename std::remove_reference::type&& move(T &&t) noexcept { + return static_cast::type &&>(t); +} + +} + namespace temporaries { struct A { @@ -295,12 +308,12 @@ { int k = const_a_ref(A()); } { int k = const_a_ref(a); } { int k = rvalue_ref(A()); } - { int k = rvalue_ref(static_cast(a)); } + { int k = rvalue_ref(std::move(a)); } { int k = const_a_ref(A().ret_a()); } { int k = const_a_ref(to_lvalue_ref(A().ret_a())); } - { int k = const_a_ref(to_lvalue_ref(static_cast(a))); } + { int k = const_a_ref(to_lvalue_ref(std::move(a))); } { int k = by_value_a(A().ret_a()); } - { int k = by_value_a(to_lvalue_ref(static_cast(a))); } + { int k = by_value_a(to_lvalue_ref(std::move(a))); } { int k = (A().ret_a(), A().ret_i()); } { int k = (const_a_ref(A().ret_a()), A().ret_i()); }// } @@ -345,10 +358,10 @@ { int k = const_a_ref(A()); } { int k = const_a_ref(a); } { int k = rvalue_ref(A()); } - { int k = rvalue_ref(static_cast(a)); } + { int k = rvalue_ref(std::move(a)); } { int k = const_a_ref(A().ret_a()); } { int k = const_a_ref(to_lvalue_ref(A().ret_a())); } - { int k = const_a_ref(to_lvalue_ref(static_cast(a))); } + { int k = const_a_ref(to_lvalue_ref(std::move(a))); } { int k = by_value_a(A().ret_a()); } { int k = by_value_a(to_lvalue_ref(static_cast(a))); } { int k = (A().ret_a(), A().ret_i()); }// expected-error {{is not a constant expression}} @@ -380,4 +393,125 @@ // expected-note@-1 {{is not a constant expression}} expected-note@-1 {{temporary created here}} } +struct S1 { + S1* ptr = nullptr; + consteval S1(int i) : ptr(this) { + if (this == ptr && i) + ptr = nullptr; + } + constexpr ~S1() {} +}; + +void test1() { + S1 s(1); + s = S1(1); + s = S1(0); // expected-error {{is not a constant expression}} + // expected-note@-1 {{is not a constant expression}} expected-note@-1 {{temporary created here}} +} + +} +namespace ctor { + +consteval int f_eval() { // expected-note+ {{declared here}} + return 0; } + +struct A { + int(*ptr)(); + consteval A(int(*p)() = nullptr) : ptr(p) {} +}; + +struct B { + int(*ptr)(); + B() : ptr(nullptr) {} + consteval B(int(*p)(), int) : ptr(p) {} +}; + +void test() { + { A a; } + { A a(&f_eval); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { B b(nullptr, 0); } + { B b(&f_eval, 0); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { A a{}; } + { A a{&f_eval}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { B b{nullptr, 0}; } + { B b{&f_eval, 0}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { A a = A(); } + { A a = A(&f_eval); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { B b = B(nullptr, 0); } + { B b = B(&f_eval, 0); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { A a = A{}; } + { A a = A{&f_eval}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { B b = B{nullptr, 0}; } + { B b = B{&f_eval, 0}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { A a; a = A(); } + { A a; a = A(&f_eval); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { B b; b = B(nullptr, 0); } + { B b; b = B(&f_eval, 0); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { A a; a = A{}; } + { A a; a = A{&f_eval}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { B b; b = B{nullptr, 0}; } + { B b; b = B{&f_eval, 0}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { A* a; a = new A(); } + { A* a; a = new A(&f_eval); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { B* b; b = new B(nullptr, 0); } + { B* b; b = new B(&f_eval, 0); } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { A* a; a = new A{}; } + { A* a; a = new A{&f_eval}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { B* b; b = new B{nullptr, 0}; } + { B* b; b = new B{&f_eval, 0}; } // expected-error {{is not a constant expression}} expected-note {{to a consteval}} +} + +} + +namespace copy_ctor { + +consteval int f_eval() { // expected-note+ {{declared here}} + return 0; +} + +struct Copy { + int(*ptr)(); + constexpr Copy(int(*p)() = nullptr) : ptr(p) {} + consteval Copy(const Copy&) = default; +}; + +constexpr const Copy &to_lvalue_ref(const Copy &&a) { + return a; +} + +void test() { + constexpr const Copy C; + // there is no the copy constructor call when its argument is a prvalue because of garanteed copy elision. + // so we need to test with both prvalue and xvalues. + { Copy c(C); } + { Copy c((Copy(&f_eval))); }// expected-error {{cannot take address of consteval}} + { Copy c(std::move(C)); } + { Copy c(std::move(Copy(&f_eval))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { Copy c(to_lvalue_ref((Copy(&f_eval)))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { Copy c(to_lvalue_ref(std::move(C))); } + { Copy c(to_lvalue_ref(std::move(Copy(&f_eval)))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { Copy c = Copy(C); } + { Copy c = Copy(Copy(&f_eval)); }// expected-error {{cannot take address of consteval}} + { Copy c = Copy(std::move(C)); } + { Copy c = Copy(std::move(Copy(&f_eval))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { Copy c = Copy(to_lvalue_ref(Copy(&f_eval))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { Copy c = Copy(to_lvalue_ref(std::move(C))); } + { Copy c = Copy(to_lvalue_ref(std::move(Copy(&f_eval)))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { Copy c; c = Copy(C); } + { Copy c; c = Copy(Copy(&f_eval)); }// expected-error {{cannot take address of consteval}} + { Copy c; c = Copy(std::move(C)); } + { Copy c; c = Copy(std::move(Copy(&f_eval))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { Copy c; c = Copy(to_lvalue_ref(Copy(&f_eval))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { Copy c; c = Copy(to_lvalue_ref(std::move(C))); } + { Copy c; c = Copy(to_lvalue_ref(std::move(Copy(&f_eval)))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { Copy* c; c = new Copy(C); } + { Copy* c; c = new Copy(Copy(&f_eval)); }// expected-error {{cannot take address of consteval}} + { Copy* c; c = new Copy(std::move(C)); } + { Copy* c; c = new Copy(std::move(Copy(&f_eval))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { Copy* c; c = new Copy(to_lvalue_ref(Copy(&f_eval))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} + { Copy* c; c = new Copy(to_lvalue_ref(std::move(C))); } + { Copy* c; c = new Copy(to_lvalue_ref(std::move(Copy(&f_eval)))); }// expected-error {{is not a constant expression}} expected-note {{to a consteval}} +} + +} // namespace special_ctor