| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1 | //===--- ParseExpr.cpp - Expression Parsing -------------------------------===// | 
 | 2 | // | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
| Chris Lattner | 0bc735f | 2007-12-29 19:59:25 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
 | 6 | // License. See LICENSE.TXT for details. | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
 | 10 | // This file implements the Expression parsing implementation.  Expressions in | 
 | 11 | // C99 basically consist of a bunch of binary operators with unary operators and | 
 | 12 | // other random stuff at the leaves. | 
 | 13 | // | 
 | 14 | // In the C99 grammar, these unary operators bind tightest and are represented | 
 | 15 | // as the 'cast-expression' production.  Everything else is either a binary | 
 | 16 | // operator (e.g. '/') or a ternary operator ("?:").  The unary leaves are | 
 | 17 | // handled by ParseCastExpression, the higher level pieces are handled by | 
 | 18 | // ParseBinaryExpression. | 
 | 19 | // | 
 | 20 | //===----------------------------------------------------------------------===// | 
 | 21 |  | 
 | 22 | #include "clang/Parse/Parser.h" | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 23 | #include "clang/Parse/DeclSpec.h" | 
| Steve Naroff | 296e8d5 | 2008-08-28 19:20:44 +0000 | [diff] [blame] | 24 | #include "clang/Parse/Scope.h" | 
| Chris Lattner | c46d1a1 | 2008-10-20 06:45:43 +0000 | [diff] [blame] | 25 | #include "ExtensionRAIIObject.h" | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 26 | #include "llvm/ADT/SmallVector.h" | 
 | 27 | #include "llvm/ADT/SmallString.h" | 
 | 28 | using namespace clang; | 
 | 29 |  | 
 | 30 | /// PrecedenceLevels - These are precedences for the binary/ternary operators in | 
 | 31 | /// the C99 grammar.  These have been named to relate with the C99 grammar | 
 | 32 | /// productions.  Low precedences numbers bind more weakly than high numbers. | 
 | 33 | namespace prec { | 
 | 34 |   enum Level { | 
 | 35 |     Unknown        = 0,    // Not binary operator. | 
 | 36 |     Comma          = 1,    // , | 
 | 37 |     Assignment     = 2,    // =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |= | 
 | 38 |     Conditional    = 3,    // ? | 
 | 39 |     LogicalOr      = 4,    // || | 
 | 40 |     LogicalAnd     = 5,    // && | 
 | 41 |     InclusiveOr    = 6,    // | | 
 | 42 |     ExclusiveOr    = 7,    // ^ | 
 | 43 |     And            = 8,    // & | 
 | 44 |     Equality       = 9,    // ==, != | 
 | 45 |     Relational     = 10,   //  >=, <=, >, < | 
 | 46 |     Shift          = 11,   // <<, >> | 
 | 47 |     Additive       = 12,   // -, + | 
 | 48 |     Multiplicative = 13    // *, /, % | 
 | 49 |   }; | 
 | 50 | } | 
 | 51 |  | 
 | 52 |  | 
 | 53 | /// getBinOpPrecedence - Return the precedence of the specified binary operator | 
 | 54 | /// token.  This returns: | 
 | 55 | /// | 
 | 56 | static prec::Level getBinOpPrecedence(tok::TokenKind Kind) { | 
 | 57 |   switch (Kind) { | 
 | 58 |   default:                        return prec::Unknown; | 
 | 59 |   case tok::comma:                return prec::Comma; | 
 | 60 |   case tok::equal: | 
 | 61 |   case tok::starequal: | 
 | 62 |   case tok::slashequal: | 
 | 63 |   case tok::percentequal: | 
 | 64 |   case tok::plusequal: | 
 | 65 |   case tok::minusequal: | 
 | 66 |   case tok::lesslessequal: | 
 | 67 |   case tok::greatergreaterequal: | 
 | 68 |   case tok::ampequal: | 
 | 69 |   case tok::caretequal: | 
 | 70 |   case tok::pipeequal:            return prec::Assignment; | 
 | 71 |   case tok::question:             return prec::Conditional; | 
 | 72 |   case tok::pipepipe:             return prec::LogicalOr; | 
 | 73 |   case tok::ampamp:               return prec::LogicalAnd; | 
 | 74 |   case tok::pipe:                 return prec::InclusiveOr; | 
 | 75 |   case tok::caret:                return prec::ExclusiveOr; | 
 | 76 |   case tok::amp:                  return prec::And; | 
 | 77 |   case tok::exclaimequal: | 
 | 78 |   case tok::equalequal:           return prec::Equality; | 
 | 79 |   case tok::lessequal: | 
 | 80 |   case tok::less: | 
 | 81 |   case tok::greaterequal: | 
 | 82 |   case tok::greater:              return prec::Relational; | 
 | 83 |   case tok::lessless: | 
 | 84 |   case tok::greatergreater:       return prec::Shift; | 
 | 85 |   case tok::plus: | 
 | 86 |   case tok::minus:                return prec::Additive; | 
 | 87 |   case tok::percent: | 
 | 88 |   case tok::slash: | 
 | 89 |   case tok::star:                 return prec::Multiplicative; | 
 | 90 |   } | 
 | 91 | } | 
 | 92 |  | 
 | 93 |  | 
 | 94 | /// ParseExpression - Simple precedence-based parser for binary/ternary | 
 | 95 | /// operators. | 
 | 96 | /// | 
 | 97 | /// Note: we diverge from the C99 grammar when parsing the assignment-expression | 
 | 98 | /// production.  C99 specifies that the LHS of an assignment operator should be | 
 | 99 | /// parsed as a unary-expression, but consistency dictates that it be a | 
 | 100 | /// conditional-expession.  In practice, the important thing here is that the | 
 | 101 | /// LHS of an assignment has to be an l-value, which productions between | 
 | 102 | /// unary-expression and conditional-expression don't produce.  Because we want | 
 | 103 | /// consistency, we parse the LHS as a conditional-expression, then check for | 
 | 104 | /// l-value-ness in semantic analysis stages. | 
 | 105 | /// | 
 | 106 | ///       multiplicative-expression: [C99 6.5.5] | 
 | 107 | ///         cast-expression | 
 | 108 | ///         multiplicative-expression '*' cast-expression | 
 | 109 | ///         multiplicative-expression '/' cast-expression | 
 | 110 | ///         multiplicative-expression '%' cast-expression | 
 | 111 | /// | 
 | 112 | ///       additive-expression: [C99 6.5.6] | 
 | 113 | ///         multiplicative-expression | 
 | 114 | ///         additive-expression '+' multiplicative-expression | 
 | 115 | ///         additive-expression '-' multiplicative-expression | 
 | 116 | /// | 
 | 117 | ///       shift-expression: [C99 6.5.7] | 
 | 118 | ///         additive-expression | 
 | 119 | ///         shift-expression '<<' additive-expression | 
 | 120 | ///         shift-expression '>>' additive-expression | 
 | 121 | /// | 
 | 122 | ///       relational-expression: [C99 6.5.8] | 
 | 123 | ///         shift-expression | 
 | 124 | ///         relational-expression '<' shift-expression | 
 | 125 | ///         relational-expression '>' shift-expression | 
 | 126 | ///         relational-expression '<=' shift-expression | 
 | 127 | ///         relational-expression '>=' shift-expression | 
 | 128 | /// | 
 | 129 | ///       equality-expression: [C99 6.5.9] | 
 | 130 | ///         relational-expression | 
 | 131 | ///         equality-expression '==' relational-expression | 
 | 132 | ///         equality-expression '!=' relational-expression | 
 | 133 | /// | 
 | 134 | ///       AND-expression: [C99 6.5.10] | 
 | 135 | ///         equality-expression | 
 | 136 | ///         AND-expression '&' equality-expression | 
 | 137 | /// | 
 | 138 | ///       exclusive-OR-expression: [C99 6.5.11] | 
 | 139 | ///         AND-expression | 
 | 140 | ///         exclusive-OR-expression '^' AND-expression | 
 | 141 | /// | 
 | 142 | ///       inclusive-OR-expression: [C99 6.5.12] | 
 | 143 | ///         exclusive-OR-expression | 
 | 144 | ///         inclusive-OR-expression '|' exclusive-OR-expression | 
 | 145 | /// | 
 | 146 | ///       logical-AND-expression: [C99 6.5.13] | 
 | 147 | ///         inclusive-OR-expression | 
 | 148 | ///         logical-AND-expression '&&' inclusive-OR-expression | 
 | 149 | /// | 
 | 150 | ///       logical-OR-expression: [C99 6.5.14] | 
 | 151 | ///         logical-AND-expression | 
 | 152 | ///         logical-OR-expression '||' logical-AND-expression | 
 | 153 | /// | 
 | 154 | ///       conditional-expression: [C99 6.5.15] | 
 | 155 | ///         logical-OR-expression | 
 | 156 | ///         logical-OR-expression '?' expression ':' conditional-expression | 
 | 157 | /// [GNU]   logical-OR-expression '?' ':' conditional-expression | 
 | 158 | /// | 
 | 159 | ///       assignment-expression: [C99 6.5.16] | 
 | 160 | ///         conditional-expression | 
 | 161 | ///         unary-expression assignment-operator assignment-expression | 
| Chris Lattner | 50dd289 | 2008-02-26 00:51:44 +0000 | [diff] [blame] | 162 | /// [C++]   throw-expression [C++ 15] | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 163 | /// | 
 | 164 | ///       assignment-operator: one of | 
 | 165 | ///         = *= /= %= += -= <<= >>= &= ^= |= | 
 | 166 | /// | 
 | 167 | ///       expression: [C99 6.5.17] | 
 | 168 | ///         assignment-expression | 
 | 169 | ///         expression ',' assignment-expression | 
 | 170 | /// | 
 | 171 | Parser::ExprResult Parser::ParseExpression() { | 
| Chris Lattner | 50dd289 | 2008-02-26 00:51:44 +0000 | [diff] [blame] | 172 |   if (Tok.is(tok::kw_throw)) | 
 | 173 |     return ParseThrowExpression(); | 
 | 174 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 175 |   ExprResult LHS = ParseCastExpression(false); | 
 | 176 |   if (LHS.isInvalid) return LHS; | 
 | 177 |    | 
 | 178 |   return ParseRHSOfBinaryExpression(LHS, prec::Comma); | 
 | 179 | } | 
 | 180 |  | 
| Fariborz Jahanian | 397fcc1 | 2007-09-19 19:14:32 +0000 | [diff] [blame] | 181 | /// This routine is called when the '@' is seen and consumed.  | 
 | 182 | /// Current token is an Identifier and is not a 'try'. This | 
| Chris Lattner | c97c204 | 2007-10-03 22:03:06 +0000 | [diff] [blame] | 183 | /// routine is necessary to disambiguate @try-statement from, | 
 | 184 | /// for example, @encode-expression. | 
| Fariborz Jahanian | 397fcc1 | 2007-09-19 19:14:32 +0000 | [diff] [blame] | 185 | /// | 
| Fariborz Jahanian | b384d32 | 2007-10-04 20:19:06 +0000 | [diff] [blame] | 186 | Parser::ExprResult Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) { | 
| Steve Naroff | a642beb | 2007-10-15 20:55:58 +0000 | [diff] [blame] | 187 |   ExprResult LHS = ParseObjCAtExpression(AtLoc); | 
| Fariborz Jahanian | 397fcc1 | 2007-09-19 19:14:32 +0000 | [diff] [blame] | 188 |   if (LHS.isInvalid) return LHS; | 
 | 189 |   | 
 | 190 |   return ParseRHSOfBinaryExpression(LHS, prec::Comma); | 
 | 191 | } | 
 | 192 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 193 | /// ParseAssignmentExpression - Parse an expr that doesn't include commas. | 
 | 194 | /// | 
 | 195 | Parser::ExprResult Parser::ParseAssignmentExpression() { | 
| Chris Lattner | 50dd289 | 2008-02-26 00:51:44 +0000 | [diff] [blame] | 196 |   if (Tok.is(tok::kw_throw)) | 
 | 197 |     return ParseThrowExpression(); | 
 | 198 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 199 |   ExprResult LHS = ParseCastExpression(false); | 
 | 200 |   if (LHS.isInvalid) return LHS; | 
 | 201 |    | 
 | 202 |   return ParseRHSOfBinaryExpression(LHS, prec::Assignment); | 
 | 203 | } | 
 | 204 |  | 
| Chris Lattner | b93fb49 | 2008-06-02 21:31:07 +0000 | [diff] [blame] | 205 | /// ParseAssignmentExprWithObjCMessageExprStart - Parse an assignment expression | 
 | 206 | /// where part of an objc message send has already been parsed.  In this case | 
 | 207 | /// LBracLoc indicates the location of the '[' of the message send, and either | 
 | 208 | /// ReceiverName or ReceiverExpr is non-null indicating the receiver of the | 
 | 209 | /// message. | 
 | 210 | /// | 
 | 211 | /// Since this handles full assignment-expression's, it handles postfix | 
 | 212 | /// expressions and other binary operators for these expressions as well. | 
 | 213 | Parser::ExprResult  | 
 | 214 | Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc, | 
| Steve Naroff | 5cb93b8 | 2008-11-19 15:54:23 +0000 | [diff] [blame] | 215 |                                                     SourceLocation NameLoc, | 
| Chris Lattner | b93fb49 | 2008-06-02 21:31:07 +0000 | [diff] [blame] | 216 |                                                    IdentifierInfo *ReceiverName, | 
 | 217 |                                                     ExprTy *ReceiverExpr) { | 
| Steve Naroff | 5cb93b8 | 2008-11-19 15:54:23 +0000 | [diff] [blame] | 218 |   ExprResult R = ParseObjCMessageExpressionBody(LBracLoc, NameLoc, ReceiverName, | 
| Chris Lattner | b93fb49 | 2008-06-02 21:31:07 +0000 | [diff] [blame] | 219 |                                                 ReceiverExpr); | 
 | 220 |   if (R.isInvalid) return R; | 
 | 221 |   R = ParsePostfixExpressionSuffix(R); | 
 | 222 |   if (R.isInvalid) return R; | 
 | 223 |   return ParseRHSOfBinaryExpression(R, 2); | 
 | 224 | } | 
 | 225 |  | 
 | 226 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 227 | Parser::ExprResult Parser::ParseConstantExpression() { | 
 | 228 |   ExprResult LHS = ParseCastExpression(false); | 
 | 229 |   if (LHS.isInvalid) return LHS; | 
 | 230 |    | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 231 |   return ParseRHSOfBinaryExpression(LHS, prec::Conditional); | 
 | 232 | } | 
 | 233 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 234 | /// ParseRHSOfBinaryExpression - Parse a binary expression that starts with | 
 | 235 | /// LHS and has a precedence of at least MinPrec. | 
 | 236 | Parser::ExprResult | 
 | 237 | Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) { | 
 | 238 |   unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind()); | 
 | 239 |   SourceLocation ColonLoc; | 
 | 240 |  | 
 | 241 |   while (1) { | 
 | 242 |     // If this token has a lower precedence than we are allowed to parse (e.g. | 
 | 243 |     // because we are called recursively, or because the token is not a binop), | 
 | 244 |     // then we are done! | 
 | 245 |     if (NextTokPrec < MinPrec) | 
 | 246 |       return LHS; | 
 | 247 |  | 
 | 248 |     // Consume the operator, saving the operator token for error reporting. | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 249 |     Token OpToken = Tok; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 250 |     ConsumeToken(); | 
 | 251 |      | 
 | 252 |     // Special case handling for the ternary operator. | 
 | 253 |     ExprResult TernaryMiddle(true); | 
 | 254 |     if (NextTokPrec == prec::Conditional) { | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 255 |       if (Tok.isNot(tok::colon)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 256 |         // Handle this production specially: | 
 | 257 |         //   logical-OR-expression '?' expression ':' conditional-expression | 
 | 258 |         // In particular, the RHS of the '?' is 'expression', not | 
 | 259 |         // 'logical-OR-expression' as we might expect. | 
 | 260 |         TernaryMiddle = ParseExpression(); | 
| Chris Lattner | dbd583c | 2007-08-31 04:58:34 +0000 | [diff] [blame] | 261 |         if (TernaryMiddle.isInvalid) { | 
 | 262 |           Actions.DeleteExpr(LHS.Val); | 
 | 263 |           return TernaryMiddle; | 
 | 264 |         } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 265 |       } else { | 
 | 266 |         // Special case handling of "X ? Y : Z" where Y is empty: | 
 | 267 |         //   logical-OR-expression '?' ':' conditional-expression   [GNU] | 
 | 268 |         TernaryMiddle = ExprResult(false); | 
 | 269 |         Diag(Tok, diag::ext_gnu_conditional_expr); | 
 | 270 |       } | 
 | 271 |        | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 272 |       if (Tok.isNot(tok::colon)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 273 |         Diag(Tok, diag::err_expected_colon); | 
| Chris Lattner | 1ab3b96 | 2008-11-18 07:48:38 +0000 | [diff] [blame] | 274 |         Diag(OpToken, diag::err_matching) << "?"; | 
| Chris Lattner | dbd583c | 2007-08-31 04:58:34 +0000 | [diff] [blame] | 275 |         Actions.DeleteExpr(LHS.Val); | 
 | 276 |         Actions.DeleteExpr(TernaryMiddle.Val); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 277 |         return ExprResult(true); | 
 | 278 |       } | 
 | 279 |        | 
 | 280 |       // Eat the colon. | 
 | 281 |       ColonLoc = ConsumeToken(); | 
 | 282 |     } | 
 | 283 |      | 
 | 284 |     // Parse another leaf here for the RHS of the operator. | 
 | 285 |     ExprResult RHS = ParseCastExpression(false); | 
| Chris Lattner | dbd583c | 2007-08-31 04:58:34 +0000 | [diff] [blame] | 286 |     if (RHS.isInvalid) { | 
 | 287 |       Actions.DeleteExpr(LHS.Val); | 
 | 288 |       Actions.DeleteExpr(TernaryMiddle.Val); | 
 | 289 |       return RHS; | 
 | 290 |     } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 291 |  | 
 | 292 |     // Remember the precedence of this operator and get the precedence of the | 
 | 293 |     // operator immediately to the right of the RHS. | 
 | 294 |     unsigned ThisPrec = NextTokPrec; | 
 | 295 |     NextTokPrec = getBinOpPrecedence(Tok.getKind()); | 
 | 296 |  | 
 | 297 |     // Assignment and conditional expressions are right-associative. | 
| Chris Lattner | d7d860d | 2007-12-18 06:06:23 +0000 | [diff] [blame] | 298 |     bool isRightAssoc = ThisPrec == prec::Conditional || | 
 | 299 |                         ThisPrec == prec::Assignment; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 300 |  | 
 | 301 |     // Get the precedence of the operator to the right of the RHS.  If it binds | 
 | 302 |     // more tightly with RHS than we do, evaluate it completely first. | 
 | 303 |     if (ThisPrec < NextTokPrec || | 
 | 304 |         (ThisPrec == NextTokPrec && isRightAssoc)) { | 
 | 305 |       // If this is left-associative, only parse things on the RHS that bind | 
 | 306 |       // more tightly than the current operator.  If it is left-associative, it | 
 | 307 |       // is okay, to bind exactly as tightly.  For example, compile A=B=C=D as | 
 | 308 |       // A=(B=(C=D)), where each paren is a level of recursion here. | 
 | 309 |       RHS = ParseRHSOfBinaryExpression(RHS, ThisPrec + !isRightAssoc); | 
| Chris Lattner | dbd583c | 2007-08-31 04:58:34 +0000 | [diff] [blame] | 310 |       if (RHS.isInvalid) { | 
 | 311 |         Actions.DeleteExpr(LHS.Val); | 
 | 312 |         Actions.DeleteExpr(TernaryMiddle.Val); | 
 | 313 |         return RHS; | 
 | 314 |       } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 315 |  | 
 | 316 |       NextTokPrec = getBinOpPrecedence(Tok.getKind()); | 
 | 317 |     } | 
 | 318 |     assert(NextTokPrec <= ThisPrec && "Recursion didn't work!"); | 
 | 319 |    | 
| Chris Lattner | d56d6b6 | 2007-08-31 05:01:50 +0000 | [diff] [blame] | 320 |     if (!LHS.isInvalid) { | 
 | 321 |       // Combine the LHS and RHS into the LHS (e.g. build AST). | 
 | 322 |       if (TernaryMiddle.isInvalid) | 
| Douglas Gregor | eaebc75 | 2008-11-06 23:29:22 +0000 | [diff] [blame] | 323 |         LHS = Actions.ActOnBinOp(CurScope, OpToken.getLocation(),  | 
 | 324 |                                  OpToken.getKind(), LHS.Val, RHS.Val); | 
| Chris Lattner | d56d6b6 | 2007-08-31 05:01:50 +0000 | [diff] [blame] | 325 |       else | 
| Steve Naroff | f69936d | 2007-09-16 03:34:24 +0000 | [diff] [blame] | 326 |         LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc, | 
| Chris Lattner | d56d6b6 | 2007-08-31 05:01:50 +0000 | [diff] [blame] | 327 |                                          LHS.Val, TernaryMiddle.Val, RHS.Val); | 
 | 328 |     } else { | 
 | 329 |       // We had a semantic error on the LHS.  Just free the RHS and continue. | 
 | 330 |       Actions.DeleteExpr(TernaryMiddle.Val); | 
 | 331 |       Actions.DeleteExpr(RHS.Val); | 
 | 332 |     } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 333 |   } | 
 | 334 | } | 
 | 335 |  | 
 | 336 | /// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is | 
 | 337 | /// true, parse a unary-expression. | 
 | 338 | /// | 
 | 339 | ///       cast-expression: [C99 6.5.4] | 
 | 340 | ///         unary-expression | 
 | 341 | ///         '(' type-name ')' cast-expression | 
 | 342 | /// | 
 | 343 | ///       unary-expression:  [C99 6.5.3] | 
 | 344 | ///         postfix-expression | 
 | 345 | ///         '++' unary-expression | 
 | 346 | ///         '--' unary-expression | 
 | 347 | ///         unary-operator cast-expression | 
 | 348 | ///         'sizeof' unary-expression | 
 | 349 | ///         'sizeof' '(' type-name ')' | 
 | 350 | /// [GNU]   '__alignof' unary-expression | 
 | 351 | /// [GNU]   '__alignof' '(' type-name ')' | 
| Douglas Gregor | 85bb3da | 2008-11-06 15:17:27 +0000 | [diff] [blame] | 352 | /// [C++0x] 'alignof' '(' type-id ')' | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 353 | /// [GNU]   '&&' identifier | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 354 | /// [C++]   new-expression | 
 | 355 | /// [C++]   delete-expression | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 356 | /// | 
 | 357 | ///       unary-operator: one of | 
 | 358 | ///         '&'  '*'  '+'  '-'  '~'  '!' | 
 | 359 | /// [GNU]   '__extension__'  '__real'  '__imag' | 
 | 360 | /// | 
 | 361 | ///       primary-expression: [C99 6.5.1] | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 362 | /// [C99]   identifier | 
| Sebastian Redl | c42e118 | 2008-11-11 11:37:55 +0000 | [diff] [blame] | 363 | /// [C++]   id-expression | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 364 | ///         constant | 
 | 365 | ///         string-literal | 
 | 366 | /// [C++]   boolean-literal  [C++ 2.13.5] | 
 | 367 | ///         '(' expression ')' | 
 | 368 | ///         '__func__'        [C99 6.4.2.2] | 
 | 369 | /// [GNU]   '__FUNCTION__' | 
 | 370 | /// [GNU]   '__PRETTY_FUNCTION__' | 
 | 371 | /// [GNU]   '(' compound-statement ')' | 
 | 372 | /// [GNU]   '__builtin_va_arg' '(' assignment-expression ',' type-name ')' | 
 | 373 | /// [GNU]   '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')' | 
 | 374 | /// [GNU]   '__builtin_choose_expr' '(' assign-expr ',' assign-expr ',' | 
 | 375 | ///                                     assign-expr ')' | 
 | 376 | /// [GNU]   '__builtin_types_compatible_p' '(' type-name ',' type-name ')' | 
| Fariborz Jahanian | 095ffca | 2007-09-26 17:03:44 +0000 | [diff] [blame] | 377 | /// [OBJC]  '[' objc-message-expr ']'     | 
| Chris Lattner | 5ac87ed | 2008-01-25 18:58:06 +0000 | [diff] [blame] | 378 | /// [OBJC]  '@selector' '(' objc-selector-arg ')' | 
| Fariborz Jahanian | 095ffca | 2007-09-26 17:03:44 +0000 | [diff] [blame] | 379 | /// [OBJC]  '@protocol' '(' identifier ')'              | 
 | 380 | /// [OBJC]  '@encode' '(' type-name ')'                 | 
| Fariborz Jahanian | 0ccb27d | 2007-09-05 19:52:07 +0000 | [diff] [blame] | 381 | /// [OBJC]  objc-string-literal | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 382 | /// [C++]   simple-type-specifier '(' expression-list[opt] ')'      [C++ 5.2.3] | 
 | 383 | /// [C++]   typename-specifier '(' expression-list[opt] ')'         [TODO] | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 384 | /// [C++]   'const_cast' '<' type-name '>' '(' expression ')'       [C++ 5.2p1] | 
 | 385 | /// [C++]   'dynamic_cast' '<' type-name '>' '(' expression ')'     [C++ 5.2p1] | 
 | 386 | /// [C++]   'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] | 
 | 387 | /// [C++]   'static_cast' '<' type-name '>' '(' expression ')'      [C++ 5.2p1] | 
| Sebastian Redl | c42e118 | 2008-11-11 11:37:55 +0000 | [diff] [blame] | 388 | /// [C++]   'typeid' '(' expression ')'                             [C++ 5.2p1] | 
 | 389 | /// [C++]   'typeid' '(' type-id ')'                                [C++ 5.2p1] | 
| Argyrios Kyrtzidis | d7464be | 2008-07-16 07:23:27 +0000 | [diff] [blame] | 390 | /// [C++]   'this'          [C++ 9.3.2] | 
| Steve Naroff | 296e8d5 | 2008-08-28 19:20:44 +0000 | [diff] [blame] | 391 | /// [clang] '^' block-literal | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 392 | /// | 
 | 393 | ///       constant: [C99 6.4.4] | 
 | 394 | ///         integer-constant | 
 | 395 | ///         floating-constant | 
 | 396 | ///         enumeration-constant -> identifier | 
 | 397 | ///         character-constant | 
 | 398 | /// | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 399 | ///       id-expression: [C++ 5.1] | 
 | 400 | ///                   unqualified-id | 
 | 401 | ///                   qualified-id           [TODO] | 
 | 402 | /// | 
 | 403 | ///       unqualified-id: [C++ 5.1] | 
 | 404 | ///                   identifier | 
 | 405 | ///                   operator-function-id | 
 | 406 | ///                   conversion-function-id [TODO] | 
 | 407 | ///                   '~' class-name         [TODO] | 
 | 408 | ///                   template-id            [TODO] | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 409 | /// | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 410 | ///       new-expression: [C++ 5.3.4] | 
 | 411 | ///                   '::'[opt] 'new' new-placement[opt] new-type-id | 
 | 412 | ///                                     new-initializer[opt] | 
 | 413 | ///                   '::'[opt] 'new' new-placement[opt] '(' type-id ')' | 
 | 414 | ///                                     new-initializer[opt] | 
 | 415 | /// | 
 | 416 | ///       delete-expression: [C++ 5.3.5] | 
 | 417 | ///                   '::'[opt] 'delete' cast-expression | 
 | 418 | ///                   '::'[opt] 'delete' '[' ']' cast-expression | 
 | 419 | /// | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 420 | Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) { | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 421 |   if (getLang().CPlusPlus) { | 
 | 422 |     // Annotate typenames and C++ scope specifiers. | 
 | 423 |     // Used only in C++; in C let the typedef name be handled as an identifier. | 
 | 424 |     TryAnnotateTypeOrScopeToken(); | 
 | 425 |   } | 
 | 426 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 427 |   ExprResult Res; | 
 | 428 |   tok::TokenKind SavedKind = Tok.getKind(); | 
 | 429 |    | 
 | 430 |   // This handles all of cast-expression, unary-expression, postfix-expression, | 
 | 431 |   // and primary-expression.  We handle them together like this for efficiency | 
 | 432 |   // and to simplify handling of an expression starting with a '(' token: which | 
 | 433 |   // may be one of a parenthesized expression, cast-expression, compound literal | 
 | 434 |   // expression, or statement expression. | 
 | 435 |   // | 
 | 436 |   // If the parsed tokens consist of a primary-expression, the cases below | 
 | 437 |   // call ParsePostfixExpressionSuffix to handle the postfix expression | 
 | 438 |   // suffixes.  Cases that cannot be followed by postfix exprs should | 
 | 439 |   // return without invoking ParsePostfixExpressionSuffix. | 
 | 440 |   switch (SavedKind) { | 
 | 441 |   case tok::l_paren: { | 
 | 442 |     // If this expression is limited to being a unary-expression, the parent can | 
 | 443 |     // not start a cast expression. | 
 | 444 |     ParenParseOption ParenExprType = | 
 | 445 |       isUnaryExpression ? CompoundLiteral : CastExpr; | 
 | 446 |     TypeTy *CastTy; | 
 | 447 |     SourceLocation LParenLoc = Tok.getLocation(); | 
 | 448 |     SourceLocation RParenLoc; | 
 | 449 |     Res = ParseParenExpression(ParenExprType, CastTy, RParenLoc); | 
 | 450 |     if (Res.isInvalid) return Res; | 
 | 451 |      | 
 | 452 |     switch (ParenExprType) { | 
 | 453 |     case SimpleExpr:   break;    // Nothing else to do. | 
 | 454 |     case CompoundStmt: break;  // Nothing else to do. | 
 | 455 |     case CompoundLiteral: | 
 | 456 |       // We parsed '(' type-name ')' '{' ... '}'.  If any suffixes of | 
 | 457 |       // postfix-expression exist, parse them now. | 
 | 458 |       break; | 
 | 459 |     case CastExpr: | 
 | 460 |       // We parsed '(' type-name ')' and the thing after it wasn't a '{'.  Parse | 
 | 461 |       // the cast-expression that follows it next. | 
 | 462 |       // TODO: For cast expression with CastTy. | 
 | 463 |       Res = ParseCastExpression(false); | 
 | 464 |       if (!Res.isInvalid) | 
| Steve Naroff | f69936d | 2007-09-16 03:34:24 +0000 | [diff] [blame] | 465 |         Res = Actions.ActOnCastExpr(LParenLoc, CastTy, RParenLoc, Res.Val); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 466 |       return Res; | 
 | 467 |     } | 
 | 468 |        | 
 | 469 |     // These can be followed by postfix-expr pieces. | 
 | 470 |     return ParsePostfixExpressionSuffix(Res); | 
 | 471 |   } | 
 | 472 |      | 
 | 473 |     // primary-expression | 
 | 474 |   case tok::numeric_constant: | 
 | 475 |     // constant: integer-constant | 
 | 476 |     // constant: floating-constant | 
 | 477 |      | 
| Steve Naroff | f69936d | 2007-09-16 03:34:24 +0000 | [diff] [blame] | 478 |     Res = Actions.ActOnNumericConstant(Tok); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 479 |     ConsumeToken(); | 
 | 480 |      | 
 | 481 |     // These can be followed by postfix-expr pieces. | 
 | 482 |     return ParsePostfixExpressionSuffix(Res); | 
 | 483 |  | 
 | 484 |   case tok::kw_true: | 
 | 485 |   case tok::kw_false: | 
 | 486 |     return ParseCXXBoolLiteral(); | 
 | 487 |  | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 488 |   case tok::identifier: {      // primary-expression: identifier | 
 | 489 |                                // unqualified-id: identifier | 
 | 490 |                                // constant: enumeration-constant | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 491 |  | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 492 |     // Consume the identifier so that we can see if it is followed by a '('. | 
 | 493 |     // Function designators are allowed to be undeclared (C99 6.5.1p2), so we | 
 | 494 |     // need to know whether or not this identifier is a function designator or | 
 | 495 |     // not. | 
 | 496 |     IdentifierInfo &II = *Tok.getIdentifierInfo(); | 
 | 497 |     SourceLocation L = ConsumeToken(); | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 498 |     Res = Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren)); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 499 |     // These can be followed by postfix-expr pieces. | 
 | 500 |     return ParsePostfixExpressionSuffix(Res); | 
 | 501 |   } | 
 | 502 |   case tok::char_constant:     // constant: character-constant | 
| Steve Naroff | f69936d | 2007-09-16 03:34:24 +0000 | [diff] [blame] | 503 |     Res = Actions.ActOnCharacterConstant(Tok); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 504 |     ConsumeToken(); | 
 | 505 |     // These can be followed by postfix-expr pieces. | 
 | 506 |     return ParsePostfixExpressionSuffix(Res);     | 
 | 507 |   case tok::kw___func__:       // primary-expression: __func__ [C99 6.4.2.2] | 
 | 508 |   case tok::kw___FUNCTION__:   // primary-expression: __FUNCTION__ [GNU] | 
 | 509 |   case tok::kw___PRETTY_FUNCTION__:  // primary-expression: __P..Y_F..N__ [GNU] | 
| Chris Lattner | d9f6910 | 2008-08-10 01:53:14 +0000 | [diff] [blame] | 510 |     Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 511 |     ConsumeToken(); | 
 | 512 |     // These can be followed by postfix-expr pieces. | 
 | 513 |     return ParsePostfixExpressionSuffix(Res); | 
 | 514 |   case tok::string_literal:    // primary-expression: string-literal | 
 | 515 |   case tok::wide_string_literal: | 
 | 516 |     Res = ParseStringLiteralExpression(); | 
 | 517 |     if (Res.isInvalid) return Res; | 
 | 518 |     // This can be followed by postfix-expr pieces (e.g. "foo"[1]). | 
 | 519 |     return ParsePostfixExpressionSuffix(Res); | 
 | 520 |   case tok::kw___builtin_va_arg: | 
 | 521 |   case tok::kw___builtin_offsetof: | 
 | 522 |   case tok::kw___builtin_choose_expr: | 
| Nate Begeman | e2ce1d9 | 2008-01-17 17:46:27 +0000 | [diff] [blame] | 523 |   case tok::kw___builtin_overload: | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 524 |   case tok::kw___builtin_types_compatible_p: | 
 | 525 |     return ParseBuiltinPrimaryExpression(); | 
 | 526 |   case tok::plusplus:      // unary-expression: '++' unary-expression | 
 | 527 |   case tok::minusminus: {  // unary-expression: '--' unary-expression | 
 | 528 |     SourceLocation SavedLoc = ConsumeToken(); | 
 | 529 |     Res = ParseCastExpression(true); | 
 | 530 |     if (!Res.isInvalid) | 
| Douglas Gregor | 7425373 | 2008-11-19 15:42:04 +0000 | [diff] [blame] | 531 |       Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, Res.Val); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 532 |     return Res; | 
 | 533 |   } | 
 | 534 |   case tok::amp:           // unary-expression: '&' cast-expression | 
 | 535 |   case tok::star:          // unary-expression: '*' cast-expression | 
 | 536 |   case tok::plus:          // unary-expression: '+' cast-expression | 
 | 537 |   case tok::minus:         // unary-expression: '-' cast-expression | 
 | 538 |   case tok::tilde:         // unary-expression: '~' cast-expression | 
 | 539 |   case tok::exclaim:       // unary-expression: '!' cast-expression | 
 | 540 |   case tok::kw___real:     // unary-expression: '__real' cast-expression [GNU] | 
| Chris Lattner | 3508084 | 2008-02-02 20:20:10 +0000 | [diff] [blame] | 541 |   case tok::kw___imag: {   // unary-expression: '__imag' cast-expression [GNU] | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 542 |     SourceLocation SavedLoc = ConsumeToken(); | 
 | 543 |     Res = ParseCastExpression(false); | 
 | 544 |     if (!Res.isInvalid) | 
| Douglas Gregor | 7425373 | 2008-11-19 15:42:04 +0000 | [diff] [blame] | 545 |       Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, Res.Val); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 546 |     return Res; | 
| Chris Lattner | 3508084 | 2008-02-02 20:20:10 +0000 | [diff] [blame] | 547 |   }     | 
 | 548 |        | 
 | 549 |   case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU] | 
 | 550 |     // __extension__ silences extension warnings in the subexpression. | 
| Chris Lattner | c46d1a1 | 2008-10-20 06:45:43 +0000 | [diff] [blame] | 551 |     ExtensionRAIIObject O(Diags);  // Use RAII to do this. | 
| Chris Lattner | 3508084 | 2008-02-02 20:20:10 +0000 | [diff] [blame] | 552 |     SourceLocation SavedLoc = ConsumeToken(); | 
 | 553 |     Res = ParseCastExpression(false); | 
 | 554 |     if (!Res.isInvalid) | 
| Douglas Gregor | 7425373 | 2008-11-19 15:42:04 +0000 | [diff] [blame] | 555 |       Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, Res.Val); | 
| Chris Lattner | 3508084 | 2008-02-02 20:20:10 +0000 | [diff] [blame] | 556 |     return Res; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 557 |   } | 
 | 558 |   case tok::kw_sizeof:     // unary-expression: 'sizeof' unary-expression | 
 | 559 |                            // unary-expression: 'sizeof' '(' type-name ')' | 
| Douglas Gregor | 85bb3da | 2008-11-06 15:17:27 +0000 | [diff] [blame] | 560 |   case tok::kw_alignof: | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 561 |   case tok::kw___alignof:  // unary-expression: '__alignof' unary-expression | 
 | 562 |                            // unary-expression: '__alignof' '(' type-name ')' | 
| Douglas Gregor | 85bb3da | 2008-11-06 15:17:27 +0000 | [diff] [blame] | 563 |                            // unary-expression: 'alignof' '(' type-id ')' | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 564 |     return ParseSizeofAlignofExpression(); | 
 | 565 |   case tok::ampamp: {      // unary-expression: '&&' identifier | 
 | 566 |     SourceLocation AmpAmpLoc = ConsumeToken(); | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 567 |     if (Tok.isNot(tok::identifier)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 568 |       Diag(Tok, diag::err_expected_ident); | 
 | 569 |       return ExprResult(true); | 
 | 570 |     } | 
 | 571 |      | 
 | 572 |     Diag(AmpAmpLoc, diag::ext_gnu_address_of_label); | 
| Steve Naroff | 1b273c4 | 2007-09-16 14:56:35 +0000 | [diff] [blame] | 573 |     Res = Actions.ActOnAddrLabel(AmpAmpLoc, Tok.getLocation(), | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 574 |                                  Tok.getIdentifierInfo()); | 
 | 575 |     ConsumeToken(); | 
 | 576 |     return Res; | 
 | 577 |   } | 
 | 578 |   case tok::kw_const_cast: | 
 | 579 |   case tok::kw_dynamic_cast: | 
 | 580 |   case tok::kw_reinterpret_cast: | 
 | 581 |   case tok::kw_static_cast: | 
| Argyrios Kyrtzidis | b348b81 | 2008-08-16 19:45:32 +0000 | [diff] [blame] | 582 |     Res = ParseCXXCasts(); | 
 | 583 |     // These can be followed by postfix-expr pieces. | 
 | 584 |     return ParsePostfixExpressionSuffix(Res); | 
| Sebastian Redl | c42e118 | 2008-11-11 11:37:55 +0000 | [diff] [blame] | 585 |   case tok::kw_typeid: | 
 | 586 |     Res = ParseCXXTypeid(); | 
 | 587 |     // This can be followed by postfix-expr pieces. | 
 | 588 |     return ParsePostfixExpressionSuffix(Res); | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 589 |   case tok::kw_this: | 
| Argyrios Kyrtzidis | 289d773 | 2008-08-16 19:34:46 +0000 | [diff] [blame] | 590 |     Res = ParseCXXThis(); | 
 | 591 |     // This can be followed by postfix-expr pieces. | 
 | 592 |     return ParsePostfixExpressionSuffix(Res); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 593 |  | 
 | 594 |   case tok::kw_char: | 
 | 595 |   case tok::kw_wchar_t: | 
 | 596 |   case tok::kw_bool: | 
 | 597 |   case tok::kw_short: | 
 | 598 |   case tok::kw_int: | 
 | 599 |   case tok::kw_long: | 
 | 600 |   case tok::kw_signed: | 
 | 601 |   case tok::kw_unsigned: | 
 | 602 |   case tok::kw_float: | 
 | 603 |   case tok::kw_double: | 
 | 604 |   case tok::kw_void: | 
 | 605 |   case tok::kw_typeof: { | 
 | 606 |     if (!getLang().CPlusPlus) | 
 | 607 |       goto UnhandledToken; | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 608 |   case tok::annot_qualtypename: | 
 | 609 |     assert(getLang().CPlusPlus && "Expected C++"); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 610 |     // postfix-expression: simple-type-specifier '(' expression-list[opt] ')' | 
 | 611 |     // | 
 | 612 |     DeclSpec DS; | 
 | 613 |     ParseCXXSimpleTypeSpecifier(DS); | 
 | 614 |     if (Tok.isNot(tok::l_paren)) | 
| Chris Lattner | 1ab3b96 | 2008-11-18 07:48:38 +0000 | [diff] [blame] | 615 |       return Diag(Tok, diag::err_expected_lparen_after_type) | 
 | 616 |               << DS.getSourceRange(); | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 617 |  | 
 | 618 |     Res = ParseCXXTypeConstructExpression(DS); | 
 | 619 |     // This can be followed by postfix-expr pieces. | 
 | 620 |     return ParsePostfixExpressionSuffix(Res); | 
 | 621 |   } | 
 | 622 |  | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 623 |   case tok::annot_cxxscope: // [C++] id-expression: qualified-id | 
 | 624 |   case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id | 
 | 625 |                          //                      template-id | 
 | 626 |     Res = ParseCXXIdExpression(); | 
 | 627 |     return ParsePostfixExpressionSuffix(Res); | 
| Douglas Gregor | 1cd1b1e | 2008-11-06 22:13:31 +0000 | [diff] [blame] | 628 |  | 
| Sebastian Redl | 4c5d320 | 2008-11-21 19:14:01 +0000 | [diff] [blame] | 629 |   case tok::kw_new: // [C++] new-expression | 
 | 630 |     // FIXME: ParseCXXIdExpression currently steals :: tokens. | 
 | 631 |     return ParseCXXNewExpression(); | 
 | 632 |  | 
 | 633 |   case tok::kw_delete: // [C++] delete-expression | 
 | 634 |     return ParseCXXDeleteExpression(); | 
 | 635 |  | 
| Chris Lattner | c97c204 | 2007-10-03 22:03:06 +0000 | [diff] [blame] | 636 |   case tok::at: { | 
 | 637 |     SourceLocation AtLoc = ConsumeToken(); | 
| Steve Naroff | a642beb | 2007-10-15 20:55:58 +0000 | [diff] [blame] | 638 |     return ParseObjCAtExpression(AtLoc); | 
| Chris Lattner | c97c204 | 2007-10-03 22:03:06 +0000 | [diff] [blame] | 639 |   } | 
| Fariborz Jahanian | 0ccb27d | 2007-09-05 19:52:07 +0000 | [diff] [blame] | 640 |   case tok::l_square: | 
| Steve Naroff | a642beb | 2007-10-15 20:55:58 +0000 | [diff] [blame] | 641 |     // These can be followed by postfix-expr pieces. | 
| Chris Lattner | 039a642 | 2008-05-09 05:28:21 +0000 | [diff] [blame] | 642 |     if (getLang().ObjC1) | 
 | 643 |       return ParsePostfixExpressionSuffix(ParseObjCMessageExpression()); | 
 | 644 |     // FALL THROUGH. | 
| Steve Naroff | 296e8d5 | 2008-08-28 19:20:44 +0000 | [diff] [blame] | 645 |   case tok::caret: | 
 | 646 |     if (getLang().Blocks) | 
 | 647 |       return ParsePostfixExpressionSuffix(ParseBlockLiteralExpression()); | 
 | 648 |     Diag(Tok, diag::err_expected_expression); | 
 | 649 |     return ExprResult(true); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 650 |   default: | 
| Argyrios Kyrtzidis | 987a14b | 2008-08-22 15:38:55 +0000 | [diff] [blame] | 651 |   UnhandledToken: | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 652 |     Diag(Tok, diag::err_expected_expression); | 
 | 653 |     return ExprResult(true); | 
 | 654 |   } | 
 | 655 |    | 
 | 656 |   // unreachable. | 
 | 657 |   abort(); | 
 | 658 | } | 
 | 659 |  | 
 | 660 | /// ParsePostfixExpressionSuffix - Once the leading part of a postfix-expression | 
 | 661 | /// is parsed, this method parses any suffixes that apply. | 
 | 662 | /// | 
 | 663 | ///       postfix-expression: [C99 6.5.2] | 
 | 664 | ///         primary-expression | 
 | 665 | ///         postfix-expression '[' expression ']' | 
 | 666 | ///         postfix-expression '(' argument-expression-list[opt] ')' | 
 | 667 | ///         postfix-expression '.' identifier | 
 | 668 | ///         postfix-expression '->' identifier | 
 | 669 | ///         postfix-expression '++' | 
 | 670 | ///         postfix-expression '--' | 
 | 671 | ///         '(' type-name ')' '{' initializer-list '}' | 
 | 672 | ///         '(' type-name ')' '{' initializer-list ',' '}' | 
 | 673 | /// | 
 | 674 | ///       argument-expression-list: [C99 6.5.2] | 
 | 675 | ///         argument-expression | 
 | 676 | ///         argument-expression-list ',' assignment-expression | 
 | 677 | /// | 
 | 678 | Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { | 
 | 679 |    | 
 | 680 |   // Now that the primary-expression piece of the postfix-expression has been | 
 | 681 |   // parsed, see if there are any postfix-expression pieces here. | 
 | 682 |   SourceLocation Loc; | 
 | 683 |   while (1) { | 
 | 684 |     switch (Tok.getKind()) { | 
 | 685 |     default:  // Not a postfix-expression suffix. | 
 | 686 |       return LHS; | 
 | 687 |     case tok::l_square: {  // postfix-expression: p-e '[' expression ']' | 
 | 688 |       Loc = ConsumeBracket(); | 
 | 689 |       ExprResult Idx = ParseExpression(); | 
 | 690 |        | 
 | 691 |       SourceLocation RLoc = Tok.getLocation(); | 
 | 692 |        | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 693 |       if (!LHS.isInvalid && !Idx.isInvalid && Tok.is(tok::r_square)) | 
| Douglas Gregor | 337c6b9 | 2008-11-19 17:17:41 +0000 | [diff] [blame] | 694 |         LHS = Actions.ActOnArraySubscriptExpr(CurScope, LHS.Val, Loc,  | 
 | 695 |                                               Idx.Val, RLoc); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 696 |       else  | 
 | 697 |         LHS = ExprResult(true); | 
 | 698 |  | 
 | 699 |       // Match the ']'. | 
 | 700 |       MatchRHSPunctuation(tok::r_square, Loc); | 
 | 701 |       break; | 
 | 702 |     } | 
 | 703 |        | 
 | 704 |     case tok::l_paren: {   // p-e: p-e '(' argument-expression-list[opt] ')' | 
| Argyrios Kyrtzidis | 0cd5b42 | 2008-08-16 20:03:01 +0000 | [diff] [blame] | 705 |       ExprListTy ArgExprs; | 
 | 706 |       CommaLocsTy CommaLocs; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 707 |        | 
 | 708 |       Loc = ConsumeParen(); | 
 | 709 |        | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 710 |       if (Tok.isNot(tok::r_paren)) { | 
| Argyrios Kyrtzidis | 0cd5b42 | 2008-08-16 20:03:01 +0000 | [diff] [blame] | 711 |         if (ParseExpressionList(ArgExprs, CommaLocs)) { | 
 | 712 |           SkipUntil(tok::r_paren); | 
 | 713 |           return ExprResult(true); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 714 |         } | 
 | 715 |       } | 
 | 716 |          | 
 | 717 |       // Match the ')'. | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 718 |       if (!LHS.isInvalid && Tok.is(tok::r_paren)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 719 |         assert((ArgExprs.size() == 0 || ArgExprs.size()-1 == CommaLocs.size())&& | 
 | 720 |                "Unexpected number of commas!"); | 
| Steve Naroff | f69936d | 2007-09-16 03:34:24 +0000 | [diff] [blame] | 721 |         LHS = Actions.ActOnCallExpr(LHS.Val, Loc, &ArgExprs[0], ArgExprs.size(), | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 722 |                                     &CommaLocs[0], Tok.getLocation()); | 
 | 723 |       } | 
 | 724 |        | 
| Chris Lattner | 2ff5426 | 2007-07-21 05:18:12 +0000 | [diff] [blame] | 725 |       MatchRHSPunctuation(tok::r_paren, Loc); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 726 |       break; | 
 | 727 |     } | 
 | 728 |     case tok::arrow:       // postfix-expression: p-e '->' identifier | 
 | 729 |     case tok::period: {    // postfix-expression: p-e '.' identifier | 
 | 730 |       tok::TokenKind OpKind = Tok.getKind(); | 
 | 731 |       SourceLocation OpLoc = ConsumeToken();  // Eat the "." or "->" token. | 
 | 732 |        | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 733 |       if (Tok.isNot(tok::identifier)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 734 |         Diag(Tok, diag::err_expected_ident); | 
 | 735 |         return ExprResult(true); | 
 | 736 |       } | 
 | 737 |        | 
 | 738 |       if (!LHS.isInvalid) | 
| Steve Naroff | f69936d | 2007-09-16 03:34:24 +0000 | [diff] [blame] | 739 |         LHS = Actions.ActOnMemberReferenceExpr(LHS.Val, OpLoc, OpKind, | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 740 |                                                Tok.getLocation(), | 
 | 741 |                                                *Tok.getIdentifierInfo()); | 
 | 742 |       ConsumeToken(); | 
 | 743 |       break; | 
 | 744 |     } | 
 | 745 |     case tok::plusplus:    // postfix-expression: postfix-expression '++' | 
 | 746 |     case tok::minusminus:  // postfix-expression: postfix-expression '--' | 
 | 747 |       if (!LHS.isInvalid) | 
| Douglas Gregor | 7425373 | 2008-11-19 15:42:04 +0000 | [diff] [blame] | 748 |         LHS = Actions.ActOnPostfixUnaryOp(CurScope, Tok.getLocation(),  | 
 | 749 |                                           Tok.getKind(), LHS.Val); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 750 |       ConsumeToken(); | 
 | 751 |       break; | 
 | 752 |     } | 
 | 753 |   } | 
 | 754 | } | 
 | 755 |  | 
 | 756 |  | 
 | 757 | /// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression. | 
 | 758 | ///       unary-expression:  [C99 6.5.3] | 
 | 759 | ///         'sizeof' unary-expression | 
 | 760 | ///         'sizeof' '(' type-name ')' | 
 | 761 | /// [GNU]   '__alignof' unary-expression | 
 | 762 | /// [GNU]   '__alignof' '(' type-name ')' | 
| Douglas Gregor | 85bb3da | 2008-11-06 15:17:27 +0000 | [diff] [blame] | 763 | /// [C++0x] 'alignof' '(' type-id ')' | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 764 | Parser::ExprResult Parser::ParseSizeofAlignofExpression() { | 
| Douglas Gregor | 85bb3da | 2008-11-06 15:17:27 +0000 | [diff] [blame] | 765 |   assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof) | 
 | 766 |           || Tok.is(tok::kw_alignof)) && | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 767 |          "Not a sizeof/alignof expression!"); | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 768 |   Token OpTok = Tok; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 769 |   ConsumeToken(); | 
 | 770 |    | 
 | 771 |   // If the operand doesn't start with an '(', it must be an expression. | 
 | 772 |   ExprResult Operand; | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 773 |   if (Tok.isNot(tok::l_paren)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 774 |     Operand = ParseCastExpression(true); | 
 | 775 |   } else { | 
 | 776 |     // If it starts with a '(', we know that it is either a parenthesized | 
 | 777 |     // type-name, or it is a unary-expression that starts with a compound | 
 | 778 |     // literal, or starts with a primary-expression that is a parenthesized | 
 | 779 |     // expression. | 
 | 780 |     ParenParseOption ExprType = CastExpr; | 
 | 781 |     TypeTy *CastTy; | 
 | 782 |     SourceLocation LParenLoc = Tok.getLocation(), RParenLoc; | 
 | 783 |     Operand = ParseParenExpression(ExprType, CastTy, RParenLoc); | 
 | 784 |      | 
 | 785 |     // If ParseParenExpression parsed a '(typename)' sequence only, the this is | 
 | 786 |     // sizeof/alignof a type.  Otherwise, it is sizeof/alignof an expression. | 
| Chris Lattner | 4c1a2a9 | 2007-11-13 20:50:37 +0000 | [diff] [blame] | 787 |     if (ExprType == CastExpr) | 
| Sebastian Redl | 0518999 | 2008-11-11 17:56:53 +0000 | [diff] [blame] | 788 |       return Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(), | 
 | 789 |                                             OpTok.is(tok::kw_sizeof), | 
 | 790 |                                             /*isType=*/true, CastTy, | 
 | 791 |                                             SourceRange(LParenLoc, RParenLoc)); | 
| Chris Lattner | 4c1a2a9 | 2007-11-13 20:50:37 +0000 | [diff] [blame] | 792 |      | 
 | 793 |     // If this is a parenthesized expression, it is the start of a  | 
 | 794 |     // unary-expression, but doesn't include any postfix pieces.  Parse these | 
 | 795 |     // now if present. | 
 | 796 |     Operand = ParsePostfixExpressionSuffix(Operand); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 797 |   } | 
 | 798 |    | 
 | 799 |   // If we get here, the operand to the sizeof/alignof was an expresion. | 
 | 800 |   if (!Operand.isInvalid) | 
| Sebastian Redl | 0518999 | 2008-11-11 17:56:53 +0000 | [diff] [blame] | 801 |     Operand = Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(), | 
 | 802 |                                              OpTok.is(tok::kw_sizeof), | 
 | 803 |                                              /*isType=*/false, Operand.Val, | 
 | 804 |                                              SourceRange()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 805 |   return Operand; | 
 | 806 | } | 
 | 807 |  | 
 | 808 | /// ParseBuiltinPrimaryExpression | 
 | 809 | /// | 
 | 810 | ///       primary-expression: [C99 6.5.1] | 
 | 811 | /// [GNU]   '__builtin_va_arg' '(' assignment-expression ',' type-name ')' | 
 | 812 | /// [GNU]   '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')' | 
 | 813 | /// [GNU]   '__builtin_choose_expr' '(' assign-expr ',' assign-expr ',' | 
 | 814 | ///                                     assign-expr ')' | 
 | 815 | /// [GNU]   '__builtin_types_compatible_p' '(' type-name ',' type-name ')' | 
| Nate Begeman | e2ce1d9 | 2008-01-17 17:46:27 +0000 | [diff] [blame] | 816 | /// [CLANG] '__builtin_overload' '(' expr (',' expr)* ')' | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 817 | ///  | 
 | 818 | /// [GNU] offsetof-member-designator: | 
 | 819 | /// [GNU]   identifier | 
 | 820 | /// [GNU]   offsetof-member-designator '.' identifier | 
 | 821 | /// [GNU]   offsetof-member-designator '[' expression ']' | 
 | 822 | /// | 
 | 823 | Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() { | 
 | 824 |   ExprResult Res(false); | 
 | 825 |   const IdentifierInfo *BuiltinII = Tok.getIdentifierInfo(); | 
 | 826 |  | 
 | 827 |   tok::TokenKind T = Tok.getKind(); | 
 | 828 |   SourceLocation StartLoc = ConsumeToken();   // Eat the builtin identifier. | 
 | 829 |  | 
 | 830 |   // All of these start with an open paren. | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 831 |   if (Tok.isNot(tok::l_paren)) { | 
| Chris Lattner | 08631c5 | 2008-11-23 21:45:46 +0000 | [diff] [blame^] | 832 |     Diag(Tok, diag::err_expected_lparen_after_id) << BuiltinII; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 833 |     return ExprResult(true); | 
 | 834 |   } | 
 | 835 |    | 
 | 836 |   SourceLocation LParenLoc = ConsumeParen(); | 
 | 837 |   // TODO: Build AST. | 
 | 838 |  | 
 | 839 |   switch (T) { | 
 | 840 |   default: assert(0 && "Not a builtin primary expression!"); | 
| Anders Carlsson | 7c50aca | 2007-10-15 20:28:48 +0000 | [diff] [blame] | 841 |   case tok::kw___builtin_va_arg: { | 
 | 842 |     ExprResult Expr = ParseAssignmentExpression(); | 
 | 843 |     if (Expr.isInvalid) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 844 |       SkipUntil(tok::r_paren); | 
| Eli Friedman | 0976278 | 2008-08-20 22:07:34 +0000 | [diff] [blame] | 845 |       return ExprResult(true); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 846 |     } | 
 | 847 |  | 
 | 848 |     if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) | 
 | 849 |       return ExprResult(true); | 
 | 850 |  | 
| Anders Carlsson | 7c50aca | 2007-10-15 20:28:48 +0000 | [diff] [blame] | 851 |     TypeTy *Ty = ParseTypeName(); | 
| Chris Lattner | 6eb2109 | 2007-08-30 15:52:49 +0000 | [diff] [blame] | 852 |      | 
| Anders Carlsson | 7c50aca | 2007-10-15 20:28:48 +0000 | [diff] [blame] | 853 |     if (Tok.isNot(tok::r_paren)) { | 
 | 854 |       Diag(Tok, diag::err_expected_rparen); | 
 | 855 |       return ExprResult(true); | 
 | 856 |     } | 
 | 857 |     Res = Actions.ActOnVAArg(StartLoc, Expr.Val, Ty, ConsumeParen()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 858 |     break; | 
| Anders Carlsson | 7c50aca | 2007-10-15 20:28:48 +0000 | [diff] [blame] | 859 |   } | 
| Chris Lattner | f9aa3cb | 2007-08-30 15:51:11 +0000 | [diff] [blame] | 860 |   case tok::kw___builtin_offsetof: { | 
| Chris Lattner | 9fddf0a | 2007-08-30 17:08:45 +0000 | [diff] [blame] | 861 |     SourceLocation TypeLoc = Tok.getLocation(); | 
| Chris Lattner | f9aa3cb | 2007-08-30 15:51:11 +0000 | [diff] [blame] | 862 |     TypeTy *Ty = ParseTypeName(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 863 |  | 
 | 864 |     if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) | 
 | 865 |       return ExprResult(true); | 
 | 866 |      | 
 | 867 |     // We must have at least one identifier here. | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 868 |     if (Tok.isNot(tok::identifier)) { | 
| Chris Lattner | f9aa3cb | 2007-08-30 15:51:11 +0000 | [diff] [blame] | 869 |       Diag(Tok, diag::err_expected_ident); | 
 | 870 |       SkipUntil(tok::r_paren); | 
 | 871 |       return true; | 
 | 872 |     } | 
 | 873 |      | 
 | 874 |     // Keep track of the various subcomponents we see. | 
 | 875 |     llvm::SmallVector<Action::OffsetOfComponent, 4> Comps; | 
 | 876 |      | 
 | 877 |     Comps.push_back(Action::OffsetOfComponent()); | 
 | 878 |     Comps.back().isBrackets = false; | 
 | 879 |     Comps.back().U.IdentInfo = Tok.getIdentifierInfo(); | 
 | 880 |     Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 881 |  | 
 | 882 |     while (1) { | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 883 |       if (Tok.is(tok::period)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 884 |         // offsetof-member-designator: offsetof-member-designator '.' identifier | 
| Chris Lattner | f9aa3cb | 2007-08-30 15:51:11 +0000 | [diff] [blame] | 885 |         Comps.push_back(Action::OffsetOfComponent()); | 
 | 886 |         Comps.back().isBrackets = false; | 
 | 887 |         Comps.back().LocStart = ConsumeToken(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 888 |          | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 889 |         if (Tok.isNot(tok::identifier)) { | 
| Chris Lattner | f9aa3cb | 2007-08-30 15:51:11 +0000 | [diff] [blame] | 890 |           Diag(Tok, diag::err_expected_ident); | 
 | 891 |           SkipUntil(tok::r_paren); | 
 | 892 |           return true; | 
 | 893 |         } | 
 | 894 |         Comps.back().U.IdentInfo = Tok.getIdentifierInfo(); | 
 | 895 |         Comps.back().LocEnd = ConsumeToken(); | 
 | 896 |          | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 897 |       } else if (Tok.is(tok::l_square)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 898 |         // offsetof-member-designator: offsetof-member-design '[' expression ']' | 
| Chris Lattner | f9aa3cb | 2007-08-30 15:51:11 +0000 | [diff] [blame] | 899 |         Comps.push_back(Action::OffsetOfComponent()); | 
 | 900 |         Comps.back().isBrackets = true; | 
 | 901 |         Comps.back().LocStart = ConsumeBracket(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 902 |         Res = ParseExpression(); | 
 | 903 |         if (Res.isInvalid) { | 
 | 904 |           SkipUntil(tok::r_paren); | 
 | 905 |           return Res; | 
 | 906 |         } | 
| Chris Lattner | f9aa3cb | 2007-08-30 15:51:11 +0000 | [diff] [blame] | 907 |         Comps.back().U.E = Res.Val; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 908 |  | 
| Chris Lattner | f9aa3cb | 2007-08-30 15:51:11 +0000 | [diff] [blame] | 909 |         Comps.back().LocEnd = | 
 | 910 |           MatchRHSPunctuation(tok::r_square, Comps.back().LocStart); | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 911 |       } else if (Tok.is(tok::r_paren)) { | 
| Steve Naroff | 1b273c4 | 2007-09-16 14:56:35 +0000 | [diff] [blame] | 912 |         Res = Actions.ActOnBuiltinOffsetOf(StartLoc, TypeLoc, Ty, &Comps[0], | 
| Chris Lattner | 6eb2109 | 2007-08-30 15:52:49 +0000 | [diff] [blame] | 913 |                                            Comps.size(), ConsumeParen()); | 
 | 914 |         break; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 915 |       } else { | 
| Chris Lattner | f9aa3cb | 2007-08-30 15:51:11 +0000 | [diff] [blame] | 916 |         // Error occurred. | 
 | 917 |         return ExprResult(true); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 918 |       } | 
 | 919 |     } | 
 | 920 |     break; | 
| Chris Lattner | f9aa3cb | 2007-08-30 15:51:11 +0000 | [diff] [blame] | 921 |   } | 
| Steve Naroff | d04fdd5 | 2007-08-03 21:21:27 +0000 | [diff] [blame] | 922 |   case tok::kw___builtin_choose_expr: { | 
 | 923 |     ExprResult Cond = ParseAssignmentExpression(); | 
 | 924 |     if (Cond.isInvalid) { | 
 | 925 |       SkipUntil(tok::r_paren); | 
 | 926 |       return Cond; | 
 | 927 |     } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 928 |     if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) | 
 | 929 |       return ExprResult(true); | 
 | 930 |      | 
| Steve Naroff | d04fdd5 | 2007-08-03 21:21:27 +0000 | [diff] [blame] | 931 |     ExprResult Expr1 = ParseAssignmentExpression(); | 
 | 932 |     if (Expr1.isInvalid) { | 
 | 933 |       SkipUntil(tok::r_paren); | 
 | 934 |       return Expr1; | 
 | 935 |     }     | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 936 |     if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) | 
 | 937 |       return ExprResult(true); | 
 | 938 |      | 
| Steve Naroff | d04fdd5 | 2007-08-03 21:21:27 +0000 | [diff] [blame] | 939 |     ExprResult Expr2 = ParseAssignmentExpression(); | 
 | 940 |     if (Expr2.isInvalid) { | 
 | 941 |       SkipUntil(tok::r_paren); | 
 | 942 |       return Expr2; | 
 | 943 |     }     | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 944 |     if (Tok.isNot(tok::r_paren)) { | 
| Steve Naroff | d04fdd5 | 2007-08-03 21:21:27 +0000 | [diff] [blame] | 945 |       Diag(Tok, diag::err_expected_rparen); | 
 | 946 |       return ExprResult(true); | 
 | 947 |     } | 
| Steve Naroff | 1b273c4 | 2007-09-16 14:56:35 +0000 | [diff] [blame] | 948 |     Res = Actions.ActOnChooseExpr(StartLoc, Cond.Val, Expr1.Val, Expr2.Val, | 
| Chris Lattner | 6eb2109 | 2007-08-30 15:52:49 +0000 | [diff] [blame] | 949 |                                   ConsumeParen()); | 
 | 950 |     break; | 
| Steve Naroff | d04fdd5 | 2007-08-03 21:21:27 +0000 | [diff] [blame] | 951 |   } | 
| Nate Begeman | e2ce1d9 | 2008-01-17 17:46:27 +0000 | [diff] [blame] | 952 |   case tok::kw___builtin_overload: { | 
 | 953 |     llvm::SmallVector<ExprTy*, 8> ArgExprs; | 
 | 954 |     llvm::SmallVector<SourceLocation, 8> CommaLocs; | 
 | 955 |  | 
 | 956 |     // For each iteration through the loop look for assign-expr followed by a | 
 | 957 |     // comma.  If there is no comma, break and attempt to match r-paren. | 
 | 958 |     if (Tok.isNot(tok::r_paren)) { | 
 | 959 |       while (1) { | 
 | 960 |         ExprResult ArgExpr = ParseAssignmentExpression(); | 
 | 961 |         if (ArgExpr.isInvalid) { | 
 | 962 |           SkipUntil(tok::r_paren); | 
 | 963 |           return ExprResult(true); | 
 | 964 |         } else | 
 | 965 |           ArgExprs.push_back(ArgExpr.Val); | 
 | 966 |          | 
 | 967 |         if (Tok.isNot(tok::comma)) | 
 | 968 |           break; | 
 | 969 |         // Move to the next argument, remember where the comma was. | 
 | 970 |         CommaLocs.push_back(ConsumeToken()); | 
 | 971 |       } | 
 | 972 |     } | 
 | 973 |      | 
 | 974 |     // Attempt to consume the r-paren | 
 | 975 |     if (Tok.isNot(tok::r_paren)) { | 
 | 976 |       Diag(Tok, diag::err_expected_rparen); | 
 | 977 |       SkipUntil(tok::r_paren); | 
 | 978 |       return ExprResult(true); | 
 | 979 |     } | 
| Nate Begeman | e2ce1d9 | 2008-01-17 17:46:27 +0000 | [diff] [blame] | 980 |     Res = Actions.ActOnOverloadExpr(&ArgExprs[0], ArgExprs.size(),  | 
 | 981 |                                     &CommaLocs[0], StartLoc, ConsumeParen()); | 
 | 982 |     break; | 
 | 983 |   } | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 984 |   case tok::kw___builtin_types_compatible_p: | 
| Steve Naroff | 363bcff | 2007-08-01 23:45:51 +0000 | [diff] [blame] | 985 |     TypeTy *Ty1 = ParseTypeName(); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 986 |      | 
 | 987 |     if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) | 
 | 988 |       return ExprResult(true); | 
 | 989 |      | 
| Steve Naroff | 363bcff | 2007-08-01 23:45:51 +0000 | [diff] [blame] | 990 |     TypeTy *Ty2 = ParseTypeName(); | 
 | 991 |      | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 992 |     if (Tok.isNot(tok::r_paren)) { | 
| Steve Naroff | 363bcff | 2007-08-01 23:45:51 +0000 | [diff] [blame] | 993 |       Diag(Tok, diag::err_expected_rparen); | 
 | 994 |       return ExprResult(true); | 
 | 995 |     } | 
| Steve Naroff | 1b273c4 | 2007-09-16 14:56:35 +0000 | [diff] [blame] | 996 |     Res = Actions.ActOnTypesCompatibleExpr(StartLoc, Ty1, Ty2, ConsumeParen()); | 
| Chris Lattner | 6eb2109 | 2007-08-30 15:52:49 +0000 | [diff] [blame] | 997 |     break; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 998 |   }       | 
 | 999 |    | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1000 |   // These can be followed by postfix-expr pieces because they are | 
 | 1001 |   // primary-expressions. | 
 | 1002 |   return ParsePostfixExpressionSuffix(Res); | 
 | 1003 | } | 
 | 1004 |  | 
 | 1005 | /// ParseParenExpression - This parses the unit that starts with a '(' token, | 
 | 1006 | /// based on what is allowed by ExprType.  The actual thing parsed is returned | 
 | 1007 | /// in ExprType. | 
 | 1008 | /// | 
 | 1009 | ///       primary-expression: [C99 6.5.1] | 
 | 1010 | ///         '(' expression ')' | 
 | 1011 | /// [GNU]   '(' compound-statement ')'      (if !ParenExprOnly) | 
 | 1012 | ///       postfix-expression: [C99 6.5.2] | 
 | 1013 | ///         '(' type-name ')' '{' initializer-list '}' | 
 | 1014 | ///         '(' type-name ')' '{' initializer-list ',' '}' | 
 | 1015 | ///       cast-expression: [C99 6.5.4] | 
 | 1016 | ///         '(' type-name ')' cast-expression | 
 | 1017 | /// | 
 | 1018 | Parser::ExprResult Parser::ParseParenExpression(ParenParseOption &ExprType, | 
 | 1019 |                                                 TypeTy *&CastTy, | 
 | 1020 |                                                 SourceLocation &RParenLoc) { | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 1021 |   assert(Tok.is(tok::l_paren) && "Not a paren expr!"); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1022 |   SourceLocation OpenLoc = ConsumeParen(); | 
| Chris Lattner | ab18c4c | 2007-07-24 16:58:17 +0000 | [diff] [blame] | 1023 |   ExprResult Result(true); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1024 |   CastTy = 0; | 
 | 1025 |    | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 1026 |   if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1027 |     Diag(Tok, diag::ext_gnu_statement_expr); | 
| Chris Lattner | 98414c1 | 2007-08-31 21:49:55 +0000 | [diff] [blame] | 1028 |     Parser::StmtResult Stmt = ParseCompoundStatement(true); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1029 |     ExprType = CompoundStmt; | 
| Chris Lattner | ab18c4c | 2007-07-24 16:58:17 +0000 | [diff] [blame] | 1030 |      | 
 | 1031 |     // If the substmt parsed correctly, build the AST node. | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 1032 |     if (!Stmt.isInvalid && Tok.is(tok::r_paren)) | 
| Steve Naroff | 1b273c4 | 2007-09-16 14:56:35 +0000 | [diff] [blame] | 1033 |       Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.Val, Tok.getLocation()); | 
| Chris Lattner | ab18c4c | 2007-07-24 16:58:17 +0000 | [diff] [blame] | 1034 |      | 
| Argyrios Kyrtzidis | 78c8d80 | 2008-10-05 19:56:22 +0000 | [diff] [blame] | 1035 |   } else if (ExprType >= CompoundLiteral && isTypeIdInParens()) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1036 |     // Otherwise, this is a compound literal expression or cast expression. | 
 | 1037 |     TypeTy *Ty = ParseTypeName(); | 
 | 1038 |  | 
 | 1039 |     // Match the ')'. | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 1040 |     if (Tok.is(tok::r_paren)) | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1041 |       RParenLoc = ConsumeParen(); | 
 | 1042 |     else | 
 | 1043 |       MatchRHSPunctuation(tok::r_paren, OpenLoc); | 
 | 1044 |      | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 1045 |     if (Tok.is(tok::l_brace)) { | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1046 |       if (!getLang().C99)   // Compound literals don't exist in C90. | 
 | 1047 |         Diag(OpenLoc, diag::ext_c99_compound_literal); | 
 | 1048 |       Result = ParseInitializer(); | 
 | 1049 |       ExprType = CompoundLiteral; | 
| Steve Naroff | 4aa88f8 | 2007-07-19 01:06:55 +0000 | [diff] [blame] | 1050 |       if (!Result.isInvalid) | 
| Steve Naroff | f69936d | 2007-09-16 03:34:24 +0000 | [diff] [blame] | 1051 |         return Actions.ActOnCompoundLiteral(OpenLoc, Ty, RParenLoc, Result.Val); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1052 |     } else if (ExprType == CastExpr) { | 
 | 1053 |       // Note that this doesn't parse the subsequence cast-expression, it just | 
 | 1054 |       // returns the parsed type to the callee. | 
 | 1055 |       ExprType = CastExpr; | 
 | 1056 |       CastTy = Ty; | 
 | 1057 |       return ExprResult(false); | 
 | 1058 |     } else { | 
 | 1059 |       Diag(Tok, diag::err_expected_lbrace_in_compound_literal); | 
 | 1060 |       return ExprResult(true); | 
 | 1061 |     } | 
 | 1062 |     return Result; | 
 | 1063 |   } else { | 
 | 1064 |     Result = ParseExpression(); | 
 | 1065 |     ExprType = SimpleExpr; | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 1066 |     if (!Result.isInvalid && Tok.is(tok::r_paren)) | 
| Steve Naroff | f69936d | 2007-09-16 03:34:24 +0000 | [diff] [blame] | 1067 |       Result = Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.Val); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1068 |   } | 
 | 1069 |    | 
 | 1070 |   // Match the ')'. | 
 | 1071 |   if (Result.isInvalid) | 
 | 1072 |     SkipUntil(tok::r_paren); | 
 | 1073 |   else { | 
| Chris Lattner | 4e1d99a | 2007-10-09 17:41:39 +0000 | [diff] [blame] | 1074 |     if (Tok.is(tok::r_paren)) | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1075 |       RParenLoc = ConsumeParen(); | 
 | 1076 |     else | 
 | 1077 |       MatchRHSPunctuation(tok::r_paren, OpenLoc); | 
 | 1078 |   } | 
 | 1079 |    | 
 | 1080 |   return Result; | 
 | 1081 | } | 
 | 1082 |  | 
 | 1083 | /// ParseStringLiteralExpression - This handles the various token types that | 
 | 1084 | /// form string literals, and also handles string concatenation [C99 5.1.1.2, | 
 | 1085 | /// translation phase #6]. | 
 | 1086 | /// | 
 | 1087 | ///       primary-expression: [C99 6.5.1] | 
 | 1088 | ///         string-literal | 
 | 1089 | Parser::ExprResult Parser::ParseStringLiteralExpression() { | 
 | 1090 |   assert(isTokenStringLiteral() && "Not a string literal!"); | 
 | 1091 |    | 
 | 1092 |   // String concat.  Note that keywords like __func__ and __FUNCTION__ are not | 
 | 1093 |   // considered to be strings for concatenation purposes. | 
| Chris Lattner | d217773 | 2007-07-20 16:59:19 +0000 | [diff] [blame] | 1094 |   llvm::SmallVector<Token, 4> StringToks; | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1095 |    | 
 | 1096 |   do { | 
 | 1097 |     StringToks.push_back(Tok); | 
 | 1098 |     ConsumeStringToken(); | 
 | 1099 |   } while (isTokenStringLiteral()); | 
 | 1100 |  | 
 | 1101 |   // Pass the set of string tokens, ready for concatenation, to the actions. | 
| Steve Naroff | f69936d | 2007-09-16 03:34:24 +0000 | [diff] [blame] | 1102 |   return Actions.ActOnStringLiteral(&StringToks[0], StringToks.size()); | 
| Reid Spencer | 5f016e2 | 2007-07-11 17:01:13 +0000 | [diff] [blame] | 1103 | } | 
| Argyrios Kyrtzidis | 0cd5b42 | 2008-08-16 20:03:01 +0000 | [diff] [blame] | 1104 |  | 
 | 1105 | /// ParseExpressionList - Used for C/C++ (argument-)expression-list. | 
 | 1106 | /// | 
 | 1107 | ///       argument-expression-list: | 
 | 1108 | ///         assignment-expression | 
 | 1109 | ///         argument-expression-list , assignment-expression | 
 | 1110 | /// | 
 | 1111 | /// [C++] expression-list: | 
 | 1112 | /// [C++]   assignment-expression | 
 | 1113 | /// [C++]   expression-list , assignment-expression | 
 | 1114 | /// | 
 | 1115 | bool Parser::ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs) { | 
 | 1116 |   while (1) { | 
 | 1117 |     ExprResult Expr = ParseAssignmentExpression(); | 
 | 1118 |     if (Expr.isInvalid) | 
 | 1119 |       return true; | 
| Argyrios Kyrtzidis | 4fdc1ca | 2008-08-18 22:49:40 +0000 | [diff] [blame] | 1120 |  | 
 | 1121 |     Exprs.push_back(Expr.Val); | 
| Argyrios Kyrtzidis | 0cd5b42 | 2008-08-16 20:03:01 +0000 | [diff] [blame] | 1122 |  | 
 | 1123 |     if (Tok.isNot(tok::comma)) | 
 | 1124 |       return false; | 
 | 1125 |     // Move to the next argument, remember where the comma was. | 
 | 1126 |     CommaLocs.push_back(ConsumeToken()); | 
 | 1127 |   } | 
 | 1128 | } | 
| Steve Naroff | 296e8d5 | 2008-08-28 19:20:44 +0000 | [diff] [blame] | 1129 |  | 
 | 1130 | /// ParseBlockLiteralExpression - Parse a block literal, which roughly looks | 
| Steve Naroff | 17dab4f | 2008-09-16 23:11:46 +0000 | [diff] [blame] | 1131 | /// like ^(int x){ return x+1; } | 
| Steve Naroff | 296e8d5 | 2008-08-28 19:20:44 +0000 | [diff] [blame] | 1132 | /// | 
 | 1133 | ///         block-literal: | 
 | 1134 | /// [clang]   '^' block-args[opt] compound-statement | 
| Steve Naroff | 296e8d5 | 2008-08-28 19:20:44 +0000 | [diff] [blame] | 1135 | /// [clang] block-args: | 
 | 1136 | /// [clang]   '(' parameter-list ')' | 
 | 1137 | /// | 
 | 1138 | Parser::ExprResult Parser::ParseBlockLiteralExpression() { | 
 | 1139 |   assert(Tok.is(tok::caret) && "block literal starts with ^"); | 
 | 1140 |   SourceLocation CaretLoc = ConsumeToken(); | 
 | 1141 |    | 
 | 1142 |   // Enter a scope to hold everything within the block.  This includes the  | 
 | 1143 |   // argument decls, decls within the compound expression, etc.  This also | 
 | 1144 |   // allows determining whether a variable reference inside the block is | 
 | 1145 |   // within or outside of the block. | 
 | 1146 |   EnterScope(Scope::BlockScope|Scope::FnScope|Scope::BreakScope| | 
 | 1147 |              Scope::ContinueScope|Scope::DeclScope); | 
| Steve Naroff | 090276f | 2008-10-10 01:28:17 +0000 | [diff] [blame] | 1148 |  | 
 | 1149 |   // Inform sema that we are starting a block. | 
 | 1150 |   Actions.ActOnBlockStart(CaretLoc, CurScope); | 
| Steve Naroff | 296e8d5 | 2008-08-28 19:20:44 +0000 | [diff] [blame] | 1151 |    | 
 | 1152 |   // Parse the return type if present. | 
 | 1153 |   DeclSpec DS; | 
 | 1154 |   Declarator ParamInfo(DS, Declarator::PrototypeContext); | 
 | 1155 |    | 
 | 1156 |   // If this block has arguments, parse them.  There is no ambiguity here with | 
 | 1157 |   // the expression case, because the expression case requires a parameter list. | 
 | 1158 |   if (Tok.is(tok::l_paren)) { | 
 | 1159 |     ParseParenDeclarator(ParamInfo); | 
 | 1160 |     // Parse the pieces after the identifier as if we had "int(...)". | 
 | 1161 |     ParamInfo.SetIdentifier(0, CaretLoc); | 
 | 1162 |     if (ParamInfo.getInvalidType()) { | 
 | 1163 |       // If there was an error parsing the arguments, they may have tried to use | 
 | 1164 |       // ^(x+y) which requires an argument list.  Just skip the whole block | 
 | 1165 |       // literal. | 
 | 1166 |       ExitScope(); | 
 | 1167 |       return true; | 
 | 1168 |     } | 
 | 1169 |   } else { | 
 | 1170 |     // Otherwise, pretend we saw (void). | 
 | 1171 |     ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false, | 
| Argyrios Kyrtzidis | 971c4fa | 2008-10-24 21:46:40 +0000 | [diff] [blame] | 1172 |                                                        0, 0, 0, CaretLoc)); | 
| Steve Naroff | 296e8d5 | 2008-08-28 19:20:44 +0000 | [diff] [blame] | 1173 |   } | 
 | 1174 |  | 
 | 1175 |   // Inform sema that we are starting a block. | 
| Steve Naroff | 090276f | 2008-10-10 01:28:17 +0000 | [diff] [blame] | 1176 |   Actions.ActOnBlockArguments(ParamInfo); | 
| Steve Naroff | 296e8d5 | 2008-08-28 19:20:44 +0000 | [diff] [blame] | 1177 |    | 
| Steve Naroff | 17dab4f | 2008-09-16 23:11:46 +0000 | [diff] [blame] | 1178 |   ExprResult Result = true; | 
| Steve Naroff | 296e8d5 | 2008-08-28 19:20:44 +0000 | [diff] [blame] | 1179 |   if (Tok.is(tok::l_brace)) { | 
 | 1180 |     StmtResult Stmt = ParseCompoundStatementBody(); | 
 | 1181 |     if (!Stmt.isInvalid) { | 
 | 1182 |       Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.Val, CurScope); | 
 | 1183 |     } else { | 
 | 1184 |       Actions.ActOnBlockError(CaretLoc, CurScope); | 
| Steve Naroff | 296e8d5 | 2008-08-28 19:20:44 +0000 | [diff] [blame] | 1185 |     } | 
 | 1186 |   } | 
| Steve Naroff | 296e8d5 | 2008-08-28 19:20:44 +0000 | [diff] [blame] | 1187 |   ExitScope(); | 
 | 1188 |   return Result; | 
 | 1189 | } | 
 | 1190 |  |