From 27e2ff964fc3e18c27488e15dc74b44ef32d2fe0 Mon Sep 17 00:00:00 2001 From: Yaron Keren Date: Mon, 17 Apr 2017 08:51:20 +0000 Subject: Address http://bugs.llvm.org/pr30994 so that a non-friend can properly replace a friend, and a visible friend can properly replace an invisible friend but not vice verse, and definitions are not replaced. This fixes the two FIXME in SemaTemplate/friend-template.cpp. The code implements Richard Smith suggestion in comment 3 of the PR. reviewer: Vassil Vassilev Differential Revision: https://reviews.llvm.org/D31540 llvm-svn: 300443 --- clang/lib/AST/Decl.cpp | 4 ++++ clang/lib/AST/DeclBase.cpp | 15 +++++++++++++++ 2 files changed, 19 insertions(+) (limited to 'clang/lib') diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 2b22e5bb50a..6a288cdb21f 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1536,6 +1536,10 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const { if (isa(this)) return false; + if (getFriendObjectKind() > OldD->getFriendObjectKind() && + !isThisDeclarationADefinition()) + return false; + // For parameters, pick the newer one. This is either an error or (in // Objective-C) permitted as an extension. if (isa(this)) diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index cda70c5edcd..ae7444579b0 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -861,6 +861,21 @@ const FunctionType *Decl::getFunctionType(bool BlocksToo) const { return Ty->getAs(); } +bool Decl::isThisDeclarationADefinition() const { + if (auto *TD = dyn_cast(this)) + return TD->isThisDeclarationADefinition(); + if (auto *FD = dyn_cast(this)) + return FD->isThisDeclarationADefinition(); + if (auto *VD = dyn_cast(this)) + return VD->isThisDeclarationADefinition(); + if (auto *CTD = dyn_cast(this)) + return CTD->isThisDeclarationADefinition(); + if (auto *FTD = dyn_cast(this)) + return FTD->isThisDeclarationADefinition(); + if (auto *VTD = dyn_cast(this)) + return VTD->isThisDeclarationADefinition(); + return false; +} /// Starting at a given context (a Decl or DeclContext), look for a /// code context that is not a closure (a lambda, block, etc.). -- cgit v1.2.3