+ gcc_assert (!TREE_USED (fn));
+
+ /* Restore PROCESSING_TEMPLATE_DECL. */
+ processing_template_decl = saved_processing_template_decl;
+
+ return fn;
+}
+
+/* Add an implicit declaration to TYPE for the kind of function
+ indicated by SFK. Return the FUNCTION_DECL for the new implicit
+ declaration. */
+
+tree
+lazily_declare_fn (special_function_kind sfk, tree type)
+{
+ tree fn;
+ bool const_p;
+
+ /* Figure out whether or not the argument has a const reference
+ type. */
+ if (sfk == sfk_copy_constructor)
+ const_p = TYPE_HAS_CONST_INIT_REF (type);
+ else if (sfk == sfk_assignment_operator)
+ const_p = TYPE_HAS_CONST_ASSIGN_REF (type);
+ else
+ /* In this case, CONST_P will be ignored. */
+ const_p = false;
+ /* Declare the function. */
+ fn = implicitly_declare_fn (sfk, type, const_p);
+ /* A destructor may be virtual. */
+ if (sfk == sfk_destructor)
+ check_for_override (fn, type);
+ /* Add it to CLASSTYPE_METHOD_VEC. */
+ add_method (type, fn, NULL_TREE);
+ /* Add it to TYPE_METHODS. */
+ if (sfk == sfk_destructor
+ && DECL_VIRTUAL_P (fn)
+ && abi_version_at_least (2))
+ /* The ABI requires that a virtual destructor go at the end of the
+ vtable. */
+ TYPE_METHODS (type) = chainon (TYPE_METHODS (type), fn);
+ else
+ {
+ /* G++ 3.2 put the implicit destructor at the *beginning* of the
+ TYPE_METHODS list, which cause the destructor to be emitted
+ in an incorrect location in the vtable. */
+ if (warn_abi && DECL_VIRTUAL_P (fn))
+ warning (0, "vtable layout for class %qT may not be ABI-compliant"
+ "and may change in a future version of GCC due to "
+ "implicit virtual destructor",
+ type);
+ TREE_CHAIN (fn) = TYPE_METHODS (type);
+ TYPE_METHODS (type) = fn;
+ }
+ maybe_add_class_template_decl_list (type, fn, /*friend_p=*/0);
+ if (sfk == sfk_assignment_operator)
+ CLASSTYPE_LAZY_ASSIGNMENT_OP (type) = 0;
+ else
+ {
+ /* Remember that the function has been created. */
+ if (sfk == sfk_constructor)
+ CLASSTYPE_LAZY_DEFAULT_CTOR (type) = 0;
+ else if (sfk == sfk_copy_constructor)
+ CLASSTYPE_LAZY_COPY_CTOR (type) = 0;
+ else if (sfk == sfk_destructor)
+ CLASSTYPE_LAZY_DESTRUCTOR (type) = 0;
+ /* Create appropriate clones. */
+ clone_function_decl (fn, /*update_method_vec=*/true);
+ }
+