From 84821e7143fc6175cf2036b9ca3d0ad6924820f8 Mon Sep 17 00:00:00 2001 From: John McCall Date: Tue, 13 Apr 2010 06:39:49 +0000 Subject: [PATCH] Parse constructor names in friend declarations. Part of the fix for PR6207. llvm-svn: 101119 --- clang/lib/Parse/ParseDecl.cpp | 24 ++++++++++++++++-------- clang/lib/Sema/SemaDecl.cpp | 9 ++++++++- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index da4a00284477..09ae231c5e74 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -904,7 +904,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // reinforced by the NAD status of core issue 635. TemplateIdAnnotation *TemplateId = static_cast(Next.getAnnotationValue()); - if (DSContext == DSC_top_level && TemplateId->Name && + if ((DSContext == DSC_top_level || + (DSContext == DSC_class && DS.isFriendSpecified())) && + TemplateId->Name && Actions.isCurrentClassName(*TemplateId->Name, CurScope, &SS)) { if (isConstructorDeclarator()) { // The user meant this to be an out-of-line constructor @@ -949,7 +951,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // If we're in a context where the identifier could be a class name, // check whether this is a constructor declaration. - if (DSContext == DSC_top_level && + if ((DSContext == DSC_top_level || + (DSContext == DSC_class && DS.isFriendSpecified())) && Actions.isCurrentClassName(*Next.getIdentifierInfo(), CurScope, &SS)) { if (isConstructorDeclarator()) @@ -2599,12 +2602,17 @@ void Parser::ParseDirectDeclarator(Declarator &D) { Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) { // We found something that indicates the start of an unqualified-id. // Parse that unqualified-id. - bool AllowConstructorName - = ((D.getCXXScopeSpec().isSet() && - D.getContext() == Declarator::FileContext) || - (!D.getCXXScopeSpec().isSet() && - D.getContext() == Declarator::MemberContext)) && - !D.getDeclSpec().hasTypeSpecifier(); + bool AllowConstructorName; + if (D.getDeclSpec().hasTypeSpecifier()) + AllowConstructorName = false; + else if (D.getCXXScopeSpec().isSet()) + AllowConstructorName = + (D.getContext() == Declarator::FileContext || + (D.getContext() == Declarator::MemberContext && + D.getDeclSpec().isFriendSpecified())); + else + AllowConstructorName = (D.getContext() == Declarator::MemberContext); + if (ParseUnqualifiedId(D.getCXXScopeSpec(), /*EnteringContext=*/true, /*AllowDestructorName=*/true, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 171bee66ca20..005311f075bf 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3188,6 +3188,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (CheckMemberSpecialization(NewFD, Previous)) NewFD->setInvalidDecl(); } + + // Make sure this is set before checking the function declaration. + // We'll override the visibility type later. + if (isFriend) NewFD->setObjectOfFriendDecl(false); // Perform semantic checking on the function declaration. bool OverloadableAttrRequired = false; // FIXME: HACK! @@ -3199,7 +3203,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, "previous declaration set still overloaded"); if (isFriend && Redeclaration) { - AccessSpecifier Access = NewFD->getPreviousDeclaration()->getAccess(); + AccessSpecifier Access = AS_public; + if (!NewFD->isInvalidDecl()) + Access = NewFD->getPreviousDeclaration()->getAccess(); + if (FunctionTemplate) { FunctionTemplate->setObjectOfFriendDecl(true); FunctionTemplate->setAccess(Access);