]> granicus.if.org Git - clang/commitdiff
Implement DR482: namespace members can be redeclared with a qualified name
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 5 Dec 2013 07:51:02 +0000 (07:51 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 5 Dec 2013 07:51:02 +0000 (07:51 +0000)
within their namespace, and such a redeclaration isn't required to be a
definition any more.

Update DR status page to say Clang 3.4 instead of SVN and add new Clang 3.5
category (but keep Clang 3.4 yellow for now).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@196481 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
test/CXX/dcl.decl/dcl.meaning/p1.cpp
test/CXX/drs/dr1xx.cpp
test/CXX/drs/dr4xx.cpp
test/CXX/temp/p3.cpp
test/SemaCXX/nested-name-spec.cpp
www/cxx_dr_status.html
www/make_cxx_dr_status

index 4f92d95944ff3cc195bc233d9614a5f15a497040..07c6cbbdffa15239dd3d93d888492ba2a9b20a09 100644 (file)
@@ -4458,6 +4458,9 @@ def warn_member_extra_qualification : Warning<
   "extra qualification on member %0">, InGroup<Microsoft>;
 def err_member_extra_qualification : Error<
   "extra qualification on member %0">;
+def warn_namespace_member_extra_qualification : Warning<
+  "extra qualification on member %0">,
+  InGroup<DiagGroup<"extra-qualification">>;
 def err_member_qualification : Error<
   "non-friend class member %0 cannot have a qualified name">;  
 def note_member_def_close_match : Note<"member declaration nearly matches">;
index 17f19dc2065cafb57a22aaecd80ec716b7fbbf03..451ebd254f31a386c3d7afad8a37fbad6c211045 100644 (file)
@@ -4115,33 +4115,31 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC,
 /// \returns true if we cannot safely recover from this error, false otherwise.
 bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
                                         DeclarationName Name,
-                                      SourceLocation Loc) {
+                                        SourceLocation Loc) {
   DeclContext *Cur = CurContext;
   while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur))
     Cur = Cur->getParent();
-  
-  // C++ [dcl.meaning]p1:
-  //   A declarator-id shall not be qualified except for the definition
-  //   of a member function (9.3) or static data member (9.4) outside of
-  //   its class, the definition or explicit instantiation of a function 
-  //   or variable member of a namespace outside of its namespace, or the
-  //   definition of an explicit specialization outside of its namespace,
-  //   or the declaration of a friend function that is a member of 
-  //   another class or namespace (11.3). [...]
-    
-  // The user provided a superfluous scope specifier that refers back to the
-  // class or namespaces in which the entity is already declared.
+
+  // If the user provided a superfluous scope specifier that refers back to the
+  // class in which the entity is already declared, diagnose and ignore it.
   //
   // class X {
   //   void X::f();
   // };
+  //
+  // Note, it was once ill-formed to give redundant qualification in all
+  // contexts, but that rule was removed by DR482.
   if (Cur->Equals(DC)) {
-    Diag(Loc, LangOpts.MicrosoftExt? diag::warn_member_extra_qualification
-                                   : diag::err_member_extra_qualification)
-      << Name << FixItHint::CreateRemoval(SS.getRange());
-    SS.clear();
+    if (Cur->isRecord()) {
+      Diag(Loc, LangOpts.MicrosoftExt ? diag::warn_member_extra_qualification
+                                      : diag::err_member_extra_qualification)
+        << Name << FixItHint::CreateRemoval(SS.getRange());
+      SS.clear();
+    } else {
+      Diag(Loc, diag::warn_namespace_member_extra_qualification) << Name;
+    }
     return false;
-  } 
+  }
 
   // Check whether the qualifying scope encloses the scope of the original
   // declaration.
@@ -7248,11 +7246,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
         }
       }
 
-    } else if (!D.isFunctionDefinition() && D.getCXXScopeSpec().isSet() &&
+    } else if (!D.isFunctionDefinition() &&
+               isa<CXXMethodDecl>(NewFD) && NewFD->isOutOfLine() &&
                !isFriend && !isFunctionTemplateSpecialization &&
                !isExplicitSpecialization) {
       // An out-of-line member function declaration must also be a
-      // definition (C++ [dcl.meaning]p1).
+      // definition (C++ [class.mfct]p2).
       // Note that this is not the case for explicit specializations of
       // function templates or member functions of class templates, per
       // C++ [temp.expl.spec]p2. We also allow these declarations as an 
index 049126761400b37dd4960c4bf0bfcae0438496e5..162e46ecab1fadaab8e1bda9a1f500768e0cbf17 100644 (file)
@@ -12133,11 +12133,13 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
   // If there is no declaration, there was an error parsing it.
   if (D == 0 || D->isInvalidDecl()) return;
 
-  // We should only get called for declarations with scope specifiers, like:
-  //   int foo::bar;
-  assert(D->isOutOfLine());
-  EnterDeclaratorContext(S, D->getDeclContext());
-  
+  // We will always have a nested name specifier here, but this declaration
+  // might not be out of line if the specifier names the current namespace:
+  //   extern int n;
+  //   int ::n = 0;
+  if (D->isOutOfLine())
+    EnterDeclaratorContext(S, D->getDeclContext());
+
   // If we are parsing the initializer for a static data member, push a
   // new expression evaluation context that is associated with this static
   // data member.
@@ -12152,10 +12154,10 @@ void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) {
   if (D == 0 || D->isInvalidDecl()) return;
 
   if (isStaticDataMember(D))
-    PopExpressionEvaluationContext();  
+    PopExpressionEvaluationContext();
 
-  assert(D->isOutOfLine());
-  ExitDeclaratorContext(S);
+  if (D->isOutOfLine())
+    ExitDeclaratorContext(S);
 }
 
 /// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
index ec9a2611872cad5833b1e87ef616b29dda18a955..5747380f2806d9b9af1f4a8c03d8ddf284ce2214 100644 (file)
@@ -29,9 +29,17 @@ namespace NS {
   template<typename T> void wibble(T);
 }
 namespace NS {
-  void NS::foo() {} // expected-error{{extra qualification on member 'foo'}}
-  int NS::bar; // expected-error{{extra qualification on member 'bar'}}
-  struct NS::X { }; // expected-error{{extra qualification on member 'X'}}
-  template<typename T> struct NS::Y; // expected-error{{extra qualification on member 'Y'}}
-  template<typename T> void NS::wibble(T) { } // expected-error{{extra qualification on member 'wibble'}}
+  // Under DR482, these are all valid, except for forward-declaring a struct
+  // with a nested-name-specifier.
+  void NS::foo(); // expected-warning {{extra qualification}}
+  extern int NS::bar; // expected-warning {{extra qualification}}
+  struct NS::X; // expected-error {{forward declaration of struct cannot have a nested name specifier}} expected-warning {{extra qualification}}
+  template<typename T> struct NS::Y; // expected-error {{forward declaration of struct cannot have a nested name specifier}} expected-warning {{extra qualification}}
+  template<typename T> void NS::wibble(T); // expected-warning {{extra qualification}}
+
+  void NS::foo() {} // expected-warning{{extra qualification on member 'foo'}}
+  int NS::bar; // expected-warning{{extra qualification on member 'bar'}}
+  struct NS::X { }; // expected-warning{{extra qualification on member 'X'}}
+  template<typename T> struct NS::Y { }; // expected-warning{{extra qualification on member 'Y'}}
+  template<typename T> void NS::wibble(T) { } // expected-warning{{extra qualification on member 'wibble'}}
 }
index 7045148034fbfda61c7cc3399ae1f65f29977b0f..f65638561f394a12499f2e952a464b48ef57c253 100644 (file)
@@ -592,11 +592,10 @@ namespace dr155 { // dr155: dup 632
   struct S { int n; } s = { { 1 } }; // expected-warning {{braces around scalar initializer}}
 }
 
-namespace dr159 { // dr159: no
+namespace dr159 { // dr159: 3.5
   namespace X { void f(); }
   void f();
-  // FIXME: This should be accepted.
-  void dr159::f() {} // expected-error {{extra qualification}}
+  void dr159::f() {} // expected-warning {{extra qualification}}
   void dr159::X::f() {}
 }
 
index 1d3b94064cdda3cf701bccfe8e523f7b63b777ac..f295431125e71592d63a705a68faab1cb27ed9cc 100644 (file)
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
 // RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-// expected-no-diagnostics
+// RUN: %clang_cc1 -std=c++1y %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
 
 namespace dr408 { // dr408: 3.4
   template<int N> void g() { int arr[N != 1 ? 1 : -1]; }
@@ -30,3 +30,37 @@ namespace dr408 { // dr408: 3.4
   template<> int R<int>::arr[2];
   template void R<int>::f();
 }
+
+namespace dr482 { // dr482: 3.5
+  extern int a;
+  void f();
+
+  int dr482::a = 0; // expected-warning {{extra qualification}}
+  void dr482::f() {} // expected-warning {{extra qualification}}
+
+  inline namespace X { // expected-error 0-1{{C++11 feature}}
+    extern int b;
+    void g();
+    struct S;
+  }
+  int dr482::b = 0; // expected-warning {{extra qualification}}
+  void dr482::g() {} // expected-warning {{extra qualification}}
+  struct dr482::S {}; // expected-warning {{extra qualification}}
+
+  void dr482::f(); // expected-warning {{extra qualification}}
+  void dr482::g(); // expected-warning {{extra qualification}}
+
+  // FIXME: The following are valid in DR482's wording, but these are bugs in
+  // the wording which we deliberately don't implement.
+  namespace N { typedef int type; }
+  typedef int N::type; // expected-error {{typedef declarator cannot be qualified}}
+  struct A {
+    struct B;
+    struct A::B {}; // expected-error {{extra qualification}}
+
+#if __cplusplus >= 201103L
+    enum class C;
+    enum class A::C {}; // expected-error {{extra qualification}}
+#endif
+  };
+}
index 11f72de918cb9557c9e31a6c4c04dcc7c9383763..e9fd8a3090e860c1db1479689cefee1ba2c4be86 100644 (file)
@@ -8,7 +8,8 @@ template<typename T> int S<T>::a, S<T>::b; // expected-error {{can only declare
 
 template<typename T> struct A { static A a; } A<T>::a; // expected-error {{expected ';' after struct}} \
                                                           expected-error {{use of undeclared identifier 'T'}} \
-                                                          expected-error{{extra qualification}}
+                                                          expected-error {{no member named 'a'}} \
+                                                          expected-warning {{extra qualification}}
 
 template<typename T> struct B { } f(); // expected-error {{expected ';' after struct}} \
                                           expected-error {{requires a type specifier}}
index df4f1b269d70ab7e3f77b464536ae90f84ab266f..f1f9bbb507f4add474c1365e069caa58a867e1e6 100644 (file)
@@ -160,7 +160,7 @@ namespace N {
   void f();
   // FIXME: if we move this to a separate definition of N, things break!
 }
-void ::global_func2(int) { } // expected-error{{extra qualification on member 'global_func2'}}
+void ::global_func2(int) { } // expected-warning{{extra qualification on member 'global_func2'}}
 
 void N::f() { } // okay
 
index a360ace7fe1f5be4d077e5791ff47808842e7110..c9f95a18bb3b537ea084968a260fde6628ca9c10 100644 (file)
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#29">29</a></td>
     <td>CD1</td>
     <td>Linkage of locally declared functions</td>
-    <td class="svn" align="center">SVN</td>
+    <td class="svn" align="center">Clang 3.4</td>
   </tr>
   <tr>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#30">30</a></td>
   <tr>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#81">81</a></td>
     <td>NAD</td>
-    <td>Null pointers and C compatibility</td>
+    <td>Null pointers and C compatability</td>
     <td class="na" align="center">N/A</td>
   </tr>
   <tr>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#136">136</a></td>
     <td>CD1</td>
     <td>Default arguments and friend declarations</td>
-    <td class="svn" align="center">SVN</td>
+    <td class="svn" align="center">Clang 3.4</td>
   </tr>
   <tr>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#137">137</a></td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#159">159</a></td>
     <td>TC1</td>
     <td>Namespace qualification in declarators</td>
-    <td class="none" align="center">No</td>
+    <td class="svn" align="center">SVN</td>
   </tr>
   <tr>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#160">160</a></td>
@@ -2488,7 +2488,7 @@ of class templates</td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#408">408</a></td>
     <td>CD2</td>
     <td>sizeof applied to unknown-bound array static data member of template</td>
-    <td class="svn" align="center">SVN</td>
+    <td class="svn" align="center">Clang 3.4</td>
   </tr>
   <tr>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#409">409</a></td>
@@ -2932,7 +2932,7 @@ of class templates</td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#482">482</a></td>
     <td>DRWP</td>
     <td>Qualified declarators in redeclarations</td>
-    <td class="none" align="center">Unknown</td>
+    <td class="svn" align="center">SVN</td>
   </tr>
   <tr>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#483">483</a></td>
@@ -8159,7 +8159,7 @@ and <I>POD class</I></td>
   <tr class="open">
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1391">1391</a></td>
     <td>drafting</td>
-    <td>Conversions to parameter types with non-deduced template arguments</td>
+    <td>Conversions to parameter types with non deduced template arguments</td>
     <td align="center">Not resolved</td>
   </tr>
   <tr>
index 4750e1b2cbb05350f223b7dfdcdf7096470005aa..54f3b7e208e7026f306dc0d0e7a2ea7d4bcc5cdb 100755 (executable)
@@ -101,9 +101,12 @@ def availability(issue):
   if status == 'unknown':
     avail = 'Unknown'
     avail_style = ' class="none"'
-  elif status == '3.4':
+  elif status == '3.5':
     avail = 'SVN'
     avail_style = ' class="svn"'
+  elif status == '3.4':
+    avail = 'Clang %s' % status
+    avail_style = ' class="svn"'
   elif status in ('3.1', '3.2', '3.3'):
     avail = 'Clang %s' % status
     avail_style = ' class="full"'