15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===--- ParseInit.cpp - Initializer Parsing ------------------------------===// 25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// The LLVM Compiler Infrastructure 45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This file implements initializer parsing as specified by C99 6.7.8. 115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Parse/Parser.h" 15500d3297d2a21edeac4d46cbcbe21bc2352c2a28Chris Lattner#include "clang/Parse/ParseDiagnostic.h" 160fbda68b50ce17d7ad36ef7a5ed77518a5cd272eDouglas Gregor#include "RAIIObjectsForParser.h" 1719510856727e0e14a3696b2a72c35163bff2a71fJohn McCall#include "clang/Sema/Designator.h" 1819510856727e0e14a3696b2a72c35163bff2a71fJohn McCall#include "clang/Sema/Scope.h" 194aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff#include "llvm/ADT/SmallString.h" 2062a7217b1a848fadeca15d868aa7abe15a321b52Daniel Dunbar#include "llvm/Support/raw_ostream.h" 215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang; 225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 24b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor/// MayBeDesignationStart - Return true if the current token might be the start 25b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor/// of a designator. If we can tell it is impossible that it is a designator, 26b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor/// return false. 27b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregorbool Parser::MayBeDesignationStart() { 28b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor switch (Tok.getKind()) { 29b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor default: 30b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor return false; 31b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor 325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::period: // designator: '.' identifier 33b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor return true; 34b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor 35b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor case tok::l_square: { // designator: array-designator 364e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (!PP.getLangOpts().CPlusPlus0x) 37efcadc64ee200ae74b3859097e3e7ec5fa93a252Chris Lattner return true; 38b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor 39b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor // C++11 lambda expressions and C99 designators can be ambiguous all the 40b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor // way through the closing ']' and to the next character. Handle the easy 41b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor // cases here, and fall back to tentative parsing if those fail. 42b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor switch (PP.LookAhead(0).getKind()) { 43b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor case tok::equal: 44b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor case tok::r_square: 45b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor // Definitely starts a lambda expression. 46b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor return false; 47b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor 48b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor case tok::amp: 49b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor case tok::kw_this: 50b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor case tok::identifier: 51b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor // We have to do additional analysis, because these could be the 52b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor // start of a constant expression or a lambda capture list. 53b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor break; 54b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor 55b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor default: 56b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor // Anything not mentioned above cannot occur following a '[' in a 57b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor // lambda expression. 58b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor return true; 59b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor } 60b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor 61d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor // Handle the complicated case below. 62d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor break; 63b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor } 645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::identifier: // designation: identifier ':' 65efcadc64ee200ae74b3859097e3e7ec5fa93a252Chris Lattner return PP.LookAhead(0).is(tok::colon); 665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 67d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor 68d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor // Parse up to (at most) the token after the closing ']' to determine 69d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor // whether this is a C99 designator or a lambda. 70d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor TentativeParsingAction Tentative(*this); 71d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor ConsumeBracket(); 72d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor while (true) { 73d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor switch (Tok.getKind()) { 74d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor case tok::equal: 75d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor case tok::amp: 76d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor case tok::identifier: 77d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor case tok::kw_this: 78d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor // These tokens can occur in a capture list or a constant-expression. 79d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor // Keep looking. 80d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor ConsumeToken(); 81d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor continue; 82d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor 83d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor case tok::comma: 84d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor // Since a comma cannot occur in a constant-expression, this must 85d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor // be a lambda. 86d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor Tentative.Revert(); 87d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor return false; 88d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor 89d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor case tok::r_square: { 90d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor // Once we hit the closing square bracket, we look at the next 91d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor // token. If it's an '=', this is a designator. Otherwise, it's a 92d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor // lambda expression. This decision favors lambdas over the older 93d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor // GNU designator syntax, which allows one to omit the '=', but is 94d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor // consistent with GCC. 95d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor ConsumeBracket(); 96d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor tok::TokenKind Kind = Tok.getKind(); 97d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor Tentative.Revert(); 98d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor return Kind == tok::equal; 99d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor } 100d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor 101d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor default: 102d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor // Anything else cannot occur in a lambda capture list, so it 103d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor // must be a designator. 104d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor Tentative.Revert(); 105d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor return true; 106d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor } 107d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor } 108d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor 109d267b3f03a3b35ca218dc2b0995ccff35092cf33Douglas Gregor return true; 1105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1126aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregorstatic void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc, 1136aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor Designation &Desig) { 1146aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // If we have exactly one array designator, this used the GNU 1156aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // 'designation: array-designator' extension, otherwise there should be no 1166aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // designators at all! 1176aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor if (Desig.getNumDesignators() == 1 && 1186aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor (Desig.getDesignator(0).isArrayDesignator() || 1196aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor Desig.getDesignator(0).isArrayRangeDesignator())) 1206aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor P.Diag(Loc, diag::ext_gnu_missing_equal_designator); 1216aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor else if (Desig.getNumDesignators() > 0) 1226aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor P.Diag(Loc, diag::err_expected_equal_designator); 1236aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor} 1246aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor 1255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseInitializerWithPotentialDesignator - Parse the 'initializer' production 1265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// checking to see if the token stream starts with a designator. 1275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 1285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// designation: 1295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// designator-list '=' 1305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] array-designator 1315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] identifier ':' 1325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 1335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// designator-list: 1345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// designator 1355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// designator-list designator 1365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 1375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// designator: 1385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// array-designator 1395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// '.' identifier 1405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 1415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// array-designator: 1425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// '[' constant-expression ']' 1435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] '[' constant-expression '...' constant-expression ']' 1445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 1455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// NOTE: [OBC] allows '[ objc-receiver objc-message-args ]' as an 146838cb21b800e55d88201fa76b978a7d11478c655Chris Lattner/// initializer (because it is an expression). We need to consider this case 147838cb21b800e55d88201fa76b978a7d11478c655Chris Lattner/// when parsing array designators. 1485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 14960d7b3a319d84d688752be3870615ac0f111fb16John McCallExprResult Parser::ParseInitializerWithPotentialDesignator() { 15020df9b7ab9388b2a488c5b1293cd196b1e073b4eSebastian Redl 151eccc53a0a0ed1abc7bb4c04ed9566ce0c5c63140Chris Lattner // If this is the old-style GNU extension: 152eccc53a0a0ed1abc7bb4c04ed9566ce0c5c63140Chris Lattner // designation ::= identifier ':' 153eccc53a0a0ed1abc7bb4c04ed9566ce0c5c63140Chris Lattner // Handle it as a field designator. Otherwise, this must be the start of a 154eccc53a0a0ed1abc7bb4c04ed9566ce0c5c63140Chris Lattner // normal expression. 155eccc53a0a0ed1abc7bb4c04ed9566ce0c5c63140Chris Lattner if (Tok.is(tok::identifier)) { 15605c13a3411782108d65aab3c77b1a231a4963bc0Douglas Gregor const IdentifierInfo *FieldName = Tok.getIdentifierInfo(); 157eeae8f072748affce25ab4064982626361293390Douglas Gregor 158f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<256> NewSyntax; 15901eb9b9683535d8a65c704ad2c545903409e2d36Daniel Dunbar llvm::raw_svector_ostream(NewSyntax) << '.' << FieldName->getName() 16062a7217b1a848fadeca15d868aa7abe15a321b52Daniel Dunbar << " = "; 161eeae8f072748affce25ab4064982626361293390Douglas Gregor 16205c13a3411782108d65aab3c77b1a231a4963bc0Douglas Gregor SourceLocation NameLoc = ConsumeToken(); // Eat the identifier. 1631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1647f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!"); 16505c13a3411782108d65aab3c77b1a231a4963bc0Douglas Gregor SourceLocation ColonLoc = ConsumeToken(); 16605c13a3411782108d65aab3c77b1a231a4963bc0Douglas Gregor 16740a0f9c1ca14f0b4a07eb9894523b55093bc182bDouglas Gregor Diag(NameLoc, diag::ext_gnu_old_style_field_designator) 168849b243d4065f56742a4677d6dc8277609a151f8Douglas Gregor << FixItHint::CreateReplacement(SourceRange(NameLoc, ColonLoc), 169849b243d4065f56742a4677d6dc8277609a151f8Douglas Gregor NewSyntax.str()); 170eeae8f072748affce25ab4064982626361293390Douglas Gregor 1715908a9293b88a3da57ae59b522275d05e1ab11e0Douglas Gregor Designation D; 17205c13a3411782108d65aab3c77b1a231a4963bc0Douglas Gregor D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc)); 1731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return Actions.ActOnDesignatedInitializer(D, ColonLoc, true, 17405c13a3411782108d65aab3c77b1a231a4963bc0Douglas Gregor ParseInitializer()); 175eccc53a0a0ed1abc7bb4c04ed9566ce0c5c63140Chris Lattner } 1761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1770a68b9449136b0d5664bfa48a51a0c1181d2eca8Chris Lattner // Desig - This is initialized when we see our first designator. We may have 1780a68b9449136b0d5664bfa48a51a0c1181d2eca8Chris Lattner // an objc message send with no designator, so we don't want to create this 1790a68b9449136b0d5664bfa48a51a0c1181d2eca8Chris Lattner // eagerly. 1805908a9293b88a3da57ae59b522275d05e1ab11e0Douglas Gregor Designation Desig; 1811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Parse each designator in the designator list until we find an initializer. 1837f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner while (Tok.is(tok::period) || Tok.is(tok::l_square)) { 1847f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner if (Tok.is(tok::period)) { 1855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // designator: '.' identifier 18605c13a3411782108d65aab3c77b1a231a4963bc0Douglas Gregor SourceLocation DotLoc = ConsumeToken(); 1871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1880a68b9449136b0d5664bfa48a51a0c1181d2eca8Chris Lattner if (Tok.isNot(tok::identifier)) { 1890a68b9449136b0d5664bfa48a51a0c1181d2eca8Chris Lattner Diag(Tok.getLocation(), diag::err_expected_field_designator); 19020df9b7ab9388b2a488c5b1293cd196b1e073b4eSebastian Redl return ExprError(); 1910a68b9449136b0d5664bfa48a51a0c1181d2eca8Chris Lattner } 1921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1935908a9293b88a3da57ae59b522275d05e1ab11e0Douglas Gregor Desig.AddDesignator(Designator::getField(Tok.getIdentifierInfo(), DotLoc, 1945908a9293b88a3da57ae59b522275d05e1ab11e0Douglas Gregor Tok.getLocation())); 1950a68b9449136b0d5664bfa48a51a0c1181d2eca8Chris Lattner ConsumeToken(); // Eat the identifier. 1967f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner continue; 1977f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner } 1981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1997f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner // We must have either an array designator now or an objc message send. 2007f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner assert(Tok.is(tok::l_square) && "Unexpected token!"); 2011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 202e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner // Handle the two forms of array designator: 203e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner // array-designator: '[' constant-expression ']' 204e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner // array-designator: '[' constant-expression '...' constant-expression ']' 205e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner // 206e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner // Also, we have to handle the case where the expression after the 207e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner // designator an an objc message send: '[' objc-message-expr ']'. 208e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner // Interesting cases are: 209e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner // [foo bar] -> objc message send 210e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner // [foo] -> array designator 211e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner // [foo ... bar] -> array designator 212e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner // [4][foo bar] -> obsolete GNU designation with objc message send. 213e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner // 2146ee326af4e77e6f05973486097884d7431f2108dRichard Smith // We do not need to check for an expression starting with [[ here. If it 2156ee326af4e77e6f05973486097884d7431f2108dRichard Smith // contains an Objective-C message send, then it is not an ill-formed 2166ee326af4e77e6f05973486097884d7431f2108dRichard Smith // attribute. If it is a lambda-expression within an array-designator, then 2176ee326af4e77e6f05973486097884d7431f2108dRichard Smith // it will be rejected because a constant-expression cannot begin with a 2186ee326af4e77e6f05973486097884d7431f2108dRichard Smith // lambda-expression. 2190fbda68b50ce17d7ad36ef7a5ed77518a5cd272eDouglas Gregor InMessageExpressionRAIIObject InMessage(*this, true); 2200fbda68b50ce17d7ad36ef7a5ed77518a5cd272eDouglas Gregor 2214a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor BalancedDelimiterTracker T(*this, tok::l_square); 2224a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor T.consumeOpen(); 2234a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor SourceLocation StartLoc = T.getOpenLocation(); 2244a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor 22560d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult Idx; 2266aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor 2276aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // If Objective-C is enabled and this is a typename (class message 2286aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // send) or send to 'super', parse this as a message send 2296aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // expression. We handle C++ and C separately, since C++ requires 2306aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // much more complicated parsing. 2314e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().ObjC1 && getLangOpts().CPlusPlus) { 2326aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // Send to 'super'. 2336aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super && 2340fbda68b50ce17d7ad36ef7a5ed77518a5cd272eDouglas Gregor NextToken().isNot(tok::period) && 2350fbda68b50ce17d7ad36ef7a5ed77518a5cd272eDouglas Gregor getCurScope()->isInObjcMethodScope()) { 2366aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor CheckArrayDesignatorSyntax(*this, StartLoc, Desig); 2376aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, 238b3d8748e797c6c2f1dc01186c8eeb3b1b5fe970cJohn McCall ConsumeToken(), 239b3d8748e797c6c2f1dc01186c8eeb3b1b5fe970cJohn McCall ParsedType(), 2409ae2f076ca5ab1feb3ba95629099ec2319833701John McCall 0); 2416aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor } 2426aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor 2436aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // Parse the receiver, which is either a type or an expression. 2446aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor bool IsExpr; 2456aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor void *TypeOrExpr; 2466aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) { 2476aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor SkipUntil(tok::r_square); 2486aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor return ExprError(); 2496aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor } 2506aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor 2516aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // If the receiver was a type, we have a class message; parse 2526aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // the rest of it. 2536aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor if (!IsExpr) { 2546aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor CheckArrayDesignatorSyntax(*this, StartLoc, Desig); 2556aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, 2566aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor SourceLocation(), 257b3d8748e797c6c2f1dc01186c8eeb3b1b5fe970cJohn McCall ParsedType::getFromOpaquePtr(TypeOrExpr), 2589ae2f076ca5ab1feb3ba95629099ec2319833701John McCall 0); 2596aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor } 2601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2616aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // If the receiver was an expression, we still don't know 2626aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // whether we have a message send or an array designator; just 2636aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // adopt the expression for further analysis below. 2646aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // FIXME: potentially-potentially evaluated expression above? 26560d7b3a319d84d688752be3870615ac0f111fb16John McCall Idx = ExprResult(static_cast<Expr*>(TypeOrExpr)); 2664e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie } else if (getLangOpts().ObjC1 && Tok.is(tok::identifier)) { 267eb483eb3ee80300f15d6d13573d82493c2194461Chris Lattner IdentifierInfo *II = Tok.getIdentifierInfo(); 2682725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor SourceLocation IILoc = Tok.getLocation(); 269b3d8748e797c6c2f1dc01186c8eeb3b1b5fe970cJohn McCall ParsedType ReceiverType; 2701e46136c5222ad040fd783ca7ee6b2215f0b89d6Chris Lattner // Three cases. This is a message send to a type: [type foo] 2711e46136c5222ad040fd783ca7ee6b2215f0b89d6Chris Lattner // This is a message send to super: [super foo] 2721e46136c5222ad040fd783ca7ee6b2215f0b89d6Chris Lattner // This is a message sent to an expr: [super.bar foo] 273f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall switch (Sema::ObjCMessageKind Kind 27423c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor = Actions.getObjCMessageKind(getCurScope(), II, IILoc, 2752725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor II == Ident_super, 2761569f95831a8c99e9f664137bf8f40e47ee3d90fDouglas Gregor NextToken().is(tok::period), 2771569f95831a8c99e9f664137bf8f40e47ee3d90fDouglas Gregor ReceiverType)) { 278f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall case Sema::ObjCSuperMessage: 279f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall case Sema::ObjCClassMessage: 2806aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor CheckArrayDesignatorSyntax(*this, StartLoc, Desig); 281f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall if (Kind == Sema::ObjCSuperMessage) 2822725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, 2832725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor ConsumeToken(), 284b3d8748e797c6c2f1dc01186c8eeb3b1b5fe970cJohn McCall ParsedType(), 2859ae2f076ca5ab1feb3ba95629099ec2319833701John McCall 0); 2861569f95831a8c99e9f664137bf8f40e47ee3d90fDouglas Gregor ConsumeToken(); // the identifier 2871569f95831a8c99e9f664137bf8f40e47ee3d90fDouglas Gregor if (!ReceiverType) { 2882725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor SkipUntil(tok::r_square); 2892725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor return ExprError(); 2902725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor } 2912725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor 2922725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, 2932725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor SourceLocation(), 2941569f95831a8c99e9f664137bf8f40e47ee3d90fDouglas Gregor ReceiverType, 2959ae2f076ca5ab1feb3ba95629099ec2319833701John McCall 0); 2962725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor 297f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall case Sema::ObjCInstanceMessage: 2982725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor // Fall through; we'll just parse the expression and 2992725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor // (possibly) treat this like an Objective-C message send 3002725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor // later. 3012725ca8eb3354975ca77ed4b88ede7b60b216b9aDouglas Gregor break; 302eb483eb3ee80300f15d6d13573d82493c2194461Chris Lattner } 3037f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner } 3041d922960e083906a586609ac6978678147250177Sebastian Redl 3056aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // Parse the index expression, if we haven't already gotten one 3066aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // above (which can only happen in Objective-C++). 3077f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner // Note that we parse this as an assignment expression, not a constant 3087f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner // expression (allowing *=, =, etc) to handle the objc case. Sema needs 3097f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner // to validate that the expression is a constant. 3106aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // FIXME: We also need to tell Sema that we're in a 3116aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor // potentially-potentially evaluated context. 3126aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor if (!Idx.get()) { 3136aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor Idx = ParseAssignmentExpression(); 3146aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor if (Idx.isInvalid()) { 3156aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor SkipUntil(tok::r_square); 3163fe198bf0d6118c7b080c17c3bb28d7c84e458b9Benjamin Kramer return Idx; 3176aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor } 3187f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner } 3191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3207f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner // Given an expression, we could either have a designator (if the next 3217f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner // tokens are '...' or ']' or an objc message send. If this is an objc 3221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // message send, handle it now. An objc-message send is the start of 3237f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner // an assignment-expression production. 3244e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().ObjC1 && Tok.isNot(tok::ellipsis) && 3257f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner Tok.isNot(tok::r_square)) { 3266aa14d832704ae176c92d4e0f22dfb3f3d83a70aDouglas Gregor CheckArrayDesignatorSyntax(*this, Tok.getLocation(), Desig); 3271d922960e083906a586609ac6978678147250177Sebastian Redl return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, 3281d922960e083906a586609ac6978678147250177Sebastian Redl SourceLocation(), 329b3d8748e797c6c2f1dc01186c8eeb3b1b5fe970cJohn McCall ParsedType(), 330b3d8748e797c6c2f1dc01186c8eeb3b1b5fe970cJohn McCall Idx.take()); 3317f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner } 332e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner 333e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner // If this is a normal array designator, remember it. 334e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner if (Tok.isNot(tok::ellipsis)) { 3355908a9293b88a3da57ae59b522275d05e1ab11e0Douglas Gregor Desig.AddDesignator(Designator::getArray(Idx.release(), StartLoc)); 336e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner } else { 337e232942571a80549514791bbdbbd0bb44fab6b56Chris Lattner // Handle the gnu array range extension. 3387f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner Diag(Tok, diag::ext_gnu_array_range); 33905c13a3411782108d65aab3c77b1a231a4963bc0Douglas Gregor SourceLocation EllipsisLoc = ConsumeToken(); 3402f7ece7c77eb17e24e8f0f4e1b7fb01aa5111f96Sebastian Redl 34160d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult RHS(ParseConstantExpression()); 3420e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (RHS.isInvalid()) { 3435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SkipUntil(tok::r_square); 3443fe198bf0d6118c7b080c17c3bb28d7c84e458b9Benjamin Kramer return RHS; 3455c749428a9938d5e2e9564b1c9b7a9252c30ee27Chris Lattner } 3465908a9293b88a3da57ae59b522275d05e1ab11e0Douglas Gregor Desig.AddDesignator(Designator::getArrayRange(Idx.release(), 3475908a9293b88a3da57ae59b522275d05e1ab11e0Douglas Gregor RHS.release(), 3485908a9293b88a3da57ae59b522275d05e1ab11e0Douglas Gregor StartLoc, EllipsisLoc)); 3495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 3500e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 3514a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor T.consumeClose(); 3524a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor Desig.getDesignator(Desig.getNumDesignators() - 1).setRBracketLoc( 3534a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor T.getCloseLocation()); 3545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 3557f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner 3560a68b9449136b0d5664bfa48a51a0c1181d2eca8Chris Lattner // Okay, we're done with the designator sequence. We know that there must be 3570a68b9449136b0d5664bfa48a51a0c1181d2eca8Chris Lattner // at least one designator, because the only case we can get into this method 3580a68b9449136b0d5664bfa48a51a0c1181d2eca8Chris Lattner // without a designator is when we have an objc message send. That case is 3590a68b9449136b0d5664bfa48a51a0c1181d2eca8Chris Lattner // handled and returned from above. 3605908a9293b88a3da57ae59b522275d05e1ab11e0Douglas Gregor assert(!Desig.empty() && "Designator is empty?"); 36120df9b7ab9388b2a488c5b1293cd196b1e073b4eSebastian Redl 3620a68b9449136b0d5664bfa48a51a0c1181d2eca8Chris Lattner // Handle a normal designator sequence end, which is an equal. 3637f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner if (Tok.is(tok::equal)) { 36405c13a3411782108d65aab3c77b1a231a4963bc0Douglas Gregor SourceLocation EqualLoc = ConsumeToken(); 3655908a9293b88a3da57ae59b522275d05e1ab11e0Douglas Gregor return Actions.ActOnDesignatedInitializer(Desig, EqualLoc, false, 36605c13a3411782108d65aab3c77b1a231a4963bc0Douglas Gregor ParseInitializer()); 3677f9690d79f04b405f9e41e98f2e2698ffd640c8eChris Lattner } 36820df9b7ab9388b2a488c5b1293cd196b1e073b4eSebastian Redl 3690a68b9449136b0d5664bfa48a51a0c1181d2eca8Chris Lattner // We read some number of designators and found something that isn't an = or 37079ed6b5902ed92175b70ed3c4d7b3f239af847ceChris Lattner // an initializer. If we have exactly one array designator, this 3710a68b9449136b0d5664bfa48a51a0c1181d2eca8Chris Lattner // is the GNU 'designation: array-designator' extension. Otherwise, it is a 3720a68b9449136b0d5664bfa48a51a0c1181d2eca8Chris Lattner // parse error. 3731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (Desig.getNumDesignators() == 1 && 3745908a9293b88a3da57ae59b522275d05e1ab11e0Douglas Gregor (Desig.getDesignator(0).isArrayDesignator() || 3755908a9293b88a3da57ae59b522275d05e1ab11e0Douglas Gregor Desig.getDesignator(0).isArrayRangeDesignator())) { 376eeae8f072748affce25ab4064982626361293390Douglas Gregor Diag(Tok, diag::ext_gnu_missing_equal_designator) 377849b243d4065f56742a4677d6dc8277609a151f8Douglas Gregor << FixItHint::CreateInsertion(Tok.getLocation(), "= "); 378eeae8f072748affce25ab4064982626361293390Douglas Gregor return Actions.ActOnDesignatedInitializer(Desig, Tok.getLocation(), 37968c56dea080efd6db7a444de84c270bf4e2d4d2eDouglas Gregor true, ParseInitializer()); 38079ed6b5902ed92175b70ed3c4d7b3f239af847ceChris Lattner } 38120df9b7ab9388b2a488c5b1293cd196b1e073b4eSebastian Redl 38279ed6b5902ed92175b70ed3c4d7b3f239af847ceChris Lattner Diag(Tok, diag::err_expected_equal_designator); 38320df9b7ab9388b2a488c5b1293cd196b1e073b4eSebastian Redl return ExprError(); 3845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3870eec2b58678f71af6b5fcf4c439290c0d640546bChris Lattner/// ParseBraceInitializer - Called when parsing an initializer that has a 3880eec2b58678f71af6b5fcf4c439290c0d640546bChris Lattner/// leading open brace. 3890eec2b58678f71af6b5fcf4c439290c0d640546bChris Lattner/// 3905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// initializer: [C99 6.7.8] 3915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// '{' initializer-list '}' 3925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// '{' initializer-list ',' '}' 3935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] '{' '}' 3945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 3955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// initializer-list: 396dcaa1ca0b475dfa887e1d061678a1e3501288510Douglas Gregor/// designation[opt] initializer ...[opt] 397dcaa1ca0b475dfa887e1d061678a1e3501288510Douglas Gregor/// initializer-list ',' designation[opt] initializer ...[opt] 3985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 39960d7b3a319d84d688752be3870615ac0f111fb16John McCallExprResult Parser::ParseBraceInitializer() { 4000fbda68b50ce17d7ad36ef7a5ed77518a5cd272eDouglas Gregor InMessageExpressionRAIIObject InMessage(*this, false); 4010fbda68b50ce17d7ad36ef7a5ed77518a5cd272eDouglas Gregor 4024a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor BalancedDelimiterTracker T(*this, tok::l_brace); 4034a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor T.consumeOpen(); 4044a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor SourceLocation LBraceLoc = T.getOpenLocation(); 405a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl 406eccc53a0a0ed1abc7bb4c04ed9566ce0c5c63140Chris Lattner /// InitExprs - This is the actual list of expressions contained in the 407eccc53a0a0ed1abc7bb4c04ed9566ce0c5c63140Chris Lattner /// initializer. 4084e28d9e2ba9ce237549b45cfd4136ec6536d1325Benjamin Kramer ExprVector InitExprs; 409a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl 410220ad7c8d1adc23799e480faf189332f1eb032e6Chris Lattner if (Tok.is(tok::r_brace)) { 411930d8b5ecc074cca01ecd9a522a55f55f3b72396Douglas Gregor // Empty initializers are a C++ feature and a GNU extension to C. 4124e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (!getLangOpts().CPlusPlus) 413930d8b5ecc074cca01ecd9a522a55f55f3b72396Douglas Gregor Diag(LBraceLoc, diag::ext_gnu_empty_initializer); 414220ad7c8d1adc23799e480faf189332f1eb032e6Chris Lattner // Match the '}'. 4155354e77e60e82828c7c2361f5c688c2667ab59ccBenjamin Kramer return Actions.ActOnInitList(LBraceLoc, MultiExprArg(), ConsumeBrace()); 416220ad7c8d1adc23799e480faf189332f1eb032e6Chris Lattner } 41720df9b7ab9388b2a488c5b1293cd196b1e073b4eSebastian Redl 4184aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff bool InitExprsOk = true; 41920df9b7ab9388b2a488c5b1293cd196b1e073b4eSebastian Redl 4204aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff while (1) { 4219d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet // Handle Microsoft __if_exists/if_not_exists if necessary. 4224e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) || 4239d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet Tok.is(tok::kw___if_not_exists))) { 4249d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet if (ParseMicrosoftIfExistsBraceInitializer(InitExprs, InitExprsOk)) { 4259d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet if (Tok.isNot(tok::comma)) break; 4269d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet ConsumeToken(); 4279d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet } 4289d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet if (Tok.is(tok::r_brace)) break; 4299d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet continue; 4309d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet } 4319d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet 4324aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff // Parse: designation[opt] initializer 43320df9b7ab9388b2a488c5b1293cd196b1e073b4eSebastian Redl 4344aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff // If we know that this cannot be a designation, just parse the nested 4354aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff // initializer directly. 43660d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult SubElt; 437b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor if (MayBeDesignationStart()) 4385908a9293b88a3da57ae59b522275d05e1ab11e0Douglas Gregor SubElt = ParseInitializerWithPotentialDesignator(); 4395908a9293b88a3da57ae59b522275d05e1ab11e0Douglas Gregor else 4404aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff SubElt = ParseInitializer(); 4411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 442dcaa1ca0b475dfa887e1d061678a1e3501288510Douglas Gregor if (Tok.is(tok::ellipsis)) 443dcaa1ca0b475dfa887e1d061678a1e3501288510Douglas Gregor SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken()); 444dcaa1ca0b475dfa887e1d061678a1e3501288510Douglas Gregor 4454aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff // If we couldn't parse the subelement, bail out. 4460e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (!SubElt.isInvalid()) { 447effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl InitExprs.push_back(SubElt.release()); 44865bb89c3825406bdeeab6b2d8408b72deac8bbb2Chris Lattner } else { 44965bb89c3825406bdeeab6b2d8408b72deac8bbb2Chris Lattner InitExprsOk = false; 4501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 45165bb89c3825406bdeeab6b2d8408b72deac8bbb2Chris Lattner // We have two ways to try to recover from this error: if the code looks 452fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // grammatically ok (i.e. we have a comma coming up) try to continue 45365bb89c3825406bdeeab6b2d8408b72deac8bbb2Chris Lattner // parsing the rest of the initializer. This allows us to emit 45465bb89c3825406bdeeab6b2d8408b72deac8bbb2Chris Lattner // diagnostics for later elements that we find. If we don't see a comma, 45565bb89c3825406bdeeab6b2d8408b72deac8bbb2Chris Lattner // assume there is a parse error, and just skip to recover. 456a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl // FIXME: This comment doesn't sound right. If there is a r_brace 457a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl // immediately, it can't be an error, since there is no other way of 458a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl // leaving this loop except through this if. 45965bb89c3825406bdeeab6b2d8408b72deac8bbb2Chris Lattner if (Tok.isNot(tok::comma)) { 46065bb89c3825406bdeeab6b2d8408b72deac8bbb2Chris Lattner SkipUntil(tok::r_brace, false, true); 46165bb89c3825406bdeeab6b2d8408b72deac8bbb2Chris Lattner break; 46265bb89c3825406bdeeab6b2d8408b72deac8bbb2Chris Lattner } 46365bb89c3825406bdeeab6b2d8408b72deac8bbb2Chris Lattner } 4640e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 4654aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff // If we don't have a comma continued list, we're done. 46604d6666eee19bbf25bdfcb8e79eb8b00ace03f0cChris Lattner if (Tok.isNot(tok::comma)) break; 46720df9b7ab9388b2a488c5b1293cd196b1e073b4eSebastian Redl 468eccc53a0a0ed1abc7bb4c04ed9566ce0c5c63140Chris Lattner // TODO: save comma locations if some client cares. 4694aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff ConsumeToken(); 47020df9b7ab9388b2a488c5b1293cd196b1e073b4eSebastian Redl 4714aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff // Handle trailing comma. 47204d6666eee19bbf25bdfcb8e79eb8b00ace03f0cChris Lattner if (Tok.is(tok::r_brace)) break; 4735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 4744a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor 4754a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor bool closed = !T.consumeClose(); 4764a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor 4774a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor if (InitExprsOk && closed) 4783fe198bf0d6118c7b080c17c3bb28d7c84e458b9Benjamin Kramer return Actions.ActOnInitList(LBraceLoc, InitExprs, 4794a8dfb511e8f84b2e38b7a86d8ddf05ac1e1a41bDouglas Gregor T.getCloseLocation()); 48020df9b7ab9388b2a488c5b1293cd196b1e073b4eSebastian Redl 48120df9b7ab9388b2a488c5b1293cd196b1e073b4eSebastian Redl return ExprError(); // an error occurred. 4825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 4835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4849d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet 4859d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet// Return true if a comma (or closing brace) is necessary after the 4869d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet// __if_exists/if_not_exists statement. 4879d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichetbool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs, 4889d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet bool &InitExprsOk) { 4899d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet bool trailingComma = false; 4909d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet IfExistsCondition Result; 4919d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet if (ParseMicrosoftIfExistsCondition(Result)) 4929d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet return false; 4939d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet 4949d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet BalancedDelimiterTracker Braces(*this, tok::l_brace); 4959d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet if (Braces.consumeOpen()) { 4969d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet Diag(Tok, diag::err_expected_lbrace); 4979d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet return false; 4989d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet } 4999d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet 5009d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet switch (Result.Behavior) { 5019d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet case IEB_Parse: 5029d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet // Parse the declarations below. 5039d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet break; 5049d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet 5059d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet case IEB_Dependent: 5069d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists) 5079d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet << Result.IsIfExists; 5089d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet // Fall through to skip. 5099d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet 5109d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet case IEB_Skip: 5119d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet Braces.skipToEnd(); 5129d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet return false; 5139d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet } 5149d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet 5159d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet while (Tok.isNot(tok::eof)) { 5169d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet trailingComma = false; 5179d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet // If we know that this cannot be a designation, just parse the nested 5189d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet // initializer directly. 5199d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet ExprResult SubElt; 520b3f323d6c41cb614a249dbc4af7493762786521aDouglas Gregor if (MayBeDesignationStart()) 5219d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet SubElt = ParseInitializerWithPotentialDesignator(); 5229d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet else 5239d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet SubElt = ParseInitializer(); 5249d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet 5259d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet if (Tok.is(tok::ellipsis)) 5269d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken()); 5279d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet 5289d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet // If we couldn't parse the subelement, bail out. 5299d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet if (!SubElt.isInvalid()) 5309d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet InitExprs.push_back(SubElt.release()); 5319d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet else 5329d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet InitExprsOk = false; 5339d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet 5349d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet if (Tok.is(tok::comma)) { 5359d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet ConsumeToken(); 5369d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet trailingComma = true; 5379d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet } 5389d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet 5399d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet if (Tok.is(tok::r_brace)) 5409d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet break; 5419d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet } 5429d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet 5439d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet Braces.consumeClose(); 5449d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet 5459d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet return !trailingComma; 5469d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0cFrancois Pichet} 547