add an action callback for __builtin_offsetof
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41606 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Parse/ParseExpr.cpp b/Parse/ParseExpr.cpp
index 46bcd67..8797158 100644
--- a/Parse/ParseExpr.cpp
+++ b/Parse/ParseExpr.cpp
@@ -773,40 +773,66 @@
ParseTypeName();
break;
- case tok::kw___builtin_offsetof:
- ParseTypeName();
+ case tok::kw___builtin_offsetof: {
+ TypeTy *Ty = ParseTypeName();
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
return ExprResult(true);
// We must have at least one identifier here.
- if (ExpectAndConsume(tok::identifier, diag::err_expected_ident, "",
- tok::r_paren))
- return ExprResult(true);
+ if (Tok.getKind() != tok::identifier) {
+ Diag(Tok, diag::err_expected_ident);
+ SkipUntil(tok::r_paren);
+ return true;
+ }
+
+ // Keep track of the various subcomponents we see.
+ llvm::SmallVector<Action::OffsetOfComponent, 4> Comps;
+
+ Comps.push_back(Action::OffsetOfComponent());
+ Comps.back().isBrackets = false;
+ Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
+ Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken();
while (1) {
if (Tok.getKind() == tok::period) {
// offsetof-member-designator: offsetof-member-designator '.' identifier
- ConsumeToken();
+ Comps.push_back(Action::OffsetOfComponent());
+ Comps.back().isBrackets = false;
+ Comps.back().LocStart = ConsumeToken();
- if (ExpectAndConsume(tok::identifier, diag::err_expected_ident, "",
- tok::r_paren))
- return ExprResult(true);
+ if (Tok.getKind() != tok::identifier) {
+ Diag(Tok, diag::err_expected_ident);
+ SkipUntil(tok::r_paren);
+ return true;
+ }
+ Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
+ Comps.back().LocEnd = ConsumeToken();
+
} else if (Tok.getKind() == tok::l_square) {
// offsetof-member-designator: offsetof-member-design '[' expression ']'
- SourceLocation LSquareLoc = ConsumeBracket();
+ Comps.push_back(Action::OffsetOfComponent());
+ Comps.back().isBrackets = true;
+ Comps.back().LocStart = ConsumeBracket();
Res = ParseExpression();
if (Res.isInvalid) {
SkipUntil(tok::r_paren);
return Res;
}
+ Comps.back().U.E = Res.Val;
- MatchRHSPunctuation(tok::r_square, LSquareLoc);
+ Comps.back().LocEnd =
+ MatchRHSPunctuation(tok::r_square, Comps.back().LocStart);
+ } else if (Tok.getKind() == tok::r_paren) {
+ return Actions.ParseBuiltinOffsetOf(StartLoc, Ty, &Comps[0],
+ Comps.size(), ConsumeParen());
} else {
- break;
+ // Error occurred.
+ return ExprResult(true);
}
}
break;
+ }
case tok::kw___builtin_choose_expr: {
ExprResult Cond = ParseAssignmentExpression();
if (Cond.isInvalid) {