Implement explicit instantiations of member classes of class templates, e.g.,

  template<typename T>
  struct X {
    struct Inner;
  };

  template struct X<int>::Inner;

This change is larger than it looks because it also fixes some
a problem with nested-name-specifiers and tags. We weren't requiring
the DeclContext associated with the scope specifier of a tag to be
complete. Therefore, when looking for something like "struct
X<int>::Inner", we weren't instantiating X<int>. 

This, naturally, uncovered a problem with member pointers, where we
were requiring the left-hand side of a member pointer access
expression (e.g., x->*) to be a complete type. However, this is wrong:
the semantics of this expression does not require a complete type (EDG
agrees).

Stuart vouched for me. Blame him.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71756 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 5650396..963c5ad 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -514,10 +514,10 @@
         //
         //   template class Foo<X>
         //
-        // but it is actually a declaration. Most likely, this was
+        // but it actually has a definition. Most likely, this was
         // meant to be an explicit specialization, but the user forgot
         // the '<>' after 'template'.
-        assert(TK == Action::TK_Definition && "Can only get a definition here");
+        assert(TK == Action::TK_Definition && "Expected a definition here");
 
         SourceLocation LAngleLoc 
           = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
@@ -554,7 +554,8 @@
                                  TemplateParams? TemplateParams->size() : 0));
     }
     TemplateId->Destroy();
-  } else if (TemplateParams && TK != Action::TK_Reference)
+  } else if (TemplateParams && TK != Action::TK_Reference) {
+    // Class template declaration or definition.
     TagOrTempResult = Actions.ActOnClassTemplate(CurScope, TagType, TK, 
                                                  StartLoc, SS, Name, NameLoc, 
                                                  Attr,
@@ -562,9 +563,28 @@
                                                       &(*TemplateParams)[0],
                                                       TemplateParams->size()),
                                                  AS);
-  else
-    TagOrTempResult = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS, Name, 
-                                       NameLoc, Attr, AS);
+  } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
+             TK == Action::TK_Declaration) {
+    // Explicit instantiation of a member of a class template
+    // specialization, e.g.,
+    //
+    //   template struct Outer<int>::Inner;
+    //
+    TagOrTempResult
+      = Actions.ActOnExplicitInstantiation(CurScope, 
+                                           TemplateInfo.TemplateLoc, 
+                                           TagType, StartLoc, SS, Name, 
+                                           NameLoc, Attr);
+  } else {
+    if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
+        TK == Action::TK_Definition) {
+      // FIXME: Diagnose this particular error.
+    }
+
+    // Declaration or definition of a class type
+    TagOrTempResult = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS, 
+                                       Name, NameLoc, Attr, AS);
+  }
 
   // Parse the optional base clause (C++ only).
   if (getLang().CPlusPlus && Tok.is(tok::colon))