aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-05-12 21:31:51 +0000
committerDouglas Gregor <dgregor@apple.com>2009-05-12 21:31:51 +0000
commit1426e534b4fca6a05b1120d634aae46be79ca17c (patch)
treec7e2cb48eceb9e463b06b8d08b69c8569c0e85f1 /lib/Parse/ParseDecl.cpp
parent7a574ccd5247189693e0764bf1f5711d33ca6064 (diff)
Refactor the parsing of declarations so that template declarations can
parse just a single declaration and provide a reasonable diagnostic when the "only one declarator per template declaration" rule is violated. This eliminates some ugly, ugly hackery where we used to require thatn the layout of a DeclGroup of a single element be the same as the layout of a single declaration. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71596 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
-rw-r--r--lib/Parse/ParseDecl.cpp157
1 files changed, 89 insertions, 68 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index b3c2d8c555..9d7d9d400f 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -233,8 +233,14 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
SourceLocation &DeclEnd) {
DeclPtrTy SingleDecl;
switch (Tok.getKind()) {
- case tok::kw_export:
case tok::kw_template:
+ if (NextToken().isNot(tok::less)) {
+ SingleDecl = ParseExplicitInstantiation(DeclEnd);
+ break;
+ }
+ // Fall through for template declarations and specializations
+
+ case tok::kw_export:
SingleDecl = ParseTemplateDeclarationOrSpecialization(Context, DeclEnd);
break;
case tok::kw_namespace:
@@ -302,15 +308,11 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
return DG;
}
-
-/// ParseInitDeclaratorListAfterFirstDeclarator - Parse 'declaration' after
-/// parsing 'declaration-specifiers declarator'. This method is split out this
-/// way to handle the ambiguity between top-level function-definitions and
-/// declarations.
+/// \brief Parse 'declaration' after parsing 'declaration-specifiers
+/// declarator'. This method parses the remainder of the declaration
+/// (including any attributes or initializer, among other things) and
+/// finalizes the declaration.
///
-/// init-declarator-list: [C99 6.7]
-/// init-declarator
-/// init-declarator-list ',' init-declarator
/// init-declarator: [C99 6.7]
/// declarator
/// declarator '=' initializer
@@ -327,6 +329,81 @@ Parser::DeclGroupPtrTy 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::ParseDeclarationAfterDeclarator(Declarator &D) {
+ // If a simple-asm-expr is present, parse it.
+ if (Tok.is(tok::kw_asm)) {
+ SourceLocation Loc;
+ OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
+ if (AsmLabel.isInvalid()) {
+ SkipUntil(tok::semi, true, true);
+ return DeclPtrTy();
+ }
+
+ D.setAsmLabel(AsmLabel.release());
+ D.SetRangeEnd(Loc);
+ }
+
+ // If attributes are present, parse them.
+ if (Tok.is(tok::kw___attribute)) {
+ SourceLocation Loc;
+ AttributeList *AttrList = ParseAttributes(&Loc);
+ D.AddAttributes(AttrList, Loc);
+ }
+
+ // Inform the current actions module that we just parsed this declarator.
+ DeclPtrTy ThisDecl = Actions.ActOnDeclarator(CurScope, D);
+
+ // Parse declarator '=' initializer.
+ if (Tok.is(tok::equal)) {
+ ConsumeToken();
+ if (getLang().CPlusPlus0x && Tok.is(tok::kw_delete)) {
+ SourceLocation DelLoc = ConsumeToken();
+ Actions.SetDeclDeleted(ThisDecl, DelLoc);
+ } else {
+ OwningExprResult Init(ParseInitializer());
+ if (Init.isInvalid()) {
+ SkipUntil(tok::semi, true, true);
+ return DeclPtrTy();
+ }
+ Actions.AddInitializerToDecl(ThisDecl, move(Init));
+ }
+ } else if (Tok.is(tok::l_paren)) {
+ // Parse C++ direct initializer: '(' expression-list ')'
+ SourceLocation LParenLoc = ConsumeParen();
+ ExprVector Exprs(Actions);
+ CommaLocsTy CommaLocs;
+
+ if (ParseExpressionList(Exprs, CommaLocs)) {
+ SkipUntil(tok::r_paren);
+ } else {
+ // Match the ')'.
+ SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+
+ assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
+ "Unexpected number of commas!");
+ Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc,
+ move_arg(Exprs),
+ &CommaLocs[0], RParenLoc);
+ }
+ } else {
+ Actions.ActOnUninitializedDecl(ThisDecl);
+ }
+
+ return ThisDecl;
+}
+
+/// ParseInitDeclaratorListAfterFirstDeclarator - Parse 'declaration' after
+/// parsing 'declaration-specifiers declarator'. This method is split out this
+/// way to handle the ambiguity between top-level function-definitions and
+/// declarations.
+///
+/// init-declarator-list: [C99 6.7]
+/// init-declarator
+/// init-declarator-list ',' init-declarator
+///
+/// According to the standard grammar, =default and =delete are function
+/// definitions, but that definitely doesn't fit with the parser here.
+///
Parser::DeclGroupPtrTy Parser::
ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
// Declarators may be grouped together ("int X, *Y, Z();"). Remember the decls
@@ -336,65 +413,9 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
// At this point, we know that it is not a function definition. Parse the
// rest of the init-declarator-list.
while (1) {
- // If a simple-asm-expr is present, parse it.
- if (Tok.is(tok::kw_asm)) {
- SourceLocation Loc;
- OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
- if (AsmLabel.isInvalid()) {
- SkipUntil(tok::semi, true, true);
- return DeclGroupPtrTy();
- }
-
- D.setAsmLabel(AsmLabel.release());
- D.SetRangeEnd(Loc);
- }
-
- // If attributes are present, parse them.
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
- D.AddAttributes(AttrList, Loc);
- }
-
- // Inform the current actions module that we just parsed this declarator.
- 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(ThisDecl, DelLoc);
- } else {
- OwningExprResult Init(ParseInitializer());
- if (Init.isInvalid()) {
- SkipUntil(tok::semi, true, true);
- return DeclGroupPtrTy();
- }
- Actions.AddInitializerToDecl(ThisDecl, move(Init));
- }
- } else if (Tok.is(tok::l_paren)) {
- // Parse C++ direct initializer: '(' expression-list ')'
- SourceLocation LParenLoc = ConsumeParen();
- ExprVector Exprs(Actions);
- CommaLocsTy CommaLocs;
-
- if (ParseExpressionList(Exprs, CommaLocs)) {
- SkipUntil(tok::r_paren);
- } else {
- // Match the ')'.
- SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
-
- assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
- "Unexpected number of commas!");
- Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc,
- move_arg(Exprs),
- &CommaLocs[0], RParenLoc);
- }
- } else {
- Actions.ActOnUninitializedDecl(ThisDecl);
- }
+ DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D);
+ if (ThisDecl.get())
+ DeclsInGroup.push_back(ThisDecl);
// If we don't have a comma, it is either the end of the list (a ';') or an
// error, bail out.