Skip to content

Commit

Permalink
Implement P1937 consteval in unevaluated contexts
Browse files Browse the repository at this point in the history
In an unevaluated contexts, consteval functions should not be
immediately evaluated.
  • Loading branch information
cor3ntin authored and AaronBallman committed Aug 6, 2021
1 parent 3c8e94b commit 131b462
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 5 deletions.
7 changes: 4 additions & 3 deletions clang/lib/Sema/SemaExpr.cpp
Expand Up @@ -16641,7 +16641,8 @@ void Sema::CheckUnusedVolatileAssignment(Expr *E) {
}

ExprResult Sema::CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl) {
if (!E.isUsable() || !Decl || !Decl->isConsteval() || isConstantEvaluated() ||
if (isUnevaluatedContext() || !E.isUsable() || !Decl ||
!Decl->isConsteval() || isConstantEvaluated() ||
RebuildingImmediateInvocation)
return E;

Expand Down Expand Up @@ -18758,8 +18759,8 @@ void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) {
OdrUse = false;

if (auto *FD = dyn_cast<FunctionDecl>(E->getDecl()))
if (!isConstantEvaluated() && FD->isConsteval() &&
!RebuildingImmediateInvocation)
if (!isUnevaluatedContext() && !isConstantEvaluated() &&
FD->isConsteval() && !RebuildingImmediateInvocation)
ExprEvalContexts.back().ReferenceToConsteval.insert(E);
MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse,
RefsMinusAssignments);
Expand Down
33 changes: 32 additions & 1 deletion clang/test/CXX/basic/basic.def.odr/p2-typeid.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s

// C++ [basic.def.odr]p2:
// An expression is potentially evaluated unless it [...] is the
Expand All @@ -16,7 +17,7 @@ struct Poly {

struct NonPoly { };

template<typename T, typename Result = T>
template<typename T, typename Result = T>
struct X {
Result f(T t) { return t + t; } // expected-error{{invalid operands}}

Expand All @@ -34,3 +35,33 @@ void test(X<Poly> xp, X<Poly, Poly&> xpr, X<NonPoly> xnp, X<NonPoly, NonPoly&> x
// Triggers an error (as it should);
xpr.g(Poly()); // expected-note{{instantiation of member function}}
}

#if __cplusplus >= 202002L

namespace unevaluated {

struct S {
void f();
};
struct T {
virtual void f();
};

consteval S *null_s() { return nullptr; }
consteval S *make_s() { return new S; }
consteval T *null_t() { return nullptr; }
consteval T *make_t() { return new T; } // #alloc

void func() {
(void)typeid(*null_s());
(void)typeid(*make_s());
(void)typeid(*null_t()); // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
(void)typeid(*make_t()); // expected-error {{call to consteval function 'unevaluated::make_t' is not a constant expression}} \
expected-note {{pointer to heap-allocated object is not a constant expression}} \
expected-note@#alloc {{heap allocation performed here}} \
expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
}

} // namespace unevaluated

#endif
18 changes: 18 additions & 0 deletions clang/test/SemaCXX/cxx2a-consteval.cpp
Expand Up @@ -594,3 +594,21 @@ void test() {
}

} // namespace special_ctor

namespace unevaluated {

template <typename T, typename U> struct is_same { static const bool value = false; };
template <typename T> struct is_same<T, T> { static const bool value = true; };

long f(); // expected-note {{declared here}}
auto consteval g(auto a) {
return a;
}

auto e = g(f()); // expected-error {{is not a constant expression}}
// expected-note@-1 {{non-constexpr function 'f' cannot be used in a constant expression}}

using T = decltype(g(f()));
static_assert(is_same<long, T>::value);

} // namespace unevaluated
3 changes: 2 additions & 1 deletion clang/www/cxx_status.html
Expand Up @@ -1105,10 +1105,11 @@ <h2 id="cxx20">C++20 implementation status</h2>
<tr>
<td rowspan=2>Immediate functions (<tt>consteval</tt>)</td>
<td><a href="https://wg21.link/p1073r3">P1073R3</a></td>
<td rowspan=2 class="none" align="center">No</td>
<td class="partial" align="center">Partial</td>
</tr>
<tr> <!-- from Prague -->
<td><a href="https://wg21.link/p1937r2">P1937R2</a></td>
<td class="unreleased" align="center">Clang 14</td>
</tr>
<tr>
<td><tt>std::is_constant_evaluated</tt></td>
Expand Down

0 comments on commit 131b462

Please sign in to comment.