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))