r298126 - Implement DR 373 "Lookup on namespace qualified name in using-directive"

Matthias Gehre via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 17 14:41:20 PDT 2017


Author: mgehre
Date: Fri Mar 17 16:41:20 2017
New Revision: 298126

URL: http://llvm.org/viewvc/llvm-project?rev=298126&view=rev
Log:
Implement DR 373 "Lookup on namespace qualified name in using-directive"

Summary:
3.4.6 [basic.lookup.udir] paragraph 1:
In a using-directive or namespace-alias-definition, during the lookup for a namespace-name or for a name in a nested-name-specifier, only namespace names are considered.

Reviewers: rsmith, aaron.ballman

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D30848

Modified:
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
    cfe/trunk/test/CXX/drs/dr3xx.cpp
    cfe/trunk/www/cxx_dr_status.html

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=298126&r1=298125&r2=298126&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Fri Mar 17 16:41:20 2017
@@ -1534,7 +1534,8 @@ private:
                                       bool EnteringContext,
                                       bool *MayBePseudoDestructor = nullptr,
                                       bool IsTypename = false,
-                                      IdentifierInfo **LastII = nullptr);
+                                      IdentifierInfo **LastII = nullptr,
+                                      bool OnlyNamespace = false);
 
   //===--------------------------------------------------------------------===//
   // C++0x 5.1.2: Lambda expressions

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=298126&r1=298125&r2=298126&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Mar 17 16:41:20 2017
@@ -5140,7 +5140,8 @@ public:
                                    CXXScopeSpec &SS,
                                    NamedDecl *ScopeLookupResult,
                                    bool ErrorRecoveryLookup,
-                                   bool *IsCorrectedToColon = nullptr);
+                                   bool *IsCorrectedToColon = nullptr,
+                                   bool OnlyNamespace = false);
 
   /// \brief The parser has parsed a nested-name-specifier 'identifier::'.
   ///
@@ -5164,13 +5165,16 @@ public:
   /// are allowed.  The bool value pointed by this parameter is set to 'true'
   /// if the identifier is treated as if it was followed by ':', not '::'.
   ///
+  /// \param OnlyNamespace If true, only considers namespaces in lookup.
+  ///
   /// \returns true if an error occurred, false otherwise.
   bool ActOnCXXNestedNameSpecifier(Scope *S,
                                    NestedNameSpecInfo &IdInfo,
                                    bool EnteringContext,
                                    CXXScopeSpec &SS,
                                    bool ErrorRecoveryLookup = false,
-                                   bool *IsCorrectedToColon = nullptr);
+                                   bool *IsCorrectedToColon = nullptr,
+                                   bool OnlyNamespace = false);
 
   ExprResult ActOnDecltypeExpression(Expr *E);
 

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=298126&r1=298125&r2=298126&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Fri Mar 17 16:41:20 2017
@@ -266,15 +266,26 @@ Decl *Parser::ParseNamespaceAlias(Source
 
   CXXScopeSpec SS;
   // Parse (optional) nested-name-specifier.
-  ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false);
+  ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false,
+                                 /*MayBePseudoDestructor=*/nullptr,
+                                 /*IsTypename=*/false,
+                                 /*LastII=*/nullptr,
+                                 /*OnlyNamespace=*/true);
 
-  if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
+  if (Tok.isNot(tok::identifier)) {
     Diag(Tok, diag::err_expected_namespace_name);
     // Skip to end of the definition and eat the ';'.
     SkipUntil(tok::semi);
     return nullptr;
   }
 
+  if (SS.isInvalid()) {
+    // Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier.
+    // Skip to end of the definition and eat the ';'.
+    SkipUntil(tok::semi);
+    return nullptr;
+  }
+
   // Parse identifier.
   IdentifierInfo *Ident = Tok.getIdentifierInfo();
   SourceLocation IdentLoc = ConsumeToken();
@@ -487,13 +498,17 @@ Decl *Parser::ParseUsingDirective(unsign
 
   CXXScopeSpec SS;
   // Parse (optional) nested-name-specifier.
-  ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false);
+  ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false,
+                                 /*MayBePseudoDestructor=*/nullptr,
+                                 /*IsTypename=*/false,
+                                 /*LastII=*/nullptr,
+                                 /*OnlyNamespace=*/true);
 
   IdentifierInfo *NamespcName = nullptr;
   SourceLocation IdentLoc = SourceLocation();
 
   // Parse namespace-name.
-  if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
+  if (Tok.isNot(tok::identifier)) {
     Diag(Tok, diag::err_expected_namespace_name);
     // If there was invalid namespace name, skip to end of decl, and eat ';'.
     SkipUntil(tok::semi);
@@ -501,6 +516,13 @@ Decl *Parser::ParseUsingDirective(unsign
     return nullptr;
   }
 
+  if (SS.isInvalid()) {
+    // Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier.
+    // Skip to end of the definition and eat the ';'.
+    SkipUntil(tok::semi);
+    return nullptr;
+  }
+
   // Parse identifier.
   NamespcName = Tok.getIdentifierInfo();
   IdentLoc = ConsumeToken();

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=298126&r1=298125&r2=298126&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Fri Mar 17 16:41:20 2017
@@ -141,13 +141,16 @@ void Parser::CheckForTemplateAndDigraph(
 /// filled in with the leading identifier in the last component of the
 /// nested-name-specifier, if any.
 ///
+/// \param OnlyNamespace If true, only considers namespaces in lookup.
+///
 /// \returns true if there was an error parsing a scope specifier
 bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
                                             ParsedType ObjectType,
                                             bool EnteringContext,
                                             bool *MayBePseudoDestructor,
                                             bool IsTypename,
-                                            IdentifierInfo **LastII) {
+                                            IdentifierInfo **LastII,
+                                            bool OnlyNamespace) {
   assert(getLangOpts().CPlusPlus &&
          "Call sites of this function should be guarded by checking for C++");
 
@@ -450,9 +453,9 @@ bool Parser::ParseOptionalCXXScopeSpecif
 
       bool IsCorrectedToColon = false;
       bool *CorrectionFlagPtr = ColonIsSacred ? &IsCorrectedToColon : nullptr;
-      if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), IdInfo,
-                                              EnteringContext, SS,
-                                              false, CorrectionFlagPtr)) {
+      if (Actions.ActOnCXXNestedNameSpecifier(
+              getCurScope(), IdInfo, EnteringContext, SS, false,
+              CorrectionFlagPtr, OnlyNamespace)) {
         // Identifier is not recognized as a nested name, but we can have
         // mistyped '::' instead of ':'.
         if (CorrectionFlagPtr && IsCorrectedToColon) {

Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=298126&r1=298125&r2=298126&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Fri Mar 17 16:41:20 2017
@@ -461,6 +461,7 @@ class NestedNameSpecifierValidatorCCC :
 ///        are allowed.  The bool value pointed by this parameter is set to
 ///       'true' if the identifier is treated as if it was followed by ':',
 ///        not '::'.
+/// \param OnlyNamespace If true, only considers namespaces in lookup.
 ///
 /// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in
 /// that it contains an extra parameter \p ScopeLookupResult, which provides
@@ -473,15 +474,15 @@ class NestedNameSpecifierValidatorCCC :
 /// scope if it *knows* that the result is correct.  It should not return in a
 /// dependent context, for example. Nor will it extend \p SS with the scope
 /// specifier.
-bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
-                                       NestedNameSpecInfo &IdInfo,
-                                       bool EnteringContext,
-                                       CXXScopeSpec &SS,
+bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
+                                       bool EnteringContext, CXXScopeSpec &SS,
                                        NamedDecl *ScopeLookupResult,
                                        bool ErrorRecoveryLookup,
-                                       bool *IsCorrectedToColon) {
+                                       bool *IsCorrectedToColon,
+                                       bool OnlyNamespace) {
   LookupResult Found(*this, IdInfo.Identifier, IdInfo.IdentifierLoc,
-                     LookupNestedNameSpecifierName);
+                     OnlyNamespace ? LookupNamespaceName
+                                   : LookupNestedNameSpecifierName);
   QualType ObjectType = GetTypeFromParser(IdInfo.ObjectType);
 
   // Determine where to perform name lookup
@@ -594,7 +595,9 @@ bool Sema::BuildCXXNestedNameSpecifier(S
         return true;
       }
       // Replacement '::' -> ':' is not allowed, just issue respective error.
-      Diag(R.getNameLoc(), diag::err_expected_class_or_namespace)
+      Diag(R.getNameLoc(), OnlyNamespace
+                               ? diag::err_expected_namespace_name
+                               : diag::err_expected_class_or_namespace)
           << IdInfo.Identifier << getLangOpts().CPlusPlus;
       if (NamedDecl *ND = R.getAsSingle<NamedDecl>())
         Diag(ND->getLocation(), diag::note_entity_declared_at)
@@ -819,19 +822,17 @@ bool Sema::BuildCXXNestedNameSpecifier(S
   return true;
 }
 
-bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
-                                       NestedNameSpecInfo &IdInfo,
-                                       bool EnteringContext,
-                                       CXXScopeSpec &SS,
+bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
+                                       bool EnteringContext, CXXScopeSpec &SS,
                                        bool ErrorRecoveryLookup,
-                                       bool *IsCorrectedToColon) {
+                                       bool *IsCorrectedToColon,
+                                       bool OnlyNamespace) {
   if (SS.isInvalid())
     return true;
 
-  return BuildCXXNestedNameSpecifier(S, IdInfo,
-                                     EnteringContext, SS,
+  return BuildCXXNestedNameSpecifier(S, IdInfo, EnteringContext, SS,
                                      /*ScopeLookupResult=*/nullptr, false,
-                                     IsCorrectedToColon);
+                                     IsCorrectedToColon, OnlyNamespace);
 }
 
 bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,

Modified: cfe/trunk/test/CXX/drs/dr3xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr3xx.cpp?rev=298126&r1=298125&r2=298126&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr3xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr3xx.cpp Fri Mar 17 16:41:20 2017
@@ -908,18 +908,21 @@ namespace dr372 { // dr372: no
   }
 }
 
-namespace dr373 { // dr373: no
-  // FIXME: This is valid.
-  namespace X { int dr373; } // expected-note 2{{here}}
+namespace dr373 { // dr373: 5
+  namespace X { int dr373; }
   struct dr373 { // expected-note {{here}}
     void f() {
-      using namespace dr373::X; // expected-error {{no namespace named 'X' in 'dr373::dr373'}}
+      using namespace dr373::X;
       int k = dr373; // expected-error {{does not refer to a value}}
 
-      namespace Y = dr373::X; // expected-error {{no namespace named 'X' in 'dr373::dr373'}}
+      namespace Y = dr373::X;
       k = Y::dr373;
     }
   };
+
+  struct A { struct B {}; }; // expected-note 2{{here}}
+  namespace X = A::B;   // expected-error {{expected namespace name}}
+  using namespace A::B; // expected-error {{expected namespace name}}
 }
 
 namespace dr374 { // dr374: yes c++11

Modified: cfe/trunk/www/cxx_dr_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_status.html?rev=298126&r1=298125&r2=298126&view=diff
==============================================================================
--- cfe/trunk/www/cxx_dr_status.html (original)
+++ cfe/trunk/www/cxx_dr_status.html Fri Mar 17 16:41:20 2017
@@ -2279,7 +2279,7 @@ of class templates</td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#373">373</a></td>
     <td>C++11</td>
     <td>Lookup on namespace qualified name in using-directive</td>
-    <td class="none" align="center">No</td>
+    <td class="svn" align="center">SVN</td>
   </tr>
   <tr id="374">
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#374">374</a></td>




More information about the cfe-commits mailing list