r205129 - Sema: Implement DR317

David Majnemer david.majnemer at gmail.com
Sat Mar 29 23:44:54 PDT 2014


Author: majnemer
Date: Sun Mar 30 01:44:54 2014
New Revision: 205129

URL: http://llvm.org/viewvc/llvm-project?rev=205129&view=rev
Log:
Sema: Implement DR317

Summary:
Declaring a function as inline after it has been defined is in violation
of [dcl.fct.spec]p4.  The program would get a strong definition instead
of getting a function with linkonce_odr linkage.

Reviewers: rsmith

CC: cfe-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D3220

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CXX/drs/dr3xx.cpp
    cfe/trunk/test/Parser/cxx-friend.cpp
    cfe/trunk/test/SemaTemplate/inject-templated-friend-post.cpp
    cfe/trunk/test/SemaTemplate/inject-templated-friend.cpp
    cfe/trunk/www/cxx_dr_status.html

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=205129&r1=205128&r2=205129&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Mar 30 01:44:54 2014
@@ -3714,6 +3714,8 @@ def warn_redefinition_of_typedef : ExtWa
 def err_redefinition_variably_modified_typedef : Error<
   "redefinition of %select{typedef|type alias}0 for variably-modified type %1">;
 
+def err_inline_decl_follows_def : Error<
+  "inline declaration of %0 follows non-inline definition">;
 def err_inline_declaration_block_scope : Error<
   "inline declaration of %0 not allowed in block scope">;
 def err_static_non_static : Error<

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=205129&r1=205128&r2=205129&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Mar 30 01:44:54 2014
@@ -584,6 +584,7 @@ bool Sema::MergeCXXFunctionDecl(Function
     }
   }
 
+  const FunctionDecl *Def;
   // C++11 [dcl.constexpr]p1: If any declaration of a function or function
   // template has a constexpr specifier then all its declarations shall
   // contain the constexpr specifier.
@@ -592,6 +593,13 @@ bool Sema::MergeCXXFunctionDecl(Function
       << New << New->isConstexpr();
     Diag(Old->getLocation(), diag::note_previous_declaration);
     Invalid = true;
+  } else if (!Old->isInlined() && New->isInlined() && Old->isDefined(Def)) {
+    // 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.
+    Diag(New->getLocation(), diag::err_inline_decl_follows_def) << New;
+    Diag(Def->getLocation(), diag::note_previous_definition);
+    Invalid = true;
   }
 
   // C++11 [dcl.fct.default]p4: If a friend declaration specifies a default

Modified: cfe/trunk/test/CXX/drs/dr3xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr3xx.cpp?rev=205129&r1=205128&r2=205129&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr3xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr3xx.cpp Sun Mar 30 01:44:54 2014
@@ -192,9 +192,9 @@ namespace dr314 { // dr314: dup 1710
 // dr315: na
 // dr316: sup 1004
 
-namespace dr317 { // dr317: no
-  void f() {}
-  inline void f(); // FIXME: ill-formed
+namespace dr317 { // dr317: 3.5
+  void f() {} // expected-note {{previous}}
+  inline void f(); // expected-error {{inline declaration of 'f' follows non-inline definition}}
 
   int g();
   int n = g();
@@ -202,8 +202,8 @@ namespace dr317 { // dr317: no
 
   int h();
   int m = h();
-  int h() { return 0; }
-  inline int h(); // FIXME: ill-formed
+  int h() { return 0; } // expected-note {{previous}}
+  inline int h(); // expected-error {{inline declaration of 'h' follows non-inline definition}}
 }
 
 namespace dr318 { // dr318: sup 1310

Modified: cfe/trunk/test/Parser/cxx-friend.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-friend.cpp?rev=205129&r1=205128&r2=205129&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx-friend.cpp (original)
+++ cfe/trunk/test/Parser/cxx-friend.cpp Sun Mar 30 01:44:54 2014
@@ -30,7 +30,7 @@ class B {
   void f(A *a) { a->f(); }
 };
 
-void bar() {} // expected-note {{previous definition is here}}
+inline void bar() {} // expected-note {{previous definition is here}}
 class E {
   friend void bar() {} // expected-error {{redefinition of 'bar'}}
 };

Modified: cfe/trunk/test/SemaTemplate/inject-templated-friend-post.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/inject-templated-friend-post.cpp?rev=205129&r1=205128&r2=205129&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/inject-templated-friend-post.cpp (original)
+++ cfe/trunk/test/SemaTemplate/inject-templated-friend-post.cpp Sun Mar 30 01:44:54 2014
@@ -24,7 +24,7 @@ struct Streamer;
 
 typedef struct Foo {} Foo;
 
-std_ostream& operator << (std_ostream&, const Streamer<Foo>&);
+inline std_ostream& operator << (std_ostream&, const Streamer<Foo>&);
 
 void test(const Streamer<Foo>& foo)
 {

Modified: cfe/trunk/test/SemaTemplate/inject-templated-friend.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/inject-templated-friend.cpp?rev=205129&r1=205128&r2=205129&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/inject-templated-friend.cpp (original)
+++ cfe/trunk/test/SemaTemplate/inject-templated-friend.cpp Sun Mar 30 01:44:54 2014
@@ -29,7 +29,7 @@ struct Streamer
 
 typedef struct Foo {} Foo;
 
-std_ostream& operator << (std_ostream&, const Streamer<Foo>&);
+inline std_ostream& operator << (std_ostream&, const Streamer<Foo>&);
 #ifdef REDEFINE
 std_ostream& operator << (std_ostream& o, const Streamer<Foo>&) // expected-note{{is here}}
 {

Modified: cfe/trunk/www/cxx_dr_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_status.html?rev=205129&r1=205128&r2=205129&view=diff
==============================================================================
--- cfe/trunk/www/cxx_dr_status.html (original)
+++ cfe/trunk/www/cxx_dr_status.html Sun Mar 30 01:44:54 2014
@@ -1943,7 +1943,7 @@ of class templates</td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#317">317</a></td>
     <td>CD1</td>
     <td>Can a function be declared inline after it has been called?</td>
-    <td class="none" align="center">No</td>
+    <td class="svn" align="center">SVN</td>
   </tr>
   <tr id="318">
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#318">318</a></td>





More information about the cfe-commits mailing list