]> granicus.if.org Git - clang/commitdiff
Improve the diagnostic when a new declaration conflicts with a using shadow
authorJohn McCall <rjmccall@apple.com>
Thu, 10 Dec 2009 19:51:03 +0000 (19:51 +0000)
committerJohn McCall <rjmccall@apple.com>
Thu, 10 Dec 2009 19:51:03 +0000 (19:51 +0000)
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
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaDeclObjC.cpp
test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp [new file with mode: 0644]

index 9a342b592ca54c033a19800290f9a25c79a58d2a..f319cf231a268dff14d52e09b4db00adb9a9fd3c 100644 (file)
@@ -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 ':'">;
index a35fd58cfa0c480073cb041a8abbdc738a834587..8739890c9ace3ea70467101cd6f8add95b75363e 100644 (file)
@@ -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">;
index a171217073ec864eb7f4bd70b90e995764866845..6574ad2e87d4923127781878fcee272a11a6bf0c 100644 (file)
@@ -803,6 +803,15 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
   else
     Old = dyn_cast<FunctionDecl>(OldD);
   if (!Old) {
+    if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(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);
index f97b7637451cf7ace4dabb49d9b31d2779d3715b..70ee24c68e8fab1f2a9393b6bc3c8627b915c6d3 100644 (file)
@@ -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;
   }
 
index 7f46d2c4384024f8d797d46a574a54482cbd1811..a768e1bdf7819ccd967a70736fb4fbf098dd4bca 100644 (file)
@@ -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 (file)
index 0000000..ce62212
--- /dev/null
@@ -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 <typename> 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 <typename> 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 <typename T> class Test0 {
+    void test() {
+      int foo(T);
+      using ns::foo;
+    }
+  };
+
+  template <typename T> class Test1 {
+    void test() {
+      using ns::foo;
+      int foo(T);
+    }
+  };
+}
+