[PATCH] D26065: Improve diagnostics if friend function redefines file-level function.
Serge Pavlov via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 27 23:00:27 PDT 2016
sepavloff created this revision.
sepavloff added a subscriber: cfe-commits.
Clang makes check for function redefinition after it merged the new
declaration with the existing one. As a result, it produces poor
diagnostics in the case of a friend function defined inline, as in
the code:
void func() {}
class C { void func() {} };
Error message in this case states that `inline declaration of 'func'
follows non-inline definition`, which is misleading, as `func` does
not have explicit `inline` specifier.
With this changes compiler reports function redefinition if the new
function is a friend defined inline and it does not have explicit
`inline` specifier.
https://reviews.llvm.org/D26065
Files:
lib/Sema/SemaDeclCXX.cpp
test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp
Index: test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp
===================================================================
--- test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp
@@ -4,3 +4,31 @@
}
inline void f0(); // expected-error {{inline declaration of 'f0' follows non-inline definition}}
+
+void func_01() {} // expected-note{{previous definition is here}}
+struct C01 {
+ friend void func_01() {} // expected-error{{redefinition of 'func_01'}}
+};
+
+void func_02() {} // expected-note{{previous definition is here}}
+struct C02 {
+ friend inline void func_02(); // expected-error{{inline declaration of 'func_02' follows non-inline definition}}
+};
+
+void func_03() {} // expected-note{{previous definition is here}}
+struct C03 {
+ friend inline void func_03() {} // expected-error{{inline declaration of 'func_03' follows non-inline definition}}
+};
+
+void func_04() {} // expected-note{{previous definition is here}}
+inline void func_04() {} // expected-error{{inline declaration of 'func_04' follows non-inline definition}}
+
+void func_06() {} // expected-note{{previous definition is here}}
+template<typename T> struct C06 {
+ friend inline void func_06() {} // expected-error{{inline declaration of 'func_06' follows non-inline definition}}
+};
+
+void func_07() {} // expected-note{{previous definition is here}}
+template<typename T> struct C07 {
+ friend inline void func_07(); // expected-error{{inline declaration of 'func_07' follows non-inline definition}}
+};
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -639,7 +639,12 @@
Diag(Old->getLocation(), diag::note_previous_declaration);
Invalid = true;
} else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() &&
- Old->isDefined(Def)) {
+ Old->isDefined(Def) &&
+ // If a friend function is inlined but does not have 'inline'
+ // specifier, it is a definition. Do not report attribute conflict
+ // in this case, redefinition will be diagnosed later.
+ (New->getFriendObjectKind() == Decl::FOK_None ||
+ New->isInlineSpecified())) {
// C++11 [dcl.fcn.spec]p4:
// If the definition of a function appears in a translation unit before its
// first declaration as inline, the program is ill-formed.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D26065.76166.patch
Type: text/x-patch
Size: 2467 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20161028/91fd0a71/attachment.bin>
More information about the cfe-commits
mailing list