[clang] 131b462 - Implement P1937 consteval in unevaluated contexts
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 6 07:30:17 PDT 2021
Author: Corentin Jabot
Date: 2021-08-06T10:29:28-04:00
New Revision: 131b4620ee7847102479f399ce3e35a3c1cb5461
URL: https://github.com/llvm/llvm-project/commit/131b4620ee7847102479f399ce3e35a3c1cb5461
DIFF: https://github.com/llvm/llvm-project/commit/131b4620ee7847102479f399ce3e35a3c1cb5461.diff
LOG: Implement P1937 consteval in unevaluated contexts
In an unevaluated contexts, consteval functions should not be
immediately evaluated.
Added:
Modified:
clang/lib/Sema/SemaExpr.cpp
clang/test/CXX/basic/basic.def.odr/p2-typeid.cpp
clang/test/SemaCXX/cxx2a-consteval.cpp
clang/www/cxx_status.html
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index d316687c4cd8e..8ef4a9d96320b 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -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;
@@ -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);
diff --git a/clang/test/CXX/basic/basic.def.odr/p2-typeid.cpp b/clang/test/CXX/basic/basic.def.odr/p2-typeid.cpp
index 55debe3ca731d..fafcd127feec2 100644
--- a/clang/test/CXX/basic/basic.def.odr/p2-typeid.cpp
+++ b/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
@@ -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}}
@@ -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
diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index ecf8c1e0f5bd7..04c8898aa5bad 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -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 at -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
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index 60ce69db99225..3cbee7026c5c2 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -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>
More information about the cfe-commits
mailing list