diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2813,7 +2813,8 @@ 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 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -18964,6 +18964,12 @@ 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 --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -613,6 +613,27 @@ } // namespace unevaluated +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;