diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -2165,7 +2165,6 @@ Comps.back().U.IdentInfo = Tok.getIdentifierInfo(); Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken(); - // FIXME: This loop leaks the index expressions on error. while (1) { if (Tok.is(tok::period)) { // offsetof-member-designator: offsetof-member-designator '.' identifier @@ -2200,6 +2199,28 @@ ST.consumeClose(); Comps.back().LocEnd = ST.getCloseLocation(); + } else if (Tok.is(tok::arrow)) { + // offsetof-member-designator: offsetof-member-design '->' identifier + // Push array index 0 into offsets. + Comps.push_back(Sema::OffsetOfComponent()); + Comps.back().isBrackets = true; + SourceLocation SavedLoc = ConsumeToken(); + Comps.back().LocStart = Comps.back().LocEnd = SavedLoc; + Res = Actions.ActOnIntegerConstant(SourceLocation(), 0); + Comps.back().U.E = Res.get(); + + Comps.push_back(Sema::OffsetOfComponent()); + Comps.back().isBrackets = false; + Comps.back().LocStart = SavedLoc; + + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_expected) << tok::identifier; + SkipUntil(tok::r_paren, StopAtSemi); + return ExprError(); + } + Comps.back().U.IdentInfo = Tok.getIdentifierInfo(); + Comps.back().LocEnd = ConsumeToken(); + } else { if (Tok.isNot(tok::r_paren)) { PT.consumeClose(); diff --git a/clang/test/Parser/offsetof.c b/clang/test/Parser/offsetof.c --- a/clang/test/Parser/offsetof.c +++ b/clang/test/Parser/offsetof.c @@ -3,5 +3,3 @@ struct a { struct { int b; } x[2]; }; int a = __builtin_offsetof(struct a, x; // expected-error{{expected ')'}} expected-note{{to match this '('}} -// FIXME: This actually shouldn't give an error -int b = __builtin_offsetof(struct a, x->b); // expected-error{{expected ')'}} expected-note{{to match this '('}}