diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-03-26 00:10:35 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-03-26 00:10:35 +0000 |
commit | befc20e1dc869edb0e7b560e69f32d5c71f867ab (patch) | |
tree | cc632d95aec3f7ff8a85e7f01fe420acab35ce6b /lib/Sema/SemaTemplate.cpp | |
parent | 1329c274628cc8c4e8ad472b41d1a78c8123f611 (diff) |
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
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 24b35ee5f5..c0476a8d3f 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -42,6 +42,28 @@ TemplateNameKind Sema::isTemplateName(IdentifierInfo &II, Scope *S, 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 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK, // 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 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK, = 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); |