diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 57519787ecc47d..8c4f7f48850f75 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -166,6 +166,8 @@ Bug Fixes - Allow use of an elaborated type specifier as a ``_Generic`` selection association in C++ mode. This fixes `Issue 55562 `_. +- Clang will allow calling a ``consteval`` function in a default argument. This + fixes `Issue 48230 `_. Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 1c5c64d1b36504..bd48a4ab93d1fb 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2867,7 +2867,8 @@ Expr *ParmVarDecl::getDefaultArg() { Expr *Arg = getInit(); if (auto *E = dyn_cast_or_null(Arg)) - return E->getSubExpr(); + if (!isa(E)) + return E->getSubExpr(); return Arg; } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 01a3599087f843..9e6a4212b3a112 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -19611,6 +19611,12 @@ class EvaluatedExprMarker : public UsedDeclVisitor { Inherited::Visit(E); } + void VisitConstantExpr(ConstantExpr *E) { + // Don't mark declarations within a ConstantExpression, as this expression + // will be evaluated and folded to a value. + return; + } + void VisitDeclRefExpr(DeclRefExpr *E) { // If we were asked not to visit local variables, don't. if (SkipLocalVariables) { diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp index 6b6f8d22cdb899..df2a9925c0154e 100644 --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -651,6 +651,27 @@ static_assert(baz() == sizeof(int)); } // namespace value_dependent +namespace default_argument { + +// Previously calls of consteval functions in default arguments were rejected. +// Now we show that we don't reject such calls. +consteval int foo() { return 1; } +consteval int bar(int i = foo()) { return i * i; } + +struct Test1 { + Test1(int i = bar(13)) {} + void v(int i = bar(13) * 2 + bar(15)) {} +}; +Test1 t1; + +struct Test2 { + constexpr Test2(int i = bar()) {} + constexpr void v(int i = bar(bar(bar(foo())))) {} +}; +Test2 t2; + +} // namespace default_argument + namespace PR50779 { struct derp { int b = 0;