summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-08-18 00:00:49 +0000
committerJohn McCall <rjmccall@apple.com>2009-08-18 00:00:49 +0000
commit5ed6e8f54ce256921afbfd0a7535d9992de80a78 (patch)
treef7304024c15f7b2a54057ae508844f1c66ef3472
parent26657ea8bc09e205f90d525e3564e235d6fe0d58 (diff)
downloadbcm5719-llvm-5ed6e8f54ce256921afbfd0a7535d9992de80a78.tar.gz
bcm5719-llvm-5ed6e8f54ce256921afbfd0a7535d9992de80a78.zip
Teach Sema how to pop out of friend function definitions in nested classes.
llvm-svn: 79291
-rw-r--r--clang/lib/Sema/SemaDecl.cpp33
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp3
2 files changed, 23 insertions, 13 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index f6988d174df..2d360599149 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -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() &&
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 068978cd926..2de348485e7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -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
OpenPOWER on IntegriCloud