forked from OSchip/llvm-project
Improve handling of friend function templates somewhat
llvm-svn: 82950
This commit is contained in:
parent
277e767578
commit
a29a3ffd18
|
@ -4220,9 +4220,6 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
|
|||
DeclarationName Name = GetNameForDeclarator(D);
|
||||
assert(Name);
|
||||
|
||||
// The existing declaration we found.
|
||||
FunctionDecl *FD = NULL;
|
||||
|
||||
// The context we found the declaration in, or in which we should
|
||||
// create the declaration.
|
||||
DeclContext *DC;
|
||||
|
@ -4230,19 +4227,20 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
|
|||
// FIXME: handle local classes
|
||||
|
||||
// Recover from invalid scope qualifiers as if they just weren't there.
|
||||
NamedDecl *PrevDecl = 0;
|
||||
if (!ScopeQual.isInvalid() && ScopeQual.isSet()) {
|
||||
DC = computeDeclContext(ScopeQual);
|
||||
|
||||
// FIXME: handle dependent contexts
|
||||
if (!DC) return DeclPtrTy();
|
||||
|
||||
Decl *Dec = LookupQualifiedNameWithType(DC, Name, T);
|
||||
PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName, true);
|
||||
|
||||
// If searching in that context implicitly found a declaration in
|
||||
// a different context, treat it like it wasn't found at all.
|
||||
// TODO: better diagnostics for this case. Suggesting the right
|
||||
// qualified scope would be nice...
|
||||
if (!Dec || Dec->getDeclContext() != DC) {
|
||||
if (!PrevDecl || !PrevDecl->getDeclContext()->Equals(DC)) {
|
||||
D.setInvalidType();
|
||||
Diag(Loc, diag::err_qualified_friend_not_found) << Name << T;
|
||||
return DeclPtrTy();
|
||||
|
@ -4250,11 +4248,9 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
|
|||
|
||||
// C++ [class.friend]p1: A friend of a class is a function or
|
||||
// class that is not a member of the class . . .
|
||||
if (DC == CurContext)
|
||||
if (DC->Equals(CurContext))
|
||||
Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
|
||||
|
||||
FD = cast<FunctionDecl>(Dec);
|
||||
|
||||
// Otherwise walk out to the nearest namespace scope looking for matches.
|
||||
} else {
|
||||
// TODO: handle local class contexts.
|
||||
|
@ -4268,15 +4264,15 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
|
|||
// declarations should stop at the nearest enclosing namespace,
|
||||
// not that they should only consider the nearest enclosing
|
||||
// namespace.
|
||||
while (DC->isRecord()) DC = DC->getParent();
|
||||
while (DC->isRecord())
|
||||
DC = DC->getParent();
|
||||
|
||||
Decl *Dec = LookupQualifiedNameWithType(DC, Name, T);
|
||||
PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName, true);
|
||||
|
||||
// TODO: decide what we think about using declarations.
|
||||
if (Dec) {
|
||||
FD = cast<FunctionDecl>(Dec);
|
||||
if (PrevDecl)
|
||||
break;
|
||||
}
|
||||
|
||||
if (DC->isFileContext()) break;
|
||||
DC = DC->getParent();
|
||||
}
|
||||
|
@ -4286,24 +4282,11 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
|
|||
// C++0x changes this for both friend types and functions.
|
||||
// Most C++ 98 compilers do seem to give an error here, so
|
||||
// we do, too.
|
||||
if (FD && DC == CurContext && !getLangOptions().CPlusPlus0x)
|
||||
if (PrevDecl && DC->Equals(CurContext) && !getLangOptions().CPlusPlus0x)
|
||||
Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
|
||||
}
|
||||
|
||||
bool Redeclaration = (FD != 0);
|
||||
|
||||
// If we found a match, create a friend function declaration with
|
||||
// that function as the previous declaration.
|
||||
if (Redeclaration) {
|
||||
// Create it in the semantic context of the original declaration.
|
||||
DC = FD->getDeclContext();
|
||||
|
||||
// If we didn't find something matching the type exactly, create
|
||||
// a declaration. This declaration should only be findable via
|
||||
// argument-dependent lookup.
|
||||
} else {
|
||||
assert(DC->isFileContext());
|
||||
|
||||
if (DC->isFileContext()) {
|
||||
// This implies that it has to be an operator or function.
|
||||
if (D.getKind() == Declarator::DK_Constructor ||
|
||||
D.getKind() == Declarator::DK_Destructor ||
|
||||
|
@ -4315,20 +4298,15 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
|
|||
}
|
||||
}
|
||||
|
||||
NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, DInfo,
|
||||
/* PrevDecl = */ FD,
|
||||
bool Redeclaration = false;
|
||||
NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, DInfo, PrevDecl,
|
||||
MultiTemplateParamsArg(*this),
|
||||
IsDefinition,
|
||||
Redeclaration);
|
||||
if (!ND) return DeclPtrTy();
|
||||
|
||||
assert(cast<FunctionDecl>(ND)->getPreviousDeclaration() == FD &&
|
||||
"lost reference to previous declaration");
|
||||
|
||||
FD = cast<FunctionDecl>(ND);
|
||||
|
||||
assert(FD->getDeclContext() == DC);
|
||||
assert(FD->getLexicalDeclContext() == CurContext);
|
||||
assert(ND->getDeclContext() == DC);
|
||||
assert(ND->getLexicalDeclContext() == CurContext);
|
||||
|
||||
// Add the function declaration to the appropriate lookup tables,
|
||||
// adjusting the redeclarations list as necessary. We don't
|
||||
|
@ -4338,18 +4316,18 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
|
|||
// lookup context is in lexical scope.
|
||||
if (!CurContext->isDependentContext()) {
|
||||
DC = DC->getLookupContext();
|
||||
DC->makeDeclVisibleInContext(FD, /* Recoverable=*/ false);
|
||||
DC->makeDeclVisibleInContext(ND, /* Recoverable=*/ false);
|
||||
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
|
||||
PushOnScopeChains(FD, EnclosingScope, /*AddToContext=*/ false);
|
||||
PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false);
|
||||
}
|
||||
|
||||
FriendDecl *FrD = FriendDecl::Create(Context, CurContext,
|
||||
D.getIdentifierLoc(), FD,
|
||||
D.getIdentifierLoc(), ND,
|
||||
DS.getFriendSpecLoc());
|
||||
FrD->setAccess(AS_public);
|
||||
CurContext->addDecl(FrD);
|
||||
|
||||
return DeclPtrTy::make(FD);
|
||||
return DeclPtrTy::make(ND);
|
||||
}
|
||||
|
||||
void Sema::SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: clang-cc -fsyntax-only %s
|
||||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
// PR5057
|
||||
namespace std {
|
||||
|
@ -15,3 +15,16 @@ namespace std {
|
|||
{
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
namespace N {
|
||||
template<typename T> void f1(T) { } // expected-note{{here}}
|
||||
|
||||
class X {
|
||||
template<typename T> friend void f0(T);
|
||||
template<typename T> friend void f1(T);
|
||||
};
|
||||
|
||||
template<typename T> void f0(T) { }
|
||||
template<typename T> void f1(T) { } // expected-error{{redefinition}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue