forked from OSchip/llvm-project
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:
parent
f43cbeee15
commit
3626b7e451
|
@ -11131,29 +11131,39 @@ 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
|
||||
// really only says that checks for unqualified existing
|
||||
// declarations should stop at the nearest enclosing namespace,
|
||||
// not that they should only consider the nearest enclosing
|
||||
// namespace.
|
||||
while (DC->isRecord() || DC->isTransparentContext())
|
||||
DC = DC->getParent();
|
||||
|
||||
LookupQualifiedName(Previous, DC);
|
||||
// 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
|
||||
// really only says that checks for unqualified existing
|
||||
// declarations should stop at the nearest enclosing namespace,
|
||||
// not that they should only consider the nearest enclosing
|
||||
// namespace.
|
||||
while (DC->isRecord())
|
||||
DC = DC->getParent();
|
||||
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue