From patchwork Wed Nov 28 04:32:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 1004191 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-491059-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="vRXUUzLd"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Oi7XORtb"; 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 434ST21qn9z9s1c for ; Wed, 28 Nov 2018 15:33: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:from :subject:to:message-id:date:mime-version:content-type; q=dns; s= default; b=VO0Gnwww7B6PyF5joXQxQva11UnTvUXeKERJpcO+auHygkJUMnZgk R3Ej7lk64UOJQngTQwrHnbQirwi/SKMTGjpFcUAxbnokQmDrHSoYENR/gV4oflEa P9KtKkt5TIw9v4PmYSfMhGfhBXBmFsNv4MUD9x20TuoNCZg2r0/O8I= 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:from :subject:to:message-id:date:mime-version:content-type; s= default; bh=S9ktFfXFnobIcw1d1Vn9RO08Ma4=; b=vRXUUzLdlXNQY0lDpzzq nECjtzOOCTRPux8xRx6pqIpeTG+ee5hCzdwMB5K6g8MUwpFfQdDVXsdLFc729yUm amxeFM9KjUfu+ic8TRnAcbKgxmk/HPj2bygxQEzOtNFulw45h9wQ45TvfGUNPpV3 RjaLbX5kpx+81WeOEesGFVk= Received: (qmail 69085 invoked by alias); 28 Nov 2018 04:33:16 -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 69014 invoked by uid 89); 28 Nov 2018 04:33:12 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-16.1 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=88208, 2227, 22, 27, mai X-HELO: mail-qk1-f195.google.com Received: from mail-qk1-f195.google.com (HELO mail-qk1-f195.google.com) (209.85.222.195) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 28 Nov 2018 04:33:03 +0000 Received: by mail-qk1-f195.google.com with SMTP id d19so16060425qkg.5 for ; Tue, 27 Nov 2018 20:33:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:subject:to:message-id:date:user-agent:mime-version :content-language; bh=cOKmwG1fd4SbDvBHUDnoQkW5GhnIcKfF+QxJNu+eAxU=; b=Oi7XORtbdulsryOKqS5mUOBUXKG8nS7uukrNs7vxTGggzo6oTnuBO6YB6X0WtvxbT0 elGNv4ksyhDCWp3RvAEEy4crmBra24mobisd0kWL+UCMPy57DLW45/jLEddDlbYWUSYs ithtjazzTJJ2WB40vskXZrzScGnSw+s/yp4JSWlHytjLIT9lEypHU7eT9uG4FRkqYM3K cwOqFqchum4eMbSjCUvcLZ8E1oMqId4bmIqbYrrR00d1tVkb+qtMyC1Cu21s+A58SSnw MWp8qbdSvzc3AQOuat8W+4pE4pt4GGxBQKmiUZtZwH6teZmiwP12NKLYmUDrM5CmH27J sAEw== Received: from localhost.localdomain (97-118-99-160.hlrn.qwest.net. [97.118.99.160]) by smtp.gmail.com with ESMTPSA id f19sm4372318qkh.20.2018.11.27.20.32.58 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 27 Nov 2018 20:33:00 -0800 (PST) From: Martin Sebor Subject: [PATCH] be more permissive about function alignments (PR 88208) To: Gcc Patch List Message-ID: <19112bc8-83a2-2c35-2841-d95087cd1178@gmail.com> Date: Tue, 27 Nov 2018 21:32:57 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.3.1 MIME-Version: 1.0 X-IsSubscribed: yes The tests for the new __builtin_has_attribute function have been failing on a number of targets because of a couple of assumptions that only hold on some. First, they expect that it's safe to apply attribute aligned with a smaller alignment than the target provides when GCC rejects such arguments. The tests pass on i86 and elsewhere but fail on strictly aligned targets like aarch64 or sparc. After some testing and thinking I don't think this is helpful -- I believe it's better to instead silently accept attributes that ask for a less restrictive alignment than the function ultimately ends up with (see * below). This is what testing shows Clang does on those targets. The attached patch implements this change. Second, the tests assume that the priority forms of the constructor and destructor attributes are universally supported. That's also not the case, even though the manual doesn't mention that. To avoid these failures the attached patch moves the priority forms of the attribute constructor and destructor tests into its own file that's compiled only for init_priority targets. Finally, I noticed that attribute aligned accepts zero as an argument even though it's not a power of two as the manual documents as a precondition (zero is treated the same as the attribute without an argument). A zero argument is likely to be a mistake, especially when the zero comes from macro expansion, that users might want to know about. Clang rejects a zero with an error but I think a warning is more in line with established GCC practice, so the patch also implements that. Besides x86_64-linux, I tested this change with cross-compilers for aarch64-linux-elf, powerpc64le-linux, and sparc-solaris2.11. I added tests for the changed aligned attribute for those targets To make the gcc.dg/builtin-has-attribute.c test pass with the cross-compilers I changed from a runtime test into a compile only one. Martin PS I'm not happy about duplicating the same test across all those targets. It would be much nicer to have a single test somewhere in dg.exp #include a target-specific header with macros describing the target-specific parameters. [*] See the following discussion for some background: https://gcc.gnu.org/ml/gcc/2018-11/msg00127.html PR testsuite/88208 - new test case c-c++-common/builtin-has-attribute-3.c in r266335 has multiple excess errors gcc/ChangeLog: PR testsuite/88208 * doc/extend.texi (attribute constructor): Clarify. gcc/c/ChangeLog: PR testsuite/88208 * c-decl.c (declspec_add_alignas): Adjust call to check_user_alignment. gcc/c-family/ChangeLog: PR testsuite/88208 * c-attribs.c (common_handle_aligned_attribute): Silently avoid setting alignments to values less than the target requires. (has_attribute): For attribute aligned consider both the attribute and the alignment bits. * c-common.c (c_init_attributes): Optionally issue a warning for zero alignment. gcc/testsuite/ChangeLog: PR testsuite/88208 * gcc.dg/attr-aligned-2.c: New test. * gcc.dg/builtin-has-attribute.c: Adjust. * c-c++-common/builtin-has-attribute-2.c: Same. * c-c++-common/builtin-has-attribute-3.c: Same. * c-c++-common/builtin-has-attribute-4.c: Same. * c-c++-common/builtin-has-attribute-5.c: New test. * gcc.target/aarch64/attr-aligned.c: Same. * gcc.target/i386/attr-aligned.c: Same. * gcc.target/powerpc/attr-aligned.c: Same. * gcc.target/sparc/attr-aligned.c: Same. Index: gcc/doc/extend.texi =================================================================== --- gcc/doc/extend.texi (revision 266521) +++ gcc/doc/extend.texi (working copy) @@ -2552,8 +2552,9 @@ called. Functions with these attributes are usefu initializing data that is used implicitly during the execution of the program. -You may provide an optional integer priority to control the order in -which constructor and destructor functions are run. A constructor +On some targets the attributes also accept an integer argument to +specify a priority to control the order in which constructor and +destructor functions are run. A constructor with a smaller priority number runs before a constructor with a larger priority number; the opposite relationship holds for destructors. So, if you have a constructor that allocates a resource and a destructor @@ -2566,6 +2567,10 @@ decorated with attribute @code{constructor} are in In mixed declarations, attribute @code{init_priority} can be used to impose a specific ordering. +Using the argument forms of the @code{constructor} and @code{destructor} +attributes on targets where the feature is not supported is rejected with +an error. + @item copy @itemx copy (@var{function}) @cindex @code{copy} function attribute Index: gcc/c/c-decl.c =================================================================== --- gcc/c/c-decl.c (revision 266521) +++ gcc/c/c-decl.c (working copy) @@ -11061,12 +11061,15 @@ struct c_declspecs * declspecs_add_alignas (location_t loc, struct c_declspecs *specs, tree align) { - int align_log; specs->alignas_p = true; specs->locations[cdw_alignas] = loc; if (align == error_mark_node) return specs; - align_log = check_user_alignment (align, false, true); + + /* Only accept the alignment if it's valid and greater than + the current one. Zere is invalid but by C11 required to be + silently ignored. */ + int align_log = check_user_alignment (align, false, /* warn_zero = */false); if (align_log > specs->align_log) specs->align_log = align_log; return specs; Index: gcc/c-family/c-attribs.c =================================================================== --- gcc/c-family/c-attribs.c (revision 266521) +++ gcc/c-family/c-attribs.c (working copy) @@ -2003,7 +2003,8 @@ common_handle_aligned_attribute (tree *node, tree bool objfile = (TREE_CODE (*node) == FUNCTION_DECL || (VAR_P (*node) && TREE_STATIC (*node))); /* Log2 of specified alignment. */ - int pow2align = check_user_alignment (align_expr, objfile, true); + int pow2align = check_user_alignment (align_expr, objfile, + /* warn_zero = */ true); if (pow2align == -1 || !check_cxx_fundamental_alignment_constraints (*node, pow2align, flags)) { @@ -2019,6 +2020,9 @@ common_handle_aligned_attribute (tree *node, tree unsigned curalign = 0; unsigned lastalign = 0; + /* True when SET_DECL_ALIGN() should be called for the decl when + *NO_ADD_ATTRS is false. */ + bool set_align = true; if (is_type) { if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) @@ -2067,23 +2071,35 @@ common_handle_aligned_attribute (tree *node, tree curalign = lastalign; curalign /= BITS_PER_UNIT; - bitalign /= BITS_PER_UNIT; + unsigned newalign = bitalign / BITS_PER_UNIT; - bool diagd = true; auto_diagnostic_group d; - if (DECL_USER_ALIGN (decl) || DECL_USER_ALIGN (last_decl)) - diagd = warning (OPT_Wattributes, - "ignoring attribute %<%E (%u)%> because it conflicts " - "with attribute %<%E (%u)%>", - name, bitalign, name, curalign); + if ((DECL_USER_ALIGN (decl) + || DECL_USER_ALIGN (last_decl))) + { + if (warning (OPT_Wattributes, + "ignoring attribute %<%E (%u)%> because it conflicts " + "with attribute %<%E (%u)%>", + name, newalign, name, curalign) + && note) + inform (DECL_SOURCE_LOCATION (last_decl), + "previous declaration here"); + /* Only reject attempts to relax/override an alignment + explicitly specified previously and accept declarations + that appear to relax the implicit function alignment for + the target. Both increasing and increasing the alignment + set by -falign-functions setting is permitted. */ + *no_add_attrs = true; + } else if (!warn_if_not_aligned_p) - /* Do not error out for attribute warn_if_not_aligned. */ - error ("alignment for %q+D must be at least %d", decl, curalign); - - if (diagd && note) - inform (DECL_SOURCE_LOCATION (last_decl), "previous declaration here"); - - *no_add_attrs = true; + { + /* Do not fail for attribute warn_if_not_aligned. Otherwise, + silently avoid applying the alignment to the declaration + because it's implicitly satisfied by the target. Apply + the attribute nevertheless so it can be retrieved by + __builtin_has_attribute. */ + set_align = false; + } } else if (DECL_USER_ALIGN (decl) && DECL_ALIGN (decl) > bitalign) @@ -2100,33 +2116,29 @@ common_handle_aligned_attribute (tree *node, tree && TREE_CODE (decl) == FUNCTION_DECL && DECL_ALIGN (decl) > bitalign) { - /* Don't warn function alignment here if warn_if_not_aligned_p is - true. It will be warned later. */ + /* Don't warn for function alignment here if warn_if_not_aligned_p + is true. It will be warned about later. */ if (DECL_USER_ALIGN (decl)) - error ("alignment for %q+D was previously specified as %d " - "and may not be decreased", decl, - DECL_ALIGN (decl) / BITS_PER_UNIT); - else - error ("alignment for %q+D must be at least %d", decl, - DECL_ALIGN (decl) / BITS_PER_UNIT); - *no_add_attrs = true; - } - else - { - if (warn_if_not_aligned_p) { - if (TREE_CODE (decl) == FIELD_DECL && !DECL_C_BIT_FIELD (decl)) - { - SET_DECL_WARN_IF_NOT_ALIGN (decl, bitalign); - warn_if_not_aligned_p = false; - } + /* Only reject attempts to relax/override an alignment + explicitly specified previously and accept declarations + that appear to relax the implicit function alignment for + the target. Both increasing and increasing the alignment + set by -falign-functions setting is permitted. */ + error ("alignment for %q+D was previously specified as %d " + "and may not be decreased", decl, + DECL_ALIGN (decl) / BITS_PER_UNIT); + *no_add_attrs = true; } - else - { - SET_DECL_ALIGN (decl, bitalign); - DECL_USER_ALIGN (decl) = 1; - } } + else if (warn_if_not_aligned_p + && TREE_CODE (decl) == FIELD_DECL + && !DECL_C_BIT_FIELD (decl)) + { + SET_DECL_WARN_IF_NOT_ALIGN (decl, bitalign); + warn_if_not_aligned_p = false; + set_align = false; + } if (warn_if_not_aligned_p) { @@ -2134,6 +2146,11 @@ common_handle_aligned_attribute (tree *node, tree decl); *no_add_attrs = true; } + else if (!is_type && !*no_add_attrs && set_align) + { + SET_DECL_ALIGN (decl, bitalign); + DECL_USER_ALIGN (decl) = 1; + } return NULL_TREE; } @@ -4086,11 +4103,6 @@ has_attribute (location_t atloc, tree t, tree attr with the sought attributes) has been found on the attribute chain. */ bool found_attr = false; - /* For attribute aligned ignore the attribute list and consider - the tree node itself instead. */ - if (type && !strcmp ("aligned", namestr)) - atlist = NULL_TREE; - /* When clear, the first mismatched attribute argument results in failure. Otherwise, the first matched attribute argument results in success. */ Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 266521) +++ gcc/c-family/c-common.c (working copy) @@ -5143,11 +5143,11 @@ c_init_attributes (void) then reject alignments greater than MAX_OFILE_ALIGNMENT when converted to bits. Otherwise, consider valid only alignments that are less than HOST_BITS_PER_INT - LOG2_BITS_PER_UNIT. - If ALLOW_ZERO then 0 is valid and should result in - a return of -1 with no error. */ + Zero is not considered a valid argument (and results in -1 on + return) but it only triggers a warning when WARN_ZERO is set. */ int -check_user_alignment (const_tree align, bool objfile, bool allow_zero) +check_user_alignment (const_tree align, bool objfile, bool warn_zero) { if (error_operand_p (align)) return -1; @@ -5159,8 +5159,14 @@ int return -1; } - if (allow_zero && integer_zerop (align)) - return -1; + if (integer_zerop (align)) + { + if (warn_zero) + warning (OPT_Wattributes, + "requested alignment %qE is not a positive power of 2", + align); + return -1; + } int log2bitalign; if (tree_int_cst_sgn (align) == -1 Index: gcc/testsuite/gcc.dg/attr-aligned-2.c =================================================================== --- gcc/testsuite/gcc.dg/attr-aligned-2.c (nonexistent) +++ gcc/testsuite/gcc.dg/attr-aligned-2.c (working copy) @@ -0,0 +1,20 @@ +/* Verify that valid alignment on functions is accepted for all targets + and that alignment of zero is ignored with a warning. + { dg-do compile } + { dg-options "-Wno-pedantic" } */ + +#define ASSERT(expr) _Static_assert (expr, #expr) +#define ALIGN(n) __attribute__ ((aligned (n))) +#define alignof(expr) __alignof__ (expr) + +ALIGN (0) void f0 (void) { } /* { dg-warning "requested alignment .0. is not a positive power of 2" } */ +ALIGN (1) void f1 (void) { } +ALIGN (2) void f2 (void) { } +ALIGN (3) void f3 (void) { } /* { dg-error "requested alignment '3' is not a positive power of 2" } */ +ALIGN (4) void f4 (void) { } + +ASSERT (alignof (f0) > 0); +ASSERT (alignof (f1) >= 1); +ASSERT (alignof (f2) >= 2); +ASSERT (alignof (f3) >= 1); +ASSERT (alignof (f4) >= 4); Index: gcc/testsuite/c-c++-common/builtin-has-attribute-2.c =================================================================== --- gcc/testsuite/c-c++-common/builtin-has-attribute-2.c (revision 266521) +++ gcc/testsuite/c-c++-common/builtin-has-attribute-2.c (working copy) @@ -42,8 +42,8 @@ void test_type (int n) A (0, int ATTR (aligned (4)), aligned (2)); A (0, int ATTR (aligned (2)), aligned (4)); - /* GCC retains both attributes in the */ - A (0, int ATTR (aligned (2), aligned (4)), aligned (2)); + /* GCC retains both attributes when the type is defined in the builtin. */ + A (1, int ATTR (aligned (2), aligned (4)), aligned (2)); A (1, int ATTR (aligned (2), aligned (4)), aligned (4)); /* The following fails due to bug 87524. A (1, int ATTR (aligned (4), aligned (2))), aligned (4)); */ @@ -132,7 +132,7 @@ void test_typedef (int n) A (1, MAI, may_alias); typedef ATTR (aligned (4), may_alias) char A4MAC; - A (0, A4MAC, aligned (0)); + A (0, A4MAC, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */ A (0, A4MAC, aligned (1)); A (0, A4MAC, aligned (2)); A (1, A4MAC, aligned (4)); @@ -141,7 +141,7 @@ void test_typedef (int n) typedef ATTR (may_alias, aligned (8)) char A8MAC; A (1, A8MAC, aligned); - A (0, A8MAC, aligned (0)); + A (0, A8MAC, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */ A (0, A8MAC, aligned (1)); A (0, A8MAC, aligned (2)); A (0, A8MAC, aligned (4)); Index: gcc/testsuite/c-c++-common/builtin-has-attribute-3.c =================================================================== --- gcc/testsuite/c-c++-common/builtin-has-attribute-3.c (revision 266521) +++ gcc/testsuite/c-c++-common/builtin-has-attribute-3.c (working copy) @@ -35,7 +35,7 @@ ATTR (alias ("fnoreturn")) void falias (void); void test_aligned (void) { A (0, fnone, aligned); - A (0, fnone, aligned (0)); + A (0, fnone, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */ A (0, fnone, aligned (1)); A (0, fnone, aligned (2)); A (0, fnone, aligned (4)); @@ -43,18 +43,18 @@ void test_aligned (void) A (0, fnone, aligned (16)); A (1, faligned, aligned); - A (0, faligned, aligned (0)); + A (0, faligned, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */ A (0, faligned, aligned (1)); A (0, faligned, aligned (2)); A (1, faligned_1, aligned); - A (0, faligned_1, aligned (0)); + A (0, faligned_1, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */ A (1, faligned_1, aligned (1)); A (0, faligned_1, aligned (2)); A (0, faligned_1, aligned (4)); A (1, faligned_2, aligned); - A (0, faligned_2, aligned (0)); + A (0, faligned_2, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */ A (0, faligned_2, aligned (1)); A (1, faligned_2, aligned (2)); A (0, faligned_2, aligned (4)); @@ -193,18 +193,6 @@ void test_ctor_dtor (void) A (1, fctor_dtor, constructor); A (1, fctor_dtor, destructor); - - extern ATTR (constructor (123)) void fctor_123 (void); - A (1, fctor_123, constructor); - A (0, fctor_123, destructor); - A (1, fctor_123, constructor (123)); - A (0, fctor_123, constructor (124)); - - extern ATTR (destructor (234)) void fctor_123 (void); - A (1, fctor_123, constructor (123)); - A (1, fctor_123, destructor); - A (1, fctor_123, destructor (234)); - A (0, fctor_123, destructor (235)); } Index: gcc/testsuite/c-c++-common/builtin-has-attribute-4.c =================================================================== --- gcc/testsuite/c-c++-common/builtin-has-attribute-4.c (revision 266521) +++ gcc/testsuite/c-c++-common/builtin-has-attribute-4.c (working copy) @@ -19,7 +19,7 @@ ATTR (aligned (8)) char valigned_8; void test_aligned (void) { A (0, vnone, aligned); - A (0, vnone, aligned (0)); + A (0, vnone, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */ A (0, vnone, aligned (1)); A (0, vnone, aligned (2)); A (0, vnone, aligned (4)); @@ -27,18 +27,18 @@ void test_aligned (void) A (0, vnone, aligned (16)); A (1, valigned, aligned); - A (0, valigned, aligned (0)); + A (0, valigned, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */ A (0, valigned, aligned (1)); A (0, valigned, aligned (2)); A (1, valigned_1, aligned); - A (0, valigned_1, aligned (0)); + A (0, valigned_1, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */ A (1, valigned_1, aligned (1)); A (0, valigned_1, aligned (2)); A (0, valigned_1, aligned (4)); A (1, valigned_2, aligned); - A (0, valigned_2, aligned (0)); + A (0, valigned_2, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */ A (0, valigned_2, aligned (1)); A (1, valigned_2, aligned (2)); A (0, valigned_2, aligned (4)); Index: gcc/testsuite/c-c++-common/builtin-has-attribute-5.c =================================================================== --- gcc/testsuite/c-c++-common/builtin-has-attribute-5.c (nonexistent) +++ gcc/testsuite/c-c++-common/builtin-has-attribute-5.c (working copy) @@ -0,0 +1,48 @@ +/* Verify __builtin_has_attribute return value for attributes constructor + and destructor with explicit priorities. + { dg-do compile { target init_priority } } + { dg-options "-Wall -ftrack-macro-expansion=0" } + { dg-options "-Wall -Wno-narrowing -Wno-unused -ftrack-macro-expansion=0" { target c++ } } */ + +#define ATTR(...) __attribute__ ((__VA_ARGS__)) + +#define A(expect, sym, attr) \ + typedef int Assert [1 - 2 * !(__builtin_has_attribute (sym, attr) == expect)] + +void fnone (void); + +void test_ctor_dtor_prio (void) +{ + extern ATTR (constructor) void fctor (void); + extern ATTR (destructor) void fdtor (void); + extern ATTR (constructor, destructor) void fctor_dtor (void); + + A (0, fnone, constructor); + A (0, fnone, constructor (123)); + A (0, fnone, destructor); + A (0, fnone, constructor (234)); + + A (1, fctor, constructor); + A (0, fctor, constructor (123)); + A (1, fdtor, destructor); + A (0, fdtor, destructor (234)); + + extern ATTR (constructor) void fctor_dtor (void); + extern ATTR (destructor) void fctor_dtor (void); + extern ATTR (constructor, destructor) void fctor_dtor (void); + + A (1, fctor_dtor, constructor); + A (1, fctor_dtor, destructor); + + extern ATTR (constructor (123)) void fctor_123 (void); + A (1, fctor_123, constructor); + A (0, fctor_123, destructor); + A (1, fctor_123, constructor (123)); + A (0, fctor_123, constructor (124)); + + extern ATTR (destructor (234)) void fctor_123 (void); + A (1, fctor_123, constructor (123)); + A (1, fctor_123, destructor); + A (1, fctor_123, destructor (234)); + A (0, fctor_123, destructor (235)); +} Index: gcc/testsuite/gcc.dg/builtin-has-attribute.c =================================================================== --- gcc/testsuite/gcc.dg/builtin-has-attribute.c (revision 266521) +++ gcc/testsuite/gcc.dg/builtin-has-attribute.c (working copy) @@ -3,8 +3,8 @@ Also verify that the expression in __builtin_has_attribute is not evaluated. - { dg-do run } - { dg-options "-O2 -Wall -Wc++-compat" } */ + { dg-do compile } + { dg-options "-O2 -Wall -Wc++-compat -fdump-tree-optimized -ftrack-macro-expansion=0" } */ #define ATTR(list) __attribute__ (list) @@ -11,8 +11,6 @@ #define A(expect, sym, attr) \ typedef int Assert [1 - 2 * !(__builtin_has_attribute (sym, attr) == expect)] -int nfails; - #define assert(expr) \ ((expr) \ ? (void)0 \ @@ -24,22 +22,27 @@ A (0, struct A { int i; }, aligned); /* { dg-war A (1, struct ATTR ((aligned)) B { int i; }, aligned); /* { dg-warning "expression is invalid in C\\\+\\\+" } */ -int f (void) +static int f (void) { __builtin_abort (); } -int n = 1; - int main (void) { + int n = 0, nfails = 0; + assert (0 == __builtin_has_attribute (int[n++], aligned)); assert (1 == __builtin_has_attribute (ATTR ((aligned)) int[n++], aligned)); assert (1 == __builtin_has_attribute (ATTR ((aligned)) int[f ()], aligned)); assert (1 == 1); + if (n) + __builtin_abort (); + if (nfails) __builtin_abort (); return 0; } + +/* { dg-final { scan-tree-dump-times "abort" 0 "optimized" } } */ Index: gcc/testsuite/gcc.target/aarch64/attr-aligned.c =================================================================== --- gcc/testsuite/gcc.target/aarch64/attr-aligned.c (nonexistent) +++ gcc/testsuite/gcc.target/aarch64/attr-aligned.c (working copy) @@ -0,0 +1,65 @@ +/* Verify that valid alignment on functions is accepted and results + in the alignment expected for the target and that alignment of + zero is ignored with a warning. + { dg-do compile } + { dg-options "-Wno-pedantic -ftrack-macro-expansion=0" } */ + +#define ASSERT(expr) _Static_assert (expr, #expr) +#define ALIGN(n) __attribute__ ((aligned (n))) +#define alignof(expr) __alignof__ (expr) +#define HAS_ALIGN(f, n) __builtin_has_attribute (f, __aligned__ (n)) + +#define MINALIGN(N) ((N) < 4 ? 4 : (N)) +#define MAXALIGN 16 + +/* No alignment specified. */ +void f (void) { } + +/* Empty alignment means maximum. */ +ALIGN () void f_ (void) { } + +ALIGN (0) void f0 (void) { } /* { dg-warning "requested alignment .0. is not a positive power of 2" } */ +ALIGN (1) void f1 (void) { } +ALIGN (2) void f2 (void) { } +ALIGN (4) void f4 (void) { } +ALIGN (8) void f8 (void) { } +ALIGN (16) void f16 (void) { } +ALIGN (32) void f32 (void) { } + +ASSERT (alignof (f_) == MAXALIGN); +ASSERT (alignof (f0) == alignof (f)); +ASSERT (alignof (f1) == MINALIGN (1)); +ASSERT (alignof (f2) == MINALIGN (2)); +ASSERT (alignof (f4) == MINALIGN (4)); +ASSERT (alignof (f8) == MINALIGN (8)); +ASSERT (alignof (f16) == MINALIGN (16)); +ASSERT (alignof (f32) == MINALIGN (32)); + +ASSERT (!__builtin_has_attribute (f, aligned)); +ASSERT (__builtin_has_attribute (f_, aligned)); +ASSERT (!__builtin_has_attribute (f0, aligned)); + +ASSERT (!HAS_ALIGN (f_, MAXALIGN)); + +ASSERT (HAS_ALIGN (f1, 1)); +ASSERT (!HAS_ALIGN (f1, 2)); + +ASSERT (!HAS_ALIGN (f2, 1)); +ASSERT (HAS_ALIGN (f2, 2)); +ASSERT (!HAS_ALIGN (f2, 4)); + +ASSERT (!HAS_ALIGN (f4, 2)); +ASSERT (HAS_ALIGN (f4, 4)); +ASSERT (!HAS_ALIGN (f4, 8)); + +ASSERT (!HAS_ALIGN (f8, 4)); +ASSERT (HAS_ALIGN (f8, 8)); +ASSERT (!HAS_ALIGN (f8, 16)); + +ASSERT (!HAS_ALIGN (f16, 8)); +ASSERT (HAS_ALIGN (f16, 16)); +ASSERT (!HAS_ALIGN (f16, 32)); + +ASSERT (!HAS_ALIGN (f32, 16)); +ASSERT (HAS_ALIGN (f32, 32)); +ASSERT (!HAS_ALIGN (f32, 64)); Index: gcc/testsuite/gcc.target/i386/attr-aligned.c =================================================================== --- gcc/testsuite/gcc.target/i386/attr-aligned.c (nonexistent) +++ gcc/testsuite/gcc.target/i386/attr-aligned.c (working copy) @@ -0,0 +1,65 @@ +/* Verify that valid alignment on functions is accepted and results + in the alignment expected for the target and that alignment of + zero is ignored with a warning. + { dg-do compile } + { dg-options "-Wno-pedantic -ftrack-macro-expansion=0" } */ + +#define ASSERT(expr) _Static_assert (expr, #expr) +#define ALIGN(n) __attribute__ ((aligned (n))) +#define alignof(expr) __alignof__ (expr) +#define HAS_ALIGN(f, n) __builtin_has_attribute (f, __aligned__ (n)) + +#define MINALIGN(N) N +#define MAXALIGN 16 + +/* No alignment specified. */ +void f (void) { } + +/* Empty alignment means maximum. */ +ALIGN () void f_ (void) { } + +ALIGN (0) void f0 (void) { } /* { dg-warning "requested alignment .0. is not a positive power of 2" } */ +ALIGN (1) void f1 (void) { } +ALIGN (2) void f2 (void) { } +ALIGN (4) void f4 (void) { } +ALIGN (8) void f8 (void) { } +ALIGN (16) void f16 (void) { } +ALIGN (32) void f32 (void) { } + +ASSERT (alignof (f_) == MAXALIGN); +ASSERT (alignof (f0) == alignof (f)); +ASSERT (alignof (f1) == MINALIGN (1)); +ASSERT (alignof (f2) == MINALIGN (2)); +ASSERT (alignof (f4) == MINALIGN (4)); +ASSERT (alignof (f8) == MINALIGN (8)); +ASSERT (alignof (f16) == MINALIGN (16)); +ASSERT (alignof (f32) == MINALIGN (32)); + +ASSERT (!__builtin_has_attribute (f, aligned)); +ASSERT (__builtin_has_attribute (f_, aligned)); +ASSERT (!__builtin_has_attribute (f0, aligned)); + +ASSERT (!HAS_ALIGN (f_, MAXALIGN)); + +ASSERT (HAS_ALIGN (f1, 1)); +ASSERT (!HAS_ALIGN (f1, 2)); + +ASSERT (!HAS_ALIGN (f2, 1)); +ASSERT (HAS_ALIGN (f2, 2)); +ASSERT (!HAS_ALIGN (f2, 4)); + +ASSERT (!HAS_ALIGN (f4, 2)); +ASSERT (HAS_ALIGN (f4, 4)); +ASSERT (!HAS_ALIGN (f4, 8)); + +ASSERT (!HAS_ALIGN (f8, 4)); +ASSERT (HAS_ALIGN (f8, 8)); +ASSERT (!HAS_ALIGN (f8, 16)); + +ASSERT (!HAS_ALIGN (f16, 8)); +ASSERT (HAS_ALIGN (f16, 16)); +ASSERT (!HAS_ALIGN (f16, 32)); + +ASSERT (!HAS_ALIGN (f32, 16)); +ASSERT (HAS_ALIGN (f32, 32)); +ASSERT (!HAS_ALIGN (f32, 64)); Index: gcc/testsuite/gcc.target/powerpc/attr-aligned.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/attr-aligned.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/attr-aligned.c (working copy) @@ -0,0 +1,65 @@ +/* Verify that valid alignment on functions is accepted and results + in the alignment expected for the target and that alignment of + zero is ignored with a warning. + { dg-do compile } + { dg-options "-Wno-pedantic -ftrack-macro-expansion=0" } */ + +#define ASSERT(expr) _Static_assert (expr, #expr) +#define ALIGN(n) __attribute__ ((aligned (n))) +#define alignof(expr) __alignof__ (expr) +#define HAS_ALIGN(f, n) __builtin_has_attribute (f, __aligned__ (n)) + +#define MINALIGN(N) (N < 4 ? 4 : N) +#define MAXALIGN 16 + +/* No alignment specified. */ +void f (void) { } + +/* Empty alignment means maximum. */ +ALIGN () void f_ (void) { } + +ALIGN (0) void f0 (void) { } /* { dg-warning "requested alignment .0. is not a positive power of 2" } */ +ALIGN (1) void f1 (void) { } +ALIGN (2) void f2 (void) { } +ALIGN (4) void f4 (void) { } +ALIGN (8) void f8 (void) { } +ALIGN (16) void f16 (void) { } +ALIGN (32) void f32 (void) { } + +ASSERT (alignof (f_) == MAXALIGN); +ASSERT (alignof (f0) == alignof (f)); +ASSERT (alignof (f1) == MINALIGN (1)); +ASSERT (alignof (f2) == MINALIGN (2)); +ASSERT (alignof (f4) == MINALIGN (4)); +ASSERT (alignof (f8) == MINALIGN (8)); +ASSERT (alignof (f16) == MINALIGN (16)); +ASSERT (alignof (f32) == MINALIGN (32)); + +ASSERT (!__builtin_has_attribute (f, aligned)); +ASSERT (__builtin_has_attribute (f_, aligned)); +ASSERT (!__builtin_has_attribute (f0, aligned)); + +ASSERT (!HAS_ALIGN (f_, MAXALIGN)); + +ASSERT (HAS_ALIGN (f1, 1)); +ASSERT (!HAS_ALIGN (f1, 2)); + +ASSERT (!HAS_ALIGN (f2, 1)); +ASSERT (HAS_ALIGN (f2, 2)); +ASSERT (!HAS_ALIGN (f2, 4)); + +ASSERT (!HAS_ALIGN (f4, 2)); +ASSERT (HAS_ALIGN (f4, 4)); +ASSERT (!HAS_ALIGN (f4, 8)); + +ASSERT (!HAS_ALIGN (f8, 4)); +ASSERT (HAS_ALIGN (f8, 8)); +ASSERT (!HAS_ALIGN (f8, 16)); + +ASSERT (!HAS_ALIGN (f16, 8)); +ASSERT (HAS_ALIGN (f16, 16)); +ASSERT (!HAS_ALIGN (f16, 32)); + +ASSERT (!HAS_ALIGN (f32, 16)); +ASSERT (HAS_ALIGN (f32, 32)); +ASSERT (!HAS_ALIGN (f32, 64)); Index: gcc/testsuite/gcc.target/sparc/attr-aligned.c =================================================================== --- gcc/testsuite/gcc.target/sparc/attr-aligned.c (nonexistent) +++ gcc/testsuite/gcc.target/sparc/attr-aligned.c (working copy) @@ -0,0 +1,65 @@ +/* Verify that valid alignment on functions is accepted and results + in the alignment expected for the target and that alignment of + zero is ignored with a warning. + { dg-do compile } + { dg-options "-Wno-pedantic -ftrack-macro-expansion=0" } */ + +#define ASSERT(expr) _Static_assert (expr, #expr) +#define ALIGN(n) __attribute__ ((aligned (n))) +#define alignof(expr) __alignof__ (expr) +#define HAS_ALIGN(f, n) __builtin_has_attribute (f, __aligned__ (n)) + +#define MINALIGN(N) ((N) < 4 ? 4 : (N)) +#define MAXALIGN 8 + +/* No alignment specified. */ +void f (void) { } + +/* Empty alignment means maximum. */ +ALIGN () void f_ (void) { } + +ALIGN (0) void f0 (void) { } /* { dg-warning "requested alignment .0. is not a positive power of 2" } */ +ALIGN (1) void f1 (void) { } +ALIGN (2) void f2 (void) { } +ALIGN (4) void f4 (void) { } +ALIGN (8) void f8 (void) { } +ALIGN (16) void f16 (void) { } +ALIGN (32) void f32 (void) { } + +ASSERT (alignof (f_) == MAXALIGN); +ASSERT (alignof (f0) == alignof (f)); +ASSERT (alignof (f1) == MINALIGN (1)); +ASSERT (alignof (f2) == MINALIGN (2)); +ASSERT (alignof (f4) == MINALIGN (4)); +ASSERT (alignof (f8) == MINALIGN (8)); +ASSERT (alignof (f16) == MINALIGN (16)); +ASSERT (alignof (f32) == MINALIGN (32)); + +ASSERT (!__builtin_has_attribute (f, aligned)); +ASSERT (__builtin_has_attribute (f_, aligned)); +ASSERT (!__builtin_has_attribute (f0, aligned)); + +ASSERT (!HAS_ALIGN (f_, MAXALIGN)); + +ASSERT (HAS_ALIGN (f1, 1)); +ASSERT (!HAS_ALIGN (f1, 2)); + +ASSERT (!HAS_ALIGN (f2, 1)); +ASSERT (HAS_ALIGN (f2, 2)); +ASSERT (!HAS_ALIGN (f2, 4)); + +ASSERT (!HAS_ALIGN (f4, 2)); +ASSERT (HAS_ALIGN (f4, 4)); +ASSERT (!HAS_ALIGN (f4, 8)); + +ASSERT (!HAS_ALIGN (f8, 4)); +ASSERT (HAS_ALIGN (f8, 8)); +ASSERT (!HAS_ALIGN (f8, 16)); + +ASSERT (!HAS_ALIGN (f16, 8)); +ASSERT (HAS_ALIGN (f16, 16)); +ASSERT (!HAS_ALIGN (f16, 32)); + +ASSERT (!HAS_ALIGN (f32, 16)); +ASSERT (HAS_ALIGN (f32, 32)); +ASSERT (!HAS_ALIGN (f32, 64));