diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-05-10 22:57:19 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-05-10 22:57:19 +0000 |
commit | 7da97d0f31e1ec16998d3de2cfd2e88fe3736673 (patch) | |
tree | b02158638458d3b80d52e441baab194451072e77 /lib/AST | |
parent | 0393e285fd621c02a3f4a341bbb5c1ae4c5946d5 (diff) |
Implement the semantics of the injected-class-name within a class
template. The injected-class-name is either a type or a template,
depending on whether a '<' follows it. As a type, the
injected-class-name's template argument list contains its template
parameters in declaration order.
As part of this, add logic for canonicalizing declarations, and be
sure to canonicalize declarations used in template names and template
arguments.
A TagType is dependent if the declaration it references is dependent.
I'm not happy about the rather complicated protocol needed to use
ASTContext::getTemplateSpecializationType.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71408 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/ASTContext.cpp | 30 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 13 | ||||
-rw-r--r-- | lib/AST/DeclTemplate.cpp | 59 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 3 |
4 files changed, 104 insertions, 1 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 133e8c20b8..f9d648b816 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1703,11 +1703,39 @@ QualType ASTContext::getCanonicalType(QualType T) { VAT->getIndexTypeQualifier()); } +Decl *ASTContext::getCanonicalDecl(Decl *D) { + if (TagDecl *Tag = dyn_cast<TagDecl>(D)) { + QualType T = getTagDeclType(Tag); + return cast<TagDecl>(cast<TagType>(T.getTypePtr()->CanonicalType) + ->getDecl()); + } + + if (ClassTemplateDecl *Template = dyn_cast<ClassTemplateDecl>(D)) { + while (Template->getPreviousDeclaration()) + Template = Template->getPreviousDeclaration(); + return Template; + } + + if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { + while (Function->getPreviousDeclaration()) + Function = Function->getPreviousDeclaration(); + return const_cast<FunctionDecl *>(Function); + } + + if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { + while (Var->getPreviousDeclaration()) + Var = Var->getPreviousDeclaration(); + return const_cast<VarDecl *>(Var); + } + + return D; +} + TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) { // If this template name refers to a template, the canonical // template name merely stores the template itself. if (TemplateDecl *Template = Name.getAsTemplateDecl()) - return TemplateName(Template); + return TemplateName(cast<TemplateDecl>(getCanonicalDecl(Template))); DependentTemplateName *DTN = Name.getAsDependentTemplateName(); assert(DTN && "Non-dependent template names must refer to template decls."); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 9aba33c943..621145f1af 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -14,6 +14,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Stmt.h" #include "clang/AST/Expr.h" @@ -505,6 +506,18 @@ OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const { // TagDecl Implementation //===----------------------------------------------------------------------===// +bool TagDecl::isDependentType() const { + if (isa<TemplateDecl>(this)) + return true; + + if (const TagDecl *TD = dyn_cast_or_null<TagDecl>(getDeclContext())) + return TD->isDependentType(); + + // FIXME: Tag types declared function templates are dependent types. + // FIXME: Look through block scopes. + return false; +} + void TagDecl::startDefinition() { TagType *TagT = const_cast<TagType *>(TypeForDecl->getAsTagType()); TagT->decl.setPointer(this); diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 7389b83d20..4f64f8bd50 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -120,6 +120,65 @@ void ClassTemplateDecl::Destroy(ASTContext& C) { C.Deallocate((void*)this); } +QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) { + if (!CommonPtr->InjectedClassNameType.isNull()) + return CommonPtr->InjectedClassNameType; + + // FIXME: n2800 14.6.1p1 should say how the template arguments + // corresponding to template parameter packs should be pack + // expansions. We already say that in 14.6.2.1p2, so it would be + // better to fix that redundancy. + + TemplateParameterList *Params = getTemplateParameters(); + + llvm::SmallVector<TemplateArgument, 16> TemplateArgs; + llvm::SmallVector<TemplateArgument, 16> CanonTemplateArgs; + TemplateArgs.reserve(Params->size()); + CanonTemplateArgs.reserve(Params->size()); + + for (TemplateParameterList::iterator + Param = Params->begin(), ParamEnd = Params->end(); + Param != ParamEnd; ++Param) { + if (isa<TemplateTypeParmDecl>(*Param)) { + QualType ParamType = Context.getTypeDeclType(cast<TypeDecl>(*Param)); + TemplateArgs.push_back(TemplateArgument((*Param)->getLocation(), + ParamType)); + CanonTemplateArgs.push_back( + TemplateArgument((*Param)->getLocation(), + Context.getCanonicalType(ParamType))); + } else if (NonTypeTemplateParmDecl *NTTP = + dyn_cast<NonTypeTemplateParmDecl>(*Param)) { + // FIXME: Build canonical expression, too! + Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType(), + NTTP->getLocation(), + NTTP->getType()->isDependentType(), + /*Value-dependent=*/true); + TemplateArgs.push_back(TemplateArgument(E)); + CanonTemplateArgs.push_back(TemplateArgument(E)); + } else { + TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param); + TemplateArgs.push_back(TemplateArgument(TTP->getLocation(), TTP)); + CanonTemplateArgs.push_back(TemplateArgument(TTP->getLocation(), + Context.getCanonicalDecl(TTP))); + } + } + + // FIXME: I should really move the "build-the-canonical-type" logic + // into ASTContext::getTemplateSpecializationType. + TemplateName Name = TemplateName(this); + QualType CanonType = Context.getTemplateSpecializationType( + Context.getCanonicalTemplateName(Name), + &CanonTemplateArgs[0], + CanonTemplateArgs.size()); + + CommonPtr->InjectedClassNameType + = Context.getTemplateSpecializationType(Name, + &TemplateArgs[0], + TemplateArgs.size(), + CanonType); + return CommonPtr->InjectedClassNameType; +} + //===----------------------------------------------------------------------===// // TemplateTypeParm Allocation/Deallocation Method Implementations //===----------------------------------------------------------------------===// diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index b5a884085b..bc439c8c89 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1000,6 +1000,9 @@ TypeOfExprType::TypeOfExprType(Expr *E, QualType can) assert(!isa<TypedefType>(can) && "Invalid canonical type"); } +TagType::TagType(TypeClass TC, TagDecl *D, QualType can) + : Type(TC, can, D->isDependentType()), decl(D, 0) {} + bool RecordType::classof(const TagType *TT) { return isa<RecordDecl>(TT->getDecl()); } |