aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--include/clang/Parse/Action.h12
-rw-r--r--lib/Parse/ParseDeclCXX.cpp15
-rw-r--r--lib/Parse/ParseTemplate.cpp24
-rw-r--r--lib/Sema/Sema.h1
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp2
-rw-r--r--lib/Sema/SemaDecl.cpp27
-rw-r--r--lib/Sema/SemaTemplate.cpp3
-rw-r--r--test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp27
-rw-r--r--test/Parser/cxx-template-decl.cpp8
10 files changed, 93 insertions, 29 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index df62573e8c..76d069fd8a 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -733,10 +733,11 @@ def note_template_param_prev_default_arg : Note<
"previous default template argument defined here">;
def err_template_param_default_arg_missing : Error<
"template parameter missing a default argument">;
-
+
def err_template_variable : Error<"variable %0 declared as a template">;
def err_template_variable_noparams : Error<
"extraneous 'template<>' in declaration of variable %0">;
+
// C++ Template Argument Lists
def err_template_arg_list_different_arity : Error<
"%select{too few|too many}0 template arguments for "
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 23c5428ef6..92f38ede89 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -422,6 +422,18 @@ public:
bool &OwnedDecl) {
// TagType is an instance of DeclSpec::TST, indicating what kind of tag this
// is (struct/union/enum/class).
+ return ActOnTag(S, TagSpec, TK, KWLoc, SS, Name, NameLoc, Attr, AS,
+ MultiTemplateParamsArg(*this, 0, 0), OwnedDecl);
+ }
+
+ virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
+ SourceLocation KWLoc, const CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ AttributeList *Attr, AccessSpecifier AS,
+ MultiTemplateParamsArg TemplateParameterLists,
+ bool &OwnedDecl) {
+ // TagType is an instance of DeclSpec::TST, indicating what kind of tag this
+ // is (struct/union/enum/class).
return DeclPtrTy();
}
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 930d58dd26..f28ffe3509 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -673,15 +673,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TemplateParams? TemplateParams->size() : 0));
}
TemplateId->Destroy();
- } else if (TemplateParams && TK != Action::TK_Reference) {
- // Class template declaration or definition.
- TagOrTempResult = Actions.ActOnClassTemplate(CurScope, TagType, TK,
- StartLoc, SS, Name, NameLoc,
- Attr,
- Action::MultiTemplateParamsArg(Actions,
- &(*TemplateParams)[0],
- TemplateParams->size()),
- AS);
} else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
TK == Action::TK_Declaration) {
// Explicit instantiation of a member of a class template
@@ -702,7 +693,11 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Declaration or definition of a class type
TagOrTempResult = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS,
- Name, NameLoc, Attr, AS, Owned);
+ Name, NameLoc, Attr, AS,
+ Action::MultiTemplateParamsArg(Actions,
+ TemplateParams? &(*TemplateParams)[0] : 0,
+ TemplateParams? TemplateParams->size() : 0),
+ Owned);
}
// Parse the optional base clause (C++ only).
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 57a09fbc73..df7c22cf26 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -96,9 +96,15 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
// Parse the '<' template-parameter-list '>'
SourceLocation LAngleLoc, RAngleLoc;
TemplateParameterList TemplateParams;
- ParseTemplateParameters(ParamLists.size(), TemplateParams, LAngleLoc,
- RAngleLoc);
-
+ if (ParseTemplateParameters(ParamLists.size(), TemplateParams, LAngleLoc,
+ RAngleLoc)) {
+ // Skip until the semi-colon or a }.
+ SkipUntil(tok::r_brace, true, true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ return DeclPtrTy();
+ }
+
if (!TemplateParams.empty())
isSpecialiation = false;
@@ -219,6 +225,8 @@ Parser::ParseSingleDeclarationAfterTemplate(
/// 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.
+///
+/// \returns true if an error occurred, false otherwise.
bool Parser::ParseTemplateParameters(unsigned Depth,
TemplateParameterList &TemplateParams,
SourceLocation &LAngleLoc,
@@ -226,7 +234,7 @@ bool Parser::ParseTemplateParameters(unsigned Depth,
// Get the template parameter list.
if(!Tok.is(tok::less)) {
Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
- return false;
+ return true;
}
LAngleLoc = ConsumeToken();
@@ -236,11 +244,11 @@ bool Parser::ParseTemplateParameters(unsigned Depth,
else if(ParseTemplateParameterList(Depth, TemplateParams)) {
if(!Tok.is(tok::greater)) {
Diag(Tok.getLocation(), diag::err_expected_greater);
- return false;
+ return true;
}
RAngleLoc = ConsumeToken();
}
- return true;
+ return false;
}
/// ParseTemplateParameterList - Parse a template parameter list. If
@@ -392,8 +400,8 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
SourceLocation LAngleLoc, RAngleLoc;
{
ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
- if(!ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
- RAngleLoc)) {
+ if(ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
+ RAngleLoc)) {
return DeclPtrTy();
}
}
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 7daf3f90a8..78d64b53c0 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -522,6 +522,7 @@ public:
SourceLocation KWLoc, const CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr, AccessSpecifier AS,
+ MultiTemplateParamsArg TemplateParameterLists,
bool &OwnedDecl);
virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart,
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index cf73725e7f..be1a1103b3 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -213,7 +213,7 @@ bool Sema::RequireCompleteDeclContext(const CXXScopeSpec &SS) {
if (!SS.isSet() || SS.isInvalid())
return false;
- DeclContext *DC = computeDeclContext(SS);
+ DeclContext *DC = computeDeclContext(SS, true);
if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
// If we're currently defining this type, then lookup into the
// type is okay: don't complain that it isn't complete yet.
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 2e280f58cb..d9c1224b43 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1866,14 +1866,14 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
} else {
// There is an extraneous 'template<>' for this variable. Complain
// about it, but allow the declaration of the variable.
- Diag(TemplateParams->getTemplateLoc(), diag::err_template_variable)
+ Diag(TemplateParams->getTemplateLoc(),
+ diag::err_template_variable_noparams)
<< II
<< SourceRange(TemplateParams->getTemplateLoc(),
TemplateParams->getRAngleLoc());
}
}
- // The variable can not
NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
II, R, SC,
// FIXME: Move to DeclGroup...
@@ -3522,6 +3522,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
SourceLocation KWLoc, const CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr, AccessSpecifier AS,
+ MultiTemplateParamsArg TemplateParameterLists,
bool &OwnedDecl) {
// If this is not a definition, it must have a name.
assert((Name != 0 || TK == TK_Definition) &&
@@ -3537,6 +3538,28 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
case DeclSpec::TST_enum: Kind = TagDecl::TK_enum; break;
}
+ if (TK != TK_Reference) {
+ if (TemplateParameterList *TemplateParams
+ = MatchTemplateParametersToScopeSpecifier(KWLoc, SS,
+ (TemplateParameterList**)TemplateParameterLists.get(),
+ TemplateParameterLists.size())) {
+ if (TemplateParams->size() > 0) {
+ // This is a declaration or definition of a class template (which may
+ // be a member of another template).
+ OwnedDecl = false;
+ DeclResult Result = ActOnClassTemplate(S, TagSpec, TK, KWLoc,
+ SS, Name, NameLoc, Attr,
+ move(TemplateParameterLists),
+ AS);
+ return Result.get();
+ } else {
+ // FIXME: diagnose the extraneous 'template<>', once we recover
+ // slightly better in ParseTemplate.cpp from bogus template
+ // parameters.
+ }
+ }
+ }
+
DeclContext *SearchDC = CurContext;
DeclContext *DC = CurContext;
NamedDecl *PrevDecl = 0;
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 5f772bc22c..981b8508c5 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2895,7 +2895,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
bool Owned = false;
DeclPtrTy TagD = ActOnTag(S, TagSpec, Action::TK_Reference,
- KWLoc, SS, Name, NameLoc, Attr, AS_none, Owned);
+ KWLoc, SS, Name, NameLoc, Attr, AS_none,
+ MultiTemplateParamsArg(*this, 0, 0), Owned);
if (!TagD)
return true;
diff --git a/test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp b/test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp
new file mode 100644
index 0000000000..9bafacc00a
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp
@@ -0,0 +1,27 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T, typename U>
+struct X0 {
+ struct Inner;
+};
+
+template<typename T, typename U>
+struct X0<T, U>::Inner {
+ T x;
+ U y;
+
+ void f() { x = y; } // expected-error{{incompatible}}
+};
+
+
+void test(int i, float f) {
+ X0<int, float>::Inner inner;
+ inner.x = 5;
+ inner.y = 3.4;
+ inner.f();
+
+ X0<int*, float *>::Inner inner2;
+ inner2.x = &i;
+ inner2.y = &f;
+ inner2.f(); // expected-note{{instantiation}}
+} \ No newline at end of file
diff --git a/test/Parser/cxx-template-decl.cpp b/test/Parser/cxx-template-decl.cpp
index b7117cd8d6..5f49fb15d7 100644
--- a/test/Parser/cxx-template-decl.cpp
+++ b/test/Parser/cxx-template-decl.cpp
@@ -3,12 +3,8 @@
// Errors
export class foo { }; // expected-error {{expected template}}
template x; // expected-error {{C++ requires a type specifier for all declarations}}
-export template x; // expected-error {{expected '<' after 'template'}} \
- // expected-note {{exported templates are unsupported}} \
-// expected-error {{C++ requires a type specifier for all declarations}} \
-// expected-error {{declared as a template}}
-// See Sema::ParsedFreeStandingDeclSpec about the double diagnostic. This is
-// because ParseNonTypeTemplateParameter starts parsing a DeclSpec.
+export template x; // expected-error {{expected '<' after 'template'}}
+export template<class T> class x0; // expected-note {{exported templates are unsupported}}
template < ; // expected-error {{parse error}} expected-error {{declaration does not declare anything}}
template <template X> struct Err1; // expected-error {{expected '<' after 'template'}}
template <template <typename> > struct Err2; // expected-error {{expected 'class' before '>'}}