From patchwork Tue Nov 12 00:54:08 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 1193282 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-513018-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="uE9okW8F"; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="XiZlz8jQ"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47Bq5J3ZlTz9s7T for ; Tue, 12 Nov 2019 11:54:25 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type :content-transfer-encoding; q=dns; s=default; b=Dc+OMBWfVIlKlYim 8kXMqhOW+31vEicutVwcPmPaeVEU/9gh+2cSX9APu2YgZQkfgLAN3nsA4j4a0poa ms2ONJTrtYLEfjStXN+xERXymcHyIZ22la4Pq0i/RhFDHQ4xyoYJrYW9yoqMRe+v hm5cHvdl82vrEhrI0JQobp14JI4= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type :content-transfer-encoding; s=default; bh=qCRZP9Z6xtTVXUNyg9RFgh AoUOA=; b=uE9okW8FpmYvQLJ5DHcEub4HWSBWHK47UHjsYRQXeLQyxNMm+LlyAr OXShWs90gsjjgK3dTWcTojzFnZ2h82zk/YVlVG1GhhrBvDSpELkEO5nYDs9hNUpp K/ypLx4cBbpgU5eLmX1f1gU8byOJ/GT8Zr5JM0VsixWyJIHdaw/Bw= Received: (qmail 45108 invoked by alias); 12 Nov 2019 00:54:17 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 45099 invoked by uid 89); 12 Nov 2019 00:54:17 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-22.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3 autolearn=ham version=3.3.1 spammy=UD:constexpr.c, constexpr.c, constexprc, sk:potenti X-HELO: us-smtp-delivery-1.mimecast.com Received: from us-smtp-1.mimecast.com (HELO us-smtp-delivery-1.mimecast.com) (205.139.110.61) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 12 Nov 2019 00:54:15 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1573520053; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=poQroGX221f4AZtwXY0A4JKEnb2UiGNlaZcK4O5NSZw=; b=XiZlz8jQaISPA37YT5os9UchIIH6TM08Bm8FsICdkcpM9GV5DqroFBnkpIpbEVd5Y1t+LT HoIeMOR5COSfOHSyj825DOH45PPLGxcKtuoHj4ypP5awahfY1BbOa3+fuOV6E/xQQci4B7 Dt/bhXKIczMBGYNr95UCMhUZvN0WApk= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-66-Q7rew1ojNUecnDDdi7SBOA-1; Mon, 11 Nov 2019 19:54:12 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1EAB6477 for ; Tue, 12 Nov 2019 00:54:12 +0000 (UTC) Received: from redhat.com (ovpn-120-138.rdu2.redhat.com [10.10.120.138]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 249AE5D6A3; Tue, 12 Nov 2019 00:54:10 +0000 (UTC) Date: Mon, 11 Nov 2019 19:54:08 -0500 From: Marek Polacek To: GCC Patches , Jason Merrill Subject: C++ PATCH for c++/88337 - P1327R1: Allow polymorphic typeid in constexpr Message-ID: <20191112005408.GB21634@redhat.com> MIME-Version: 1.0 User-Agent: Mutt/1.12.1 (2019-06-15) X-Mimecast-Spam-Score: 0 Content-Disposition: inline Part of P1327R1 is to allow typeid with an operand of polymorphic type in constexpr. I found that we pretty much support it already, the only tweak was to allow TYPEID_EXPR (only created in a template) in constexpr in C++20. I also noticed this in build_typeid: /* FIXME when integrating with c_fully_fold, mark resolves_to_fixed_type_p case as a non-constant expression. */ if (TYPE_POLYMORPHIC_P (TREE_TYPE (exp)) && ! resolves_to_fixed_type_p (exp, &nonnull) && ! nonnull) but I'm not quite sure what to do with it. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2019-11-11 Marek Polacek PR c++/88337 - P1327R1: Allow polymorphic typeid in constexpr. * constexpr.c (potential_constant_expression_1): Allow a typeid expression whose operand is of polymorphic type in constexpr in C++20. * g++.dg/cpp2a/constexpr-typeid1.C: New test. * g++.dg/cpp2a/constexpr-typeid2.C: New test. * g++.dg/cpp2a/constexpr-typeid3.C: New test. * g++.dg/cpp2a/constexpr-typeid4.C: New test. diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c index 20fddc57825..430c65694b7 100644 --- gcc/cp/constexpr.c +++ gcc/cp/constexpr.c @@ -7018,11 +7018,13 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, return false; case TYPEID_EXPR: - /* -- a typeid expression whose operand is of polymorphic - class type; */ + /* In C++20, a typeid expression whose operand is of polymorphic + class type can be constexpr. */ { tree e = TREE_OPERAND (t, 0); - if (!TYPE_P (e) && !type_dependent_expression_p (e) + if (cxx_dialect < cxx2a + && !TYPE_P (e) + && !type_dependent_expression_p (e) && TYPE_POLYMORPHIC_P (TREE_TYPE (e))) { if (flags & tf_error) diff --git gcc/testsuite/g++.dg/cpp2a/constexpr-typeid1.C gcc/testsuite/g++.dg/cpp2a/constexpr-typeid1.C new file mode 100644 index 00000000000..a81f649b44b --- /dev/null +++ gcc/testsuite/g++.dg/cpp2a/constexpr-typeid1.C @@ -0,0 +1,47 @@ +// PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr. +// { dg-do compile { target c++2a } } +// Test non-polymorphic type. + +#include + +struct B { + const std::type_info &ti = typeid (*this); +}; + +struct D : B { }; + +constexpr B b; +constexpr D d; + +static_assert (&b.ti == &typeid (B)); +static_assert (&B{}.ti == &typeid (B)); +static_assert (&B().ti == &typeid (B)); +static_assert (&typeid ((B())) == &typeid (B)); +static_assert (&typeid ((B{})) == &typeid (B)); + +static_assert (&d.ti == &typeid (B)); +static_assert (&D{}.ti == &typeid (B)); +static_assert (&D().ti == &typeid (B)); +static_assert (&typeid ((D())) == &typeid (D)); +static_assert (&typeid ((D{})) == &typeid (D)); + +extern D ed; +static_assert (&typeid (ed) == &typeid (D)); + +constexpr const B &r = d; +static_assert (&typeid (r) == &typeid (B)); + +constexpr bool +test () +{ + // If expression is not a glvalue expression of polymorphic type, + // typeid does not evaluate the expression + bool ok = true; + (void) typeid (ok = false, D()); + (void) typeid (ok = false, B()); + (void) typeid (ok = false, b); + (void) typeid (ok = false, d); + return ok; +} + +static_assert (test ()); diff --git gcc/testsuite/g++.dg/cpp2a/constexpr-typeid2.C gcc/testsuite/g++.dg/cpp2a/constexpr-typeid2.C new file mode 100644 index 00000000000..51c8fb451b8 --- /dev/null +++ gcc/testsuite/g++.dg/cpp2a/constexpr-typeid2.C @@ -0,0 +1,60 @@ +// PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr. +// { dg-do compile { target c++2a } } +// Test polymorphic type. + +#include + +struct B { + virtual void foo (); + const std::type_info &ti_base = typeid (*this); +}; + +struct D : B { + const std::type_info &ti = typeid (*this); +}; + +constexpr B b; +constexpr D d; + +static_assert (&b.ti_base == &typeid (B)); +static_assert (&B{}.ti_base == &typeid (B)); +static_assert (&B().ti_base == &typeid (B)); +static_assert (&typeid ((B())) == &typeid (B)); +static_assert (&typeid ((B{})) == &typeid (B)); + +static_assert (&d.ti == &typeid (D)); +static_assert (&D{}.ti == &typeid (D)); +static_assert (&D().ti == &typeid (D)); +static_assert (&typeid ((D())) == &typeid (D)); +static_assert (&typeid ((D{})) == &typeid (D)); + +extern D ed; +// ??? Should this succeed? +static_assert (&typeid (ed) == &typeid (D)); + +constexpr const B &r = d; +static_assert (&typeid (r) == &typeid (D)); + +constexpr bool +test () +{ + // If expression is a glvalue expression that identifies an object + // of a polymorphic type, the typeid expression evaluates the expression. + bool ok = true; + // Not a glvalue. + (void) typeid (ok = false, D()); + (void) typeid (ok = false, B()); + if (!ok) + return false; + + // Polymorphic glvalue -- this needs to be evaluated. + ok = false; + (void) typeid (ok = true, b); + if (!ok) + return false; + ok = false; + (void) typeid (ok = true, d); + return ok; +} + +static_assert (test ()); diff --git gcc/testsuite/g++.dg/cpp2a/constexpr-typeid3.C gcc/testsuite/g++.dg/cpp2a/constexpr-typeid3.C new file mode 100644 index 00000000000..38b9e609a9f --- /dev/null +++ gcc/testsuite/g++.dg/cpp2a/constexpr-typeid3.C @@ -0,0 +1,33 @@ +// PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr. +// { dg-do compile { target c++2a } } +// Test typeid in a template. + +#include + +struct B { virtual void fn (); }; +struct D : B { }; + +void abort (); + +template +constexpr void +fn () +{ + D d; + if (&typeid (d) != &typeid (D)) + abort (); +} +constexpr bool b1 = (fn(), true); + +// Type-dependent. +template +constexpr void +fn2 () +{ + T t{}; + if (&typeid (t) != &typeid (T)) + abort (); +} +constexpr bool b2 = (fn2(), true); +constexpr bool b3 = (fn2(), true); +constexpr bool b4 = (fn2(), true); diff --git gcc/testsuite/g++.dg/cpp2a/constexpr-typeid4.C gcc/testsuite/g++.dg/cpp2a/constexpr-typeid4.C new file mode 100644 index 00000000000..0a99aae9bf9 --- /dev/null +++ gcc/testsuite/g++.dg/cpp2a/constexpr-typeid4.C @@ -0,0 +1,19 @@ +// PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr. +// { dg-do compile { target c++17 } } +// Test typeid in a template. + +#include + +struct B { virtual void f(); }; +struct B2 : B { }; + +template +constexpr bool +fn () +{ + constexpr B2 b2; + static_assert(&typeid(b2) == &typeid(B2)); // { dg-error ".typeid. is not a constant expression because .b2. is of polymorphic type|non-constant condition" "" { target c++17_down } } + return true; +} + +static_assert (fn());