Index: lib/Parse/ParseObjc.cpp =================================================================== --- lib/Parse/ParseObjc.cpp +++ lib/Parse/ParseObjc.cpp @@ -3414,6 +3414,7 @@ ExprVector ElementExprs; // array elements. ConsumeBracket(); // consume the l_square. + bool HasInvalidEltExpr = false; while (Tok.isNot(tok::r_square)) { // Parse list of array element expressions (all must be id types). ExprResult Res(ParseAssignmentExpression()); @@ -3425,11 +3426,15 @@ return Res; } + Res = Actions.CorrectDelayedTyposInExpr(Res.get()); + if (Res.isInvalid()) + HasInvalidEltExpr = true; + // Parse the ellipsis that indicates a pack expansion. if (Tok.is(tok::ellipsis)) Res = Actions.ActOnPackExpansion(Res.get(), ConsumeToken()); if (Res.isInvalid()) - return true; + HasInvalidEltExpr = true; ElementExprs.push_back(Res.get()); @@ -3440,6 +3445,10 @@ << tok::comma); } SourceLocation EndLoc = ConsumeBracket(); // location of ']' + + if (HasInvalidEltExpr) + return ExprError(); + MultiExprArg Args(ElementExprs); return Actions.BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args); } @@ -3447,6 +3456,7 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { SmallVector Elements; // dictionary elements. ConsumeBrace(); // consume the l_square. + bool HasInvalidEltExpr = false; while (Tok.isNot(tok::r_brace)) { // Parse the comma separated key : value expressions. ExprResult KeyExpr; @@ -3476,8 +3486,15 @@ return ValueExpr; } - // Parse the ellipsis that designates this as a pack expansion. - SourceLocation EllipsisLoc; + // Check the key and value for possible typos + KeyExpr = Actions.CorrectDelayedTyposInExpr(KeyExpr.get()); + ValueExpr = Actions.CorrectDelayedTyposInExpr(ValueExpr.get()); + if (KeyExpr.isInvalid() || ValueExpr.isInvalid()) + HasInvalidEltExpr = true; + + // Parse the ellipsis that designates this as a pack expansion. Do not + // ActOnPackExpansion here, leave it to template instantiation time where + // we can get better diagnostics. if (getLangOpts().CPlusPlus) TryConsumeToken(tok::ellipsis, EllipsisLoc); @@ -3493,6 +3510,9 @@ << tok::comma); } SourceLocation EndLoc = ConsumeBrace(); + + if (HasInvalidEltExpr) + return ExprError(); // Create the ObjCDictionaryLiteral. return Actions.BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc), Index: test/SemaObjC/objc-array-literal.m =================================================================== --- test/SemaObjC/objc-array-literal.m +++ test/SemaObjC/objc-array-literal.m @@ -67,3 +67,11 @@ x = @[ @"stuff", @"hello" "world"]; // expected-warning {{concatenated NSString literal for an NSArray expression}} return x; } + +enum XXXYYYZZZType { XXXYYYZZZTypeAny }; +void foo() { + NSArray *array = @[ + @(XXXYYYZZZTypeA), // expected-error {{use of undeclared identifier 'XXXYYYZZZTypeA'; did you mean 'XXXYYYZZZTypeAny'}} + @(XXXYYYZZZTypeSomethingSomething) // expected-error {{use of undeclared identifier 'XXXYYYZZZTypeSomethingSomething'}} + ]; +} Index: test/SemaObjC/objc-dictionary-literal.m =================================================================== --- test/SemaObjC/objc-dictionary-literal.m +++ test/SemaObjC/objc-dictionary-literal.m @@ -63,3 +63,10 @@ return 0; } +enum XXXYYYZZZType { XXXYYYZZZTypeAny }; // expected-note {{'XXXYYYZZZTypeAny' declared here}} +void foo() { + NSDictionary *d = @{ + @"A" : @(XXXYYYZZZTypeA), // expected-error {{use of undeclared identifier 'XXXYYYZZZTypeA'; did you mean 'XXXYYYZZZTypeAny'}} + @"F" : @(XXXYYYZZZTypeSomethingSomething), // expected-error {{use of undeclared identifier 'XXXYYYZZZTypeSomethingSomething'}} + }; +}