]> granicus.if.org Git - clang/commitdiff
Parse constructor names in friend declarations. Part of the fix for
authorJohn McCall <rjmccall@apple.com>
Tue, 13 Apr 2010 06:39:49 +0000 (06:39 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 13 Apr 2010 06:39:49 +0000 (06:39 +0000)
PR6207.

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

lib/Parse/ParseDecl.cpp
lib/Sema/SemaDecl.cpp

index da4a00284477e96e62ee521e5aa2eb69aace9316..09ae231c5e74ec4409243ad8b02778d6eed01d1d 100644 (file)
@@ -904,7 +904,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
         // reinforced by the NAD status of core issue 635. 
         TemplateIdAnnotation *TemplateId
           = static_cast<TemplateIdAnnotation *>(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, 
index 171bee66ca20c513c37cf52dac43ca0bbcceba87..005311f075bf97b67c7d49fa8a4ba053b7cb5a76 100644 (file)
@@ -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);