Skip to content

Commit

Permalink
[clang] Allow consteval functions in default arguments
Browse files Browse the repository at this point in the history
We should not mark a function as "referenced" if we call it within a
ConstantExpr, because the expression will be folded to a value in LLVM
IR. To prevent emitting consteval function declarations, we should not "jump
over" a ConstantExpr when it is a top-level ParmVarDecl's subexpression.

Fixes #48230

Reviewed By: erichkeane, aaron.ballman, ChuanqiXu

Differenitial Revision: https://reviews.llvm.org/D119646
  • Loading branch information
Izaron authored and ChuanqiXu9 committed Jun 7, 2022
1 parent f9ac557 commit a4f8590
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 1 deletion.
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://github.com/llvm/llvm-project/issues/55562>`_.
- Clang will allow calling a ``consteval`` function in a default argument. This
fixes `Issue 48230 <https://github.com/llvm/llvm-project/issues/48230>`_.

Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2867,7 +2867,8 @@ Expr *ParmVarDecl::getDefaultArg() {

Expr *Arg = getInit();
if (auto *E = dyn_cast_or_null<FullExpr>(Arg))
return E->getSubExpr();
if (!isa<ConstantExpr>(E))
return E->getSubExpr();

return Arg;
}
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19611,6 +19611,12 @@ class EvaluatedExprMarker : public UsedDeclVisitor<EvaluatedExprMarker> {
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) {
Expand Down
21 changes: 21 additions & 0 deletions clang/test/SemaCXX/cxx2a-consteval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,27 @@ static_assert(baz<int>() == 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;
Expand Down

0 comments on commit a4f8590

Please sign in to comment.