diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 294 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 16 |
3 files changed, 168 insertions, 143 deletions
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 4319df3e92..e8e80647b4 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -807,6 +807,7 @@ error: SavedMainFileBuffer = 0; } + StoredDiagnostics.clear(); Clang.takeSourceManager(); Clang.takeFileManager(); Invocation.reset(Clang.takeInvocation()); diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 8b2fb55d9d..718c71be02 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -45,10 +45,10 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D, // Consume the tokens and store them for later parsing. - getCurrentClass().MethodDefs.push_back(LexedMethod(FnD)); - getCurrentClass().MethodDefs.back().TemplateScope - = getCurScope()->isTemplateParamScope(); - CachedTokens &Toks = getCurrentClass().MethodDefs.back().Toks; + LexedMethod* LM = new LexedMethod(this, FnD); + getCurrentClass().LateParsedDeclarations.push_back(LM); + LM->TemplateScope = getCurScope()->isTemplateParamScope(); + CachedTokens &Toks = LM->Toks; tok::TokenKind kind = Tok.getKind(); // We may have a constructor initializer or function-try-block here. @@ -62,7 +62,8 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D, // don't try to parse this method later. Diag(Tok.getLocation(), diag::err_expected_lbrace); ConsumeAnyToken(); - getCurrentClass().MethodDefs.pop_back(); + delete getCurrentClass().LateParsedDeclarations.back(); + getCurrentClass().LateParsedDeclarations.pop_back(); return FnD; } } @@ -86,13 +87,40 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D, return FnD; } +Parser::LateParsedDeclaration::~LateParsedDeclaration() {} +void Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {} +void Parser::LateParsedDeclaration::ParseLexedMethodDefs() {} + +Parser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C) + : Self(P), Class(C) {} + +Parser::LateParsedClass::~LateParsedClass() { + Self->DeallocateParsedClasses(Class); +} + +void Parser::LateParsedClass::ParseLexedMethodDeclarations() { + Self->ParseLexedMethodDeclarations(*Class); +} + +void Parser::LateParsedClass::ParseLexedMethodDefs() { + Self->ParseLexedMethodDefs(*Class); +} + +void Parser::LateParsedMethodDeclaration::ParseLexedMethodDeclarations() { + Self->ParseLexedMethodDeclaration(*this); +} + +void Parser::LexedMethod::ParseLexedMethodDefs() { + Self->ParseLexedMethodDef(*this); +} + /// ParseLexedMethodDeclarations - We finished parsing the member /// specification of a top (non-nested) C++ class. Now go over the /// stack of method declarations with some parts for which parsing was /// delayed (such as default arguments) and parse them. void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) { bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; - ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); + ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); if (HasTemplateScope) Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); @@ -104,80 +132,79 @@ void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) { if (HasClassScope) Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); - for (; !Class.MethodDecls.empty(); Class.MethodDecls.pop_front()) { - LateParsedMethodDeclaration &LM = Class.MethodDecls.front(); - - // If this is a member template, introduce the template parameter scope. - ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); - if (LM.TemplateScope) - Actions.ActOnReenterTemplateScope(getCurScope(), LM.Method); - - // Start the delayed C++ method declaration - Actions.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM.Method); - - // Introduce the parameters into scope and parse their default - // arguments. - ParseScope PrototypeScope(this, - Scope::FunctionPrototypeScope|Scope::DeclScope); - for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) { - // Introduce the parameter into scope. - Actions.ActOnDelayedCXXMethodParameter(getCurScope(), LM.DefaultArgs[I].Param); + for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) { + Class.LateParsedDeclarations[i]->ParseLexedMethodDeclarations(); + } - if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) { - // Save the current token position. - SourceLocation origLoc = Tok.getLocation(); + if (HasClassScope) + Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); +} - // Parse the default argument from its saved token stream. - Toks->push_back(Tok); // So that the current token doesn't get lost - PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false); +void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { + // If this is a member template, introduce the template parameter scope. + ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); + if (LM.TemplateScope) + Actions.ActOnReenterTemplateScope(getCurScope(), LM.Method); + + // Start the delayed C++ method declaration + Actions.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM.Method); + + // Introduce the parameters into scope and parse their default + // arguments. + ParseScope PrototypeScope(this, + Scope::FunctionPrototypeScope|Scope::DeclScope); + for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) { + // Introduce the parameter into scope. + Actions.ActOnDelayedCXXMethodParameter(getCurScope(), LM.DefaultArgs[I].Param); + + if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) { + // Save the current token position. + SourceLocation origLoc = Tok.getLocation(); + + // Parse the default argument from its saved token stream. + Toks->push_back(Tok); // So that the current token doesn't get lost + PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false); + + // Consume the previously-pushed token. + ConsumeAnyToken(); + + // Consume the '='. + assert(Tok.is(tok::equal) && "Default argument not starting with '='"); + SourceLocation EqualLoc = ConsumeToken(); + + // The argument isn't actually potentially evaluated unless it is + // used. + EnterExpressionEvaluationContext Eval(Actions, + Sema::PotentiallyEvaluatedIfUsed); + + ExprResult DefArgResult(ParseAssignmentExpression()); + if (DefArgResult.isInvalid()) + Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param); + else { + if (Tok.is(tok::cxx_defaultarg_end)) + ConsumeToken(); + else + Diag(Tok.getLocation(), diag::err_default_arg_unparsed); + Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc, + DefArgResult.take()); + } - // Consume the previously-pushed token. + assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, + Tok.getLocation()) && + "ParseAssignmentExpression went over the default arg tokens!"); + // There could be leftover tokens (e.g. because of an error). + // Skip through until we reach the original token position. + while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) ConsumeAnyToken(); - // Consume the '='. - assert(Tok.is(tok::equal) && "Default argument not starting with '='"); - SourceLocation EqualLoc = ConsumeToken(); - - // The argument isn't actually potentially evaluated unless it is - // used. - EnterExpressionEvaluationContext Eval(Actions, - Sema::PotentiallyEvaluatedIfUsed); - - ExprResult DefArgResult(ParseAssignmentExpression()); - if (DefArgResult.isInvalid()) - Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param); - else { - if (Tok.is(tok::cxx_defaultarg_end)) - ConsumeToken(); - else - Diag(Tok.getLocation(), diag::err_default_arg_unparsed); - Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc, - DefArgResult.take()); - } - - assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, - Tok.getLocation()) && - "ParseAssignmentExpression went over the default arg tokens!"); - // There could be leftover tokens (e.g. because of an error). - // Skip through until we reach the original token position. - while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) - ConsumeAnyToken(); - - delete Toks; - LM.DefaultArgs[I].Toks = 0; - } + delete Toks; + LM.DefaultArgs[I].Toks = 0; } - PrototypeScope.Exit(); - - // Finish the delayed C++ method declaration. - Actions.ActOnFinishDelayedCXXMethodDeclaration(getCurScope(), LM.Method); } + PrototypeScope.Exit(); - for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I) - ParseLexedMethodDeclarations(*Class.NestedClasses[I]); - - if (HasClassScope) - Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); + // Finish the delayed C++ method declaration. + Actions.ActOnFinishDelayedCXXMethodDeclaration(getCurScope(), LM.Method); } /// ParseLexedMethodDefs - We finished parsing the member specification of a top @@ -185,7 +212,7 @@ void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) { /// collected during its parsing and parse them all. void Parser::ParseLexedMethodDefs(ParsingClass &Class) { bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; - ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); + ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); if (HasTemplateScope) Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); @@ -193,73 +220,72 @@ void Parser::ParseLexedMethodDefs(ParsingClass &Class) { ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, HasClassScope); - for (; !Class.MethodDefs.empty(); Class.MethodDefs.pop_front()) { - LexedMethod &LM = Class.MethodDefs.front(); - - // If this is a member template, introduce the template parameter scope. - ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); - if (LM.TemplateScope) - Actions.ActOnReenterTemplateScope(getCurScope(), LM.D); - - // Save the current token position. - SourceLocation origLoc = Tok.getLocation(); - - assert(!LM.Toks.empty() && "Empty body!"); - // Append the current token at the end of the new token stream so that it - // doesn't get lost. - LM.Toks.push_back(Tok); - PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false); - - // Consume the previously pushed token. - ConsumeAnyToken(); - assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) - && "Inline method not starting with '{', ':' or 'try'"); + for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) { + Class.LateParsedDeclarations[i]->ParseLexedMethodDefs(); + } +} - // Parse the method body. Function body parsing code is similar enough - // to be re-used for method bodies as well. - ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); - Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D); +void Parser::ParseLexedMethodDef(LexedMethod &LM) { + // If this is a member template, introduce the template parameter scope. + ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); + if (LM.TemplateScope) + Actions.ActOnReenterTemplateScope(getCurScope(), LM.D); + + // Save the current token position. + SourceLocation origLoc = Tok.getLocation(); + + assert(!LM.Toks.empty() && "Empty body!"); + // Append the current token at the end of the new token stream so that it + // doesn't get lost. + LM.Toks.push_back(Tok); + PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false); + + // Consume the previously pushed token. + ConsumeAnyToken(); + assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) + && "Inline method not starting with '{', ':' or 'try'"); + + // Parse the method body. Function body parsing code is similar enough + // to be re-used for method bodies as well. + ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); + Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D); + + if (Tok.is(tok::kw_try)) { + ParseFunctionTryBlock(LM.D); + assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, + Tok.getLocation()) && + "ParseFunctionTryBlock went over the cached tokens!"); + // There could be leftover tokens (e.g. because of an error). + // Skip through until we reach the original token position. + while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) + ConsumeAnyToken(); + return; + } + if (Tok.is(tok::colon)) { + ParseConstructorInitializer(LM.D); - if (Tok.is(tok::kw_try)) { - ParseFunctionTryBlock(LM.D); - assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, - Tok.getLocation()) && - "ParseFunctionTryBlock went over the cached tokens!"); - // There could be leftover tokens (e.g. because of an error). - // Skip through until we reach the original token position. + // Error recovery. + if (!Tok.is(tok::l_brace)) { + Actions.ActOnFinishFunctionBody(LM.D, 0); + return; + } + } else + Actions.ActOnDefaultCtorInitializers(LM.D); + + ParseFunctionStatementBody(LM.D); + + if (Tok.getLocation() != origLoc) { + // Due to parsing error, we either went over the cached tokens or + // there are still cached tokens left. If it's the latter case skip the + // leftover tokens. + // Since this is an uncommon situation that should be avoided, use the + // expensive isBeforeInTranslationUnit call. + if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(), + origLoc)) while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) ConsumeAnyToken(); - continue; - } - if (Tok.is(tok::colon)) { - ParseConstructorInitializer(LM.D); - - // Error recovery. - if (!Tok.is(tok::l_brace)) { - Actions.ActOnFinishFunctionBody(LM.D, 0); - continue; - } - } else - Actions.ActOnDefaultCtorInitializers(LM.D); - - ParseFunctionStatementBody(LM.D); - - if (Tok.getLocation() != origLoc) { - // Due to parsing error, we either went over the cached tokens or - // there are still cached tokens left. If it's the latter case skip the - // leftover tokens. - // Since this is an uncommon situation that should be avoided, use the - // expensive isBeforeInTranslationUnit call. - if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(), - origLoc)) - while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) - ConsumeAnyToken(); - } } - - for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I) - ParseLexedMethodDefs(*Class.NestedClasses[I]); } /// ConsumeAndStoreUntil - Consume and store the token at the passed token diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index c02f41a268..8fed447bc2 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1203,9 +1203,8 @@ void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo, if (!LateMethod) { // Push this method onto the stack of late-parsed method // declarations. - getCurrentClass().MethodDecls.push_back( - LateParsedMethodDeclaration(ThisDecl)); - LateMethod = &getCurrentClass().MethodDecls.back(); + LateMethod = new LateParsedMethodDeclaration(this, ThisDecl); + getCurrentClass().LateParsedDeclarations.push_back(LateMethod); LateMethod->TemplateScope = getCurScope()->isTemplateParamScope(); // Add all of the parameters prior to this one (they don't @@ -1911,8 +1910,8 @@ void Parser::PushParsingClass(Decl *ClassDecl, bool NonNestedClass) { /// \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]); + for (unsigned I = 0, N = Class->LateParsedDeclarations.size(); I != N; ++I) + delete Class->LateParsedDeclarations[I]; delete Class; } @@ -1938,13 +1937,12 @@ void Parser::PopParsingClass() { } assert(!ClassStack.empty() && "Missing top-level class?"); - if (Victim->MethodDecls.empty() && Victim->MethodDefs.empty() && - Victim->NestedClasses.empty()) { + if (Victim->LateParsedDeclarations.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; + DeallocateParsedClasses(Victim); return; } @@ -1952,7 +1950,7 @@ void Parser::PopParsingClass() { // after the top-level class is completely defined. Therefore, add // it to the list of nested classes within its parent. assert(getCurScope()->isClassScope() && "Nested class outside of class scope?"); - ClassStack.top()->NestedClasses.push_back(Victim); + ClassStack.top()->LateParsedDeclarations.push_back(new LateParsedClass(this, Victim)); Victim->TemplateScope = getCurScope()->getParent()->isTemplateParamScope(); } |