aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2017-09-08 18:39:17 -0400
committerJason Merrill <jason@gcc.gnu.org>2017-09-08 18:39:17 -0400
commit27c825c5cca3243f293aee29a4abeb22242d4d2b (patch)
treed4c20252428e4348fc569284133594067d73b3c8
parentb2c5d6f1d2a71374bcd8277a0697490582bc03a8 (diff)
downloadgcc-27c825c5cca3243f293aee29a4abeb22242d4d2b.zip
gcc-27c825c5cca3243f293aee29a4abeb22242d4d2b.tar.gz
gcc-27c825c5cca3243f293aee29a4abeb22242d4d2b.tar.bz2
PR c++/70029 - ICE with ref-qualifier and -flto
PR c++/70029 - ICE with ref-qualifier and -flto gcc/ * langhooks.h (struct lang_hooks_for_types): Add copy_lang_qualifiers. * attribs.c (build_type_attribute_qual_variant): Use it. * langhooks-def.h (LANG_HOOKS_COPY_LANG_QUALIFIERS): Default to NULL. (LANG_HOOKS_FOR_TYPES_INITIALIZER): Use it. * tree.c (verify_type): Re-enable TYPE_CANONICAL main variant check. gcc/cp/ * tree.c (cxx_copy_lang_qualifiers): New. * cp-tree.h: Declare it. * cp-objcp-common.h: Define LANG_HOOKS_COPY_LANG_QUALIFIERS. From-SVN: r251911
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/attribs.c11
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/cp-objcp-common.h2
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/tree.c15
-rw-r--r--gcc/langhooks-def.h2
-rw-r--r--gcc/langhooks.h4
-rw-r--r--gcc/testsuite/g++.dg/lto/pr70029_0.C10
-rw-r--r--gcc/tree.c4
10 files changed, 63 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e4163aa..b9b0456 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2017-09-08 Jason Merrill <jason@redhat.com>
+
+ PR c++/70029 - ICE with ref-qualifier and -flto
+ * langhooks.h (struct lang_hooks_for_types): Add
+ copy_lang_qualifiers.
+ * attribs.c (build_type_attribute_qual_variant): Use it.
+ * langhooks-def.h (LANG_HOOKS_COPY_LANG_QUALIFIERS): Default to
+ NULL.
+ (LANG_HOOKS_FOR_TYPES_INITIALIZER): Use it.
+ * tree.c (verify_type): Re-enable TYPE_CANONICAL main variant check.
+
2017-09-08 Eric Botcazou <ebotcazou@adacore.com>
PR target/81988
diff --git a/gcc/attribs.c b/gcc/attribs.c
index faa0649..b8f58a7 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -959,8 +959,9 @@ build_decl_attribute_variant (tree ddecl, tree attribute)
Record such modified types already made so we don't make duplicates. */
tree
-build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
+build_type_attribute_qual_variant (tree otype, tree attribute, int quals)
{
+ tree ttype = otype;
if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute))
{
tree ntype;
@@ -983,6 +984,11 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
}
ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED);
+ if (lang_hooks.types.copy_lang_qualifiers
+ && otype != TYPE_MAIN_VARIANT (otype))
+ ttype = (lang_hooks.types.copy_lang_qualifiers
+ (ttype, TYPE_MAIN_VARIANT (otype)));
+
ntype = build_distinct_type_copy (ttype);
TYPE_ATTRIBUTES (ntype) = attribute;
@@ -1000,6 +1006,9 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
ttype = build_qualified_type (ntype, quals);
+ if (lang_hooks.types.copy_lang_qualifiers
+ && otype != TYPE_MAIN_VARIANT (otype))
+ ttype = lang_hooks.types.copy_lang_qualifiers (ttype, otype);
}
else if (TYPE_QUALS (ttype) != quals)
ttype = build_qualified_type (ttype, quals);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6c4a31d..730a2da 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2017-09-08 Jason Merrill <jason@redhat.com>
+
+ PR c++/70029 - ICE with ref-qualifier and -flto
+ * tree.c (cxx_copy_lang_qualifiers): New.
+ * cp-tree.h: Declare it.
+ * cp-objcp-common.h: Define LANG_HOOKS_COPY_LANG_QUALIFIERS.
+
2017-09-06 Jason Merrill <jason@redhat.com>
PR c++/82053 - ICE with default argument in lambda in template
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index 10fcdf3..3e4cc9c 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -99,6 +99,8 @@ extern void cp_register_dumps (gcc::dump_manager *);
#define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE cxx_builtin_function_ext_scope
#undef LANG_HOOKS_TYPE_HASH_EQ
#define LANG_HOOKS_TYPE_HASH_EQ cxx_type_hash_eq
+#undef LANG_HOOKS_COPY_LANG_QUALIFIERS
+#define LANG_HOOKS_COPY_LANG_QUALIFIERS cxx_copy_lang_qualifiers
#undef LANG_HOOKS_MISSING_NORETURN_OK_P
#define LANG_HOOKS_MISSING_NORETURN_OK_P cp_missing_noreturn_ok_p
#undef LANG_HOOKS_BLOCK_MAY_FALLTHRU
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a0e31d3..a57de33 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6963,6 +6963,7 @@ extern tree convert_bitfield_to_declared_type (tree);
extern tree cp_save_expr (tree);
extern bool cast_valid_in_integral_constant_expression_p (tree);
extern bool cxx_type_hash_eq (const_tree, const_tree);
+extern tree cxx_copy_lang_qualifiers (const_tree, const_tree);
extern void cxx_print_statistics (void);
extern bool maybe_warn_zero_as_null_pointer_constant (tree, location_t);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 12c31fb..f387f38 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -4626,6 +4626,21 @@ cxx_type_hash_eq (const_tree typea, const_tree typeb)
TYPE_RAISES_EXCEPTIONS (typeb), ce_exact);
}
+/* Copy the language-specific type variant modifiers from TYPEB to TYPEA. For
+ C++, these are the exception-specifier and ref-qualifier. */
+
+tree
+cxx_copy_lang_qualifiers (const_tree typea, const_tree typeb)
+{
+ tree type = CONST_CAST_TREE (typea);
+ if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
+ {
+ type = build_exception_variant (type, TYPE_RAISES_EXCEPTIONS (typeb));
+ type = build_ref_qualified_type (type, type_memfn_rqual (typeb));
+ }
+ return type;
+}
+
/* Apply FUNC to all language-specific sub-trees of TP in a pre-order
traversal. Called from walk_tree. */
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index ea2006c..61b081b 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -186,6 +186,7 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
lhd_omp_firstprivatize_type_sizes
#define LANG_HOOKS_OMP_MAPPABLE_TYPE lhd_omp_mappable_type
#define LANG_HOOKS_TYPE_HASH_EQ NULL
+#define LANG_HOOKS_COPY_LANG_QUALIFIERS NULL
#define LANG_HOOKS_GET_ARRAY_DESCR_INFO NULL
#define LANG_HOOKS_GET_SUBRANGE_BOUNDS NULL
#define LANG_HOOKS_GET_TYPE_BIAS NULL
@@ -211,6 +212,7 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES, \
LANG_HOOKS_OMP_MAPPABLE_TYPE, \
LANG_HOOKS_TYPE_HASH_EQ, \
+ LANG_HOOKS_COPY_LANG_QUALIFIERS, \
LANG_HOOKS_GET_ARRAY_DESCR_INFO, \
LANG_HOOKS_GET_SUBRANGE_BOUNDS, \
LANG_HOOKS_GET_TYPE_BIAS, \
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 88f6f71..b0c9829 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -123,6 +123,10 @@ struct lang_hooks_for_types
FUNCTION_TYPE or METHOD_TYPE. */
bool (*type_hash_eq) (const_tree, const_tree);
+ /* If non-NULL, return TYPE1 with any language-specific modifiers copied from
+ TYPE2. */
+ tree (*copy_lang_qualifiers) (const_tree, const_tree);
+
/* Return TRUE if TYPE uses a hidden descriptor and fills in information
for the debugger about the array bounds, strides, etc. */
bool (*get_array_descr_info) (const_tree, struct array_descr_info *);
diff --git a/gcc/testsuite/g++.dg/lto/pr70029_0.C b/gcc/testsuite/g++.dg/lto/pr70029_0.C
new file mode 100644
index 0000000..9c8c31c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr70029_0.C
@@ -0,0 +1,10 @@
+// PR c++/70029
+// { dg-lto-do assemble }
+
+struct A
+{
+ A();
+ int foo() && __attribute__ ((__warn_unused_result__)) { return 0; }
+};
+
+A a;
diff --git a/gcc/tree.c b/gcc/tree.c
index 7a70eb7..721330a 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13220,9 +13220,7 @@ verify_type (const_tree t)
debug_tree (ct);
error_found = true;
}
- /* FIXME: this is violated by the C++ FE as discussed in PR70029, when
- FUNCTION_*_QUALIFIED flags are set. */
- if (0 && TYPE_MAIN_VARIANT (t) == t && ct && TYPE_MAIN_VARIANT (ct) != ct)
+ if (TYPE_MAIN_VARIANT (t) == t && ct && TYPE_MAIN_VARIANT (ct) != ct)
{
error ("TYPE_CANONICAL of main variant is not main variant");
debug_tree (ct);