diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-02-04 19:02:06 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-02-04 19:02:06 +0000 |
commit | aaba5e346dffdbad5d1c42765a89e4a7afb0da67 (patch) | |
tree | 0bbf6ad0ff4609acaca0df33e72e02ba03d85235 /lib | |
parent | 0e8aaaf67b0c172e5a55cded30b80a83d3bd477f (diff) |
Basic representation of C++ class templates, from Andrew Sutton.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63750 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTContext.cpp | 1 | ||||
-rw-r--r-- | lib/AST/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 3 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 30 | ||||
-rw-r--r-- | lib/AST/DeclSerialization.cpp | 48 | ||||
-rw-r--r-- | lib/AST/DeclTemplate.cpp | 108 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 1 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 12 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 39 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 21 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 46 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 70 |
18 files changed, 311 insertions, 77 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7892c84f92..7784aed764 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -14,6 +14,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/TargetInfo.h" diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index c49a0eeee5..9687f34be8 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -13,6 +13,7 @@ add_clang_library(clangAST DeclGroup.cpp DeclObjC.cpp DeclSerialization.cpp + DeclTemplate.cpp ExprConstant.cpp Expr.cpp ExprCXX.cpp diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 21e1e0ce10..1e3683c857 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -13,8 +13,9 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Type.h" #include "llvm/ADT/DenseMap.h" diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 5e1875ab65..6de575411b 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -21,36 +21,6 @@ using namespace clang; // Decl Allocation/Deallocation Method Implementations //===----------------------------------------------------------------------===// -TemplateTypeParmDecl * -TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - bool Typename) { - return new (C) TemplateTypeParmDecl(DC, L, Id, Typename); -} - -NonTypeTemplateParmDecl * -NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - QualType T, SourceLocation TypeSpecStartLoc) { - return new (C) NonTypeTemplateParmDecl(DC, L, Id, T, TypeSpecStartLoc); -} - -TemplateParameterList::TemplateParameterList(Decl **Params, unsigned NumParams) - : NumParams(NumParams) { - for (unsigned Idx = 0; Idx < NumParams; ++Idx) - begin()[Idx] = Params[Idx]; -} - -TemplateParameterList * -TemplateParameterList::Create(ASTContext &C, Decl **Params, - unsigned NumParams) { - // FIXME: how do I pass in Size to ASTContext::new? - unsigned Size = sizeof(TemplateParameterList) + sizeof(Decl *) * NumParams; - unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment; - void *Mem = C.Allocate(Size, Align); - return new (Mem) TemplateParameterList(Params, NumParams); -} - CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id) : RecordDecl(CXXRecord, TK, DC, L, Id), diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp index a10b229fcd..dcb8cda33b 100644 --- a/lib/AST/DeclSerialization.cpp +++ b/lib/AST/DeclSerialization.cpp @@ -14,6 +14,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "llvm/Bitcode/Serialize.h" #include "llvm/Bitcode/Deserialize.h" @@ -597,15 +598,60 @@ TypedefDecl* TypedefDecl::CreateImpl(Deserializer& D, ASTContext& C) { //===----------------------------------------------------------------------===// void TemplateTypeParmDecl::EmitImpl(Serializer& S) const { + S.EmitInt(Depth); + S.EmitInt(Position); S.EmitBool(Typename); NamedDecl::EmitInRec(S); } TemplateTypeParmDecl * TemplateTypeParmDecl::CreateImpl(Deserializer& D, ASTContext& C) { + unsigned Depth = D.ReadInt(); + unsigned Position = D.ReadInt(); bool Typename = D.ReadBool(); TemplateTypeParmDecl *decl - = new (C) TemplateTypeParmDecl(0, SourceLocation(), NULL, Typename); + = new (C) TemplateTypeParmDecl(0, SourceLocation(), Depth, Position, + 0, Typename); + decl->NamedDecl::ReadInRec(D, C); + return decl; +} + +//===----------------------------------------------------------------------===// +// NonTypeTemplateParmDecl Serialization. +//===----------------------------------------------------------------------===// +void NonTypeTemplateParmDecl::EmitImpl(Serializer& S) const { + S.EmitInt(Depth); + S.EmitInt(Position); + NamedDecl::Emit(S); +} + +NonTypeTemplateParmDecl* +NonTypeTemplateParmDecl::CreateImpl(Deserializer& D, ASTContext& C) { + unsigned Depth = D.ReadInt(); + unsigned Position = D.ReadInt(); + NonTypeTemplateParmDecl *decl + = new (C) NonTypeTemplateParmDecl(0, SourceLocation(), Depth, Position, + 0, QualType(), SourceLocation()); + decl->NamedDecl::ReadInRec(D, C); + return decl; +} + +//===----------------------------------------------------------------------===// +// TemplateTemplateParmDecl Serialization. +//===----------------------------------------------------------------------===// +void TemplateTemplateParmDecl::EmitImpl(Serializer& S) const { + S.EmitInt(Depth); + S.EmitInt(Position); + NamedDecl::EmitInRec(S); +} + +TemplateTemplateParmDecl* +TemplateTemplateParmDecl::CreateImpl(Deserializer& D, ASTContext& C) { + unsigned Depth = D.ReadInt(); + unsigned Position = D.ReadInt(); + TemplateTemplateParmDecl *decl + = new (C) TemplateTemplateParmDecl(0, SourceLocation(), Depth, Position, + 0, 0); decl->NamedDecl::ReadInRec(D, C); return decl; } diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp new file mode 100644 index 0000000000..08cd5b377d --- /dev/null +++ b/lib/AST/DeclTemplate.cpp @@ -0,0 +1,108 @@ +//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the C++ related Decl classes for templates. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/ASTContext.h" +#include "clang/Basic/IdentifierTable.h" +#include "llvm/ADT/STLExtras.h" +using namespace clang; + +//===----------------------------------------------------------------------===// +// TemplateParameterList Implementation +//===----------------------------------------------------------------------===// + +TemplateParameterList::TemplateParameterList(Decl **Params, unsigned NumParams) + : NumParams(NumParams) { + for (unsigned Idx = 0; Idx < NumParams; ++Idx) + begin()[Idx] = Params[Idx]; +} + +TemplateParameterList * +TemplateParameterList::Create(ASTContext &C, Decl **Params, + unsigned NumParams) { + unsigned Size = sizeof(TemplateParameterList) + sizeof(Decl *) * NumParams; + unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment; + void *Mem = C.Allocate(Size, Align); + return new (Mem) TemplateParameterList(Params, NumParams); +} + +//===----------------------------------------------------------------------===// +// TemplateDecl Implementation +//===----------------------------------------------------------------------===// + +TemplateDecl::~TemplateDecl() { +} + +//===----------------------------------------------------------------------===// +// FunctionTemplateDecl Implementation +//===----------------------------------------------------------------------===// + +FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, + DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl) { + return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl); +} + +//===----------------------------------------------------------------------===// +// ClassTemplateDecl Implementation +//===----------------------------------------------------------------------===// + +ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, + DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl) { + return new (C) ClassTemplateDecl(DC, L, Name, Params, Decl); +} + +//===----------------------------------------------------------------------===// +// TemplateTypeParm Allocation/Deallocation Method Implementations +//===----------------------------------------------------------------------===// + +TemplateTypeParmDecl * +TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, unsigned P, + IdentifierInfo *Id, bool Typename) { + return new (C) TemplateTypeParmDecl(DC, L, D, P, Id, Typename); +} + +//===----------------------------------------------------------------------===// +// NonTypeTemplateParmDecl Method Implementations +//===----------------------------------------------------------------------===// + +NonTypeTemplateParmDecl * +NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, unsigned P, + IdentifierInfo *Id, QualType T, + SourceLocation TypeSpecStartLoc) { + return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, + TypeSpecStartLoc); +} + +//===----------------------------------------------------------------------===// +// TemplateTemplateParmDecl Method Implementations +//===----------------------------------------------------------------------===// + +TemplateTemplateParmDecl * +TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, unsigned P, + IdentifierInfo *Id, + TemplateParameterList *Params) { + return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params); +} + diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 35384d880c..ce13c34012 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/TargetInfo.h" diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 5d3478b2ea..f39a325e0d 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -15,6 +15,7 @@ #include "clang/AST/Type.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "llvm/ADT/StringExtras.h" diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 114f4cb570..e2601b6cf4 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1726,7 +1726,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // If this identifier is followed by a '<', we may have a template-id. DeclTy *Template; - if (NextToken().is(tok::less) && + if (getLang().CPlusPlus && NextToken().is(tok::less) && (Template = Actions.isTemplateName(*Tok.getIdentifierInfo(), CurScope))) { IdentifierInfo *II = Tok.getIdentifierInfo(); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 1fbe32a459..b2b0d8f59f 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -345,8 +345,8 @@ void Parser::ParseClassSpecifier(DeclSpec &DS, return; } - // Parse the tag portion of this. - DeclTy *TagDecl + // Create the tag portion of the class, possibly resulting in a template. + DeclTy *TagOrTempDecl = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS, Name, NameLoc, Attr, Action::MultiTemplateParamsArg( @@ -356,15 +356,15 @@ void Parser::ParseClassSpecifier(DeclSpec &DS, // Parse the optional base clause (C++ only). if (getLang().CPlusPlus && Tok.is(tok::colon)) { - ParseBaseClause(TagDecl); + ParseBaseClause(TagOrTempDecl); } // If there is a body, parse it and inform the actions module. if (Tok.is(tok::l_brace)) if (getLang().CPlusPlus) - ParseCXXMemberSpecification(StartLoc, TagType, TagDecl); + ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempDecl); else - ParseStructUnionBody(StartLoc, TagType, TagDecl); + ParseStructUnionBody(StartLoc, TagType, TagOrTempDecl); else if (TK == Action::TK_Definition) { // FIXME: Complain that we have a base-specifier list but no // definition. @@ -372,7 +372,7 @@ void Parser::ParseClassSpecifier(DeclSpec &DS, } const char *PrevSpec = 0; - if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, TagDecl)) + if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, TagOrTempDecl)) Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; } diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index b9a55147b8..e95c106f28 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -39,7 +39,7 @@ Parser::DeclTy *Parser::ParseTemplateDeclaration(unsigned Context) { // // We parse multiple levels non-recursively so that we can build a // single data structure containing all of the template parameter - // lists, and easily differentiate between the case above and: + // lists easily differentiate between the case above and: // // template<typename T> // class A { @@ -82,19 +82,16 @@ Parser::DeclTy *Parser::ParseTemplateDeclaration(unsigned Context) { } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template)); // Parse the actual template declaration. - DeclTy *TemplateDecl = ParseDeclarationOrFunctionDefinition(&ParamLists); - - return TemplateDecl; + return ParseDeclarationOrFunctionDefinition(&ParamLists); } /// ParseTemplateParameters - Parses a template-parameter-list enclosed in -/// angle brackets. Depth is the depth of this -/// template-parameter-list, which is the number of template headers -/// directly enclosing this template header. TemplateParams is the -/// current list of template parameters we're building. The template -/// parameter we parse will be added to this list. LAngleLoc and -/// RAngleLoc will receive the positions of the '<' and '>', -/// respectively, that enclose this template parameter list. +/// angle brackets. Depth is the depth of this template-parameter-list, which +/// is the number of template headers directly enclosing this template header. +/// TemplateParams is the current list of template parameters we're building. +/// The template parameter we parse will be added to this list. LAngleLoc and +/// RAngleLoc will receive the positions of the '<' and '>', respectively, +/// that enclose this template parameter list. bool Parser::ParseTemplateParameters(unsigned Depth, TemplateParameterList &TemplateParams, SourceLocation &LAngleLoc, @@ -223,8 +220,8 @@ Parser::DeclTy *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { return 0; } - DeclTy *TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword, - KeyLoc, ParamName, NameLoc, + DeclTy *TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword, + KeyLoc, ParamName, NameLoc, Depth, Position); // Grab a default type id (if given). @@ -251,7 +248,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { SourceLocation TemplateLoc = ConsumeToken(); TemplateParameterList TemplateParams; SourceLocation LParenLoc, RParenLoc; - if(!ParseTemplateParameters(Depth+1, TemplateParams, LParenLoc, + if(!ParseTemplateParameters(Depth + 1, TemplateParams, LParenLoc, RParenLoc)) { return 0; } @@ -266,10 +263,11 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { SourceLocation ClassLoc = ConsumeToken(); // Get the identifier, if given. - IdentifierInfo* ident = 0; + SourceLocation NameLoc; + IdentifierInfo* ParamName = 0; if(Tok.is(tok::identifier)) { - ident = Tok.getIdentifierInfo(); - ConsumeToken(); + ParamName = Tok.getIdentifierInfo(); + NameLoc = ConsumeToken(); } else if(Tok.is(tok::equal) || Tok.is(tok::comma) || Tok.is(tok::greater)) { // Unnamed template parameter. Don't have to do anything here, just // don't consume this token. @@ -279,6 +277,8 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { } // Get the a default value, if given. + // FIXME: I think that the results of this block need to be passed to the + // act-on call, so we can assemble the parameter correctly. OwningExprResult DefaultExpr(Actions); if(Tok.is(tok::equal)) { ConsumeToken(); @@ -288,8 +288,9 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { } } - // FIXME: Add an action for template template parameters. - return 0; + return Actions.ActOnTemplateTemplateParameter(CurScope, TemplateLoc, + &TemplateParams, ParamName, + NameLoc, Depth, Position); } /// ParseNonTypeTemplateParameter - Handle the parsing of non-type diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index c5c7dd4733..2f7e2ea0fc 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -379,7 +379,6 @@ Parser::DeclTy *Parser::ParseExternalDeclaration() { case tok::kw_export: // As in 'export template' // A function definition cannot start with a these keywords. return ParseDeclaration(Declarator::FileContext); - default: // We can't tell whether this is a function-definition or declaration yet. return ParseDeclarationOrFunctionDefinition(); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index b0e24f5d14..b27f11b77c 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -60,6 +60,7 @@ namespace clang { class SwitchStmt; class ExtVectorType; class TypedefDecl; + class TemplateDecl; class ObjCInterfaceDecl; class ObjCCompatibleAliasDecl; class ObjCProtocolDecl; @@ -1479,14 +1480,23 @@ public: virtual DeclTy *isTemplateName(IdentifierInfo &II, Scope *S, const CXXScopeSpec *SS = 0); bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl); - virtual DeclTy *ActOnTypeParameter(Scope *S, bool Typename, - SourceLocation KeyLoc, - IdentifierInfo *ParamName, - SourceLocation ParamNameLoc, + TemplateDecl *AdjustDeclIfTemplate(DeclTy *&Decl); + + virtual DeclTy *ActOnTypeParameter(Scope *S, bool Typename, + SourceLocation KeyLoc, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, unsigned Depth, unsigned Position); virtual DeclTy *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, - unsigned Depth, + unsigned Depth, unsigned Position); + virtual DeclTy *ActOnTemplateTemplateParameter(Scope *S, + SourceLocation TmpLoc, + TemplateParamsTy *Params, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, + unsigned Depth, + unsigned Position); virtual TemplateParamsTy * ActOnTemplateParameterList(unsigned Depth, SourceLocation ExportLoc, @@ -1495,6 +1505,7 @@ public: DeclTy **Params, unsigned NumParams, SourceLocation RAngleLoc); + // Objective-C declarations. virtual DeclTy *ActOnStartClassInterface(SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a3ca97b5cb..3e501f450a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/Parse/DeclSpec.h" #include "clang/Basic/TargetInfo.h" @@ -1170,7 +1171,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl, // The scope passed in may not be a decl scope. Zip up the scope tree until // we find one that is. while ((S->getFlags() & Scope::DeclScope) == 0 || - (S->getFlags() & Scope::TemplateParamScope) != 0) + (S->getFlags() & Scope::TemplateParamScope) != 0) S = S->getParent(); DeclContext *DC; @@ -2778,6 +2779,9 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, /// former case, Name will be non-null. In the later case, Name will be null. /// TagSpec indicates what kind of tag this is. TK indicates whether this is a /// reference/declaration/definition of a tag. +/// +/// This creates and returns template declarations if any template parameter +/// lists are given. Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, SourceLocation KWLoc, const CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, @@ -2786,7 +2790,12 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, // If this is not a definition, it must have a name. assert((Name != 0 || TK == TK_Definition) && "Nameless record must be a definition!"); - + assert((TemplateParameterLists.size() == 0 || TK != TK_Reference) && + "Can't have a reference to a template"); + assert((TemplateParameterLists.size() == 0 || + TagSpec != DeclSpec::TST_enum) && + "No such thing as an enum template"); + TagDecl::TagKind Kind; switch (TagSpec) { default: assert(0 && "Unknown tag type!"); @@ -2799,6 +2808,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, DeclContext *SearchDC = CurContext; DeclContext *DC = CurContext; NamedDecl *PrevDecl = 0; + TemplateDecl *PrevTemplate = 0; bool Invalid = false; @@ -2863,6 +2873,11 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, } if (PrevDecl) { + // If we found a template, keep track of the template and its + // underlying declaration. + if ((PrevTemplate = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl))) + PrevDecl = PrevTemplate->getTemplatedDecl(); + if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) { // If this is a use of a previous tag, or if the tag is already declared // in the same scope (so that the definition/declaration completes or @@ -2877,6 +2892,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, Name = 0; PrevDecl = 0; Invalid = true; + // FIXME: Add template/non-template redecl check } else { // If this is a use, just return the declaration we found. @@ -2886,7 +2902,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, // need to be changed with DeclGroups. if (TK == TK_Reference) return PrevDecl; - + // Diagnose attempts to redefine a tag. if (TK == TK_Definition) { if (TagDecl *Def = PrevTagDecl->getDefinition(Context)) { @@ -2990,6 +3006,7 @@ CreateNewDecl: // declaration of the same entity, the two will be linked via // PrevDecl. TagDecl *New; + ClassTemplateDecl *NewTemplate = 0; if (Kind == TagDecl::TK_enum) { // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: @@ -3003,11 +3020,28 @@ CreateNewDecl: // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: // struct X { int A; } D; D should chain to X. - if (getLangOptions().CPlusPlus) + if (getLangOptions().CPlusPlus) { // FIXME: Look for a way to use RecordDecl for simple structs. New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name, cast_or_null<CXXRecordDecl>(PrevDecl)); - else + + // If there's are template parameters, then this must be a class + // template. Create the template decl node also. + // FIXME: Do we always create template decls? We may not for forward + // declarations. + // FIXME: What are we actually going to do with the template decl? + if (TemplateParameterLists.size() > 0) { + // FIXME: The allocation of the parameters is probably incorrect. + // FIXME: Does the TemplateDecl have the same name as the class? + TemplateParameterList *Params = + TemplateParameterList::Create(Context, + (Decl **)TemplateParameterLists.get(), + TemplateParameterLists.size()); + NewTemplate = ClassTemplateDecl::Create(Context, DC, Loc, + DeclarationName(Name), Params, + New); + } + } else New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name, cast_or_null<RecordDecl>(PrevDecl)); } @@ -3080,6 +3114,7 @@ CreateNewDecl: } void Sema::ActOnTagStartDefinition(Scope *S, DeclTy *TagD) { + AdjustDeclIfTemplate(TagD); TagDecl *Tag = cast<TagDecl>((Decl *)TagD); // Enter the tag context. @@ -3105,6 +3140,7 @@ void Sema::ActOnTagStartDefinition(Scope *S, DeclTy *TagD) { } void Sema::ActOnTagFinishDefinition(Scope *S, DeclTy *TagD) { + AdjustDeclIfTemplate(TagD); TagDecl *Tag = cast<TagDecl>((Decl *)TagD); if (isa<CXXRecordDecl>(Tag)) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 5595215d55..35050e517b 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -757,6 +757,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, DeclTy *TagDecl, SourceLocation LBrac, SourceLocation RBrac) { + AdjustDeclIfTemplate(TagDecl); ActOnFields(S, RLoc, TagDecl, (DeclTy**)FieldCollector->getCurFields(), FieldCollector->getCurNumFields(), LBrac, RBrac, 0); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 0c755f6d1f..66cbdfd26a 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -16,6 +16,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Basic/SourceManager.h" diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 65dd9490d2..1aa2ea0207 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -536,7 +536,7 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, IEnd = IdResolver.end(); // First we lookup local scope. - // We don't consider using-dirctives, as per 7.3.4.p1 [namespace.udir] + // We don't consider using-directives, as per 7.3.4.p1 [namespace.udir] // ...During unqualified name lookup (3.4.1), the names appear as if // they were declared in the nearest enclosing namespace which contains // both the using-directive and the nominated namespace. diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index c46731e515..e15343a042 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -13,6 +13,7 @@ #include "Sema.h" #include "clang/AST/Expr.h" +#include "clang/AST/DeclTemplate.h" #include "clang/Parse/DeclSpec.h" #include "clang/Basic/LangOptions.h" @@ -38,6 +39,9 @@ Sema::DeclTy *Sema::isTemplateName(IdentifierInfo &II, Scope *S, // FIXME: We need to represent templates via some kind of // TemplateDecl, because what follows is a hack that only works in // one specific case. + if (isa<TemplateDecl>(IIDecl)) + return IIDecl; + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(IIDecl)) { if (FD->getType()->isDependentType()) return FD; @@ -50,7 +54,6 @@ Sema::DeclTy *Sema::isTemplateName(IdentifierInfo &II, Scope *S, return Ovl; } } - return 0; } return 0; } @@ -75,6 +78,18 @@ bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) { return true; } +/// AdjustDeclForTemplates - If the given decl happens to be a template, reset +/// the parameter D to reference the templated declaration and return a pointer +/// to the template declaration. Otherwise, do nothing to D and return null. +TemplateDecl *Sema::AdjustDeclIfTemplate(DeclTy *&D) +{ + if(TemplateDecl *Temp = dyn_cast<TemplateDecl>(static_cast<Decl*>(D))) { + D = Temp->getTemplatedDecl(); + return Temp; + } + return 0; +} + /// ActOnTypeParameter - Called when a C++ template type parameter /// (e.g., "typename T") has been parsed. Typename specifies whether /// the keyword "typename" was used to declare the type parameter @@ -101,8 +116,8 @@ Sema::DeclTy *Sema::ActOnTypeParameter(Scope *S, bool Typename, } TemplateTypeParmDecl *Param - = TemplateTypeParmDecl::Create(Context, CurContext, - ParamNameLoc, ParamName, Typename); + = TemplateTypeParmDecl::Create(Context, CurContext, ParamNameLoc, + Depth, Position, ParamName, Typename); if (Invalid) Param->setInvalidDecl(); @@ -124,8 +139,8 @@ Sema::DeclTy *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, unsigned Position) { QualType T = GetTypeForDeclarator(D, S); - assert(S->isTemplateParamScope() && - "Template type parameter not in template parameter scope!"); + assert(S->isTemplateParamScope() && + "Non-type template parameter not in template parameter scope!"); bool Invalid = false; IdentifierInfo *ParamName = D.getIdentifier(); @@ -133,12 +148,12 @@ Sema::DeclTy *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, NamedDecl *PrevDecl = LookupName(S, ParamName, LookupTagName); if (PrevDecl && PrevDecl->isTemplateParameter()) Invalid = Invalid || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), - PrevDecl); + PrevDecl); } |