summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Sema/Sema.h5
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp2
-rw-r--r--clang/lib/Sema/SemaDecl.cpp12
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.friend/p3.cpp2
-rw-r--r--clang/test/SemaTemplate/friend-template.cpp8
5 files changed, 24 insertions, 5 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1129adda49d..7d970a8695f 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/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/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 8c0aa1ba694..596778dbd32 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 7214988bdaf..975a9635748 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/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/clang/test/CXX/temp/temp.decls/temp.friend/p3.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p3.cpp
index d116e016f1d..0b2a25e9876 100644
--- a/clang/test/CXX/temp/temp.decls/temp.friend/p3.cpp
+++ b/clang/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/clang/test/SemaTemplate/friend-template.cpp b/clang/test/SemaTemplate/friend-template.cpp
index 703daea3e63..d1284de35f1 100644
--- a/clang/test/SemaTemplate/friend-template.cpp
+++ b/clang/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>;
+}
OpenPOWER on IntegriCloud