From: Chris Lattner Date: Thu, 30 Aug 2007 15:51:11 +0000 (+0000) Subject: add an action callback for __builtin_offsetof X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f9aa3cb0348cb567a930248992eb54b0e6915961;p=clang 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 46bcd67f3f..87971588db 100644 --- a/Parse/ParseExpr.cpp +++ b/Parse/ParseExpr.cpp @@ -773,40 +773,66 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() { 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 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 (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(); - if (ExpectAndConsume(tok::identifier, diag::err_expected_ident, "", - tok::r_paren)) - return ExprResult(true); } 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) { diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 1ddbe85fb4..1f84e0d86f 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -375,6 +375,25 @@ public: SourceLocation RPLoc) { // "({..})" return 0; } + + // __builtin_offsetof(type, identifier(.identifier|[expr])*) + struct OffsetOfComponent { + SourceLocation LocStart, LocEnd; + bool isBrackets; // true if [expr], false if .ident + union { + IdentifierInfo *IdentInfo; + ExprTy *E; + } U; + }; + + virtual ExprResult ParseBuiltinOffsetOf(SourceLocation BuiltinLoc, + TypeTy *Arg1, + OffsetOfComponent *CompPtr, + unsigned NumComponents, + SourceLocation RParenLoc) { + return 0; + } + // __builtin_types_compatible_p(type1, type2) virtual ExprResult ParseTypesCompatibleExpr(SourceLocation BuiltinLoc, TypeTy *arg1, TypeTy *arg2,