sepavloff updated this revision to Diff 101666.
sepavloff added a comment.

Rebased and enhance check


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
@@ -638,7 +638,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->isInlineSpecified() ||
+              New->getFriendObjectKind() == Decl::FOK_None)) {
     // 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.


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
@@ -638,7 +638,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->isInlineSpecified() ||
+              New->getFriendObjectKind() == Decl::FOK_None)) {
     // 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.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to