From 05ce1d3944394be8bba20d50c8da77ff3a1b657e Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 1 Mar 2018 22:20:13 +0000 Subject: [PATCH] [modules] Don't diagnose "redefinition" of a friend with a pending definition if the other definition is a merged copy of the same function. llvm-svn: 326496 --- clang/lib/Sema/SemaDecl.cpp | 9 ++++++++ clang/test/Modules/friend-definition.cpp | 39 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 clang/test/Modules/friend-definition.cpp diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 62fd020..b358b04 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12303,6 +12303,15 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD, if (I != FD && !I->isInvalidDecl() && I->getFriendObjectKind() != Decl::FOK_None) { if (FunctionDecl *Original = I->getInstantiatedFromMemberFunction()) { + if (FunctionDecl *OrigFD = FD->getInstantiatedFromMemberFunction()) { + // A merged copy of the same function, instantiated as a member of + // the same class, is OK. + if (declaresSameEntity(OrigFD, Original) && + declaresSameEntity(cast(I->getLexicalDeclContext()), + cast(FD->getLexicalDeclContext()))) + continue; + } + if (Original->isThisDeclarationADefinition()) { Definition = I; break; diff --git a/clang/test/Modules/friend-definition.cpp b/clang/test/Modules/friend-definition.cpp new file mode 100644 index 0000000..8588cbd --- /dev/null +++ b/clang/test/Modules/friend-definition.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fmodules -std=c++14 %s -verify +// expected-no-diagnostics + +#pragma clang module build A +module A {} +#pragma clang module contents +#pragma clang module begin A +template struct A { + friend A operator+(const A&, const A&) { return {}; } +}; +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module build B +module B {} +#pragma clang module contents +#pragma clang module begin B +#pragma clang module import A +inline void f() { A a; } +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module build C +module C {} +#pragma clang module contents +#pragma clang module begin C +#pragma clang module import A +inline void g() { A a; } +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module import A +#pragma clang module import B +#pragma clang module import C + +void h() { + A a; + a + a; +} -- 2.7.4