зеркало из https://github.com/microsoft/clang-1.git
Teach Sema how to pop out of friend function definitions in nested classes.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79291 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
91f21c0c83
Коммит
88232aadbe
|
@ -182,19 +182,25 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
// Determines the context to return to after temporarily entering a
|
||||
// context. This depends in an unnecessarily complicated way on the
|
||||
// exact ordering of callbacks from the parser.
|
||||
DeclContext *Sema::getContainingDC(DeclContext *DC) {
|
||||
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) {
|
||||
// A C++ out-of-line method will return to the file declaration context.
|
||||
if (MD->isOutOfLine())
|
||||
return MD->getLexicalDeclContext();
|
||||
|
||||
// A C++ inline method is parsed *after* the topmost class it was declared
|
||||
// in is fully parsed (it's "complete").
|
||||
// The parsing of a C++ inline method happens at the declaration context of
|
||||
// the topmost (non-nested) class it is lexically declared in.
|
||||
assert(isa<CXXRecordDecl>(MD->getParent()) && "C++ method not in Record.");
|
||||
DC = MD->getParent();
|
||||
// Functions defined inline within classes aren't parsed until we've
|
||||
// finished parsing the top-level class, so the top-level class is
|
||||
// the context we'll need to return to.
|
||||
if (isa<FunctionDecl>(DC)) {
|
||||
DC = DC->getLexicalParent();
|
||||
|
||||
// A function not defined within a class will always return to its
|
||||
// lexical context.
|
||||
if (!isa<CXXRecordDecl>(DC))
|
||||
return DC;
|
||||
|
||||
// A C++ inline method/friend is parsed *after* the topmost class
|
||||
// it was declared in is fully parsed ("complete"); the topmost
|
||||
// class is the context we need to return to.
|
||||
while (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC->getLexicalParent()))
|
||||
DC = RD;
|
||||
|
||||
|
@ -2387,7 +2393,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
FunctionDecl *NewFD;
|
||||
if (isFriend) {
|
||||
// DC is the namespace in which the function is being declared.
|
||||
assert(DC->isFileContext() || PrevDecl);
|
||||
assert(DC->isFileContext() || D.getCXXScopeSpec().isSet());
|
||||
|
||||
// C++ [class.friend]p5
|
||||
// A function can be defined in a friend declaration of a
|
||||
|
@ -2398,6 +2404,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
D.getIdentifierLoc(), Name, R,
|
||||
isInline,
|
||||
D.getDeclSpec().getFriendSpecLoc());
|
||||
|
||||
} else if (D.getKind() == Declarator::DK_Constructor) {
|
||||
// This is a C++ constructor declaration.
|
||||
assert(DC->isRecord() &&
|
||||
|
|
|
@ -3590,6 +3590,9 @@ Sema::DeclPtrTy Sema::ActOnFriendDecl(Scope *S,
|
|||
Redeclaration);
|
||||
FD = cast_or_null<FriendFunctionDecl>(ND);
|
||||
|
||||
assert(FD->getDeclContext() == DC);
|
||||
assert(FD->getLexicalDeclContext() == CurContext);
|
||||
|
||||
// If this is a dependent context, just add the decl to the
|
||||
// class's decl list and don't both with the lookup tables. This
|
||||
// doesn't affect lookup because any call that might find this
|
||||
|
|
Загрузка…
Ссылка в новой задаче