The injected-class-name of class templates and class template
specializations can be treated as a template. Finally, we can parse
and process the first implementation of Fibonacci I wrote!
Note that this code does not handle all of the cases where
injected-class-names can be treated as templates. In particular,
there's an ambiguity case that we should be able to handle (but
can't), e.g.,
template <class T> struct Base { };
template <class T> struct Derived : Base<int>, Base<char> {
typename Derived::Base b; // error: ambiguous
typename Derived::Base<double> d; // OK
};
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67720 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 24b35ee..c0476a8 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -42,6 +42,28 @@
return TNK_Template_template_parm;
else
assert(false && "Unknown TemplateDecl");
+ } else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(IIDecl)) {
+ // C++ [temp.local]p1:
+ // Like normal (non-template) classes, class templates have an
+ // injected-class-name (Clause 9). The injected-class-name
+ // can be used with or without a template-argument-list. When
+ // it is used without a template-argument-list, it is
+ // equivalent to the injected-class-name followed by the
+ // template-parameters of the class template enclosed in
+ // <>. When it is used with a template-argument-list, it
+ // refers to the specified class template specialization,
+ // which could be the current specialization or another
+ // specialization.
+ if (Record->isInjectedClassName()) {
+ Record = cast<CXXRecordDecl>(Context.getCanonicalDecl(Record));
+ if ((Template = Record->getDescribedClassTemplate()))
+ return TNK_Class_template;
+ else if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
+ Template = Spec->getSpecializedTemplate();
+ return TNK_Class_template;
+ }
+ }
}
// FIXME: What follows is a gross hack.
@@ -469,7 +491,7 @@
// If we had a scope specifier, we better have a previous template
// declaration!
- TagDecl *NewClass =
+ CXXRecordDecl *NewClass =
CXXRecordDecl::Create(Context, Kind, SemanticContext, NameLoc, Name,
PrevClassTemplate?
PrevClassTemplate->getTemplatedDecl() : 0);
@@ -478,7 +500,8 @@
= ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
DeclarationName(Name), TemplateParams,
NewClass, PrevClassTemplate);
-
+ NewClass->setDescribedClassTemplate(NewTemplate);
+
// Set the lexical context of these templates
NewClass->setLexicalDeclContext(CurContext);
NewTemplate->setLexicalDeclContext(CurContext);