From patchwork Thu Mar 21 03:18:29 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 229545 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 7B12B2C00B9 for ; Thu, 21 Mar 2013 14:18:52 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=oaHkGp+1hdWSge5F/JwYPUSoR2rU9J+4cPqyTMLgFjB928 YcbD8gpYU6HOLpdw+eAPjXOv7P+jsBNpkn8ohue2VM2MDC1YQVdsYZwdG1rmgqEU B8+kIBEDUxj2+1I33sGfiPJP7V119moOx4z1/Hc8UG2XUd2o7WgD2vM2a8hkE= 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 :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=yGDWMHJKsog75lz5v3s+I+YmRw8=; b=Cbl2SIxUajyA+uV8qQ6o qZVxDHdKpXVhGNUhL60HO9MCprr2f6UvG1BNEMEKSAg7YUpcnoHrQLZVLN72fonl Sn/2HX/1QykPd9KJJ487MjlhabtefglvaPSxLYw4WVtCxqKKFxH6qHJLt4vLciFx 8uuq+FcZbs46gecJKgu44wY= Received: (qmail 30439 invoked by alias); 21 Mar 2013 03:18:46 -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 30415 invoked by uid 89); 21 Mar 2013 03:18:35 -0000 X-Spam-SWARE-Status: No, score=-8.1 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.1 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Thu, 21 Mar 2013 03:18:32 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r2L3IV6j003962 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 20 Mar 2013 23:18:31 -0400 Received: from [10.3.113.56] (ovpn-113-56.phx2.redhat.com [10.3.113.56]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r2L3ITBK004373 for ; Wed, 20 Mar 2013 23:18:30 -0400 Message-ID: <514A7C05.4080607@redhat.com> Date: Wed, 20 Mar 2013 23:18:29 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux i686; rv:21.0) Gecko/20100101 Thunderbird/21.0a2 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for c++/54532 (constexpr ptrmem) While a class is still being defined, we don't know the offsets of the members, so a pointer-to-member expression can't be lowered to an integer, it needs to stay as a PTRMEM_CST. But it's still a constant as far as the language is concerned, so we need to allow it and then lower it when the class is complete. Tested x86_64-pc-linux-gnu, applying to trunk. commit c41c286c3b13d1d1b3831fab38497146bd0c2f8b Author: Jason Merrill Date: Fri Feb 15 16:25:27 2013 -0500 PR c++/54532 * expr.c (cplus_expand_constant): Do nothing if the class is incomplete. * semantics.c (reduced_constant_expression_p): Allow PTRMEM_CST. * typeck2.c (store_init_value): Use reduced_constant_expression_p. * decl.c (maybe_register_incomplete_var): Handle PTRMEM_CST. (complete_vars): Likewise. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index facaae7..4ccb541 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -14018,7 +14018,10 @@ grokmethod (cp_decl_specifier_seq *declspecs, /* VAR is a VAR_DECL. If its type is incomplete, remember VAR so that - we can lay it out later, when and if its type becomes complete. */ + we can lay it out later, when and if its type becomes complete. + + Also handle constexpr pointer to member variables where the initializer + is an unlowered PTRMEM_CST because the class isn't complete yet. */ void maybe_register_incomplete_var (tree var) @@ -14043,6 +14046,15 @@ maybe_register_incomplete_var (tree var) incomplete_var iv = {var, inner_type}; vec_safe_push (incomplete_vars, iv); } + else if (TYPE_PTRMEM_P (inner_type) + && DECL_INITIAL (var) + && TREE_CODE (DECL_INITIAL (var)) == PTRMEM_CST) + { + tree context = TYPE_PTRMEM_CLASS_TYPE (inner_type); + gcc_assert (TYPE_BEING_DEFINED (context)); + incomplete_var iv = {var, context}; + vec_safe_push (incomplete_vars, iv); + } } } @@ -14062,10 +14074,17 @@ complete_vars (tree type) { tree var = iv->decl; tree type = TREE_TYPE (var); - /* Complete the type of the variable. The VAR_DECL itself - will be laid out in expand_expr. */ - complete_type (type); - cp_apply_type_quals_to_decl (cp_type_quals (type), var); + + if (TYPE_PTRMEM_P (type)) + DECL_INITIAL (var) = cplus_expand_constant (DECL_INITIAL (var)); + else + { + /* Complete the type of the variable. The VAR_DECL itself + will be laid out in expand_expr. */ + complete_type (type); + cp_apply_type_quals_to_decl (cp_type_quals (type), var); + } + /* Remove this entry from the list. */ incomplete_vars->unordered_remove (ix); } diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index ffd18ca..f15b049 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -43,6 +43,10 @@ cplus_expand_constant (tree cst) /* Find the member. */ member = PTRMEM_CST_MEMBER (cst); + /* We can't lower this until the class is complete. */ + if (!COMPLETE_TYPE_P (DECL_CONTEXT (member))) + return cst; + if (TREE_CODE (member) == FIELD_DECL) { /* Find the offset for the field. */ diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 5143e4b..3691d86 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -6838,6 +6838,9 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t, bool reduced_constant_expression_p (tree t) { + if (TREE_CODE (t) == PTRMEM_CST) + /* Even if we can't lower this yet, it's constant. */ + return true; /* FIXME are we calling this too much? */ return initializer_constant_valid_p (t, TREE_TYPE (t)) != NULL_TREE; } diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 3bac67c..6ef46a1 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -792,7 +792,7 @@ store_init_value (tree decl, tree init, vec** cleanups, int flags) will perform the dynamic initialization. */ if (value != error_mark_node && (TREE_SIDE_EFFECTS (value) - || ! initializer_constant_valid_p (value, TREE_TYPE (value)))) + || ! reduced_constant_expression_p (value))) { if (TREE_CODE (type) == ARRAY_TYPE && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type))) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static11.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static11.C new file mode 100644 index 0000000..91cc25a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static11.C @@ -0,0 +1,14 @@ +// PR c++/54532 +// { dg-do compile { target c++11 } } + +#define SA(X) static_assert(X,#X) + +struct A { + int i; + constexpr static int A::*p = &A::i; +}; + +constexpr A a = { 42 }; +SA(a.*A::p == 42); + +constexpr int A::* A::p;