Put friend decls in the correct context.

When we find a friend declaration we have to skip transparent contexts for doing
lookups, but we should not skip them when inserting the new decl if the lookup
found nothing.

Fixes PR15841.

llvm-svn: 180571
This commit is contained in:
Rafael Espindola 2013-04-25 20:12:36 +00:00
parent f43cbeee15
commit 3626b7e451
2 changed files with 39 additions and 17 deletions

View File

@ -11131,7 +11131,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
// Find the appropriate context according to the above.
DC = CurContext;
while (true) {
// Skip class contexts. If someone can cite chapter and verse
// for this behavior, that would be nice --- it's what GCC and
// EDG do, and it seems like a reasonable intent, but the spec
@ -11139,21 +11139,31 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
// declarations should stop at the nearest enclosing namespace,
// not that they should only consider the nearest enclosing
// namespace.
while (DC->isRecord() || DC->isTransparentContext())
while (DC->isRecord())
DC = DC->getParent();
LookupQualifiedName(Previous, DC);
DeclContext *LookupDC = DC;
while (LookupDC->isTransparentContext())
LookupDC = LookupDC->getParent();
while (true) {
LookupQualifiedName(Previous, LookupDC);
// TODO: decide what we think about using declarations.
if (isLocal || !Previous.empty())
if (isLocal)
break;
if (isTemplateId) {
if (isa<TranslationUnitDecl>(DC)) break;
} else {
if (DC->isFileContext()) break;
if (!Previous.empty()) {
DC = LookupDC;
break;
}
DC = DC->getParent();
if (isTemplateId) {
if (isa<TranslationUnitDecl>(LookupDC)) break;
} else {
if (LookupDC->isFileContext()) break;
}
LookupDC = LookupDC->getParent();
}
DCScope = getScopeForDeclContext(S, DC);

View File

@ -152,3 +152,15 @@ namespace test15 {
const int a = 5; // expected-note {{previous definition is here}}
static const int a; // expected-error {{redefinition of 'a'}}
}
namespace test16 {
extern "C" {
class Foo {
int x;
friend int bar(Foo *y);
};
int bar(Foo *y) {
return y->x;
}
}
}