From patchwork Mon May 5 20:27:03 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 345880 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.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 889CE140F90 for ; Tue, 6 May 2014 06:27:18 +1000 (EST) 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:cc:subject:message-id:mime-version:content-type; q=dns; s=default; b=nRh/orf97tYNlQXWzh/lG4gVWo7WNTrNKC9wArgGYC3LTTBzcA 4vuKwvoHyIgeLdG8y41Ro27lVioQ5/0wB/maTPRx3WtXUnK5ABVANmdg8f1zhjbW lQVDwsEqccJjP4EcWem46OvxkzyHj3R0DEYkSlyTRoMPpZWIATYvhWxC4= 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:cc:subject:message-id:mime-version:content-type; s= default; bh=R24N59FQelTIPnI7STDLVw/1UvQ=; b=cn+YXE3waSrgdq91GBtG k5uKXUhagXRDka3+XLQaXOLZsyos21qFv4IwFZW3ghPeZ540bQHFc4PDGfDCYJv3 AHpmDu2f7wHGI4PTCvOomHHBSD2AyjHBP1cl1mBtU4YnRRUiZ3PCQb5rjJsulQpG a19be+5tcTm4HGi13Ki2FPQ= Received: (qmail 18305 invoked by alias); 5 May 2014 20:27:11 -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 18293 invoked by uid 89); 5 May 2014 20:27:11 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.1 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 05 May 2014 20:27:09 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s45KR7rS019503 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 5 May 2014 16:27:07 -0400 Received: from redhat.com (ovpn-116-53.ams2.redhat.com [10.36.116.53]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s45KR3iT014950 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=NO); Mon, 5 May 2014 16:27:06 -0400 Date: Mon, 5 May 2014 22:27:03 +0200 From: Marek Polacek To: GCC Patches Cc: "Joseph S. Myers" Subject: [C PATCH] Don't reject valid code with _Alignas (PR c/61053) Message-ID: <20140505202703.GR11802@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) In this PR the issue is that we reject (valid) code such as _Alignas (long long) long long foo; with -m32, because we trip this condition: alignas_align = 1U << declspecs->align_log; if (alignas_align < TYPE_ALIGN_UNIT (type)) { if (name) error_at (loc, "%<_Alignas%> specifiers cannot reduce " "alignment of %qE", name); and error later on, since alignas_align is 4 (correct, see PR52023 for why), but TYPE_ALIGN_UNIT of long long is 8. I think TYPE_ALIGN_UNIT is wrong here as that won't give us minimal alignment required. In c_sizeof_or_alignof_type we already have the code to compute such minimal alignment so I just moved the code to a separate function and used that instead of TYPE_ALIGN_UNIT. Note that the test is run only on i?86 and x86_64, because we can't (?) easily determine which target requires what alignment. Regtested/bootstrapped on x86_64-unknown-linux-gnu and powerpc64-unknown-linux-gnu, ok for trunk? 2014-05-05 Marek Polacek PR c/61053 c-family/ * c-common.c (min_align_of_type): New function factored out from... (c_sizeof_or_alignof_type): ...here. * c-common.h (min_align_of_type): Declare. c/ * c-decl.c (grokdeclarator): Use min_align_of_type instead of TYPE_ALIGN_UNIT. testsuite/ * gcc.dg/pr61053.c: New test. Marek diff --git gcc/c-family/c-common.c gcc/c-family/c-common.c index 0ad955d..6d4440e 100644 --- gcc/c-family/c-common.c +++ gcc/c-family/c-common.c @@ -4931,6 +4931,26 @@ c_common_get_alias_set (tree t) return -1; } +/* Return the least alignment required for type TYPE. */ + +unsigned int +min_align_of_type (tree type) +{ + unsigned int align = TYPE_ALIGN (type); + align = MIN (align, BIGGEST_ALIGNMENT); +#ifdef BIGGEST_FIELD_ALIGNMENT + align = MIN (align, BIGGEST_FIELD_ALIGNMENT); +#endif + unsigned int field_align = align; +#ifdef ADJUST_FIELD_ALIGN + tree field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, + type); + field_align = ADJUST_FIELD_ALIGN (field, field_align); +#endif + align = MIN (align, field_align); + return align / BITS_PER_UNIT; +} + /* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where the IS_SIZEOF parameter indicates which operator is being applied. The COMPLAIN flag controls whether we should diagnose possibly @@ -5009,21 +5029,7 @@ c_sizeof_or_alignof_type (location_t loc, size_int (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT)); else if (min_alignof) - { - unsigned int align = TYPE_ALIGN (type); - align = MIN (align, BIGGEST_ALIGNMENT); -#ifdef BIGGEST_FIELD_ALIGNMENT - align = MIN (align, BIGGEST_FIELD_ALIGNMENT); -#endif - unsigned int field_align = align; -#ifdef ADJUST_FIELD_ALIGN - tree field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, - type); - field_align = ADJUST_FIELD_ALIGN (field, field_align); -#endif - align = MIN (align, field_align); - value = size_int (align / BITS_PER_UNIT); - } + value = size_int (min_align_of_type (type)); else value = size_int (TYPE_ALIGN_UNIT (type)); } diff --git gcc/c-family/c-common.h gcc/c-family/c-common.h index 57b7dce..d34d2bb 100644 --- gcc/c-family/c-common.h +++ gcc/c-family/c-common.h @@ -758,6 +758,7 @@ extern tree c_wrap_maybe_const (tree, bool); extern tree c_save_expr (tree); extern tree c_common_truthvalue_conversion (location_t, tree); extern void c_apply_type_quals_to_decl (int, tree); +extern unsigned int min_align_of_type (tree); extern tree c_sizeof_or_alignof_type (location_t, tree, bool, bool, int); extern tree c_alignof_expr (location_t, tree); /* Print an error message for invalid operands to arith operation CODE. diff --git gcc/c/c-decl.c gcc/c/c-decl.c index 6e7c589..9f7419a 100644 --- gcc/c/c-decl.c +++ gcc/c/c-decl.c @@ -5931,7 +5931,7 @@ grokdeclarator (const struct c_declarator *declarator, else if (declspecs->align_log != -1) { alignas_align = 1U << declspecs->align_log; - if (alignas_align < TYPE_ALIGN_UNIT (type)) + if (alignas_align < min_align_of_type (type)) { if (name) error_at (loc, "%<_Alignas%> specifiers cannot reduce " diff --git gcc/testsuite/gcc.dg/pr61053.c gcc/testsuite/gcc.dg/pr61053.c index e69de29..e3db534 100644 --- gcc/testsuite/gcc.dg/pr61053.c +++ gcc/testsuite/gcc.dg/pr61053.c @@ -0,0 +1,75 @@ +/* PR c/61053 */ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +_Alignas (char) char cc; +_Alignas (short int) char cs; +_Alignas (int) char ci; +_Alignas (long int) char cl; +_Alignas (long long int) char cll; +_Alignas (float) char cf; +_Alignas (double) char cd; +_Alignas (long double) char cld; + +_Alignas (char) short int sc; /* { dg-error "cannot reduce alignment" } */ +_Alignas (short int) short int ss; +_Alignas (int) short int si; +_Alignas (long int) short int sl; +_Alignas (long long int) short int sll; +_Alignas (float) short int sf; +_Alignas (double) short int sd; +_Alignas (long double) short int sld; + +_Alignas (char) int ic; /* { dg-error "cannot reduce alignment" } */ +_Alignas (short int) int is; /* { dg-error "cannot reduce alignment" } */ +_Alignas (int) int ii; +_Alignas (long int) int il; +_Alignas (long long int) int ill; +_Alignas (float) int if_; +_Alignas (double) int id; +_Alignas (long double) int ild; + +_Alignas (char) long int lic; /* { dg-error "cannot reduce alignment" } */ +_Alignas (short int) long int lis; /* { dg-error "cannot reduce alignment" } */ +_Alignas (int) long int lii; /* { dg-error "cannot reduce alignment" "" { target { lp64 } } } */ +_Alignas (long int) long int lil; +_Alignas (long long int) long int lill; +_Alignas (float) long int lif; /* { dg-error "cannot reduce alignment" "" { target { lp64 } } } */ +_Alignas (double) long int lid; +_Alignas (long double) long int lild; + +_Alignas (char) long long int llic; /* { dg-error "cannot reduce alignment" } */ +_Alignas (short int) long long int llis; /* { dg-error "cannot reduce alignment" } */ +_Alignas (int) long long int llii; /* { dg-error "cannot reduce alignment" "" { target { lp64 } } } */ +_Alignas (long int) long long int llil; +_Alignas (long long int) long long int llill; +_Alignas (float) long long int llif; /* { dg-error "cannot reduce alignment" "" { target { lp64 } } } */ +_Alignas (double) long long int llid; +_Alignas (long double) long long int llild; + +_Alignas (char) float fc; /* { dg-error "cannot reduce alignment" } */ +_Alignas (short int) float fs; /* { dg-error "cannot reduce alignment" } */ +_Alignas (int) float fi; +_Alignas (long int) float fl; +_Alignas (long long int) float fll; +_Alignas (float) float ff; +_Alignas (double) float fd; +_Alignas (long double) float fld; + +_Alignas (char) double dc; /* { dg-error "cannot reduce alignment" } */ +_Alignas (short int) double ds; /* { dg-error "cannot reduce alignment" } */ +_Alignas (int) double di; /* { dg-error "cannot reduce alignment" "" { target { lp64 } } } */ +_Alignas (long int) double dl; +_Alignas (long long int) double dll; +_Alignas (float) double df; /* { dg-error "cannot reduce alignment" "" { target { lp64 } } } */ +_Alignas (double) double dd; +_Alignas (long double) double dld; + +_Alignas (char) long double ldc; /* { dg-error "cannot reduce alignment" } */ +_Alignas (short int) long double lds; /* { dg-error "cannot reduce alignment" } */ +_Alignas (int) long double ldi; /* { dg-error "cannot reduce alignment" "" { target { lp64 } } } */ +_Alignas (long int) long double ldl; /* { dg-error "cannot reduce alignment" "" { target { lp64 } } } */ +_Alignas (long long int) long double ldll; /* { dg-error "cannot reduce alignment" "" { target { lp64 } } } */ +_Alignas (float) long double ldf; /* { dg-error "cannot reduce alignment" "" { target { lp64 } } } */ +_Alignas (double) long double ldd; /* { dg-error "cannot reduce alignment" "" { target { lp64 } } } */ +_Alignas (long double) long double ldld;