diff options
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 36 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 22 |
2 files changed, 45 insertions, 13 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index aa2c0f512a..d7f8e982aa 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -468,7 +468,10 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, } // Parse nested-name-specifier. - ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); + IdentifierInfo *LastII = 0; + ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false, + /*MayBePseudoDtor=*/0, /*IsTypename=*/false, + /*LastII=*/&LastII); // Check nested-name specifier. if (SS.isInvalid()) { @@ -476,18 +479,31 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, return 0; } + SourceLocation TemplateKWLoc; + UnqualifiedId Name; + // Parse the unqualified-id. We allow parsing of both constructor and // destructor names and allow the action module to diagnose any semantic // errors. - SourceLocation TemplateKWLoc; - UnqualifiedId Name; - if (ParseUnqualifiedId(SS, - /*EnteringContext=*/false, - /*AllowDestructorName=*/true, - /*AllowConstructorName=*/true, - ParsedType(), - TemplateKWLoc, - Name)) { + // + // C++11 [class.qual]p2: + // [...] in a using-declaration that is a member-declaration, if the name + // specified after the nested-name-specifier is the same as the identifier + // or the simple-template-id's template-name in the last component of the + // nested-name-specifier, the name is [...] considered to name the + // constructor. + if (getLangOpts().CPlusPlus11 && Context == Declarator::MemberContext && + Tok.is(tok::identifier) && NextToken().is(tok::semi) && + SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() && + !SS.getScopeRep()->getAsNamespace() && + !SS.getScopeRep()->getAsNamespaceAlias()) { + SourceLocation IdLoc = ConsumeToken(); + ParsedType Type = Actions.getInheritingConstructorName(SS, IdLoc, *LastII); + Name.setConstructorName(Type, IdLoc, IdLoc); + } else if (ParseUnqualifiedId(SS, /*EnteringContext=*/ false, + /*AllowDestructorName=*/ true, + /*AllowConstructorName=*/ true, ParsedType(), + TemplateKWLoc, Name)) { SkipUntil(tok::semi); return 0; } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index f72e68e2a1..22938afede 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -168,19 +168,26 @@ void Parser::CheckForLParenAfterColonColon() { /// if we do end up determining that we are parsing a destructor name, /// the last component of the nested-name-specifier is not parsed as /// part of the scope specifier. - -/// member access expression, e.g., the \p T:: in \p p->T::m. +/// +/// \param IsTypename If \c true, this nested-name-specifier is known to be +/// part of a type name. This is used to improve error recovery. +/// +/// \param LastII When non-NULL, points to an IdentifierInfo* that will be +/// filled in with the leading identifier in the last component of the +/// nested-name-specifier, if any. /// /// \returns true if there was an error parsing a scope specifier bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, ParsedType ObjectType, bool EnteringContext, bool *MayBePseudoDestructor, - bool IsTypename) { + bool IsTypename, + IdentifierInfo **LastII) { assert(getLangOpts().CPlusPlus && "Call sites of this function should be guarded by checking for C++"); if (Tok.is(tok::annot_cxxscope)) { + assert(!LastII && "want last identifier but have already annotated scope"); Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS); @@ -188,6 +195,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; } + if (LastII) + *LastII = 0; + bool HasScopeSpecifier = false; if (Tok.is(tok::coloncolon)) { @@ -334,6 +344,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; } + if (LastII) + *LastII = TemplateId->Name; + // Consume the template-id token. ConsumeToken(); @@ -405,6 +418,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; } + if (LastII) + *LastII = ⅈ + // We have an identifier followed by a '::'. Lookup this name // as the name in a nested-name-specifier. SourceLocation IdLoc = ConsumeToken(); |