[PATCH] Sema: Implement DR317
David Majnemer
david.majnemer at gmail.com
Sat Mar 29 22:37:09 PDT 2014
Hi rsmith,
Declaring a function as inline after it has been defined is in violation
of [dcl.fct.spec]p4. The programm would get a strong definition instead
of getting a function with linkonce_odr linkage.
http://llvm-reviews.chandlerc.com/D3220
Files:
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDeclCXX.cpp
test/CXX/drs/dr3xx.cpp
test/Parser/cxx-friend.cpp
test/SemaTemplate/inject-templated-friend-post.cpp
test/SemaTemplate/inject-templated-friend.cpp
www/cxx_dr_status.html
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -3714,6 +3714,8 @@
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<
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -584,14 +584,22 @@
}
}
+ 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.
if (New->isConstexpr() != Old->isConstexpr()) {
Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch)
<< New << New->isConstexpr();
Diag(Old->getLocation(), diag::note_previous_declaration);
Invalid = true;
+ } else if (!Old->isInlined() && Old->isDefined(Def) && New->isInlined()) {
+ // 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
Index: test/CXX/drs/dr3xx.cpp
===================================================================
--- test/CXX/drs/dr3xx.cpp
+++ test/CXX/drs/dr3xx.cpp
@@ -192,18 +192,18 @@
// dr315: na
// dr316: sup 1004
-namespace dr317 { // dr317: no
- void f() {}
- inline void f(); // FIXME: ill-formed
+namespace dr317 { // dr317: yes
+ void f() {} // expected-note {{previous}}
+ inline void f(); // expected-error {{inline declaration of 'f' follows non-inline definition}}
int g();
int n = g();
inline int g() { return 0; }
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
Index: test/Parser/cxx-friend.cpp
===================================================================
--- test/Parser/cxx-friend.cpp
+++ test/Parser/cxx-friend.cpp
@@ -30,7 +30,7 @@
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'}}
};
Index: test/SemaTemplate/inject-templated-friend-post.cpp
===================================================================
--- test/SemaTemplate/inject-templated-friend-post.cpp
+++ test/SemaTemplate/inject-templated-friend-post.cpp
@@ -24,7 +24,7 @@
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)
{
Index: test/SemaTemplate/inject-templated-friend.cpp
===================================================================
--- test/SemaTemplate/inject-templated-friend.cpp
+++ test/SemaTemplate/inject-templated-friend.cpp
@@ -29,7 +29,7 @@
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}}
{
Index: www/cxx_dr_status.html
===================================================================
--- www/cxx_dr_status.html
+++ www/cxx_dr_status.html
@@ -1943,7 +1943,7 @@
<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="full" align="center">Yes</td>
</tr>
<tr id="318">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#318">318</a></td>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3220.1.patch
Type: text/x-patch
Size: 4592 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140329/742fcf08/attachment.bin>
More information about the cfe-commits
mailing list