diff --git a/gcc/c-family/c-ada-spec.cc b/gcc/c-family/c-ada-spec.cc
index c7ae03223..bb091930f 100644
--- a/gcc/c-family/c-ada-spec.cc
+++ b/gcc/c-family/c-ada-spec.cc
@@ -1381,6 +1381,8 @@ separate_class_package (tree decl)
 }
 
 static bool package_prefix = true;
+static tree current_template = NULL_TREE;
+static tree current_template_instance = NULL_TREE;
 
 /* Dump in PP the name of an identifier NODE of type TYPE, following Ada
    syntax.  LIMITED_ACCESS indicates whether NODE can be accessed through a
@@ -1902,6 +1904,58 @@ dump_template_types (pretty_printer *pp, tree types, int spc)
     }
 }
 
+/* If NODE is a concrete template instance emitted in a nested package,
+   dump the type name owned by that package.  */
+
+static bool
+dump_template_type_name (pretty_printer *pp, tree node, int spc)
+{
+  if (!package_prefix || !cpp_check)
+    return false;
+
+  if (current_template_instance
+      && TYPE_MAIN_VARIANT (node)
+	 == TYPE_MAIN_VARIANT (current_template_instance))
+    {
+      package_prefix = false;
+      dump_ada_node (pp, current_template_instance, current_template,
+		     spc, false, true);
+      package_prefix = true;
+      return true;
+    }
+
+  for (int i = 0; i < to_dump_count; i++)
+    {
+      tree tmpl = to_dump[i];
+
+      if (!cpp_check (tmpl, IS_TEMPLATE))
+	continue;
+
+      /* DECL_SIZE_UNIT is DECL_TEMPLATE_INSTANTIATIONS in this context.  */
+      for (tree inst = DECL_SIZE_UNIT (tmpl);
+	   inst && inst != error_mark_node;
+	   inst = TREE_CHAIN (inst))
+	{
+	  tree types = TREE_PURPOSE (inst);
+	  tree instance = TREE_VALUE (inst);
+
+	  if (!RECORD_OR_UNION_TYPE_P (instance)
+	      || TYPE_MAIN_VARIANT (instance) != TYPE_MAIN_VARIANT (node))
+	    continue;
+
+	  package_prefix = false;
+	  dump_ada_node (pp, TYPE_NAME (instance), tmpl, spc, false, true);
+	  dump_template_types (pp, types, spc);
+	  pp_dot (pp);
+	  dump_ada_node (pp, TYPE_NAME (instance), tmpl, spc, false, true);
+	  package_prefix = true;
+	  return true;
+	}
+    }
+
+  return false;
+}
+
 /* Dump in PP the contents of all class instantiations associated with
    a given template T.  SPC is the indentation level.  */
 
@@ -1953,6 +2007,10 @@ dump_ada_template (pretty_printer *pp, tree t, int spc)
       spc += INDENT_INCR;
       newline_and_indent (pp, spc);
 
+      tree previous_template = current_template;
+      tree previous_template_instance = current_template_instance;
+      current_template = t;
+      current_template_instance = instance;
       TREE_VISITED (get_underlying_decl (instance)) = 1;
       pp_string (pp, "type ");
       dump_ada_node (pp, instance, t, spc, false, true);
@@ -1975,6 +2033,8 @@ dump_ada_template (pretty_printer *pp, tree t, int spc)
       dump_ada_node (pp, instance, t, spc, false, true);
       dump_template_types (pp, types, spc);
       package_prefix = true;
+      current_template = previous_template;
+      current_template_instance = previous_template_instance;
       pp_semicolon (pp);
       pp_newline (pp);
       pp_newline (pp);
@@ -2460,8 +2520,11 @@ dump_ada_node (pretty_printer *pp, tree node, tree type, int spc,
     case RECORD_TYPE:
     case UNION_TYPE:
       if (name_only)
-	dump_ada_node (pp, TYPE_NAME (node), node, spc, limited_access,
-		       true);
+	{
+	  if (!dump_template_type_name (pp, node, spc))
+	    dump_ada_node (pp, TYPE_NAME (node), node, spc, limited_access,
+			   true);
+	}
       else
 	dump_ada_structure (pp, node, type, false, spc);
       break;
diff --git a/gcc/testsuite/g++.dg/ada-spec/template-instantiation-qualification.C b/gcc/testsuite/g++.dg/ada-spec/template-instantiation-qualification.C
new file mode 100644
index 000000000..45b595ab8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ada-spec/template-instantiation-qualification.C
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-ada-spec-slim" } */
+/* { dg-final { scan-file template_instantiation_qualification_c.ads "subtype Int_Box is Box_int.Box;" } } */
+/* { dg-final { scan-file template_instantiation_qualification_c.ads "subtype Double_Box is Box_double.Box;" } } */
+/* { dg-final { scan-file template_instantiation_qualification_c.ads "item : aliased Box_int.Box;" } } */
+/* { dg-final { scan-file template_instantiation_qualification_c.ads "function identity \(value : Box_double.Box\) return Box_double.Box" } } */
+/* { dg-final { scan-file template_instantiation_qualification_c.ads "subtype Alias_Int_Box is Box_int.Box;" } } */
+
+template <typename T>
+class Box
+{
+public:
+  Box ();
+  T value () const;
+
+private:
+  T value_;
+};
+
+extern template class Box<int>;
+extern template class Box<double>;
+
+using Int_Box = Box<int>;
+using Double_Box = Box<double>;
+template <typename T> using Alias_Box = Box<T>;
+using Alias_Int_Box = Alias_Box<int>;
+
+struct Holder
+{
+  Box<int> item;
+};
+
+Box<double> identity (Box<double> value);
+
+/* { dg-final { cleanup-ada-spec } } */
