diff options
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/MinimalAction.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 3 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 59 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 66 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 15 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 25 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 7 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 98 |
8 files changed, 155 insertions, 120 deletions
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp index 049228f56c..f31aef61d3 100644 --- a/lib/Parse/MinimalAction.cpp +++ b/lib/Parse/MinimalAction.cpp @@ -144,7 +144,7 @@ MinimalAction::isTemplateName(IdentifierInfo &II, Scope *S, /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is /// popped. Action::DeclPtrTy -MinimalAction::ActOnDeclarator(Scope *S, Declarator &D, DeclPtrTy LastInGroup) { +MinimalAction::ActOnDeclarator(Scope *S, Declarator &D) { IdentifierInfo *II = D.getIdentifier(); // If there is no identifier associated with this declarator, bail out. diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index e139cf9c3e..45eaa74681 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -27,8 +27,7 @@ Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) { assert((Tok.is(tok::l_brace) || Tok.is(tok::colon)) && "Current token not a '{' or ':'!"); - DeclPtrTy FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0, - DeclPtrTy()); + DeclPtrTy FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0); // Consume the tokens and store them for later parsing. diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 5a8b2b8569..1f8522f094 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -228,27 +228,36 @@ void Parser::FuzzyParseMicrosoftDeclSpec() { /// [C++0x] static_assert-declaration /// others... [FIXME] /// -Parser::DeclPtrTy Parser::ParseDeclaration(unsigned Context) { +Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context) { + DeclPtrTy SingleDecl; switch (Tok.getKind()) { case tok::kw_export: case tok::kw_template: - return ParseTemplateDeclarationOrSpecialization(Context); + SingleDecl = ParseTemplateDeclarationOrSpecialization(Context); + break; case tok::kw_namespace: - return ParseNamespace(Context); + SingleDecl = ParseNamespace(Context); + break; case tok::kw_using: - return ParseUsingDirectiveOrDeclaration(Context); + SingleDecl = ParseUsingDirectiveOrDeclaration(Context); + break; case tok::kw_static_assert: - return ParseStaticAssertDeclaration(); + SingleDecl = ParseStaticAssertDeclaration(); + break; default: return ParseSimpleDeclaration(Context); } + + // This routine returns a DeclGroup, if the thing we parsed only contains a + // single decl, convert it now. + return Actions.ConvertDeclToDeclGroup(SingleDecl); } /// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl] /// declaration-specifiers init-declarator-list[opt] ';' ///[C90/C++]init-declarator-list ';' [TODO] /// [OMP] threadprivate-directive [TODO] -Parser::DeclPtrTy Parser::ParseSimpleDeclaration(unsigned Context) { +Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context) { // Parse the common declaration-specifiers piece. DeclSpec DS; ParseDeclarationSpecifiers(DS); @@ -257,7 +266,8 @@ Parser::DeclPtrTy Parser::ParseSimpleDeclaration(unsigned Context) { // declaration-specifiers init-declarator-list[opt] ';' if (Tok.is(tok::semi)) { ConsumeToken(); - return Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + return Actions.ConvertDeclToDeclGroup(TheDecl); } Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context); @@ -291,12 +301,11 @@ Parser::DeclPtrTy Parser::ParseSimpleDeclaration(unsigned Context) { /// According to the standard grammar, =default and =delete are function /// definitions, but that definitely doesn't fit with the parser here. /// -Parser::DeclPtrTy Parser:: +Parser::DeclGroupPtrTy Parser:: ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { - - // Declarators may be grouped together ("int X, *Y, Z();"). Provide info so - // that they can be chained properly if the actions want this. - Parser::DeclPtrTy LastDeclInGroup; + // Declarators may be grouped together ("int X, *Y, Z();"). Remember the decls + // that we parse together here. + llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup; // At this point, we know that it is not a function definition. Parse the // rest of the init-declarator-list. @@ -307,7 +316,7 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { OwningExprResult AsmLabel(ParseSimpleAsm(&Loc)); if (AsmLabel.isInvalid()) { SkipUntil(tok::semi); - return DeclPtrTy(); + return DeclGroupPtrTy(); } D.setAsmLabel(AsmLabel.release()); @@ -322,21 +331,22 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { } // Inform the current actions module that we just parsed this declarator. - LastDeclInGroup = Actions.ActOnDeclarator(CurScope, D, LastDeclInGroup); + DeclPtrTy ThisDecl = Actions.ActOnDeclarator(CurScope, D); + DeclsInGroup.push_back(ThisDecl); // Parse declarator '=' initializer. if (Tok.is(tok::equal)) { ConsumeToken(); if (getLang().CPlusPlus0x && Tok.is(tok::kw_delete)) { SourceLocation DelLoc = ConsumeToken(); - Actions.SetDeclDeleted(LastDeclInGroup, DelLoc); + Actions.SetDeclDeleted(ThisDecl, DelLoc); } else { OwningExprResult Init(ParseInitializer()); if (Init.isInvalid()) { SkipUntil(tok::semi); - return DeclPtrTy(); + return DeclGroupPtrTy(); } - Actions.AddInitializerToDecl(LastDeclInGroup, move(Init)); + Actions.AddInitializerToDecl(ThisDecl, move(Init)); } } else if (Tok.is(tok::l_paren)) { // Parse C++ direct initializer: '(' expression-list ')' @@ -355,12 +365,12 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { if (!InvalidExpr) { assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() && "Unexpected number of commas!"); - Actions.AddCXXDirectInitializerToDecl(LastDeclInGroup, LParenLoc, + Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc, move_arg(Exprs), &CommaLocs[0], RParenLoc); } } else { - Actions.ActOnUninitializedDecl(LastDeclInGroup); + Actions.ActOnUninitializedDecl(ThisDecl); } // If we don't have a comma, it is either the end of the list (a ';') or an @@ -395,23 +405,26 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { // for(is key; in keys) is error. if (D.getContext() == Declarator::ForContext && isTokIdentifier_in()) { Diag(Tok, diag::err_parse_error); - return DeclPtrTy(); + return DeclGroupPtrTy(); } - return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup); + + return Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0], + DeclsInGroup.size()); } // If this is an ObjC2 for-each loop, this is a successful declarator // parse. The syntax for these looks like: // 'for' '(' declaration 'in' expr ')' statement if (D.getContext() == Declarator::ForContext && isTokIdentifier_in()) - return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup); + return Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0], + DeclsInGroup.size()); Diag(Tok, diag::err_parse_error); // Skip to end of block or statement SkipUntil(tok::r_brace, true, true); if (Tok.is(tok::semi)) ConsumeToken(); - return DeclPtrTy(); + return DeclGroupPtrTy(); } /// ParseSpecifierQualifierList diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index c50a033e56..37a460cd41 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -663,14 +663,17 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const /// constant-initializer: /// '=' constant-expression /// -Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { +void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { // static_assert-declaration - if (Tok.is(tok::kw_static_assert)) - return ParseStaticAssertDeclaration(); + if (Tok.is(tok::kw_static_assert)) { + ParseStaticAssertDeclaration(); + return; + } - if (Tok.is(tok::kw_template)) - return ParseTemplateDeclarationOrSpecialization(Declarator::MemberContext, - AS); + if (Tok.is(tok::kw_template)) { + ParseTemplateDeclarationOrSpecialization(Declarator::MemberContext, AS); + return; + } // Handle: member-declaration ::= '__extension__' member-declaration if (Tok.is(tok::kw___extension__)) { @@ -692,14 +695,15 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { // class-specifier or an enum-specifier or in a friend declaration. // FIXME: Friend declarations. switch (DS.getTypeSpecType()) { - case DeclSpec::TST_struct: - case DeclSpec::TST_union: - case DeclSpec::TST_class: - case DeclSpec::TST_enum: - return Actions.ParsedFreeStandingDeclSpec(CurScope, DS); - default: - Diag(DSStart, diag::err_no_declarators); - return DeclPtrTy(); + case DeclSpec::TST_struct: + case DeclSpec::TST_union: + case DeclSpec::TST_class: + case DeclSpec::TST_enum: + Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + return; + default: + Diag(DSStart, diag::err_no_declarators); + return; } } @@ -714,7 +718,7 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { SkipUntil(tok::r_brace, true); if (Tok.is(tok::semi)) ConsumeToken(); - return DeclPtrTy(); + return; } // function-definition: @@ -724,7 +728,7 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { Diag(Tok, diag::err_func_def_no_params); ConsumeBrace(); SkipUntil(tok::r_brace, true); - return DeclPtrTy(); + return; } if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { @@ -734,10 +738,11 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { // assumes the declarator represents a function, not a typedef. ConsumeBrace(); SkipUntil(tok::r_brace, true); - return DeclPtrTy(); + return; } - return ParseCXXInlineMethodDef(AS, DeclaratorInfo); + ParseCXXInlineMethodDef(AS, DeclaratorInfo); + return; } } @@ -745,7 +750,7 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { // member-declarator // member-declarator-list ',' member-declarator - DeclPtrTy LastDeclInGroup; + llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup; OwningExprResult BitfieldSize(Actions); OwningExprResult Init(Actions); @@ -784,14 +789,14 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { } // NOTE: If Sema is the Action module and declarator is an instance field, - // this call will *not* return the created decl; LastDeclInGroup will be - // returned instead. + // this call will *not* return the created decl; It will return null. // See Sema::ActOnCXXMemberDeclarator for details. - LastDeclInGroup = Actions.ActOnCXXMemberDeclarator(CurScope, AS, - DeclaratorInfo, - BitfieldSize.release(), - Init.release(), - LastDeclInGroup); + DeclPtrTy ThisDecl = Actions.ActOnCXXMemberDeclarator(CurScope, AS, + DeclaratorInfo, + BitfieldSize.release(), + Init.release()); + if (ThisDecl) + DeclsInGroup.push_back(ThisDecl); if (DeclaratorInfo.isFunctionDeclarator() && DeclaratorInfo.getDeclSpec().getStorageClassSpec() @@ -807,7 +812,7 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { // Push this method onto the stack of late-parsed method // declarations. getCurTopClassStack().MethodDecls.push_back( - LateParsedMethodDeclaration(LastDeclInGroup)); + LateParsedMethodDeclaration(ThisDecl)); LateMethod = &getCurTopClassStack().MethodDecls.back(); // Add all of the parameters prior to this one (they don't @@ -853,8 +858,9 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { if (Tok.is(tok::semi)) { ConsumeToken(); - // Reverse the chain list. - return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup); + Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0], + DeclsInGroup.size()); + return; } Diag(Tok, diag::err_expected_semi_decl_list); @@ -862,7 +868,7 @@ Parser::DeclPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { SkipUntil(tok::r_brace, true, true); if (Tok.is(tok::semi)) ConsumeToken(); - return DeclPtrTy(); + return; } /// ParseCXXMemberSpecification - Parse the class definition. diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 8ff1944a9d..05c919cbea 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -215,7 +215,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, tok::ObjCKeywordKind contextKey) { llvm::SmallVector<DeclPtrTy, 32> allMethods; llvm::SmallVector<DeclPtrTy, 16> allProperties; - llvm::SmallVector<DeclPtrTy, 8> allTUVariables; + llvm::SmallVector<DeclGroupPtrTy, 8> allTUVariables; tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword; SourceLocation AtEndLoc; @@ -253,8 +253,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, // FIXME: as the name implies, this rule allows function definitions. // We could pass a flag or check for functions during semantic analysis. - DeclPtrTy VFDecl = ParseDeclarationOrFunctionDefinition(); - allTUVariables.push_back(VFDecl); + allTUVariables.push_back(ParseDeclarationOrFunctionDefinition()); continue; } @@ -359,13 +358,9 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, // Insert collected methods declarations into the @interface object. // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit. Actions.ActOnAtEnd(AtEndLoc, interfaceDecl, - allMethods.empty() ? 0 : &allMethods[0], - allMethods.size(), - allProperties.empty() ? 0 : &allProperties[0], - allProperties.size(), - allTUVariables.empty() ? 0 : - &allTUVariables[0], - allTUVariables.size()); + &allMethods[0], allMethods.size(), + &allProperties[0], allProperties.size(), + &allTUVariables[0], allTUVariables.size()); } /// Parse property attribute declarations. diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index b996c74fcf..b1a32decff 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -101,7 +101,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) { default: { if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) { SourceLocation DeclStart = Tok.getLocation(); - DeclPtrTy Decl = ParseDeclaration(Declarator::BlockContext); + DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext); // FIXME: Pass in the right location for the end of the declstmt. return Actions.ActOnDeclStmt(Decl, DeclStart, DeclStart); } @@ -444,7 +444,7 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { if (isDeclarationStatement()) { // FIXME: Save the __extension__ on the decl as a node somehow. SourceLocation DeclStart = Tok.getLocation(); - DeclPtrTy Res = ParseDeclaration(Declarator::BlockContext); + DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext); // FIXME: Pass in the right location for the end of the declstmt. R = Actions.ActOnDeclStmt(Res, DeclStart, DeclStart); } else { @@ -912,10 +912,9 @@ Parser::OwningStmtResult Parser::ParseForStatement() { Diag(Tok, diag::ext_c99_variable_decl_in_for_loop); SourceLocation DeclStart = Tok.getLocation(); - DeclPtrTy aBlockVarDecl = ParseSimpleDeclaration(Declarator::ForContext); + DeclGroupPtrTy VarDecls = ParseSimpleDeclaration(Declarator::ForContext); // FIXME: Pass in the right location for the end of the declstmt. - FirstPart = Actions.ActOnDeclStmt(aBlockVarDecl, DeclStart, - DeclStart); + FirstPart = Actions.ActOnDeclStmt(VarDecls, DeclStart, DeclStart); if ((ForEach = isTokIdentifier_in())) { ConsumeToken(); // consume 'in' SecondPart = ParseExpression(); @@ -929,12 +928,10 @@ Parser::OwningStmtResult Parser::ParseForStatement() { if (Tok.is(tok::semi)) { ConsumeToken(); - } - else if ((ForEach = isTokIdentifier_in())) { + } else if ((ForEach = isTokIdentifier_in())) { ConsumeToken(); // consume 'in' SecondPart = ParseExpression(); - } - else { + } else { if (!Value.isInvalid()) Diag(Tok, diag::err_expected_semi_for); SkipUntil(tok::semi); } @@ -995,11 +992,11 @@ Parser::OwningStmtResult Parser::ParseForStatement() { return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart), move(SecondPart), move(ThirdPart), RParenLoc, move(Body)); - else - return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, - move(FirstPart), - move(SecondPart), - RParenLoc, move(Body)); + + return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, + move(FirstPart), + move(SecondPart), + RParenLoc, move(Body)); } /// ParseGotoStatement diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 29b8a147db..b962cbf646 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -94,7 +94,12 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template)); // Parse the actual template declaration. - return ParseDeclarationOrFunctionDefinition(&ParamLists, AS); + + // FIXME: This accepts template<typename x> int y; + // FIXME: Converting DeclGroupPtr to DeclPtr like this is an insanely gruesome + // hack, will bring up on cfe-dev. + DeclGroupPtrTy DG = ParseDeclarationOrFunctionDefinition(&ParamLists, AS); + return DeclPtrTy::make(DG.get()); } /// ParseTemplateParameters - Parses a template-parameter-list enclosed in diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 00a3349c21..56f922d400 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -324,8 +324,8 @@ void Parser::Initialize() { /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the /// action tells us to. This returns true if the EOF was encountered. -bool Parser::ParseTopLevelDecl(DeclPtrTy &Result) { - Result = DeclPtrTy(); +bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { + Result = DeclGroupPtrTy(); if (Tok.is(tok::eof)) { Actions.ActOnEndOfTranslationUnit(); return true; @@ -342,7 +342,7 @@ bool Parser::ParseTopLevelDecl(DeclPtrTy &Result) { void Parser::ParseTranslationUnit() { Initialize(); - DeclPtrTy Res; + DeclGroupPtrTy Res; while (!ParseTopLevelDecl(Res)) /*parse them all*/; @@ -368,20 +368,21 @@ void Parser::ParseTranslationUnit() { /// [GNU] asm-definition: /// simple-asm-expr ';' /// -Parser::DeclPtrTy Parser::ParseExternalDeclaration() { +Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration() { + DeclPtrTy SingleDecl; switch (Tok.getKind()) { case tok::semi: Diag(Tok, diag::ext_top_level_semi); ConsumeToken(); // TODO: Invoke action for top-level semicolon. - return DeclPtrTy(); + return DeclGroupPtrTy(); case tok::r_brace: Diag(Tok, diag::err_expected_external_declaration); ConsumeBrace(); - return DeclPtrTy(); + return DeclGroupPtrTy(); case tok::eof: Diag(Tok, diag::err_expected_external_declaration); - return DeclPtrTy(); + return DeclGroupPtrTy(); case tok::kw___extension__: { // __extension__ silences extension warnings in the subexpression. ExtensionRAIIObject O(Diags); // Use RAII to do this. @@ -394,20 +395,26 @@ Parser::DeclPtrTy Parser::ParseExternalDeclaration() { ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "top-level asm block"); - if (!Result.isInvalid()) - return Actions.ActOnFileScopeAsmDecl(Tok.getLocation(), move(Result)); - return DeclPtrTy(); + if (Result.isInvalid()) + return DeclGroupPtrTy(); + SingleDecl = Actions.ActOnFileScopeAsmDecl(Tok.getLocation(), move(Result)); + break; } case tok::at: - // @ is not a legal token unless objc is enabled, no need to check. - return ParseObjCAtDirectives(); + // @ is not a legal token unless objc is enabled, no need to check for ObjC. + /// FIXME: ParseObjCAtDirectives should return a DeclGroup for things like + /// @class foo, bar; + SingleDecl = ParseObjCAtDirectives(); + break; case tok::minus: case tok::plus: - if (getLang().ObjC1) - return ParseObjCMethodDefinition(); - Diag(Tok, diag::err_expected_external_declaration); - ConsumeToken(); - return DeclPtrTy(); + if (!getLang().ObjC1) { + Diag(Tok, diag::err_expected_external_declaration); + ConsumeToken(); + return DeclGroupPtrTy(); + } + SingleDecl = ParseObjCMethodDefinition(); + break; case tok::kw_using: case tok::kw_namespace: case tok::kw_typedef: @@ -420,6 +427,10 @@ Parser::DeclPtrTy Parser::ParseExternalDeclaration() { // We can't tell whether this is a function-definition or declaration yet. return ParseDeclarationOrFunctionDefinition(); } + + // This routine returns a DeclGroup, if the thing we parsed only contains a + // single decl, convert it now. + return Actions.ConvertDeclToDeclGroup(SingleDecl); } /// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or @@ -438,7 +449,7 @@ Parser::DeclPtrTy Parser::ParseExternalDeclaration() { /// [!C99] init-declarator-list ';' [TODO: warn in c99 mode] /// [OMP] threadprivate-directive [TODO] /// -Parser::DeclPtrTy +Parser::DeclGroupPtrTy Parser::ParseDeclarationOrFunctionDefinition( TemplateParameterLists *TemplateParams, AccessSpecifier AS) { @@ -450,7 +461,8 @@ Parser::ParseDeclarationOrFunctionDefinition( // declaration-specifiers init-declarator-list[opt] ';' if (Tok.is(tok::semi)) { ConsumeToken(); - return Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS); + return Actions.ConvertDeclToDeclGroup(TheDecl); } // ObjC2 allows prefix attributes on class interfaces and protocols. @@ -462,14 +474,18 @@ Parser::ParseDeclarationOrFunctionDefinition( !Tok.isObjCAtKeyword(tok::objc_protocol)) { Diag(Tok, diag::err_objc_unexpected_attr); SkipUntil(tok::semi); // FIXME: better skip? - return DeclPtrTy(); + return DeclGroupPtrTy(); } const char *PrevSpec = 0; if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec)) Diag(AtLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; + + DeclPtrTy TheDecl; if (Tok.isObjCAtKeyword(tok::objc_protocol)) - return ParseObjCAtProtocolDeclaration(AtLoc, DS.getAttributes()); - return ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes()); + TheDecl = ParseObjCAtProtocolDeclaration(AtLoc, DS.getAttributes()); + else + TheDecl = ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes()); + return Actions.ConvertDeclToDeclGroup(TheDecl); } // If the declspec consisted only of 'extern' and we have a string @@ -477,8 +493,10 @@ Parser::ParseDeclarationOrFunctionDefinition( // 'extern "C"'. if (Tok.is(tok::string_literal) && getLang().CPlusPlus && DS.getStorageClassSpec() == DeclSpec::SCS_extern && - DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) - return ParseLinkage(Declarator::FileContext); + DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) { + DeclPtrTy TheDecl = ParseLinkage(Declarator::FileContext); + return Actions.ConvertDeclToDeclGroup(TheDecl); + } // Parse the first declarator. Declarator DeclaratorInfo(DS, Declarator::FileContext); @@ -489,7 +507,7 @@ Parser::ParseDeclarationOrFunctionDefinition( SkipUntil(tok::r_brace, true, true); if (Tok.is(tok::semi)) ConsumeToken(); - return DeclPtrTy(); + return DeclGroupPtrTy(); } // If the declarator is the start of a function definition, handle it. @@ -500,8 +518,12 @@ Parser::ParseDeclarationOrFunctionDefinition( Tok.is(tok::kw___attribute) || // int X() __attr__ -> not a function def (getLang().CPlusPlus && Tok.is(tok::l_paren)) ) { // int X(0) -> not a function def [C++] - // FALL THROUGH. - } else if (DeclaratorInfo.isFunctionDeclarator() && + // Parse the init-declarator-list for a normal declaration. + return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo); + } + + + if (DeclaratorInfo.isFunctionDeclarator() && (Tok.is(tok::l_brace) || // int X() {} (!getLang().CPlusPlus && isDeclarationSpecifier()) || // int X(f) int f; {} @@ -519,20 +541,18 @@ Parser::ParseDeclarationOrFunctionDefinition( } else { SkipUntil(tok::semi); } - return DeclPtrTy(); + return DeclGroupPtrTy(); } - return ParseFunctionDefinition(DeclaratorInfo); - } else { - if (DeclaratorInfo.isFunctionDeclarator()) - Diag(Tok, diag::err_expected_fn_body); - else - Diag(Tok, diag::err_invalid_token_after_toplevel_declarator); - SkipUntil(tok::semi); - return DeclPtrTy(); + DeclPtrTy TheDecl = ParseFunctionDefinition(DeclaratorInfo); + return Actions.ConvertDeclToDeclGroup(TheDecl); } - - // Parse the init-declarator-list for a normal declaration. - return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo); + + if (DeclaratorInfo.isFunctionDeclarator()) + Diag(Tok, diag::err_expected_fn_body); + else + Diag(Tok, diag::err_invalid_token_after_toplevel_declarator); + SkipUntil(tok::semi); + return DeclGroupPtrTy(); } /// ParseFunctionDefinition - We parsed and verified that the specified |