r184889 - Implement DR136

David Majnemer david.majnemer at gmail.com
Tue Jun 25 16:09:30 PDT 2013


Author: majnemer
Date: Tue Jun 25 18:09:30 2013
New Revision: 184889

URL: http://llvm.org/viewvc/llvm-project?rev=184889&view=rev
Log:
Implement DR136

Friend declarations that specify a default argument must be a definition
and the only declaration in the translation unit.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CXX/drs/dr1xx.cpp
    cfe/trunk/test/CodeGenCXX/2004-11-27-FriendDefaultArgCrash.cpp
    cfe/trunk/test/SemaCXX/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=184889&r1=184888&r2=184889&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jun 25 18:09:30 2013
@@ -4270,6 +4270,10 @@ def err_member_def_undefined_record : Er
   "out-of-line definition of %0 from class %1 without definition">;
 def err_member_def_does_not_match : Error<
   "out-of-line definition of %0 does not match any declaration in %1">;
+def err_friend_decl_with_def_arg_must_be_def : Error<
+  "friend declaration specifying a default argument must be a definition">;
+def err_friend_decl_with_def_arg_redeclared : Error<
+  "friend declaration specifying a default argument must be the only declaration">;
 def err_friend_decl_does_not_match : Error<
   "friend declaration of %0 does not match any declaration in %1">;
 def err_member_def_does_not_match_suggest : Error<

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=184889&r1=184888&r2=184889&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Jun 25 18:09:30 2013
@@ -404,6 +404,17 @@ void Sema::CheckExtraCXXDefaultArguments
   }
 }
 
+static bool functionDeclHasDefaultArgument(const FunctionDecl *FD) {
+  for (unsigned NumParams = FD->getNumParams(); NumParams > 0; --NumParams) {
+    const ParmVarDecl *PVD = FD->getParamDecl(NumParams-1);
+    if (!PVD->hasDefaultArg())
+      return false;
+    if (!PVD->hasInheritedDefaultArg())
+      return true;
+  }
+  return false;
+}
+
 /// MergeCXXFunctionDecl - Merge two declarations of the same C++
 /// function, once we already know that they have the same
 /// type. Subroutine of MergeFunctionDecl. Returns true if there was an
@@ -578,6 +589,17 @@ bool Sema::MergeCXXFunctionDecl(Function
     Invalid = true;
   }
 
+  // C++11 [dcl.fct.default]p4: If a friend declaration specifies a default
+  // argument expression, that declaration shall be a definition and shall be
+  // the only declaration of the function or function template in the
+  // translation unit.
+  if (Old->getFriendObjectKind() == Decl::FOK_Undeclared &&
+      functionDeclHasDefaultArgument(Old)) {
+    Diag(New->getLocation(), diag::err_friend_decl_with_def_arg_redeclared);
+    Diag(Old->getLocation(), diag::note_previous_declaration);
+    Invalid = true;
+  }
+
   if (CheckEquivalentExceptionSpec(Old, New))
     Invalid = true;
 
@@ -11377,6 +11399,18 @@ NamedDecl *Sema::ActOnFriendFunctionDecl
     else
       FD = cast<FunctionDecl>(ND);
 
+    // C++11 [dcl.fct.default]p4: If a friend declaration specifies a
+    // default argument expression, that declaration shall be a definition
+    // and shall be the only declaration of the function or function
+    // template in the translation unit.
+    if (functionDeclHasDefaultArgument(FD)) {
+      if (FunctionDecl *OldFD = FD->getPreviousDecl()) {
+        Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_redeclared);
+        Diag(OldFD->getLocation(), diag::note_previous_declaration);
+      } else if (!D.isFunctionDefinition())
+        Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_must_be_def);
+    }
+
     // Mark templated-scope function declarations as unsupported.
     if (FD->getNumTemplateParameterLists())
       FrD->setUnsupportedFriend(true);

Modified: cfe/trunk/test/CXX/drs/dr1xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr1xx.cpp?rev=184889&r1=184888&r2=184889&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr1xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr1xx.cpp Tue Jun 25 18:09:30 2013
@@ -357,25 +357,39 @@ namespace dr135 { // dr135: yes
   };
 }
 
-namespace dr136 { // dr136: no
-  void f(int, int, int = 0);
-  void g(int, int, int);
+namespace dr136 { // dr136: 3.4
+  void f(int, int, int = 0); // expected-note {{previous declaration is here}}
+  void g(int, int, int); // expected-note {{previous declaration is here}}
   struct A {
-    // FIXME: These declarations of f, g, and h are invalid.
-    friend void f(int, int = 0, int);
-    friend void g(int, int, int = 0);
-    friend void h(int, int, int = 0);
-    friend void i(int, int, int = 0) {}
+    friend void f(int, int = 0, int); // expected-error {{friend declaration specifying a default argument must be the only declaration}}
+    friend void g(int, int, int = 0); // expected-error {{friend declaration specifying a default argument must be the only declaration}}
+    friend void h(int, int, int = 0); // expected-error {{friend declaration specifying a default argument must be a definition}}
+    friend void i(int, int, int = 0) {} // expected-note {{previous declaration is here}}
     friend void j(int, int, int = 0) {}
     operator int();
   };
-  // FIXME: This declaration of i is invalid.
-  void i(int, int, int);
+  void i(int, int, int); // expected-error {{friend declaration specifying a default argument must be the only declaration}}
   void q() {
     j(A(), A()); // ok, has default argument
   }
-  // FIXME: Also test extern "C" friends and default arguments from other
-  // namespaces?
+  extern "C" void k(int, int, int, int); // expected-note {{previous declaration is here}}
+  namespace NSA {
+  struct A {
+    friend void dr136::k(int, int, int, int = 0); // expected-error {{friend declaration specifying a default argument must be the only declaration}} \
+                                                  // expected-note {{previous declaration is here}}
+  };
+  }
+  namespace NSB {
+  struct A {
+    friend void dr136::k(int, int, int = 0, int); // expected-error {{friend declaration specifying a default argument must be the only declaration}}
+  };
+  }
+  struct B {
+    void f(int); // expected-note {{previous declaration is here}}
+  };
+  struct C {
+    friend void B::f(int = 0); // expected-error {{friend declaration specifying a default argument must be the only declaration}}
+  };
 }
 
 namespace dr137 { // dr137: yes

Modified: cfe/trunk/test/CodeGenCXX/2004-11-27-FriendDefaultArgCrash.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/2004-11-27-FriendDefaultArgCrash.cpp?rev=184889&r1=184888&r2=184889&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/2004-11-27-FriendDefaultArgCrash.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/2004-11-27-FriendDefaultArgCrash.cpp Tue Jun 25 18:09:30 2013
@@ -4,6 +4,6 @@
 
 namespace nm {
   struct str {
-    friend int foo(int arg = 0);
+    friend void foo(int arg = 0) {};
   };
 }

Modified: cfe/trunk/test/SemaCXX/friend.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/friend.cpp?rev=184889&r1=184888&r2=184889&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/friend.cpp (original)
+++ cfe/trunk/test/SemaCXX/friend.cpp Tue Jun 25 18:09:30 2013
@@ -44,7 +44,7 @@ namespace test2 {
 // PR5134
 namespace test3 {
   class Foo {
-    friend const int getInt(int inInt = 0);
+    friend const int getInt(int inInt = 0) {}
 
   };
 }

Modified: cfe/trunk/www/cxx_dr_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_status.html?rev=184889&r1=184888&r2=184889&view=diff
==============================================================================
--- cfe/trunk/www/cxx_dr_status.html (original)
+++ cfe/trunk/www/cxx_dr_status.html Tue Jun 25 18:09:30 2013
@@ -854,7 +854,7 @@
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#136">136</a></td>
     <td>CD1</td>
     <td>Default arguments and friend declarations</td>
-    <td class="none" align="center">No</td>
+    <td class="svn" align="center">SVN</td>
   </tr>
   <tr>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#137">137</a></td>





More information about the cfe-commits mailing list