Don't try to use !Previous.empty() as a proxy for "Is this a redeclaration?" --
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
This commit is contained in:
parent
81440dc93f
commit
fdf0888b69
|
@ -8445,7 +8445,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||||
? cast<NamedDecl>(FunctionTemplate)
|
? cast<NamedDecl>(FunctionTemplate)
|
||||||
: NewFD);
|
: NewFD);
|
||||||
|
|
||||||
if (isFriend && D.isRedeclaration()) {
|
if (isFriend && NewFD->getPreviousDecl()) {
|
||||||
AccessSpecifier Access = AS_public;
|
AccessSpecifier Access = AS_public;
|
||||||
if (!NewFD->isInvalidDecl())
|
if (!NewFD->isInvalidDecl())
|
||||||
Access = NewFD->getPreviousDecl()->getAccess();
|
Access = NewFD->getPreviousDecl()->getAccess();
|
||||||
|
@ -8901,8 +8901,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
||||||
NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
|
NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
|
||||||
if (isa<CXXMethodDecl>(NewFD))
|
if (isa<CXXMethodDecl>(NewFD))
|
||||||
NewFD->setAccess(OldDecl->getAccess());
|
NewFD->setAccess(OldDecl->getAccess());
|
||||||
} else {
|
|
||||||
Redeclaration = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13785,10 +13785,9 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
|
||||||
// template in the translation unit.
|
// template in the translation unit.
|
||||||
if (functionDeclHasDefaultArgument(FD)) {
|
if (functionDeclHasDefaultArgument(FD)) {
|
||||||
// We can't look at FD->getPreviousDecl() because it may not have been set
|
// 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
|
// if we're in a dependent context. If the function is known to be a
|
||||||
// Previous set, we must have a valid previous declaration of this
|
// redeclaration, we will have narrowed Previous down to the right decl.
|
||||||
// function.
|
if (D.isRedeclaration()) {
|
||||||
if (!Previous.empty()) {
|
|
||||||
Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_redeclared);
|
Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_redeclared);
|
||||||
Diag(Previous.getRepresentativeDecl()->getLocation(),
|
Diag(Previous.getRepresentativeDecl()->getLocation(),
|
||||||
diag::note_previous_declaration);
|
diag::note_previous_declaration);
|
||||||
|
|
|
@ -379,3 +379,12 @@ namespace tag_redecl {
|
||||||
X *q = p;
|
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}}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue