Don't try to use !Previous.empty() as a proxy for "Is this a redeclaration?" --
authorRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 21 Oct 2016 03:15:03 +0000 (03:15 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 21 Oct 2016 03:15:03 +0000 (03:15 +0000)
we don't collapse that down to a single entry if it's not a redeclaration.
Instead, set the Redeclaration bit on the Declarator to indicate whether a
function is a redeclaration (which may not have been linked into the
redeclaration chain if it's a dependent context friend).

Fixes a rejects-valid; see testcase.

llvm-svn: 284802

clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/SemaCXX/friend.cpp

index b483690..2711b36 100644 (file)
@@ -8445,7 +8445,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
                                 ? cast<NamedDecl>(FunctionTemplate)
                                 : NewFD);
 
-    if (isFriend && D.isRedeclaration()) {
+    if (isFriend && NewFD->getPreviousDecl()) {
       AccessSpecifier Access = AS_public;
       if (!NewFD->isInvalidDecl())
         Access = NewFD->getPreviousDecl()->getAccess();
@@ -8901,8 +8901,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
         NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
         if (isa<CXXMethodDecl>(NewFD))
           NewFD->setAccess(OldDecl->getAccess());
-      } else {
-        Redeclaration = false;
       }
     }
   }
index c1938d5..f49525c 100644 (file)
@@ -13785,10 +13785,9 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
     // template in the translation unit.
     if (functionDeclHasDefaultArgument(FD)) {
       // We can't look at FD->getPreviousDecl() because it may not have been set
-      // if we're in a dependent context. If we get this far with a non-empty
-      // Previous set, we must have a valid previous declaration of this
-      // function.
-      if (!Previous.empty()) {
+      // if we're in a dependent context. If the function is known to be a
+      // redeclaration, we will have narrowed Previous down to the right decl.
+      if (D.isRedeclaration()) {
         Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_redeclared);
         Diag(Previous.getRepresentativeDecl()->getLocation(),
              diag::note_previous_declaration);
index 4f27f4d..1f64ba6 100644 (file)
@@ -379,3 +379,12 @@ namespace tag_redecl {
     X *q = p;
   }
 }
+
+namespace default_arg {
+  void f();
+  void f(void*); // expected-note {{previous}}
+  struct X {
+    friend void f(int a, int b = 0) {}
+    friend void f(void *p = 0) {} // expected-error {{must be the only}}
+  };
+}