aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJozef Lawrynowicz <jozef.l@mittosystems.com>2020-11-23 12:06:15 +0000
committerJozef Lawrynowicz <jozef.l@mittosystems.com>2020-11-23 12:06:15 +0000
commitfb8309d4abdcd4c8de07bd4c42e22d1e80471765 (patch)
treef2bbbaa05ee7dd1fc45845ae0d1277765032e6f5 /gcc
parentb510765dedfec573c756cb1fcfcb5b0c3830c5e9 (diff)
downloadgcc-fb8309d4abdcd4c8de07bd4c42e22d1e80471765.zip
gcc-fb8309d4abdcd4c8de07bd4c42e22d1e80471765.tar.gz
gcc-fb8309d4abdcd4c8de07bd4c42e22d1e80471765.tar.bz2
cp/decl.c: Set DECL_INITIAL before attribute processing
Attribute handlers may want to examine DECL_INITIAL for a decl, to validate the attribute being applied. For C++, DECL_INITIAL is currently not set until cp_finish_decl, by which time attribute validation has already been performed. For msp430-elf this causes the "persistent" attribute to always be rejected for C++, since DECL_INITIAL must be non-null for the attribute to be applied to a decl. This patch ensures DECL_INITIAL is set for initialized decls early in start_decl, before attribute handlers run. This allows the initialization status of the decl to be examined by the handlers. DECL_INITIAL must be restored to it's initial value after attribute validation is performed, so as to not interfere with later decl processing. gcc/cp/ChangeLog: * decl.c (start_decl): Set DECL_INITIAL for initialized decls before attribute processing. gcc/testsuite/ChangeLog: * gcc.target/msp430/data-attributes-2.c: Adjust test. * g++.target/msp430/data-attributes.C: New test. * g++.target/msp430/msp430.exp: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/decl.c13
-rw-r--r--gcc/testsuite/g++.target/msp430/data-attributes.C52
-rw-r--r--gcc/testsuite/g++.target/msp430/msp430.exp44
-rw-r--r--gcc/testsuite/gcc.target/msp430/data-attributes-2.c1
4 files changed, 110 insertions, 0 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1c6dcdb..3dd4b07 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5248,6 +5248,7 @@ start_decl (const cp_declarator *declarator,
bool was_public;
int flags;
bool alias;
+ tree initial;
*pushed_scope_p = NULL_TREE;
@@ -5272,6 +5273,10 @@ start_decl (const cp_declarator *declarator,
return error_mark_node;
}
+ /* Save the DECL_INITIAL value in case it gets clobbered to assist
+ with attribute validation. */
+ initial = DECL_INITIAL (decl);
+
if (initialized)
{
if (! toplevel_bindings_p ()
@@ -5281,6 +5286,10 @@ start_decl (const cp_declarator *declarator,
DECL_EXTERNAL (decl) = 0;
if (toplevel_bindings_p ())
TREE_STATIC (decl) = 1;
+ /* Tell 'cplus_decl_attributes' this is an initialized decl,
+ even though we might not yet have the initializer expression. */
+ if (!DECL_INITIAL (decl))
+ DECL_INITIAL (decl) = error_mark_node;
}
alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl)) != 0;
@@ -5299,6 +5308,10 @@ start_decl (const cp_declarator *declarator,
/* Set attributes here so if duplicate decl, will have proper attributes. */
cplus_decl_attributes (&decl, attributes, flags);
+ /* Restore the original DECL_INITIAL that we may have clobbered earlier to
+ assist with attribute validation. */
+ DECL_INITIAL (decl) = initial;
+
/* Dllimported symbols cannot be defined. Static data members (which
can be initialized in-class and dllimported) go through grokfield,
not here, so we don't need to exclude those decls when checking for
diff --git a/gcc/testsuite/g++.target/msp430/data-attributes.C b/gcc/testsuite/g++.target/msp430/data-attributes.C
new file mode 100644
index 0000000..4e2139e
--- /dev/null
+++ b/gcc/testsuite/g++.target/msp430/data-attributes.C
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-mcpu=msp430" } } */
+/* { dg-options "-mlarge" } */
+
+/* The msp430-specific variable attributes "lower", "upper", either", "noinit"
+ and "persistent", all conflict with one another.
+ These attributes also conflict with the "section" attribute, since they
+ specify sections to put the variables into. */
+int __attribute__((persistent)) p = 10;
+int __attribute__((persistent,lower)) pl = 20; /* { dg-warning "ignoring attribute 'lower' because it conflicts with attribute 'persistent'" } */
+int __attribute__((persistent,upper)) pu = 20; /* { dg-warning "ignoring attribute 'upper' because it conflicts with attribute 'persistent'" } */
+int __attribute__((persistent,either)) pe = 20; /* { dg-warning "ignoring attribute 'either' because it conflicts with attribute 'persistent'" } */
+/* This one results in an error because the handler for persistent sets the
+ section to .persistent there and then. */
+int __attribute__((persistent,section(".data.foo"))) ps = 20; /* { dg-error "section of 'ps' conflicts with previous declaration" } */
+int __attribute__((persistent,noinit)) pn = 2; /* { dg-warning "'noinit' attribute cannot be applied to variables with specific sections" } */
+int __attribute__((persistent)) zz; /* { dg-warning "variables marked with 'persistent' attribute must be initialized" } */
+
+int __attribute__((noinit)) n;
+int __attribute__((noinit,lower)) nl; /* { dg-warning "ignoring attribute 'lower' because it conflicts with attribute 'noinit'" } */
+int __attribute__((noinit,upper)) nu; /* { dg-warning "ignoring attribute 'upper' because it conflicts with attribute 'noinit'" } */
+int __attribute__((noinit,either)) ne; /* { dg-warning "ignoring attribute 'either' because it conflicts with attribute 'noinit'" } */
+int __attribute__((noinit,persistent)) np; /* { dg-warning "ignoring attribute 'persistent' because it conflicts with attribute 'noinit'" } */
+int __attribute__((noinit,section(".data.foo"))) ns; /* { dg-warning "ignoring attribute 'section' because it conflicts with attribute 'noinit'" } */
+
+int __attribute__((lower)) l = 20;
+int __attribute__((lower,upper)) lu = 20; /* { dg-warning "ignoring attribute 'upper' because it conflicts with attribute 'lower'" } */
+int __attribute__((lower,either)) le = 20; /* { dg-warning "ignoring attribute 'either' because it conflicts with attribute 'lower'" } */
+int __attribute__((lower,persistent)) lp = 20; /* { dg-warning "ignoring attribute 'persistent' because it conflicts with attribute 'lower'" } */
+int __attribute__((lower,noinit)) ln; /* { dg-warning "ignoring attribute 'noinit' because it conflicts with attribute 'lower'" } */
+int __attribute__((lower,section(".data.foo"))) ls = 30;
+
+int __attribute__((upper)) u = 20;
+int __attribute__((upper,lower)) ul = 20; /* { dg-warning "ignoring attribute 'lower' because it conflicts with attribute 'upper'" } */
+int __attribute__((upper,either)) ue = 20; /* { dg-warning "ignoring attribute 'either' because it conflicts with attribute 'upper'" } */
+int __attribute__((upper,persistent)) up = 20; /* { dg-warning "ignoring attribute 'persistent' because it conflicts with attribute 'upper'" } */
+int __attribute__((upper,noinit)) un; /* { dg-warning "ignoring attribute 'noinit' because it conflicts with attribute 'upper'" } */
+int __attribute__((upper,section(".data.foo"))) us = 30; /* { dg-warning "ignoring attribute 'section' because it conflicts with attribute 'upper'" } */
+
+int __attribute__((either)) e = 20;
+int __attribute__((either,lower)) el = 20; /* { dg-warning "ignoring attribute 'lower' because it conflicts with attribute 'either'" } */
+int __attribute__((either,upper)) ee = 20; /* { dg-warning "ignoring attribute 'upper' because it conflicts with attribute 'either'" } */
+int __attribute__((either,persistent)) ep = 20; /* { dg-warning "ignoring attribute 'persistent' because it conflicts with attribute 'either'" } */
+int __attribute__((either,noinit)) en; /* { dg-warning "ignoring attribute 'noinit' because it conflicts with attribute 'either'" } */
+int __attribute__((either,section(".data.foo"))) es = 30; /* { dg-warning "ignoring attribute 'section' because it conflicts with attribute 'either'" } */
+
+int __attribute__((section(".data.foo"))) s = 20;
+int __attribute__((section(".data.foo"),noinit)) sn; /* { dg-warning "ignoring attribute 'noinit' because it conflicts with attribute 'section'" } */
+int __attribute__((section(".data.foo"),persistent)) sp = 20; /* { dg-warning "ignoring attribute 'persistent' because it conflicts with attribute 'section'" } */
+int __attribute__((section(".data.foo"),lower)) sl = 2;
+int __attribute__((section(".data.foo"),upper)) su = 20; /* { dg-warning "ignoring attribute 'upper' because it conflicts with attribute 'section'" } */
+int __attribute__((section(".data.foo"),either)) se = 2; /* { dg-warning "ignoring attribute 'either' because it conflicts with attribute 'section'" } */
diff --git a/gcc/testsuite/g++.target/msp430/msp430.exp b/gcc/testsuite/g++.target/msp430/msp430.exp
new file mode 100644
index 0000000..3574c0f
--- /dev/null
+++ b/gcc/testsuite/g++.target/msp430/msp430.exp
@@ -0,0 +1,44 @@
+# Specific regression driver for MSP430.
+# Copyright (C) 2020 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>. */
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't an MSP430 target.
+if {![istarget msp430*-*-*] } then {
+ return
+}
+
+# Load support procs.
+load_lib g++-dg.exp
+
+global DEFAULT_CXXFLAGS
+if ![info exists DEFAULT_CXXFLAGS] then {
+ set DEFAULT_CXXFLAGS " -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] \
+ "" $DEFAULT_CXXFLAGS
+
+# All done.
+dg-finish
+
diff --git a/gcc/testsuite/gcc.target/msp430/data-attributes-2.c b/gcc/testsuite/gcc.target/msp430/data-attributes-2.c
index 6113e99..4e2139e 100644
--- a/gcc/testsuite/gcc.target/msp430/data-attributes-2.c
+++ b/gcc/testsuite/gcc.target/msp430/data-attributes-2.c
@@ -14,6 +14,7 @@ int __attribute__((persistent,either)) pe = 20; /* { dg-warning "ignoring attrib
section to .persistent there and then. */
int __attribute__((persistent,section(".data.foo"))) ps = 20; /* { dg-error "section of 'ps' conflicts with previous declaration" } */
int __attribute__((persistent,noinit)) pn = 2; /* { dg-warning "'noinit' attribute cannot be applied to variables with specific sections" } */
+int __attribute__((persistent)) zz; /* { dg-warning "variables marked with 'persistent' attribute must be initialized" } */
int __attribute__((noinit)) n;
int __attribute__((noinit,lower)) nl; /* { dg-warning "ignoring attribute 'lower' because it conflicts with attribute 'noinit'" } */