return value_dependent_expression_p (arg);
}
+/* Identify any expressions that use function parms. */
+
+static tree
+find_parm_usage_r (tree *tp, int *walk_subtrees, void*)
+{
+ tree t = *tp;
+ if (TREE_CODE (t) == PARM_DECL)
+ {
+ *walk_subtrees = 0;
+ return t;
+ }
+ return NULL_TREE;
+}
+
/* Returns true if ARGS (a collection of template arguments) contains
any types that require structural equality testing. */
else if (!TYPE_P (arg) && TREE_TYPE (arg)
&& TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (arg)))
return true;
+ /* Checking current_function_decl because this structural
+ comparison is only necessary for redeclaration. */
+ else if (!current_function_decl
+ && dependent_template_arg_p (arg)
+ && (cp_walk_tree_without_duplicates
+ (&arg, find_parm_usage_r, NULL)))
+ return true;
}
}
}
// PR c++/52830
// { dg-do compile { target c++11 } }
// { dg-additional-options "-fchecking" }
-// { dg-ice "comptypes" }
template<bool b> struct eif { typedef void type; };
template<> struct eif<false> {};
--- /dev/null
+// { dg-do compile { target c++11 } }
+template<unsigned u> struct size_c{ static constexpr unsigned value = u; };
+namespace g {
+template<class T> auto return_size(T t) -> size_c<sizeof(t)>;
+template<class T> auto return_size(T t) -> size_c<sizeof(t)>;
+}
+static_assert(decltype(g::return_size('a'))::value == 1u, "");
--- /dev/null
+// { dg-do compile { target c++11 } }
+template<bool u> struct bool_c{ static constexpr bool value = u; };
+template<class T> auto noexcepty(T t) -> bool_c<noexcept(t())>;
+template<class T> auto noexcepty(T t) -> bool_c<noexcept(t())>;
+struct foo { void operator()() noexcept; };
+static_assert(decltype(noexcepty(foo{}))::value, "");
--- /dev/null
+// { dg-do compile { target c++11 } }
+template<unsigned u> struct size_c{ static constexpr unsigned value = u; };
+template<class... T> auto return_size(T... t) -> size_c<sizeof...(t)>;
+template<class... T> auto return_size(T... t) -> size_c<sizeof...(t)>;
+static_assert(decltype(return_size('a'))::value == 1u, "");
--- /dev/null
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wno-pedantic" }
+template<unsigned u> struct size_c{ static constexpr unsigned value = u; };
+template<class T> auto get_align(T t) -> size_c<alignof(t)>;
+template<class T> auto get_align(T t) -> size_c<alignof(t)>;
+static_assert(decltype(get_align('a'))::value == 1u, "");
--- /dev/null
+// { dg-do compile { target c++11 } }
+template <int N> struct A { static void foo(){} };
+template <> struct A<sizeof(char)> { using foo = int; };
+
+template <class T> void f(T t1) {
+ A<sizeof(t1)>::foo();
+}
+
+template <class T> void g(T t2) {
+ /* if the comparing_specializations check breaks in cp_tree_equal
+ case PARM_DECL, the error will incorrectly report A<sizeof (t1)> */
+ A<sizeof(t2)>::foo(); // { dg-error "dependent-name .A<sizeof .t2.>::foo" }
+}
+
+void h() {
+ f(0);
+ g('0');
+}
--- /dev/null
+// { dg-do compile { target c++11 } }
+template <int N> struct A { static void foo(){} };
+template <> struct A<sizeof(char)> { using foo = int; };
+
+template<class T1> auto f(T1 t1) -> decltype(A<sizeof(t1)>::foo());
+
+/* if the comparing_specializations check breaks in cp_tree_equal
+case PARM_DECL, the error will incorrectly report A<sizeof (t1)> */
+template<class T2> auto g(T2 t2) -> decltype(A<sizeof(t2)>::foo()); // { dg-error "dependent-name .A<sizeof .t2.>::foo" }
+
+void h() {
+ f(0);
+ g('0'); // { dg-error "no matching function" }
+}