aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2019-04-18 09:50:56 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2020-04-01 00:12:47 +0200
commit013fca64fc17ba646c3564eab52fac50f0751188 (patch)
treec75868fd2d0b82c3e4ba548430629646ea5fb681 /gcc
parent1c16f7fc903c1c1c912faf7889b69d83429b7b2e (diff)
downloadgcc-013fca64fc17ba646c3564eab52fac50f0751188.zip
gcc-013fca64fc17ba646c3564eab52fac50f0751188.tar.gz
gcc-013fca64fc17ba646c3564eab52fac50f0751188.tar.bz2
d: Merge UDAs between function prototype and definitions (PR90136)
This change fixes the symbol merging in get_symbol_decl to also consider prototypes. This allows the ability to set user defined attributes on the prototype of a function, which then get applied to the definition, if found later in the compilation. The lowering of UDAs to GCC attributes has been commonized into a single function called apply_user_attributes. gcc/d/ChangeLog: PR d/90136 * d-attribs.cc: Include dmd/attrib.h. (build_attributes): Redeclare as static. (apply_user_attributes): New function. * d-tree.h (class UserAttributeDeclaration): Remove. (build_attributes): Remove. (apply_user_attributes): Declare. (finish_aggregate_type): Remove attrs argument. * decl.cc (get_symbol_decl): Merge declaration prototypes with definitions. Use apply_user_attributes. * modules.cc (layout_moduleinfo_fields): Remove last argument to finish_aggregate_type. * typeinfo.cc (layout_classinfo_interfaces): Likewise. * types.cc (layout_aggregate_members): Likewise. (finish_aggregate_type): Remove attrs argument. (TypeVisitor::visit (TypeEnum *)): Use apply_user_attributes. (TypeVisitor::visit (TypeStruct *)): Remove last argument to finish_aggregate_type. Use apply_user_attributes. (TypeVisitor::visit (TypeClass *)): Likewise. gcc/testsuite/ChangeLog: PR d/90136 * gdc.dg/pr90136a.d: New test. * gdc.dg/pr90136b.d: New test. * gdc.dg/pr90136c.d: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/d/ChangeLog22
-rw-r--r--gcc/d/d-attribs.cc27
-rw-r--r--gcc/d/d-tree.h6
-rw-r--r--gcc/d/decl.cc49
-rw-r--r--gcc/d/modules.cc2
-rw-r--r--gcc/d/typeinfo.cc2
-rw-r--r--gcc/d/types.cc31
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gdc.dg/pr90136a.d21
-rw-r--r--gcc/testsuite/gdc.dg/pr90136b.d21
-rw-r--r--gcc/testsuite/gdc.dg/pr90136c.d9
11 files changed, 146 insertions, 51 deletions
diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog
index 20817e3..d27f83e 100644
--- a/gcc/d/ChangeLog
+++ b/gcc/d/ChangeLog
@@ -1,3 +1,25 @@
+2020-04-01 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/90136
+ * d-attribs.cc: Include dmd/attrib.h.
+ (build_attributes): Redeclare as static.
+ (apply_user_attributes): New function.
+ * d-tree.h (class UserAttributeDeclaration): Remove.
+ (build_attributes): Remove.
+ (apply_user_attributes): Declare.
+ (finish_aggregate_type): Remove attrs argument.
+ * decl.cc (get_symbol_decl): Merge declaration prototypes with
+ definitions. Use apply_user_attributes.
+ * modules.cc (layout_moduleinfo_fields): Remove last argument to
+ finish_aggregate_type.
+ * typeinfo.cc (layout_classinfo_interfaces): Likewise.
+ * types.cc (layout_aggregate_members): Likewise.
+ (finish_aggregate_type): Remove attrs argument.
+ (TypeVisitor::visit (TypeEnum *)): Use apply_user_attributes.
+ (TypeVisitor::visit (TypeStruct *)): Remove last argument to
+ finish_aggregate_type. Use apply_user_attributes.
+ (TypeVisitor::visit (TypeClass *)): Likewise.
+
2020-03-31 Iain Buclaw <ibuclaw@gdcproject.org>
* d-attribs.cc (d_langhook_common_attribute_table): Add always_inline.
diff --git a/gcc/d/d-attribs.cc b/gcc/d/d-attribs.cc
index bba6f51..69434c6 100644
--- a/gcc/d/d-attribs.cc
+++ b/gcc/d/d-attribs.cc
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
+#include "dmd/attrib.h"
#include "dmd/declaration.h"
#include "dmd/mtype.h"
@@ -234,7 +235,7 @@ uda_attribute_p (const char *name)
`gcc.attribute.Attribute'. This symbol is internally recognized by the
compiler and maps them to their equivalent GCC attribute. */
-tree
+static tree
build_attributes (Expressions *eattrs)
{
if (!eattrs)
@@ -319,6 +320,30 @@ build_attributes (Expressions *eattrs)
return attribs;
}
+/* If any GCC attributes are found in the declaration SYM, apply them to the
+ type or decl NODE. */
+
+void
+apply_user_attributes (Dsymbol *sym, tree node)
+{
+ if (!sym->userAttribDecl)
+ {
+ if (DECL_P (node) && DECL_ATTRIBUTES (node) != NULL)
+ decl_attributes (&node, DECL_ATTRIBUTES (node), 0);
+
+ return;
+ }
+
+ location_t saved_location = input_location;
+ input_location = make_location_t (sym->loc);
+
+ Expressions *attrs = sym->userAttribDecl->getAttributes ();
+ decl_attributes (&node, build_attributes (attrs),
+ TYPE_P (node) ? ATTR_FLAG_TYPE_IN_PLACE : 0);
+
+ input_location = saved_location;
+}
+
/* Built-in attribute handlers. */
/* Handle a "noreturn" attribute; arguments as in
diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
index 0f831c7..89feb9e 100644
--- a/gcc/d/d-tree.h
+++ b/gcc/d/d-tree.h
@@ -29,7 +29,6 @@ class FuncDeclaration;
class StructDeclaration;
class TypeInfoDeclaration;
class VarDeclaration;
-class UserAttributeDeclaration;
class Expression;
class ClassReferenceExp;
class Module;
@@ -485,7 +484,7 @@ extern bool doing_semantic_analysis_p;
/* In d-attribs.c. */
extern tree insert_type_attribute (tree, const char *, tree = NULL_TREE);
extern tree insert_decl_attribute (tree, const char *, tree = NULL_TREE);
-extern tree build_attributes (Expressions *);
+extern void apply_user_attributes (Dsymbol *, tree);
/* In d-builtins.cc. */
extern const attribute_spec d_langhook_attribute_table[];
@@ -681,8 +680,7 @@ extern tree make_array_type (Type *, unsigned HOST_WIDE_INT);
extern tree make_struct_type (const char *, int n, ...);
extern tree insert_type_modifiers (tree, unsigned);
extern void insert_aggregate_field (tree, tree, size_t);
-extern void finish_aggregate_type (unsigned, unsigned, tree,
- UserAttributeDeclaration *);
+extern void finish_aggregate_type (unsigned, unsigned, tree);
extern tree build_ctype (Type *);
#endif /* GCC_D_TREE_H */
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 053d553..042c10c 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -1110,7 +1110,10 @@ get_symbol_decl (Declaration *decl)
/* Set function type afterwards as there could be self references. */
TREE_TYPE (decl->csym) = build_ctype (fd->type);
- if (!fd->fbody)
+ /* Set DECL_INITIAL now if the function has a definition. */
+ if (fd->fbody)
+ DECL_INITIAL (decl->csym) = error_mark_node;
+ else
DECL_EXTERNAL (decl->csym) = 1;
}
else
@@ -1151,26 +1154,38 @@ get_symbol_decl (Declaration *decl)
mangled_name);
/* The frontend doesn't handle duplicate definitions of unused symbols
with the same mangle. So a check is done here instead. */
- if (!DECL_EXTERNAL (decl->csym))
+ if (IDENTIFIER_DSYMBOL (mangled_name))
{
- if (IDENTIFIER_DSYMBOL (mangled_name))
- {
- Declaration *other = IDENTIFIER_DSYMBOL (mangled_name);
+ Declaration *other = IDENTIFIER_DSYMBOL (mangled_name);
+ tree olddecl = decl->csym;
+ decl->csym = get_symbol_decl (other);
- /* Non-templated variables shouldn't be defined twice. */
- if (!decl->isInstantiated ())
- ScopeDsymbol::multiplyDefined (decl->loc, decl, other);
-
- decl->csym = get_symbol_decl (other);
+ /* The current declaration is a prototype or marked extern, merge
+ applied user attributes and return. */
+ if (DECL_EXTERNAL (olddecl) && !DECL_INITIAL (olddecl))
+ {
+ apply_user_attributes (decl, decl->csym);
return decl->csym;
}
-
+ /* The previous declaration is a prototype or marked extern, set the
+ current declaration as the main reference of the symbol. */
+ else if (DECL_EXTERNAL (decl->csym) && !DECL_INITIAL (decl->csym))
+ {
+ IDENTIFIER_DSYMBOL (mangled_name) = decl;
+ DECL_EXTERNAL (decl->csym) = 0;
+ }
+ /* Non-extern, non-templated decls shouldn't be defined twice. */
+ else if (!decl->isInstantiated ())
+ ScopeDsymbol::multiplyDefined (decl->loc, decl, other);
+ }
+ else
+ {
IDENTIFIER_PRETTY_NAME (mangled_name)
= get_identifier (decl->toPrettyChars (true));
IDENTIFIER_DSYMBOL (mangled_name) = decl;
- }
- SET_DECL_ASSEMBLER_NAME (decl->csym, mangled_name);
+ SET_DECL_ASSEMBLER_NAME (decl->csym, mangled_name);
+ }
}
DECL_LANG_SPECIFIC (decl->csym) = build_lang_decl (decl);
@@ -1358,13 +1373,7 @@ get_symbol_decl (Declaration *decl)
}
/* Apply any user attributes that may affect semantic meaning. */
- if (decl->userAttribDecl)
- {
- Expressions *attrs = decl->userAttribDecl->getAttributes ();
- decl_attributes (&decl->csym, build_attributes (attrs), 0);
- }
- else if (DECL_ATTRIBUTES (decl->csym) != NULL)
- decl_attributes (&decl->csym, DECL_ATTRIBUTES (decl->csym), 0);
+ apply_user_attributes (decl, decl->csym);
/* %% Probably should be a little more intelligent about setting this. */
TREE_USED (decl->csym) = 1;
diff --git a/gcc/d/modules.cc b/gcc/d/modules.cc
index ba18f2c..4f54190 100644
--- a/gcc/d/modules.cc
+++ b/gcc/d/modules.cc
@@ -543,7 +543,7 @@ layout_moduleinfo_fields (Module *decl, tree type)
size_t alignsize = MAX (TYPE_ALIGN_UNIT (type),
TYPE_ALIGN_UNIT (ptr_type_node));
- finish_aggregate_type (offset, alignsize, type, NULL);
+ finish_aggregate_type (offset, alignsize, type);
return type;
}
diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
index 90a4494..6aa4f64 100644
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -1254,7 +1254,7 @@ layout_classinfo_interfaces (ClassDeclaration *decl)
/* Update the type size and record mode for the classinfo type. */
if (type != tinfo_types[TK_CLASSINFO_TYPE])
- finish_aggregate_type (structsize, TYPE_ALIGN_UNIT (type), type, NULL);
+ finish_aggregate_type (structsize, TYPE_ALIGN_UNIT (type), type);
return type;
}
diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index 0252852..e0e770a 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -352,8 +352,7 @@ layout_aggregate_members (Dsymbols *members, tree context, bool inherited_p)
tree offset = size_int (ad->anonoffset);
fixup_anonymous_offset (TYPE_FIELDS (type), offset);
- finish_aggregate_type (ad->anonstructsize, ad->anonalignsize,
- type, NULL);
+ finish_aggregate_type (ad->anonstructsize, ad->anonalignsize, type);
/* And make the corresponding data member. */
tree field = create_field_decl (type, NULL, 0, 0);
@@ -462,19 +461,8 @@ layout_aggregate_type (AggregateDeclaration *decl, tree type,
the finalized record mode. */
void
-finish_aggregate_type (unsigned structsize, unsigned alignsize,
- tree type, UserAttributeDeclaration *attrs)
+finish_aggregate_type (unsigned structsize, unsigned alignsize, tree type)
{
- TYPE_SIZE (type) = NULL_TREE;
-
- /* Write out any GCC attributes that were applied to the type declaration. */
- if (attrs)
- {
- Expressions *eattrs = attrs->getAttributes ();
- decl_attributes (&type, build_attributes (eattrs),
- ATTR_FLAG_TYPE_IN_PLACE);
- }
-
/* Set size and alignment as requested by frontend. */
TYPE_SIZE (type) = bitsize_int (structsize * BITS_PER_UNIT);
TYPE_SIZE_UNIT (type) = size_int (structsize);
@@ -878,12 +866,7 @@ public:
build_type_decl (t->ctype, t->sym);
}
- if (t->sym->userAttribDecl)
- {
- Expressions *eattrs = t->sym->userAttribDecl->getAttributes ();
- decl_attributes (&t->ctype, build_attributes (eattrs),
- ATTR_FLAG_TYPE_IN_PLACE);
- }
+ apply_user_attributes (t->sym, t->ctype);
}
/* Build a struct or union type. Layout should be exactly represented
@@ -922,8 +905,8 @@ public:
/* Put out all fields. */
layout_aggregate_type (t->sym, t->ctype, t->sym);
- finish_aggregate_type (structsize, alignsize, t->ctype,
- t->sym->userAttribDecl);
+ apply_user_attributes (t->sym, t->ctype);
+ finish_aggregate_type (structsize, alignsize, t->ctype);
}
TYPE_CONTEXT (t->ctype) = d_decl_context (t->sym);
@@ -965,8 +948,8 @@ public:
/* Put out all fields, including from each base class. */
layout_aggregate_type (t->sym, basetype, t->sym);
- finish_aggregate_type (t->sym->structsize, t->sym->alignsize,
- basetype, t->sym->userAttribDecl);
+ apply_user_attributes (t->sym, basetype);
+ finish_aggregate_type (t->sym->structsize, t->sym->alignsize, basetype);
/* Classes only live in memory, so always set the TREE_ADDRESSABLE bit. */
for (tree tv = basetype; tv != NULL_TREE; tv = TYPE_NEXT_VARIANT (tv))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 220789f..adfbdb0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2020-04-01 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/90136
+ * gdc.dg/pr90136a.d: New test.
+ * gdc.dg/pr90136b.d: New test.
+ * gdc.dg/pr90136c.d: New test.
+
2020-03-31 Andrea Corallo <andrea.corallo@arm.com>
* jit.dg/test-version.c: New testcase.
diff --git a/gcc/testsuite/gdc.dg/pr90136a.d b/gcc/testsuite/gdc.dg/pr90136a.d
new file mode 100644
index 0000000..e623b23
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr90136a.d
@@ -0,0 +1,21 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93038
+// { dg-do compile }
+// { dg-options "-fdump-tree-optimized" }
+// { dg-final { scan-tree-dump-times "sum_array \\(array\\)" 0 "optimized"} }
+
+import gcc.attribute;
+
+@attribute("forceinline") int sum_array(int[] input);
+
+int sum_array(int[] input)
+{
+ int sum = 0;
+ foreach (elem; input)
+ sum += elem;
+ return sum;
+}
+
+int test(int[] array)
+{
+ return sum_array(array);
+}
diff --git a/gcc/testsuite/gdc.dg/pr90136b.d b/gcc/testsuite/gdc.dg/pr90136b.d
new file mode 100644
index 0000000..f1f9b0a
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr90136b.d
@@ -0,0 +1,21 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93038
+// { dg-do compile }
+// { dg-options "-fdump-tree-optimized" }
+// { dg-final { scan-tree-dump-times "sum_array \\(array\\)" 1 "optimized"} }
+
+import gcc.attribute;
+
+@attribute("noinline") int sum_array(int[] input);
+
+int sum_array(int[] input)
+{
+ int sum = 0;
+ foreach (elem; input)
+ sum += elem;
+ return sum;
+}
+
+int test(int[] array)
+{
+ return sum_array(array);
+}
diff --git a/gcc/testsuite/gdc.dg/pr90136c.d b/gcc/testsuite/gdc.dg/pr90136c.d
new file mode 100644
index 0000000..cf1c5de
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr90136c.d
@@ -0,0 +1,9 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93038
+// { dg-do compile }
+// { dg-options "-Wattributes" }
+
+import gcc.attribute;
+
+@attribute("forceinline") int sum_array(int[] input);
+@attribute("noinline") int sum_array(int[] input);
+// { dg-warning "ignoring attribute .noinline. because it conflicts with attribute .forceinline." "" { target *-*-* } .-1 }