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/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