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@-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> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits