diff options
-rw-r--r-- | include/clang/Sema/Sema.h | 5 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 12 | ||||
-rw-r--r-- | test/CXX/temp/temp.decls/temp.friend/p3.cpp | 2 | ||||
-rw-r--r-- | test/SemaTemplate/friend-template.cpp | 8 |
5 files changed, 24 insertions, 5 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 1129adda49..7d970a8695 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1026,10 +1026,11 @@ public: void ActOnPopScope(SourceLocation Loc, Scope *S); void ActOnTranslationUnitScope(Scope *S); - /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with - /// no declarator (e.g. "struct foo;") is parsed. Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS); + Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, + DeclSpec &DS, + MultiTemplateParamsArg TemplateParams); StmtResult ActOnVlaStmt(const DeclSpec &DS); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 8c0aa1ba69..596778dbd3 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1547,7 +1547,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (Tok.is(tok::semi)) { ConsumeToken(); Decl *TheDecl = - Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS); + Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS, TemplateParams); DS.complete(TheDecl); return; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7214988bda..975a963574 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2132,6 +2132,16 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { /// no declarator (e.g. "struct foo;") is parsed. Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS) { + return ParsedFreeStandingDeclSpec(S, AS, DS, + MultiTemplateParamsArg(*this, 0, 0)); +} + +/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with +/// no declarator (e.g. "struct foo;") is parsed. It also accopts template +/// parameters to cope with template friend declarations. +Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, + DeclSpec &DS, + MultiTemplateParamsArg TemplateParams) { Decl *TagD = 0; TagDecl *Tag = 0; if (DS.getTypeSpecType() == DeclSpec::TST_class || @@ -2163,7 +2173,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, // whatever routines created it handled the friendship aspect. if (TagD && !Tag) return 0; - return ActOnFriendTypeDecl(S, DS, MultiTemplateParamsArg(*this, 0, 0)); + return ActOnFriendTypeDecl(S, DS, TemplateParams); } // Track whether we warned about the fact that there aren't any diff --git a/test/CXX/temp/temp.decls/temp.friend/p3.cpp b/test/CXX/temp/temp.decls/temp.friend/p3.cpp index d116e016f1..0b2a25e987 100644 --- a/test/CXX/temp/temp.decls/temp.friend/p3.cpp +++ b/test/CXX/temp/temp.decls/temp.friend/p3.cpp @@ -8,5 +8,5 @@ class B { template <class T> friend class A; template <class T> friend class Undeclared; - template <class T> friend typename A<T>::Member; // expected-warning {{non-class type 'typename A<T>::Member' cannot be a friend}} + template <class T> friend typename A<T>::Member; // expected-error {{friend type templates must use an elaborated type}} }; diff --git a/test/SemaTemplate/friend-template.cpp b/test/SemaTemplate/friend-template.cpp index 703daea3e6..d1284de35f 100644 --- a/test/SemaTemplate/friend-template.cpp +++ b/test/SemaTemplate/friend-template.cpp @@ -216,3 +216,11 @@ namespace PR8649 { X<int, float, 7> x; } + +// Don't crash, and error on invalid friend type template. +namespace friend_type_template_no_tag { + template <typename T> struct S { + template <typename U> friend S<U>; // expected-error{{friend type templates must use an elaborated type}} + }; + template struct S<int>; +} |