return true;
}
+/* True iff we have started, but not finished, defining FUNCTION_DECL DECL. */
+
+bool
+fn_being_defined (tree decl)
+{
+ /* DECL_INITIAL is set to error_mark_node in grokfndecl for a definition, and
+ changed to BLOCK by poplevel at the end of the function. */
+ return (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_INITIAL (decl) == error_mark_node);
+}
+
+/* True if DECL is an instantiation of a function template currently being
+ defined. */
+
+bool
+fn_template_being_defined (tree decl)
+{
+ if (TREE_CODE (decl) != FUNCTION_DECL
+ || !DECL_LANG_SPECIFIC (decl)
+ || !DECL_TEMPLOID_INSTANTIATION (decl)
+ || DECL_TEMPLATE_INSTANTIATED (decl))
+ return false;
+ tree tinfo = DECL_TEMPLATE_INFO (decl);
+ tree pattern = DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo));
+ return fn_being_defined (pattern);
+}
+
/* Mark DECL (either a _DECL or a BASELINK) as "used" in the program.
If DECL is a specialization or implicitly declared class member,
generate the actual definition. Return false if something goes
maybe_instantiate_decl (decl);
if (!decl_dependent_p (decl)
+ /* Don't require this yet for an instantiation of a function template
+ we're currently defining (c++/120555). */
+ && !fn_template_being_defined (decl)
&& !require_deduced_type (decl, complain))
return false;
&& uses_template_parms (DECL_TI_ARGS (decl)))
return true;
- if (!require_deduced_type (decl, complain))
- return false;
-
if (builtin_pack_fn_p (decl))
{
error ("use of built-in parameter pack %qD outside of a template",
--- /dev/null
+// PR c++/120555
+// { dg-do compile { target c++17 } }
+
+struct A { int m; };
+
+template<class T>
+constexpr auto f() {
+ if constexpr (sizeof(T) == sizeof(int))
+ return 1;
+ else
+ return A{f<int>()};
+}
+
+static_assert(f<bool>().m == 1);
+static_assert(f<int>() == 1);
+
+template <class T> constexpr auto g();
+
+template<class T>
+constexpr auto f2() {
+ if constexpr (sizeof(T) == sizeof(int))
+ return 1;
+ else
+ return A{g<int>()}; // { dg-error "auto" }
+}
+
+template <class T> constexpr auto g() { return A{1}; }
+
+static_assert(f2<bool>().m == 1);
+static_assert(f2<int>() == 1);