зеркало из https://github.com/microsoft/clang-1.git
Don't enter a new scope for a namespace-qualified declarator unless we're
in a file context. In well-formed code, only happens with friend functions. Fixes PR 5760. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91146 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
ef96eac2b8
Коммит
e7e278bce2
|
@ -365,8 +365,19 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/// ShouldEnterDeclaratorScope - Called when a C++ scope specifier
|
||||
/// is parsed as part of a declarator-id to determine whether a scope
|
||||
/// should be entered.
|
||||
///
|
||||
/// \param S the current scope
|
||||
/// \param SS the scope being entered
|
||||
/// \param isFriendDeclaration whether this is a friend declaration
|
||||
virtual bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
|
||||
/// scope or nested-name-specifier) is parsed, part of a declarator-id.
|
||||
/// scope or nested-name-specifier) is parsed as part of a declarator-id.
|
||||
/// After this method is called, according to [C++ 3.4.3p3], names should be
|
||||
/// looked up in the declarator-id's scope, until the declarator is parsed and
|
||||
/// ActOnCXXExitDeclaratorScope is called.
|
||||
|
|
|
@ -2335,6 +2335,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
|
|||
ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
|
||||
true);
|
||||
if (afterCXXScope) {
|
||||
if (Actions.ShouldEnterDeclaratorScope(CurScope, D.getCXXScopeSpec()))
|
||||
// Change the declaration context for name lookup, until this function
|
||||
// is exited (and the declarator has been parsed).
|
||||
DeclScopeObj.EnterDeclaratorScope();
|
||||
|
|
|
@ -2048,6 +2048,8 @@ public:
|
|||
SourceRange TypeRange,
|
||||
SourceLocation CCLoc);
|
||||
|
||||
virtual bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
|
||||
|
||||
/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
|
||||
/// scope or nested-name-specifier) is parsed, part of a declarator-id.
|
||||
/// After this method is called, according to [C++ 3.4.3p3], names should be
|
||||
|
|
|
@ -559,6 +559,44 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
|
|||
T.getTypePtr());
|
||||
}
|
||||
|
||||
bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
|
||||
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
|
||||
|
||||
NestedNameSpecifier *Qualifier =
|
||||
static_cast<NestedNameSpecifier*>(SS.getScopeRep());
|
||||
|
||||
// There are only two places a well-formed program may qualify a
|
||||
// declarator: first, when defining a namespace or class member
|
||||
// out-of-line, and second, when naming an explicitly-qualified
|
||||
// friend function. The latter case is governed by
|
||||
// C++03 [basic.lookup.unqual]p10:
|
||||
// In a friend declaration naming a member function, a name used
|
||||
// in the function declarator and not part of a template-argument
|
||||
// in a template-id is first looked up in the scope of the member
|
||||
// function's class. If it is not found, or if the name is part of
|
||||
// a template-argument in a template-id, the look up is as
|
||||
// described for unqualified names in the definition of the class
|
||||
// granting friendship.
|
||||
// i.e. we don't push a scope unless it's a class member.
|
||||
|
||||
switch (Qualifier->getKind()) {
|
||||
case NestedNameSpecifier::Global:
|
||||
case NestedNameSpecifier::Namespace:
|
||||
// These are always namespace scopes. We never want to enter a
|
||||
// namespace scope from anything but a file context.
|
||||
return CurContext->getLookupContext()->isFileContext();
|
||||
|
||||
case NestedNameSpecifier::Identifier:
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
// These are never namespace scopes.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Silence bogus warning.
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
|
||||
/// scope or nested-name-specifier) is parsed, part of a declarator-id.
|
||||
/// After this method is called, according to [C++ 3.4.3p3], names should be
|
||||
|
|
|
@ -4,3 +4,14 @@ friend class A; // expected-error {{'friend' used outside of class}}
|
|||
void f() { friend class A; } // expected-error {{'friend' used outside of class}}
|
||||
class C { friend class A; };
|
||||
class D { void f() { friend class A; } }; // expected-error {{'friend' used outside of class}}
|
||||
|
||||
// PR5760
|
||||
namespace test0 {
|
||||
namespace ns {
|
||||
void f(int);
|
||||
}
|
||||
|
||||
struct A {
|
||||
friend void ns::f(int a);
|
||||
};
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче