ParseInit.cpp revision 04d6666eee19bbf25bdfcb8e79eb8b00ace03f0c
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===--- ParseInit.cpp - Initializer Parsing ------------------------------===// 25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// The LLVM Compiler Infrastructure 45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 55f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This file was developed by Chris Lattner and is distributed under 65f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// the University of Illinois Open Source 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" 155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Basic/Diagnostic.h" 164aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff#include "llvm/ADT/SmallString.h" 175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang; 185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// MayBeDesignationStart - Return true if this token might be the start of a 215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// designator. 225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic bool MayBeDesignationStart(tok::TokenKind K) { 235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer switch (K) { 245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer default: return false; 255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::period: // designator: '.' identifier 265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::l_square: // designator: array-designator 275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::identifier: // designation: identifier ':' 285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return true; 295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseInitializerWithPotentialDesignator - Parse the 'initializer' production 335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// checking to see if the token stream starts with a designator. 345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// designation: 365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// designator-list '=' 375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] array-designator 385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] identifier ':' 395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// designator-list: 415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// designator 425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// designator-list designator 435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// designator: 455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// array-designator 465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// '.' identifier 475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// array-designator: 495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// '[' constant-expression ']' 505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] '[' constant-expression '...' constant-expression ']' 515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// NOTE: [OBC] allows '[ objc-receiver objc-message-args ]' as an 535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// initializer. We need to consider this case when parsing array designators. 545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerParser::ExprResult Parser::ParseInitializerWithPotentialDesignator() { 565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Parse each designator in the designator list until we find an initializer. 575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer while (1) { 585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer switch (Tok.getKind()) { 595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::equal: 605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // We read some number (at least one due to the grammar we implemented) 615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // of designators and found an '=' sign. The following tokens must be 625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // the initializer. 635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ConsumeToken(); 645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return ParseInitializer(); 655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer default: { 675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // We read some number (at least one due to the grammar we implemented) 685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // of designators and found something that isn't an = or an initializer. 695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If we have exactly one array designator [TODO CHECK], this is the GNU 705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // 'designation: array-designator' extension. Otherwise, it is a parse 715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // error. 725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation Loc = Tok.getLocation(); 735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ExprResult Init = ParseInitializer(); 745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (Init.isInvalid) return Init; 755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Diag(Tok, diag::ext_gnu_missing_equal_designator); 775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return Init; 785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::period: 805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // designator: '.' identifier 815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ConsumeToken(); 825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (ExpectAndConsume(tok::identifier, diag::err_expected_ident)) 835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return ExprResult(true); 845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer break; 855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::l_square: { 875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // array-designator: '[' constant-expression ']' 885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // array-designator: '[' constant-expression '...' constant-expression ']' 895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation StartLoc = ConsumeBracket(); 905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ExprResult Idx = ParseConstantExpression(); 925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (Idx.isInvalid) { 935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SkipUntil(tok::r_square); 945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return Idx; 955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Handle the gnu array range extension. 9804d6666eee19bbf25bdfcb8e79eb8b00ace03f0cChris Lattner if (Tok.is(tok::ellipsis)) { 995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Diag(Tok, diag::ext_gnu_array_range); 1005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ConsumeToken(); 1015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ExprResult RHS = ParseConstantExpression(); 1035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (RHS.isInvalid) { 1045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SkipUntil(tok::r_square); 1055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return RHS; 1065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer MatchRHSPunctuation(tok::r_square, StartLoc); 1105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer break; 1115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::identifier: { 1135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Due to the GNU "designation: identifier ':'" extension, we don't know 1145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // whether something starting with an identifier is an 1155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // assignment-expression or if it is an old-style structure field 1165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // designator. 1175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // TODO: Check that this is the first designator. 118d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner Token Ident = Tok; 1195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ConsumeToken(); 1205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this is the gross GNU extension, handle it now. 12204d6666eee19bbf25bdfcb8e79eb8b00ace03f0cChris Lattner if (Tok.is(tok::colon)) { 1235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Diag(Ident, diag::ext_gnu_old_style_field_designator); 1245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ConsumeToken(); 1255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return ParseInitializer(); 1265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Otherwise, we just consumed the first token of an expression. Parse 1295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // the rest of it now. 1305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return ParseAssignmentExprWithLeadingIdentifier(Ident); 1315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseInitializer 1385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// initializer: [C99 6.7.8] 1395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// assignment-expression 1405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// '{' initializer-list '}' 1415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// '{' initializer-list ',' '}' 1425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] '{' '}' 1435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 1445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// initializer-list: 1455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// designation[opt] initializer 1465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// initializer-list ',' designation[opt] initializer 1475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 1485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerParser::ExprResult Parser::ParseInitializer() { 14904d6666eee19bbf25bdfcb8e79eb8b00ace03f0cChris Lattner if (Tok.isNot(tok::l_brace)) 1505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return ParseAssignmentExpression(); 1515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation LBraceLoc = ConsumeBrace(); 1535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // We support empty initializers, but tell the user that they aren't using 1555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // C99-clean code. 15604d6666eee19bbf25bdfcb8e79eb8b00ace03f0cChris Lattner if (Tok.is(tok::r_brace)) { 1575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Diag(LBraceLoc, diag::ext_gnu_empty_initializer); 1584aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff // Match the '}'. 159f69936d1ba843c2d3186e4aa2faa87c68e5bf2fbSteve Naroff return Actions.ActOnInitList(LBraceLoc, 0, 0, ConsumeBrace()); 1604aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff } 1614aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff llvm::SmallVector<ExprTy*, 8> InitExprs; 1624aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff bool InitExprsOk = true; 1634aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff 1644aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff while (1) { 1654aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff // Parse: designation[opt] initializer 1665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1674aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff // If we know that this cannot be a designation, just parse the nested 1684aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff // initializer directly. 1694aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff ExprResult SubElt; 1704aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff if (!MayBeDesignationStart(Tok.getKind())) 1714aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff SubElt = ParseInitializer(); 1724aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff else 1734aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff SubElt = ParseInitializerWithPotentialDesignator(); 1744aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff 1754aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff // If we couldn't parse the subelement, bail out. 1764aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff if (SubElt.isInvalid) { 1774aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff InitExprsOk = false; 1784aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff SkipUntil(tok::r_brace); 1794aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff break; 1804aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff } else 1814aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff InitExprs.push_back(SubElt.Val); 1825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1834aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff // If we don't have a comma continued list, we're done. 18404d6666eee19bbf25bdfcb8e79eb8b00ace03f0cChris Lattner if (Tok.isNot(tok::comma)) break; 1854aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff 1864aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff // FIXME: save comma locations. 1874aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff ConsumeToken(); 1884aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff 1894aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff // Handle trailing comma. 19004d6666eee19bbf25bdfcb8e79eb8b00ace03f0cChris Lattner if (Tok.is(tok::r_brace)) break; 1915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 19204d6666eee19bbf25bdfcb8e79eb8b00ace03f0cChris Lattner if (InitExprsOk && Tok.is(tok::r_brace)) 193f69936d1ba843c2d3186e4aa2faa87c68e5bf2fbSteve Naroff return Actions.ActOnInitList(LBraceLoc, &InitExprs[0], InitExprs.size(), 1944aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff ConsumeBrace()); 1955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Match the '}'. 1965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer MatchRHSPunctuation(tok::r_brace, LBraceLoc); 1974aa88f8d8469ced8fe04a0c411bbccc5d313e055Steve Naroff return ExprResult(true); // an error occurred. 1985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 200