diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2648,7 +2648,7 @@ "in C++14; add 'const' to avoid a change in behavior">, InGroup>; def err_invalid_consteval_take_address : Error< - "cannot take address of consteval function %0 outside" + "cannot take address of consteval %select{function|call operator of}1 %0 outside" " of an immediate invocation">; def err_invalid_consteval_call : Error< "call to consteval function %q0 is not a constant expression">; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -17974,8 +17974,13 @@ EvaluateAndDiagnoseImmediateInvocation(SemaRef, CE); for (auto *DR : Rec.ReferenceToConsteval) { auto *FD = cast(DR->getDecl()); - SemaRef.Diag(DR->getBeginLoc(), diag::err_invalid_consteval_take_address) - << FD; + if(auto* MD = llvm::dyn_cast(FD); MD && (MD->isLambdaStaticInvoker() || isLambdaCallOperator(MD))) + SemaRef.Diag(DR->getBeginLoc(), diag::err_invalid_consteval_take_address) + << MD->getParent() << 1; + else + SemaRef.Diag(DR->getBeginLoc(), diag::err_invalid_consteval_take_address) + << FD << 0; + SemaRef.Diag(FD->getLocation(), diag::note_declared_at); } } diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1529,7 +1529,7 @@ S.Context, Class, Loc, DeclarationNameInfo(InvokerName, Loc), InvokerFunctionTy, CallOperator->getTypeSourceInfo(), SC_Static, S.getCurFPFeatures().isFPConstrained(), - /*isInline=*/true, ConstexprSpecKind::Unspecified, + /*isInline=*/true, CallOperator->getConstexprKind(), CallOperator->getBody()->getEndLoc()); for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) InvokerParams[I]->setOwningFunction(Invoke); diff --git a/clang/test/AST/ast-dump-expr-json.cpp b/clang/test/AST/ast-dump-expr-json.cpp --- a/clang/test/AST/ast-dump-expr-json.cpp +++ b/clang/test/AST/ast-dump-expr-json.cpp @@ -6867,7 +6867,8 @@ // CHECK-NEXT: "qualType": "auto ()" // CHECK-NEXT: }, // CHECK-NEXT: "storageClass": "static", -// CHECK-NEXT: "inline": true +// CHECK-NEXT: "inline": true, +// CHECK-NEXT: "constexpr": true // CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: }, diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -464,7 +464,7 @@ // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} col:3 constexpr operator() 'auto () const' inline // CHECK-NEXT: CompoundStmt // CHECK-NEXT: CXXConversionDecl 0x{{[^ ]*}} col:3 implicit constexpr operator auto (*)() 'auto (*() const noexcept)()' inline - // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} col:3 implicit __invoke 'auto ()' static inline + // CHECK-NEXT: CXXMethodDecl 0x{{[^ ]*}} col:3 implicit constexpr __invoke 'auto ()' static inline // CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} []() mutable {}; diff --git a/clang/test/AST/ast-dump-lambda.cpp b/clang/test/AST/ast-dump-lambda.cpp --- a/clang/test/AST/ast-dump-lambda.cpp +++ b/clang/test/AST/ast-dump-lambda.cpp @@ -246,7 +246,7 @@ // CHECK-NEXT: | | |-CXXMethodDecl {{.*}} col:3{{( imported)?}} constexpr operator() 'auto () const' inline // CHECK-NEXT: | | | `-CompoundStmt {{.*}} // CHECK-NEXT: | | |-CXXConversionDecl {{.*}} col:3{{( imported)?}} implicit constexpr operator auto (*)() 'auto (*() const noexcept)()' inline -// CHECK-NEXT: | | `-CXXMethodDecl {{.*}} col:3{{( imported)?}} implicit __invoke 'auto ()' static inline +// CHECK-NEXT: | | `-CXXMethodDecl {{.*}} col:3{{( imported)?}} implicit constexpr __invoke 'auto ()' static inline // CHECK-NEXT: | `-CompoundStmt {{.*}} // CHECK-NEXT: |-LambdaExpr {{.*}} '(lambda at {{.*}}ast-dump-lambda.cpp:33:3)' // CHECK-NEXT: | |-CXXRecordDecl {{.*}} col:3{{( imported)?}} implicit{{( )?}} class definition diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -1029,3 +1029,24 @@ int x = A{}; } } + +namespace GH57682 { +void test() { + constexpr auto l1 = []() consteval { // expected-error {{cannot take address of consteval call operator of '(lambda at}} \ + // expected-note 2{{declared here}} + return 3; + }; + constexpr int (*f1)(void) = l1; // expected-error {{constexpr variable 'f1' must be initialized by a constant expression}} \ + // expected-note {{pointer to a consteval declaration is not a constant expression}} + + + constexpr auto lstatic = []() static consteval { // expected-error {{cannot take address of consteval call operator of '(lambda at}} \ + // expected-note 2{{declared here}} \ + // expected-warning {{extension}} + return 3; + }; + constexpr int (*f2)(void) = lstatic; // expected-error {{constexpr variable 'f2' must be initialized by a constant expression}} \ + // expected-note {{pointer to a consteval declaration is not a constant expression}} + +} +}