Push DeclGroup much farther throughout the compiler. Now the various
productions (except the already broken ObjC cases like @class X,Y;) in
the parser that can produce more than one Decl return a DeclGroup instead
of a Decl, etc.
This allows elimination of the Decl::NextDeclarator field, and exposes
various clients that should look at all decls in a group, but which were
only looking at one (such as the dumper, printer, etc). These have been
fixed.
Still TODO:
1) there are some FIXME's in the code about potentially using
DeclGroup for better location info.
2) ParseObjCAtDirectives should return a DeclGroup due to @class etc.
3) I'm not sure what is going on with StmtIterator.cpp, or if it can
be radically simplified now.
4) I put a truly horrible hack in ParseTemplate.cpp.
I plan to bring up #3/4 on the mailing list, but don't plan to tackle
#1/2 in the short term.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68002 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index 049228f..f31aef6 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -144,7 +144,7 @@
/// 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 e139cf9..45eaa74 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -27,8 +27,7 @@
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 5a8b2b8..1f8522f 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -228,27 +228,36 @@
/// [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 @@
// 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 @@
/// 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 @@
OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
if (AsmLabel.isInvalid()) {
SkipUntil(tok::semi);
- return DeclPtrTy();
+ return DeclGroupPtrTy();
}
D.setAsmLabel(AsmLabel.release());
@@ -322,21 +331,22 @@
}
// 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 @@
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 @@
// 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 c50a033..37a460c 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -663,14 +663,17 @@
/// 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 @@
// 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 @@
SkipUntil(tok::r_brace, true);
if (Tok.is(tok::semi))
ConsumeToken();
- return DeclPtrTy();
+ return;
}
// function-definition:
@@ -724,7 +728,7 @@
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 @@
// 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 @@
// member-declarator
// member-declarator-list ',' member-declarator
- DeclPtrTy LastDeclInGroup;
+ llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
OwningExprResult BitfieldSize(Actions);
OwningExprResult Init(Actions);
@@ -784,14 +789,14 @@
}
// 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 @@
// 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 @@
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 @@
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 8ff1944..05c919c 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -215,7 +215,7 @@
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 @@
// 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 @@
// 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 b996c74..b1a32de 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -101,7 +101,7 @@
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 @@
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 @@
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 @@
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 @@
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 29b8a14..b962cbf 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -94,7 +94,12 @@
} 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 00a3349..56f922d 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -324,8 +324,8 @@
/// 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 @@
void Parser::ParseTranslationUnit() {
Initialize();
- DeclPtrTy Res;
+ DeclGroupPtrTy Res;
while (!ParseTopLevelDecl(Res))
/*parse them all*/;
@@ -368,20 +368,21 @@
/// [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 @@
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 @@
// 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 @@
/// [!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 @@
// 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 @@
!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 @@
// '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 @@
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 @@
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 @@
} 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