extern tree build_aggr_init (tree, tree, int,
tsubst_flags_t);
extern int is_class_type (tree, int);
+extern bool is_copy_initialization (tree);
extern tree build_zero_init (tree, tree, bool);
extern tree build_value_init (tree, tsubst_flags_t);
extern tree build_value_init_noctor (tree, tsubst_flags_t);
if (type == error_mark_node)
return;
+ if (VAR_P (decl) && is_copy_initialization (init))
+ flags |= LOOKUP_ONLYCONVERTING;
+
/* Warn about register storage specifiers except when in GNU global
or local register variable extension. */
if (VAR_P (decl) && DECL_REGISTER (decl) && asmspec_tree == NULL_TREE)
return stmt_expr;
}
- if (init && init != void_type_node
- && TREE_CODE (init) != TREE_LIST
- && !(TREE_CODE (init) == TARGET_EXPR
- && TARGET_EXPR_DIRECT_INIT_P (init))
- && !DIRECT_LIST_INIT_P (init))
+ if (is_copy_initialization (init))
flags |= LOOKUP_ONLYCONVERTING;
is_global = begin_init_stmts (&stmt_expr, &compound_stmt);
return 1;
}
+/* Returns true iff the initializer INIT represents copy-initialization
+ (and therefore we must set LOOKUP_ONLYCONVERTING when processing it). */
+
+bool
+is_copy_initialization (tree init)
+{
+ return (init && init != void_type_node
+ && TREE_CODE (init) != TREE_LIST
+ && !(TREE_CODE (init) == TARGET_EXPR
+ && TARGET_EXPR_DIRECT_INIT_P (init))
+ && !DIRECT_LIST_INIT_P (init));
+}
+
/* Build a reference to a member of an aggregate. This is not a C++
`&', but really something which can have its address taken, and
then act as a pointer to member, for example TYPE :: FIELD can have
const_init
= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (code_pattern);
cp_finish_decl (d, init, /*init_const_expr_p=*/const_init,
- /*asmspec_tree=*/NULL_TREE,
- LOOKUP_ONLYCONVERTING);
+ /*asmspec_tree=*/NULL_TREE, 0);
}
if (enter_context)
pop_nested_class ();
--- /dev/null
+// PR c++/87820
+// { dg-do compile { target c++11 } }
+
+struct A {
+ constexpr explicit operator int() const { return 0; }
+};
+
+template<class T>
+void f() {
+ A a;
+ T t1 = a; // { dg-error "cannot convert" }
+ T t2 = {a}; // { dg-error "cannot convert" }
+ T t3(a);
+ T t4{a};
+ T t5 = T(a);
+ T t6 = T{a};
+ new T(a);
+ new T{a};
+}
+
+template<class T>
+void g() {
+ T t;
+ int n1 = t; // { dg-error "cannot convert" }
+ int n2 = {t}; // { dg-error "cannot convert" }
+ int n3(t);
+ int n4{t};
+ int n5 = int(t);
+ int n6 = int{t};
+ new int(t);
+ new int{t};
+}
+
+template void f<int>();
+template void g<A>();
+
+template<class T>
+struct B {
+ static constexpr A a{};
+ static constexpr T t1 = a; // { dg-error "cannot convert" }
+ static constexpr T t2 = {a}; // { dg-error "cannot convert" }
+ static constexpr T t4{a};
+ static constexpr T t5 = T(a);
+ static constexpr T t6 = T{a};
+};
+
+template<class T>
+struct C {
+ static constexpr T t{};
+ static constexpr int n1 = t; // { dg-error "cannot convert" }
+ static constexpr int n2 = {t}; // { dg-error "cannot convert" }
+ static constexpr int n4{t};
+ static constexpr int n5 = int(t);
+ static constexpr int n6 = int{t};
+};
+
+template struct B<int>;
+template struct C<A>;
+
+#if __cpp_inline_variables
+template<class T>
+struct D {
+ static inline A a;
+ static inline T t1 = a; // { dg-error "cannot convert" "" { target c++17 } }
+ static inline T t2 = {a}; // { dg-error "cannot convert" "" { target c++17 } }
+ static inline T t4{a};
+ static inline T t5 = T(a);
+ static inline T t6 = T{a};
+};
+
+template<class T>
+struct E {
+ static inline T t;
+ static inline int n1 = t; // { dg-error "cannot convert" "" { target c++17 } }
+ static inline int n2 = {t}; // { dg-error "cannot convert" "" { target c++17 } }
+ static inline int n4{t};
+ static inline int n5 = int(t);
+ static inline int n6 = int{t};
+};
+
+template struct D<int>;
+template struct E<A>;
+#endif
--- /dev/null
+// PR c++/102137
+// { dg-do compile { target c++17 } }
+
+template<class T>
+struct A {
+ constexpr A() { }
+ constexpr A(int) { }
+};
+
+explicit A(...) -> A<int>;
+
+template<template<class> class TT>
+void f() {
+ TT x1 = 0; // { dg-error "deduction|no match" }
+ TT x2 = {0}; // { dg-error "explicit deduction guide" }
+ TT x3(0);
+ TT x4{0};
+ TT x5;
+ new TT(0);
+ new TT{0};
+ new TT();
+ new TT{};
+ new TT;
+}
+
+template<class T>
+void g(T t) {
+ A a1 = t; // { dg-error "deduction|no match" }
+ A a2 = {t}; // { dg-error "explicit deduction guide" }
+ A a3(t);
+ A a4{t};
+ A a5;
+ new A(t);
+ new A{t};
+}
+
+template void f<A>();
+template void g(int);
+
+template<template<class> class TT>
+struct B {
+ static inline TT x1 = 0; // { dg-error "deduction|no match" }
+ static inline TT x2 = {0}; // { dg-error "explicit deduction guide" }
+ static inline TT x4{0};
+ static inline TT x5;
+};
+
+template<class T>
+struct C {
+ static inline T t;
+ static inline A a1 = t; // { dg-error "deduction|no match" }
+ static inline A a2 = {t}; // { dg-error "explicit deduction guide" }
+ static inline A a4{t};
+ static inline A a5{};
+};
+
+template struct B<A>;
+template struct C<int>;
+
+template<template<class> class TT>
+struct E {
+ static constexpr TT x1 = 0; // { dg-error "deduction|no match" }
+ static constexpr TT x2 = {0}; // { dg-error "explicit deduction guide" }
+ static constexpr TT x4{0};
+ static constexpr TT x5{};
+};
+
+template<class T>
+struct F {
+ static constexpr T t{};
+ static constexpr A a1 = t; // { dg-error "deduction|no match" }
+ static constexpr A a2 = {t}; // { dg-error "explicit deduction guide" }
+ static constexpr A a4{t};
+ static constexpr A a5{};
+};
+
+template struct E<A>;
+template struct F<int>;