From 41ce66f8e20159d8bd39fff54ae01608da06c294 Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 10 Dec 2009 19:51:03 +0000 Subject: [PATCH] Improve the diagnostic when a new declaration conflicts with a using shadow declaration. Rename note_using_decl to note_using, which is possibly less confusing. Add a test for non-class-scope using decl collisions and be sure to note the case we can't diagnose yet. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91057 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticCommonKinds.td | 4 +- include/clang/Basic/DiagnosticSemaKinds.td | 7 +- lib/Sema/SemaDecl.cpp | 9 ++ lib/Sema/SemaDeclCXX.cpp | 17 ++-- lib/Sema/SemaDeclObjC.cpp | 8 +- .../basic.namespace/namespace.udecl/p11.cpp | 89 +++++++++++++++++++ 6 files changed, 113 insertions(+), 21 deletions(-) create mode 100644 test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 9a342b592c..f319cf231a 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -26,8 +26,8 @@ def note_type_being_defined : Note< /// e.g. to specify the '(' when we expected a ')'. def note_matching : Note<"to match this '%0'">; -def note_using_decl : Note<"using">; -def note_also_found_decl : Note<"also found">; +def note_using : Note<"using">; +def note_also_found : Note<"also found">; // Parse && Lex def err_expected_colon : Error<"expected ':'">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a35fd58cfa..8739890c9a 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -124,10 +124,11 @@ def err_using_decl_template_id : Error< def note_using_decl_target : Note<"target of using declaration">; def note_using_decl_conflict : Note<"conflicting declaration">; def err_using_decl_redeclaration : Error<"redeclaration of using decl">; -def note_previous_using_decl : Note<"previous using decl">; def err_using_decl_conflict : Error< - "%select{function|non-function}0 target of using declaration conflicts " - "with %select{function|non-function}1 declaration already in scope">; + "target of using declaration conflicts with declaration already in scope">; +def err_using_decl_conflict_reverse : Error< + "declaration conflicts with target of using declaration already in scope">; +def note_using_decl : Note<"%select{|previous }0using declaration">; def err_invalid_thread : Error< "'__thread' is only allowed on variable declarations">; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a171217073..6574ad2e87 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -803,6 +803,15 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { else Old = dyn_cast(OldD); if (!Old) { + if (UsingShadowDecl *Shadow = dyn_cast(OldD)) { + 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; + } + Diag(New->getLocation(), diag::err_redefinition_different_kind) << New->getDeclName(); Diag(OldD->getLocation(), diag::note_previous_definition); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index f97b763745..70ee24c68e 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2995,9 +2995,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, return false; case Ovl_NonFunction: - Diag(Using->getLocation(), diag::err_using_decl_conflict) - << 0 // target decl is a function - << 1; // other decl is not a function + Diag(Using->getLocation(), diag::err_using_decl_conflict); break; // We found a decl with the exact signature. @@ -3014,9 +3012,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, return true; // If we're not in a record, this is an error. - Diag(Using->getLocation(), diag::err_using_decl_conflict) - << 0 // target decl is a function - << 0; // other decl is a function + Diag(Using->getLocation(), diag::err_using_decl_conflict); break; } @@ -3043,8 +3039,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, // No conflict between a tag and a non-tag. if (!Tag) return false; - Diag(Using->getLocation(), diag::err_using_decl_conflict) - << 1 << 1; // both non-functions + Diag(Using->getLocation(), diag::err_using_decl_conflict); Diag(Target->getLocation(), diag::note_using_decl_target); Diag(Tag->getLocation(), diag::note_using_decl_conflict); return true; @@ -3053,9 +3048,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, // No conflict between a tag and a non-tag. if (!NonTag) return false; - Diag(Using->getLocation(), diag::err_using_decl_conflict) - << 1 // target not a function - << int(NonTag->isFunctionOrFunctionTemplate()); + Diag(Using->getLocation(), diag::err_using_decl_conflict); Diag(Target->getLocation(), diag::note_using_decl_target); Diag(NonTag->getLocation(), diag::note_using_decl_conflict); return true; @@ -3335,7 +3328,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, continue; Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange(); - Diag(D->getLocation(), diag::note_previous_using_decl); + Diag(D->getLocation(), diag::note_using_decl) << 1; return true; } diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 7f46d2c438..a768e1bdf7 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1349,10 +1349,10 @@ ObjCMethodDecl *Sema::LookupInstanceMethodInGlobalPool(Selector Sel, } if (issueWarning && (MethList.Method && MethList.Next)) { Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; - Diag(MethList.Method->getLocStart(), diag::note_using_decl) + Diag(MethList.Method->getLocStart(), diag::note_using) << MethList.Method->getSourceRange(); for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) - Diag(Next->Method->getLocStart(), diag::note_also_found_decl) + Diag(Next->Method->getLocStart(), diag::note_also_found) << Next->Method->getSourceRange(); } return MethList.Method; @@ -1413,10 +1413,10 @@ ObjCMethodDecl *Sema::LookupFactoryMethodInGlobalPool(Selector Sel, } if (issueWarning && (MethList.Method && MethList.Next)) { Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; - Diag(MethList.Method->getLocStart(), diag::note_using_decl) + Diag(MethList.Method->getLocStart(), diag::note_using) << MethList.Method->getSourceRange(); for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) - Diag(Next->Method->getLocStart(), diag::note_also_found_decl) + Diag(Next->Method->getLocStart(), diag::note_also_found) << Next->Method->getSourceRange(); } return MethList.Method; diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp new file mode 100644 index 0000000000..ce6221216a --- /dev/null +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp @@ -0,0 +1,89 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// C++03 [namespace.udecl]p11: +// 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. + +namespace test0 { + namespace ns { void foo(); } // expected-note {{target of using declaration}} + int foo(); // expected-note {{conflicting declaration}} + using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} +} + +namespace test1 { + namespace ns { void foo(); } // expected-note {{target of using declaration}} + using ns::foo; //expected-note {{using declaration}} + int foo(); // expected-error {{declaration conflicts with target of using declaration already in scope}} +} + +namespace test2 { + namespace ns { void foo(); } // expected-note 2 {{target of using declaration}} + void test0() { + int foo(); // expected-note {{conflicting declaration}} + using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} + } + + void test1() { + using ns::foo; //expected-note {{using declaration}} + int foo(); // expected-error {{declaration conflicts with target of using declaration already in scope}} + } +} + +namespace test3 { + namespace ns { void foo(); } // expected-note 2 {{target of using declaration}} + class Test0 { + void test() { + int foo(); // expected-note {{conflicting declaration}} + using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} + } + }; + + class Test1 { + void test() { + using ns::foo; //expected-note {{using declaration}} + int foo(); // expected-error {{declaration conflicts with target of using declaration already in scope}} + } + }; +} + +namespace test4 { + namespace ns { void foo(); } // expected-note 2 {{target of using declaration}} + template class Test0 { + void test() { + int foo(); // expected-note {{conflicting declaration}} + using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} + } + }; + + template class Test1 { + void test() { + using ns::foo; //expected-note {{using declaration}} + int foo(); // expected-error {{declaration conflicts with target of using declaration already in scope}} + } + }; +} + +// FIXME: we should be able to diagnose these, but we can't. +namespace test5 { + namespace ns { void foo(int); } + template class Test0 { + void test() { + int foo(T); + using ns::foo; + } + }; + + template class Test1 { + void test() { + using ns::foo; + int foo(T); + } + }; +} + -- 2.40.0