Commit 5cedffbc by Jason Merrill Committed by Jason Merrill

PR c++/84314 - ICE with templates and fastcall attribute.

	* attribs.c (build_type_attribute_qual_variant): Don't clobber
	TYPE_CANONICAL on an existing type.

From-SVN: r257695
parent e72f7e3e
2018-02-15 Jason Merrill <jason@redhat.com>
PR c++/84314 - ICE with templates and fastcall attribute.
* attribs.c (build_type_attribute_qual_variant): Don't clobber
TYPE_CANONICAL on an existing type.
2018-02-15 Jakub Jelinek <jakub@redhat.com> 2018-02-15 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/84383 PR tree-optimization/84383
......
...@@ -1143,19 +1143,29 @@ build_type_attribute_qual_variant (tree otype, tree attribute, int quals) ...@@ -1143,19 +1143,29 @@ build_type_attribute_qual_variant (tree otype, tree attribute, int quals)
ttype = (lang_hooks.types.copy_lang_qualifiers ttype = (lang_hooks.types.copy_lang_qualifiers
(ttype, TYPE_MAIN_VARIANT (otype))); (ttype, TYPE_MAIN_VARIANT (otype)));
ntype = build_distinct_type_copy (ttype); tree dtype = ntype = build_distinct_type_copy (ttype);
TYPE_ATTRIBUTES (ntype) = attribute; TYPE_ATTRIBUTES (ntype) = attribute;
hashval_t hash = type_hash_canon_hash (ntype); hashval_t hash = type_hash_canon_hash (ntype);
ntype = type_hash_canon (hash, ntype); ntype = type_hash_canon (hash, ntype);
/* If the target-dependent attributes make NTYPE different from if (ntype != dtype)
its canonical type, we will need to use structural equality /* This variant was already in the hash table, don't mess with
checks for this type. */ TYPE_CANONICAL. */;
if (TYPE_STRUCTURAL_EQUALITY_P (ttype) else if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
|| !comp_type_attributes (ntype, ttype)) || !comp_type_attributes (ntype, ttype))
SET_TYPE_STRUCTURAL_EQUALITY (ntype); {
/* If the target-dependent attributes make NTYPE different from
its canonical type, we will need to use structural equality
checks for this type.
But make sure we don't get here for stripping attributes from a
type; the no-attribute type might not need structural comparison,
and it should have been in the hash table already. */
gcc_assert (attribute);
SET_TYPE_STRUCTURAL_EQUALITY (ntype);
}
else if (TYPE_CANONICAL (ntype) == ntype) else if (TYPE_CANONICAL (ntype) == ntype)
TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype); TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
......
// PR c++/84314
// { dg-do compile { target { { i?86-*-* x86_64-*-* } && ia32 } } }
// { dg-additional-options "-w -std=c++11" }
template <typename a, a b> struct c { static constexpr a d = b; };
template <bool b> using e = c<bool, b>;
template <bool, typename, typename> struct conditional;
template <typename...> struct f;
template <typename g, typename h>
struct f<g, h> : conditional<g::d, g, h>::i {};
template <typename...> struct j;
template <typename g, typename h> struct j<g, h> : conditional<1, h, g>::i {};
template <typename g, typename h, typename k, typename... l>
struct j<g, h, k, l...> : conditional<1, j<h, k>, g>::i {};
struct aa : e<!bool()> {};
template <typename, typename> struct m : c<bool, false> {};
template <typename, typename n> struct o {
template <typename> static c<bool, true> p(int);
typedef decltype(p<n>(0)) i;
};
template <typename, typename> struct ab : o<int, int>::i {};
template <typename> struct s { typedef int ad; };
template <bool, typename = void> struct q;
template <typename a> struct q<true, a> { typedef a i; };
template <bool, typename ae, typename> struct conditional { typedef ae i; };
template <typename ae, typename r> struct conditional<false, ae, r> {
typedef r i;
};
struct B {
B(int);
};
template <unsigned, typename...> struct af;
template <unsigned ag, typename t, typename... ah>
struct af<ag, t, ah...> : af<1, ah...>, B {
typedef af<1, ah...> ai;
ai al(af);
template <typename... am> af(af<ag, am...> p1) : ai(al(p1)), B(0) {}
};
template <unsigned ag, typename t> struct af<ag, t> {};
template <int, typename... ao> struct ap {
template <typename... am> static constexpr bool ar() {
return j<ab<am, ao>...>::d;
}
};
template <typename... ao> class as : public af<0, ao...> {
typedef af<0, ao...> ai;
public:
template <typename...> using au = ap<m<int, int>::d, ao...>;
template <typename... am,
typename q<au<>::template ar<am...>(), bool>::i = true>
as(as<am...> an) : ai(an) {}
};
template <typename... ao> as<typename s<ao>::ad...> ax(ao...);
namespace ay {
class az {};
}
using ay::az;
namespace ay {
template <typename ba> struct C { typedef ba bc; };
}
template <typename> class bd;
template <typename bi, typename n> using bj = f<m<bi, n>, ab<bi, n>>;
template <typename bf, typename... bh> class bd<bf(bh...)> {
struct F : bj<int, bf> {};
template <typename bl, typename> using bm = typename q<bl::d>::i;
public:
template <typename bg, typename = bm<aa, void>, typename = bm<F, void>>
bd(bg);
using bn = bf;
bn bo;
};
template <typename bf, typename... bh>
template <typename bg, typename, typename>
bd<bf(bh...)>::bd(bg) {
bo;
}
typedef long long(__attribute__((fastcall)) bq)(int *);
struct v : ay::C<as<bq, bq, int>> {
bc bt() { return ax(nullptr, nullptr, az()); }
};
class w {
public:
int *cc();
};
class x : w {
void ce();
};
namespace u {
class cf {
public:
static cf cg(int, int *, int, az, bd<long long(int *)>);
};
}
void x::ce() {
auto bu = 0;
u::cf::cg(bu, cc(), 1, {}, 0);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment