From da6c89de486300c894a4178848ba02058377f0e9 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 27 Apr 2011 06:18:01 +0000 Subject: [PATCH] Introduce a new parser annotation token for primary expressions. When ClassifyName() builds a primary expression, generate one of these annotation tokens rather than jumping into the parser. llvm-svn: 130297 --- clang/include/clang/Basic/TokenKinds.def | 1 + clang/include/clang/Parse/Parser.h | 24 +++++++++++++++--- clang/lib/Parse/ParseExpr.cpp | 32 +++++++++--------------- clang/lib/Parse/ParseStmt.cpp | 15 +++++------ 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 1abdeb4116c7..eefa9c02a6d2 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -483,6 +483,7 @@ ANNOTATION(typename) // annotation for a C typedef name, a C++ (possibly ANNOTATION(template_id) // annotation for a C++ template-id that names a // function template specialization (not a type), // e.g., "std::swap" +ANNOTATION(primary_expr) // annotation for a primary expression // Annotation for #pragma unused(...) // For each argument inside the parentheses the pragma handler will produce diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 9932bbb2ad52..43089773f48b 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -392,6 +392,24 @@ private: static void setTypeAnnotation(Token &Tok, ParsedType T) { Tok.setAnnotationValue(T.getAsOpaquePtr()); } + + /// \brief Read an already-translated primary expression out of an annotation + /// token. + static ExprResult getExprAnnotation(Token &Tok) { + if (Tok.getAnnotationValue()) + return ExprResult((Expr *)Tok.getAnnotationValue()); + + return ExprResult(true); + } + + /// \brief Set the primary expression corresponding to the given annotation + /// token. + static void setExprAnnotation(Token &Tok, ExprResult ER) { + if (ER.isInvalid()) + Tok.setAnnotationValue(0); + else + Tok.setAnnotationValue(ER.get()); + } /// TryAnnotateTypeOrScopeToken - If the current token position is on a /// typename (possibly qualified in C++) or a C++ scope specifier not followed @@ -1049,10 +1067,10 @@ private: //===--------------------------------------------------------------------===// // C99 6.5: Expressions. - ExprResult ParseExpression(ExprResult Primary = ExprResult()); + ExprResult ParseExpression(); ExprResult ParseConstantExpression(); // Expr that doesn't include commas. - ExprResult ParseAssignmentExpression(ExprResult Primary = ExprResult()); + ExprResult ParseAssignmentExpression(); ExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc); @@ -1258,7 +1276,7 @@ private: } StmtResult ParseStatementOrDeclaration(StmtVector& Stmts, bool OnlyStatement = false); - StmtResult ParseExprStatement(ParsedAttributes &Attrs, ExprResult Primary); + StmtResult ParseExprStatement(ParsedAttributes &Attrs); StmtResult ParseLabeledStatement(ParsedAttributes &Attr); StmtResult ParseCaseStatement(ParsedAttributes &Attr, bool MissingCase = false, diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 12761e8d9f84..c990c52e7b16 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -174,11 +174,8 @@ static prec::Level getBinOpPrecedence(tok::TokenKind Kind, /// expression: [C99 6.5.17] /// assignment-expression ...[opt] /// expression ',' assignment-expression ...[opt] -/// -/// \param Primary if non-empty, an already-parsed expression that will be used -/// as the first primary expression. -ExprResult Parser::ParseExpression(ExprResult Primary) { - ExprResult LHS(ParseAssignmentExpression(Primary)); +ExprResult Parser::ParseExpression() { + ExprResult LHS(ParseAssignmentExpression()); return ParseRHSOfBinaryExpression(move(LHS), prec::Comma); } @@ -214,27 +211,16 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) { } /// ParseAssignmentExpression - Parse an expr that doesn't include commas. -/// -/// \param Primary if non-empty, an already-parsed expression that will be used -/// as the first primary expression. -ExprResult Parser::ParseAssignmentExpression(ExprResult Primary) { +ExprResult Parser::ParseAssignmentExpression() { if (Tok.is(tok::code_completion)) { - if (Primary.isUsable()) - Actions.CodeCompletePostfixExpression(getCurScope(), Primary); - else - Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); + Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); ConsumeCodeCompletionToken(); } - if (!Primary.isUsable() && Tok.is(tok::kw_throw)) + if (Tok.is(tok::kw_throw)) return ParseThrowExpression(); - ExprResult LHS; - if (Primary.get() || Primary.isInvalid()) - LHS = ParsePostfixExpressionSuffix(Primary); - else - LHS = ParseCastExpression(false, false, ParsedType()); - + ExprResult LHS = ParseCastExpression(false, false, ParsedType()); return ParseRHSOfBinaryExpression(move(LHS), prec::Assignment); } @@ -628,6 +614,12 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw_nullptr: return Actions.ActOnCXXNullPtrLiteral(ConsumeToken()); + case tok::annot_primary_expr: + assert(Res.get() == 0 && "Stray primary-expression annotation?"); + Res = getExprAnnotation(Tok); + ConsumeToken(); + break; + case tok::identifier: { // primary-expression: identifier // unqualified-id: identifier // constant: enumeration-constant diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 2ab2fcc69d74..07cef5597b8e 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -146,13 +146,15 @@ Retry: Tok.setKind(tok::annot_typename); setTypeAnnotation(Tok, Classification.getType()); Tok.setAnnotationEndLoc(NameLoc); - Tok.setLocation(NameLoc); PP.AnnotateCachedTokens(Tok); break; case Sema::NC_Expression: - ConsumeToken(); // the identifier - return ParseExprStatement(attrs, Classification.getExpression()); + Tok.setKind(tok::annot_primary_expr); + setExprAnnotation(Tok, Classification.getExpression()); + Tok.setAnnotationEndLoc(NameLoc); + PP.AnnotateCachedTokens(Tok); + break; case Sema::NC_TypeTemplate: case Sema::NC_FunctionTemplate: { @@ -210,7 +212,7 @@ Retry: return StmtError(); } - return ParseExprStatement(attrs, ExprResult()); + return ParseExprStatement(attrs); } case tok::kw_case: // C99 6.8.1: labeled-statement @@ -288,14 +290,13 @@ Retry: } /// \brief Parse an expression statement. -StmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs, - ExprResult Primary) { +StmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs) { // If a case keyword is missing, this is where it should be inserted. Token OldToken = Tok; // FIXME: Use the attributes // expression[opt] ';' - ExprResult Expr(ParseExpression(Primary)); + ExprResult Expr(ParseExpression()); if (Expr.isInvalid()) { // If the expression is invalid, skip ahead to the next semicolon or '}'. // Not doing this opens us up to the possibility of infinite loops if