diff options
author | John McCall <rjmccall@apple.com> | 2010-04-13 07:45:41 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-04-13 07:45:41 +0000 |
commit | 3d04336baf091b16e9d8f85b48b82dafd2695874 (patch) | |
tree | b09fd41a5f9e140413bbd153c6e36fc2dfcd80cc /lib/Sema/SemaDecl.cpp | |
parent | c09289d104b8e01ecd998e3f08b2b0561049e1dc (diff) |
Allow classes to befriend implicitly-declared members. Fixes PR6207 for
members of non-templated classes.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101122 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 005311f075..675cc36346 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1058,10 +1058,14 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { } const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old); - const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New); + CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New); if (OldMethod && NewMethod) { - if (!NewMethod->getFriendObjectKind() && - NewMethod->getLexicalDeclContext()->isRecord()) { + // Preserve triviality. + NewMethod->setTrivial(OldMethod->isTrivial()); + + bool isFriend = NewMethod->getFriendObjectKind(); + + if (!isFriend && NewMethod->getLexicalDeclContext()->isRecord()) { // -- Member function declarations with the same name and the // same parameter types cannot be overloaded if any of them // is a static member function declaration. @@ -1087,14 +1091,19 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { Diag(New->getLocation(), NewDiag); Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); - } else { - if (OldMethod->isImplicit()) { + + // Complain if this is an explicit declaration of a special + // member that was initially declared implicitly. + // + // As an exception, it's okay to befriend such methods in order + // to permit the implicit constructor/destructor/operator calls. + } else if (OldMethod->isImplicit()) { + if (isFriend) { + NewMethod->setImplicit(); + } else { Diag(NewMethod->getLocation(), diag::err_definition_of_implicitly_declared_member) - << New << getSpecialMember(Context, OldMethod); - - Diag(OldMethod->getLocation(), - diag::note_previous_implicit_declaration); + << New << getSpecialMember(Context, OldMethod); return true; } } |