aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseStmt.cpp
diff options
context:
space:
mode:
authorSean Hunt <rideau3@gmail.com>2009-11-21 08:43:09 +0000
committerSean Hunt <rideau3@gmail.com>2009-11-21 08:43:09 +0000
commitbbd37c62e34db3f5a95c899723484a76c71d7757 (patch)
tree6968f0bb9f714cd41a2035844e46e45d13736a9d /lib/Parse/ParseStmt.cpp
parent7c5c965b876c4c698d22b1e38b6b0b2534036110 (diff)
Added rudimentary C++0x attribute support.
The following attributes are currently supported in C++0x attribute lists (and in GNU ones as well): - align() - semantics believed to be conformant to n3000, except for redeclarations and what entities it may apply to - final - semantics believed to be conformant to CWG issue 817's proposed wording, except for redeclarations - noreturn - semantics believed to be conformant to n3000, except for redeclarations - carries_dependency - currently ignored (this is an optimization hint) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89543 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseStmt.cpp')
-rw-r--r--lib/Parse/ParseStmt.cpp113
1 files changed, 76 insertions, 37 deletions
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index ff08ebbe87..66e61dd949 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -78,6 +78,10 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
const char *SemiError = 0;
OwningStmtResult Res(Actions);
+ CXX0XAttributeList Attr;
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+ Attr = ParseCXX0XAttributes();
+
// Cases in this switch statement should fall through if the parser expects
// the token to end in a semicolon (in which case SemiError should be set),
// or they directly 'return;' if not.
@@ -98,14 +102,15 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
case tok::identifier:
if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement
// identifier ':' statement
- return ParseLabeledStatement();
+ return ParseLabeledStatement(Attr.AttrList);
}
// PASS THROUGH.
default: {
if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
- DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd);
+ DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd,
+ Attr);
return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
}
@@ -114,6 +119,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
return StmtError();
}
+ // FIXME: Use the attributes
// expression[opt] ';'
OwningExprResult Expr(ParseExpression());
if (Expr.isInvalid()) {
@@ -129,47 +135,50 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
}
case tok::kw_case: // C99 6.8.1: labeled-statement
- return ParseCaseStatement();
+ return ParseCaseStatement(Attr.AttrList);
case tok::kw_default: // C99 6.8.1: labeled-statement
- return ParseDefaultStatement();
+ return ParseDefaultStatement(Attr.AttrList);
case tok::l_brace: // C99 6.8.2: compound-statement
- return ParseCompoundStatement();
+ return ParseCompoundStatement(Attr.AttrList);
case tok::semi: // C99 6.8.3p3: expression[opt] ';'
return Actions.ActOnNullStmt(ConsumeToken());
case tok::kw_if: // C99 6.8.4.1: if-statement
- return ParseIfStatement();
+ return ParseIfStatement(Attr.AttrList);
case tok::kw_switch: // C99 6.8.4.2: switch-statement
- return ParseSwitchStatement();
+ return ParseSwitchStatement(Attr.AttrList);
case tok::kw_while: // C99 6.8.5.1: while-statement
- return ParseWhileStatement();
+ return ParseWhileStatement(Attr.AttrList);
case tok::kw_do: // C99 6.8.5.2: do-statement
- Res = ParseDoStatement();
+ Res = ParseDoStatement(Attr.AttrList);
SemiError = "do/while";
break;
case tok::kw_for: // C99 6.8.5.3: for-statement
- return ParseForStatement();
+ return ParseForStatement(Attr.AttrList);
case tok::kw_goto: // C99 6.8.6.1: goto-statement
- Res = ParseGotoStatement();
+ Res = ParseGotoStatement(Attr.AttrList);
SemiError = "goto";
break;
case tok::kw_continue: // C99 6.8.6.2: continue-statement
- Res = ParseContinueStatement();
+ Res = ParseContinueStatement(Attr.AttrList);
SemiError = "continue";
break;
case tok::kw_break: // C99 6.8.6.3: break-statement
- Res = ParseBreakStatement();
+ Res = ParseBreakStatement(Attr.AttrList);
SemiError = "break";
break;
case tok::kw_return: // C99 6.8.6.4: return-statement
- Res = ParseReturnStatement();
+ Res = ParseReturnStatement(Attr.AttrList);
SemiError = "return";
break;
case tok::kw_asm: {
+ if (Attr.HasAttr)
+ Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+ << Attr.Range;
bool msAsm = false;
Res = ParseAsmStatement(msAsm);
if (msAsm) return move(Res);
@@ -178,7 +187,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
}
case tok::kw_try: // C++ 15: try-block
- return ParseCXXTryBlock();
+ return ParseCXXTryBlock(Attr.AttrList);
}
// If we reached this code, the statement must end in a semicolon.
@@ -202,7 +211,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
/// identifier ':' statement
/// [GNU] identifier ':' attributes[opt] statement
///
-Parser::OwningStmtResult Parser::ParseLabeledStatement() {
+Parser::OwningStmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
"Not an identifier!");
@@ -215,10 +224,8 @@ Parser::OwningStmtResult Parser::ParseLabeledStatement() {
SourceLocation ColonLoc = ConsumeToken();
// Read label attributes, if present.
- Action::AttrTy *AttrList = 0;
if (Tok.is(tok::kw___attribute))
- // TODO: save these somewhere.
- AttrList = ParseAttributes();
+ Attr = addAttributeLists(Attr, ParseGNUAttributes());
OwningStmtResult SubStmt(ParseStatement());
@@ -236,8 +243,9 @@ Parser::OwningStmtResult Parser::ParseLabeledStatement() {
/// 'case' constant-expression ':' statement
/// [GNU] 'case' constant-expression '...' constant-expression ':' statement
///
-Parser::OwningStmtResult Parser::ParseCaseStatement() {
+Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
assert(Tok.is(tok::kw_case) && "Not a case stmt!");
+ // FIXME: Use attributes?
// It is very very common for code to contain many case statements recursively
// nested, as in (but usually without indentation):
@@ -354,7 +362,8 @@ Parser::OwningStmtResult Parser::ParseCaseStatement() {
/// 'default' ':' statement
/// Note that this does not parse the 'statement' at the end.
///
-Parser::OwningStmtResult Parser::ParseDefaultStatement() {
+Parser::OwningStmtResult Parser::ParseDefaultStatement(AttributeList *Attr) {
+ //FIXME: Use attributes?
assert(Tok.is(tok::kw_default) && "Not a default stmt!");
SourceLocation DefaultLoc = ConsumeToken(); // eat the 'default'.
@@ -408,7 +417,9 @@ Parser::OwningStmtResult Parser::ParseDefaultStatement() {
/// [OMP] barrier-directive
/// [OMP] flush-directive
///
-Parser::OwningStmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
+Parser::OwningStmtResult Parser::ParseCompoundStatement(AttributeList *Attr,
+ bool isStmtExpr) {
+ //FIXME: Use attributes?
assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
// Enter a scope to hold everything within the compound stmt. Compound
@@ -449,6 +460,10 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
while (Tok.is(tok::kw___extension__))
ConsumeToken();
+ CXX0XAttributeList Attr;
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+ Attr = ParseCXX0XAttributes();
+
// If this is the start of a declaration, parse it as such.
if (isDeclarationStatement()) {
// __extension__ silences extension warnings in the subdeclaration.
@@ -456,7 +471,8 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
ExtensionRAIIObject O(Diags);
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
- DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext,DeclEnd);
+ DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext, DeclEnd,
+ Attr);
R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
} else {
// Otherwise this was a unary __extension__ marker.
@@ -467,6 +483,7 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
continue;
}
+ // FIXME: Use attributes?
// Eat the semicolon at the end of stmt and convert the expr into a
// statement.
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
@@ -537,7 +554,8 @@ bool Parser::ParseParenExprOrCondition(OwningExprResult &CondExp,
/// [C++] 'if' '(' condition ')' statement
/// [C++] 'if' '(' condition ')' statement 'else' statement
///
-Parser::OwningStmtResult Parser::ParseIfStatement() {
+Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
assert(Tok.is(tok::kw_if) && "Not an if stmt!");
SourceLocation IfLoc = ConsumeToken(); // eat the 'if'.
@@ -659,7 +677,8 @@ Parser::OwningStmtResult Parser::ParseIfStatement() {
/// switch-statement:
/// 'switch' '(' expression ')' statement
/// [C++] 'switch' '(' condition ')' statement
-Parser::OwningStmtResult Parser::ParseSwitchStatement() {
+Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
SourceLocation SwitchLoc = ConsumeToken(); // eat the 'switch'.
@@ -734,7 +753,8 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement() {
/// while-statement: [C99 6.8.5.1]
/// 'while' '(' expression ')' statement
/// [C++] 'while' '(' condition ')' statement
-Parser::OwningStmtResult Parser::ParseWhileStatement() {
+Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
assert(Tok.is(tok::kw_while) && "Not a while stmt!");
SourceLocation WhileLoc = Tok.getLocation();
ConsumeToken(); // eat the 'while'.
@@ -805,7 +825,8 @@ Parser::OwningStmtResult Parser::ParseWhileStatement() {
/// do-statement: [C99 6.8.5.2]
/// 'do' statement 'while' '(' expression ')' ';'
/// Note: this lets the caller parse the end ';'.
-Parser::OwningStmtResult Parser::ParseDoStatement() {
+Parser::OwningStmtResult Parser::ParseDoStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
assert(Tok.is(tok::kw_do) && "Not a do stmt!");
SourceLocation DoLoc = ConsumeToken(); // eat the 'do'.
@@ -880,7 +901,8 @@ Parser::OwningStmtResult Parser::ParseDoStatement() {
/// [C++] expression-statement
/// [C++] simple-declaration
///
-Parser::OwningStmtResult Parser::ParseForStatement() {
+Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
assert(Tok.is(tok::kw_for) && "Not a for stmt!");
SourceLocation ForLoc = ConsumeToken(); // eat the 'for'.
@@ -937,8 +959,13 @@ Parser::OwningStmtResult Parser::ParseForStatement() {
if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode?
Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
+ AttributeList *AttrList = 0;
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+ AttrList = ParseCXX0XAttributes().AttrList;
+
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
- DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd);
+ DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd,
+ AttrList);
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
if (Tok.is(tok::semi)) { // for (int x = 4;
@@ -1036,7 +1063,8 @@ Parser::OwningStmtResult Parser::ParseForStatement() {
///
/// Note: this lets the caller parse the end ';'.
///
-Parser::OwningStmtResult Parser::ParseGotoStatement() {
+Parser::OwningStmtResult Parser::ParseGotoStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
SourceLocation GotoLoc = ConsumeToken(); // eat the 'goto'.
@@ -1069,7 +1097,8 @@ Parser::OwningStmtResult Parser::ParseGotoStatement() {
///
/// Note: this lets the caller parse the end ';'.
///
-Parser::OwningStmtResult Parser::ParseContinueStatement() {
+Parser::OwningStmtResult Parser::ParseContinueStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
SourceLocation ContinueLoc = ConsumeToken(); // eat the 'continue'.
return Actions.ActOnContinueStmt(ContinueLoc, CurScope);
}
@@ -1080,7 +1109,8 @@ Parser::OwningStmtResult Parser::ParseContinueStatement() {
///
/// Note: this lets the caller parse the end ';'.
///
-Parser::OwningStmtResult Parser::ParseBreakStatement() {
+Parser::OwningStmtResult Parser::ParseBreakStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
SourceLocation BreakLoc = ConsumeToken(); // eat the 'break'.
return Actions.ActOnBreakStmt(BreakLoc, CurScope);
}
@@ -1088,7 +1118,8 @@ Parser::OwningStmtResult Parser::ParseBreakStatement() {
/// ParseReturnStatement
/// jump-statement:
/// 'return' expression[opt] ';'
-Parser::OwningStmtResult Parser::ParseReturnStatement() {
+Parser::OwningStmtResult Parser::ParseReturnStatement(AttributeList *Attr) {
+ // FIXME: Use attributes?
assert(Tok.is(tok::kw_return) && "Not a return stmt!");
SourceLocation ReturnLoc = ConsumeToken(); // eat the 'return'.
@@ -1164,7 +1195,7 @@ Parser::OwningStmtResult Parser::ParseAsmStatement(bool &msAsm) {
}
DeclSpec DS;
SourceLocation Loc = Tok.getLocation();
- ParseTypeQualifierListOpt(DS);
+ ParseTypeQualifierListOpt(DS, true, false);
// GNU asms accept, but warn, about type-qualifiers other than volatile.
if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
@@ -1372,7 +1403,8 @@ Parser::DeclPtrTy Parser::ParseFunctionTryBlock(DeclPtrTy Decl) {
/// try-block:
/// 'try' compound-statement handler-seq
///
-Parser::OwningStmtResult Parser::ParseCXXTryBlock() {
+Parser::OwningStmtResult Parser::ParseCXXTryBlock(AttributeList* Attr) {
+ // FIXME: Add attributes?
assert(Tok.is(tok::kw_try) && "Expected 'try'");
SourceLocation TryLoc = ConsumeToken();
@@ -1394,11 +1426,17 @@ Parser::OwningStmtResult Parser::ParseCXXTryBlock() {
Parser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected_lbrace));
- OwningStmtResult TryBlock(ParseCompoundStatement());
+ // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
+ OwningStmtResult TryBlock(ParseCompoundStatement(0));
if (TryBlock.isInvalid())
return move(TryBlock);
StmtVector Handlers(Actions);
+ if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+ CXX0XAttributeList Attr = ParseCXX0XAttributes();
+ Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+ << Attr.Range;
+ }
if (Tok.isNot(tok::kw_catch))
return StmtError(Diag(Tok, diag::err_expected_catch));
while (Tok.is(tok::kw_catch)) {
@@ -1458,7 +1496,8 @@ Parser::OwningStmtResult Parser::ParseCXXCatchBlock() {
if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected_lbrace));
- OwningStmtResult Block(ParseCompoundStatement());
+ // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
+ OwningStmtResult Block(ParseCompoundStatement(0));
if (Block.isInvalid())
return move(Block);