"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 "
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();
}
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
// 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).
// 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;
/// 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,
// 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();
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
SourceLocation LAngleLoc, RAngleLoc;
{
ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
- if(!ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
- RAngleLoc)) {
+ if(ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
+ RAngleLoc)) {
return DeclPtrTy();
}
}
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,
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.
} 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...
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) &&
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;
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;
--- /dev/null
+// 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
// 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 '>'}}