Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -1534,7 +1534,8 @@ bool EnteringContext, bool *MayBePseudoDestructor = nullptr, bool IsTypename = false, - IdentifierInfo **LastII = nullptr); + IdentifierInfo **LastII = nullptr, + bool OnlyNamespace = false); //===--------------------------------------------------------------------===// // C++0x 5.1.2: Lambda expressions Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -5134,7 +5134,8 @@ 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::'. /// @@ -5158,13 +5159,16 @@ /// 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); Index: lib/Parse/ParseDeclCXX.cpp =================================================================== --- lib/Parse/ParseDeclCXX.cpp +++ lib/Parse/ParseDeclCXX.cpp @@ -266,7 +266,11 @@ 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)) { Diag(Tok, diag::err_expected_namespace_name); @@ -487,7 +491,11 @@ 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(); Index: lib/Parse/ParseExprCXX.cpp =================================================================== --- lib/Parse/ParseExprCXX.cpp +++ lib/Parse/ParseExprCXX.cpp @@ -141,13 +141,16 @@ /// 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 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) { Index: lib/Sema/SemaCXXScopeSpec.cpp =================================================================== --- lib/Sema/SemaCXXScopeSpec.cpp +++ lib/Sema/SemaCXXScopeSpec.cpp @@ -461,6 +461,7 @@ /// 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 @@ /// 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 @@ -819,19 +820,17 @@ 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, Index: test/CXX/drs/dr3xx.cpp =================================================================== --- test/CXX/drs/dr3xx.cpp +++ test/CXX/drs/dr3xx.cpp @@ -908,15 +908,14 @@ } } -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; } }; Index: www/cxx_dr_status.html =================================================================== --- www/cxx_dr_status.html +++ www/cxx_dr_status.html @@ -2279,7 +2279,7 @@