diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-10-10 01:11:59 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-10-10 01:11:59 +0000 |
commit | 883af83bd6f9b0b60b8c7a78b8682eb8ab40a4a8 (patch) | |
tree | 82468c67dde5778d9320aa4a6a22178ce64bf03e /lib/Sema/SemaDeclCXX.cpp | |
parent | b5ae92f2f52df88ae14504d3a3f2bddb479829b6 (diff) |
Implement the restrictions in C++ [class.friend]p6, which disallow
defining a friend function with a qualified name or in a local
class. Fixes PR9853.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141524 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 031afa078d..b16cbb80c4 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -10196,6 +10196,14 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, DCScope = getScopeForDeclContext(S, DC); + // C++ [class.friend]p6: + // A function can be defined in a friend declaration of a class if and + // only if the class is a non-local class (9.8), the function name is + // unqualified, and the function has namespace scope. + if (isLocal && IsDefinition) { + Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class); + } + // - There's a non-dependent scope specifier, in which case we // compute it and do a previous lookup there for a function // or function template. @@ -10229,6 +10237,20 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, // class that is not a member of the class . . . if (DC->Equals(CurContext)) Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member); + + if (IsDefinition) { + // C++ [class.friend]p6: + // A function can be defined in a friend declaration of a class if and + // only if the class is a non-local class (9.8), the function name is + // unqualified, and the function has namespace scope. + SemaDiagnosticBuilder DB + = Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def); + + DB << SS.getScopeRep(); + if (DC->isFileContext()) + DB << FixItHint::CreateRemoval(SS.getRange()); + SS.clear(); + } // - There's a scope specifier that does not match any template // parameter lists, in which case we use some arbitrary context, @@ -10236,10 +10258,19 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, // - There's a scope specifier that does match some template // parameter lists, which we don't handle right now. } else { + if (IsDefinition) { + // C++ [class.friend]p6: + // A function can be defined in a friend declaration of a class if and + // only if the class is a non-local class (9.8), the function name is + // unqualified, and the function has namespace scope. + Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def) + << SS.getScopeRep(); + } + DC = CurContext; assert(isa<CXXRecordDecl>(DC) && "friend declaration not in class?"); } - + if (!DC->isRecord()) { // This implies that it has to be an operator or function. if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName || @@ -10251,7 +10282,7 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, return 0; } } - + bool Redeclaration = false; bool AddToScope = true; NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, T, TInfo, Previous, |