summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParseDeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Parse/ParseDeclCXX.cpp')
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp91
1 files changed, 69 insertions, 22 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index ee142138768..a7d3b52bd23 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -921,9 +921,9 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
if (!LateMethod) {
// Push this method onto the stack of late-parsed method
// declarations.
- getCurTopClassStack().MethodDecls.push_back(
+ getCurrentClass().MethodDecls.push_back(
LateParsedMethodDeclaration(ThisDecl));
- LateMethod = &getCurTopClassStack().MethodDecls.back();
+ LateMethod = &getCurrentClass().MethodDecls.back();
// Add all of the parameters prior to this one (they don't
// have default arguments).
@@ -1000,16 +1000,16 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
SourceLocation LBraceLoc = ConsumeBrace();
- if (!CurScope->isClassScope() && // Not about to define a nested class.
- CurScope->isInCXXInlineMethodScope()) {
- // We will define a local class of an inline method.
- // Push a new LexedMethodsForTopClass for its inline methods.
- PushTopClassStack();
- }
+ // Determine whether this is a top-level (non-nested) class.
+ bool TopLevelClass = ClassStack.empty() ||
+ CurScope->isInCXXInlineMethodScope();
// Enter a scope for the class.
ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope);
+ // Note that we are parsing a new (potentially-nested) class definition.
+ ParsingClassDefinition ParsingDef(*this, TagDecl, TopLevelClass);
+
if (TagDecl)
Actions.ActOnTagStartDefinition(CurScope, TagDecl);
else {
@@ -1067,26 +1067,16 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
//
// FIXME: Only function bodies and constructor ctor-initializers are
// parsed correctly, fix the rest.
- if (!CurScope->getParent()->isClassScope() &&
- !(CurScope->getParent()->isTemplateParamScope() &&
- CurScope->getParent()->getParent()->isClassScope())) {
+ if (TopLevelClass) {
// We are not inside a nested class. This class and its nested classes
// are complete and we can parse the delayed portions of method
// declarations and the lexed inline method definitions.
- ParseLexedMethodDeclarations();
- ParseLexedMethodDefs();
-
- // For a local class of inline method, pop the LexedMethodsForTopClass that
- // was previously pushed.
-
- assert((CurScope->isInCXXInlineMethodScope() ||
- TopClassStacks.size() == 1) &&
- "MethodLexers not getting popped properly!");
- if (CurScope->isInCXXInlineMethodScope())
- PopTopClassStack();
+ ParseLexedMethodDeclarations(getCurrentClass());
+ ParseLexedMethodDefs(getCurrentClass());
}
// Leave the class scope.
+ ParsingDef.Pop();
ClassScope.Exit();
Actions.ActOnTagFinishDefinition(CurScope, TagDecl);
@@ -1236,3 +1226,60 @@ bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc,
EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
return false;
}
+
+/// \brief We have just started parsing the definition of a new class,
+/// so push that class onto our stack of classes that is currently
+/// being parsed.
+void Parser::PushParsingClass(DeclPtrTy ClassDecl, bool TopLevelClass) {
+ assert((TopLevelClass || !ClassStack.empty()) &&
+ "Nested class without outer class");
+ ClassStack.push(new ParsingClass(ClassDecl, TopLevelClass));
+}
+
+/// \brief Deallocate the given parsed class and all of its nested
+/// classes.
+void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) {
+ for (unsigned I = 0, N = Class->NestedClasses.size(); I != N; ++I)
+ DeallocateParsedClasses(Class->NestedClasses[I]);
+ delete Class;
+}
+
+/// \brief Pop the top class of the stack of classes that are
+/// currently being parsed.
+///
+/// This routine should be called when we have finished parsing the
+/// definition of a class, but have not yet popped the Scope
+/// associated with the class's definition.
+///
+/// \returns true if the class we've popped is a top-level class,
+/// false otherwise.
+void Parser::PopParsingClass() {
+ assert(!ClassStack.empty() && "Mismatched push/pop for class parsing");
+
+ ParsingClass *Victim = ClassStack.top();
+ ClassStack.pop();
+ if (Victim->TopLevelClass) {
+ // Deallocate all of the nested classes of this class,
+ // recursively: we don't need to keep any of this information.
+ DeallocateParsedClasses(Victim);
+ return;
+ }
+ assert(!ClassStack.empty() && "Missing top-level class?");
+
+ if (Victim->MethodDecls.empty() && Victim->MethodDefs.empty() &&
+ Victim->NestedClasses.empty()) {
+ // The victim is a nested class, but we will not need to perform
+ // any processing after the definition of this class since it has
+ // no members whose handling was delayed. Therefore, we can just
+ // remove this nested class.
+ delete Victim;
+ return;
+ }
+
+ // This nested class has some members that will need to be processed
+ // after the top-level class is completely defined. Therefore, add
+ // it to the list of nested classes within its parent.
+ assert(CurScope->isClassScope() && "Nested class outside of class scope?");
+ ClassStack.top()->NestedClasses.push_back(Victim);
+ Victim->TemplateScope = CurScope->getParent()->isTemplateParamScope();
+}
OpenPOWER on IntegriCloud