r200897 - DR101, PR12770: If a function is declared in the same context as a

Richard Smith richard-llvm at metafoo.co.uk
Wed Feb 5 17:31:34 PST 2014


Author: rsmith
Date: Wed Feb  5 19:31:33 2014
New Revision: 200897

URL: http://llvm.org/viewvc/llvm-project?rev=200897&view=rev
Log:
DR101, PR12770: If a function is declared in the same context as a
using-declaration, and they declare the same function (either because
the using-declaration is in the same namespace as the declaration it
imports, or because they're both extern "C"), they do not conflict.

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
    cfe/trunk/test/CXX/drs/dr1xx.cpp
    cfe/trunk/test/Modules/linkage-merge.cpp
    cfe/trunk/www/cxx_dr_status.html

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=200897&r1=200896&r2=200897&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Feb  5 19:31:33 2014
@@ -1889,7 +1889,7 @@ public:
   void mergeDeclAttributes(NamedDecl *New, Decl *Old,
                            AvailabilityMergeKind AMK = AMK_Redeclaration);
   void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls);
-  bool MergeFunctionDecl(FunctionDecl *New, Decl *Old, Scope *S,
+  bool MergeFunctionDecl(FunctionDecl *New, NamedDecl *&Old, Scope *S,
                          bool MergeTypeWithOld);
   bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
                                     Scope *S, bool MergeTypeWithOld);

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=200897&r1=200896&r2=200897&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Feb  5 19:31:33 2014
@@ -2268,8 +2268,8 @@ static bool haveIncompatibleLanguageLink
 /// merged with.
 ///
 /// Returns true if there was an error, false otherwise.
-bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
-                             bool MergeTypeWithOld) {
+bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
+                             Scope *S, bool MergeTypeWithOld) {
   // Verify the old decl was also a function.
   FunctionDecl *Old = OldD->getAsFunction();
   if (!Old) {
@@ -2283,18 +2283,34 @@ bool Sema::MergeFunctionDecl(FunctionDec
         return true;
       }
 
-      Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
-      Diag(Shadow->getTargetDecl()->getLocation(),
-           diag::note_using_decl_target);
-      Diag(Shadow->getUsingDecl()->getLocation(),
-           diag::note_using_decl) << 0;
+      // C++11 [namespace.udecl]p14:
+      //   If a function declaration in namespace scope or block scope has the
+      //   same name and the same parameter-type-list as a function introduced
+      //   by a using-declaration, and the declarations do not declare the same
+      //   function, the program is ill-formed.
+
+      // Check whether the two declarations might declare the same function.
+      Old = dyn_cast<FunctionDecl>(Shadow->getTargetDecl());
+      if (Old &&
+          !Old->getDeclContext()->getRedeclContext()->Equals(
+              New->getDeclContext()->getRedeclContext()) &&
+          !(Old->isExternC() && New->isExternC()))
+        Old = 0;
+
+      if (!Old) {
+        Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
+        Diag(Shadow->getTargetDecl()->getLocation(),
+             diag::note_using_decl_target);
+        Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl) << 0;
+        return true;
+      }
+      OldD = Old;
+    } else {
+      Diag(New->getLocation(), diag::err_redefinition_different_kind)
+        << New->getDeclName();
+      Diag(OldD->getLocation(), diag::note_previous_definition);
       return true;
     }
-
-    Diag(New->getLocation(), diag::err_redefinition_different_kind)
-      << New->getDeclName();
-    Diag(OldD->getLocation(), diag::note_previous_definition);
-    return true;
   }
 
   // If the old declaration is invalid, just give up here.

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=200897&r1=200896&r2=200897&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Feb  5 19:31:33 2014
@@ -7252,7 +7252,7 @@ bool Sema::CheckUsingShadowDecl(UsingDec
     case Ovl_NonFunction:
       Diag(Using->getLocation(), diag::err_using_decl_conflict);
       break;
-      
+
     // We found a decl with the exact signature.
     case Ovl_Match:
       // If we're in a record, we want to hide the target, so we

Modified: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp?rev=200897&r1=200896&r2=200897&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp Wed Feb  5 19:31:33 2014
@@ -1,14 +1,16 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
-// C++03 [namespace.udecl]p11:
+// C++03 [namespace.udecl]p11: (per DR101)
 //   If a function declaration in namespace scope or block scope has
 //   the same name and the same parameter types as a function
-//   introduced by a using-declaration, the program is
-//   ill-formed. [Note: two using-declarations may introduce functions
-//   with the same name and the same parameter types. If, for a call
-//   to an unqualified function name, function overload resolution
-//   selects the functions introduced by such using-declarations, the
-//   function call is ill-formed.
+//   introduced by a using-declaration, and the declarations do not declare the
+//   same function, the program is ill-formed. [Note: two using-declarations may
+//   introduce functions with the same name and the same parameter types. If,
+//   for a call to an unqualified function name, function overload resolution
+//   selects the functions introduced by such using-declarations, the function
+//   call is ill-formed.]
+//
+// FIXME: DR565 introduces parallel wording here for function templates.
 
 namespace test0 {
   namespace ns { void foo(); } // expected-note {{target of using declaration}}
@@ -89,3 +91,13 @@ namespace test5 {
   template class Test0<int>;
   template class Test1<int>;
 }
+
+namespace test6 {
+  namespace ns { void foo(); } // expected-note {{target of using declaration}}
+  using ns::foo; // expected-note {{using declaration}}
+  namespace ns {
+    using test6::foo;
+    void foo() {}
+  }
+  void foo(); // expected-error {{declaration conflicts with target of using declaration already in scope}}
+}

Modified: cfe/trunk/test/CXX/drs/dr1xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr1xx.cpp?rev=200897&r1=200896&r2=200897&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr1xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr1xx.cpp Wed Feb  5 19:31:33 2014
@@ -9,7 +9,7 @@ namespace dr100 { // dr100: yes
   B<"bar"> b; // expected-error {{does not refer to any declaration}}
 }
 
-namespace dr101 { // dr101: yes
+namespace dr101 { // dr101: 3.5
   extern "C" void dr101_f();
   typedef unsigned size_t;
   namespace X {
@@ -18,6 +18,8 @@ namespace dr101 { // dr101: yes
   }
   using X::dr101_f;
   using X::size_t;
+  extern "C" void dr101_f();
+  typedef unsigned size_t;
 }
 
 namespace dr102 { // dr102: yes

Modified: cfe/trunk/test/Modules/linkage-merge.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/linkage-merge.cpp?rev=200897&r1=200896&r2=200897&view=diff
==============================================================================
--- cfe/trunk/test/Modules/linkage-merge.cpp (original)
+++ cfe/trunk/test/Modules/linkage-merge.cpp Wed Feb  5 19:31:33 2014
@@ -7,6 +7,5 @@ static int f(int);
 int f(int);
 
 static void g(int);
-// expected-error at -1 {{declaration conflicts with target of using declaration already in scope}}
-// expected-note at Inputs/linkage-merge-foo.h:2 {{target of using declaration}}
-// expected-note at Inputs/linkage-merge-bar.h:3 {{using declaration}}
+// expected-error at -1 {{functions that differ only in their return type cannot be overloaded}}
+// expected-note at Inputs/linkage-merge-foo.h:2 {{previous declaration 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=200897&r1=200896&r2=200897&view=diff
==============================================================================
--- cfe/trunk/www/cxx_dr_status.html (original)
+++ cfe/trunk/www/cxx_dr_status.html Wed Feb  5 19:31:33 2014
@@ -645,7 +645,7 @@
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#101">101</a></td>
     <td>TC1</td>
     <td>Redeclaration of extern "C" names via using-declarations</td>
-    <td class="full" align="center">Yes</td>
+    <td class="svn" align="center">SVN</td>
   </tr>
   <tr>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#102">102</a></td>





More information about the cfe-commits mailing list