summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Sema/Sema.h2
-rw-r--r--clang/lib/Sema/SemaDecl.cpp40
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp2
-rw-r--r--clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp26
-rw-r--r--clang/test/CXX/drs/dr1xx.cpp4
-rw-r--r--clang/test/Modules/linkage-merge.cpp5
-rw-r--r--clang/www/cxx_dr_status.html2
7 files changed, 55 insertions, 26 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index c98b10134b5..aa6d2246aed 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -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);
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 995898aea48..8b750812d9c 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2268,8 +2268,8 @@ static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {
/// 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(FunctionDecl *New, Decl *OldD, Scope *S,
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.
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index fbaf5115b61..a16c843780d 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7252,7 +7252,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
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
diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
index c7966ce643f..00edee690dc 100644
--- a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
+++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp
@@ -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}}
+}
diff --git a/clang/test/CXX/drs/dr1xx.cpp b/clang/test/CXX/drs/dr1xx.cpp
index f65638561f3..21e8abc6832 100644
--- a/clang/test/CXX/drs/dr1xx.cpp
+++ b/clang/test/CXX/drs/dr1xx.cpp
@@ -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
diff --git a/clang/test/Modules/linkage-merge.cpp b/clang/test/Modules/linkage-merge.cpp
index 9cc9ae64bf9..664716d3bed 100644
--- a/clang/test/Modules/linkage-merge.cpp
+++ b/clang/test/Modules/linkage-merge.cpp
@@ -7,6 +7,5 @@ static int f(int);
int f(int);
static void g(int);
-// expected-error@-1 {{declaration conflicts with target of using declaration already in scope}}
-// expected-note@Inputs/linkage-merge-foo.h:2 {{target of using declaration}}
-// expected-note@Inputs/linkage-merge-bar.h:3 {{using declaration}}
+// expected-error@-1 {{functions that differ only in their return type cannot be overloaded}}
+// expected-note@Inputs/linkage-merge-foo.h:2 {{previous declaration is here}}
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 3600c7335c7..ace581cdf92 100644
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -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>
OpenPOWER on IntegriCloud