aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-02-04 19:02:06 +0000
committerDouglas Gregor <dgregor@apple.com>2009-02-04 19:02:06 +0000
commitaaba5e346dffdbad5d1c42765a89e4a7afb0da67 (patch)
tree0bbf6ad0ff4609acaca0df33e72e02ba03d85235 /lib
parent0e8aaaf67b0c172e5a55cded30b80a83d3bd477f (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.cpp1
-rw-r--r--lib/AST/CMakeLists.txt1
-rw-r--r--lib/AST/DeclBase.cpp3
-rw-r--r--lib/AST/DeclCXX.cpp30
-rw-r--r--lib/AST/DeclSerialization.cpp48
-rw-r--r--lib/AST/DeclTemplate.cpp108
-rw-r--r--lib/AST/Expr.cpp1
-rw-r--r--lib/AST/Type.cpp1
-rw-r--r--lib/Parse/ParseDecl.cpp2
-rw-r--r--lib/Parse/ParseDeclCXX.cpp12
-rw-r--r--lib/Parse/ParseTemplate.cpp39
-rw-r--r--lib/Parse/Parser.cpp1
-rw-r--r--lib/Sema/Sema.h21
-rw-r--r--lib/Sema/SemaDecl.cpp46
-rw-r--r--lib/Sema/SemaDeclCXX.cpp1
-rw-r--r--lib/Sema/SemaExpr.cpp1
-rw-r--r--lib/Sema/SemaLookup.cpp2
-rw-r--r--lib/Sema/SemaTemplate.cpp70
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);
}