diff options
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 40 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 2 | ||||
-rw-r--r-- | clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp | 26 | ||||
-rw-r--r-- | clang/test/CXX/drs/dr1xx.cpp | 4 | ||||
-rw-r--r-- | clang/test/Modules/linkage-merge.cpp | 5 | ||||
-rw-r--r-- | clang/www/cxx_dr_status.html | 2 |
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> |