summaryrefslogtreecommitdiff
path: root/clang/lib/Parse/ParseExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Parse/ParseExpr.cpp')
-rw-r--r--clang/lib/Parse/ParseExpr.cpp302
1 files changed, 256 insertions, 46 deletions
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index b74a95a3cd4b..1442df046bb9 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -22,6 +22,7 @@
#include "clang/Parse/Parser.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
@@ -145,7 +146,7 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
// Silence extension warnings in the sub-expression
ExtensionRAIIObject O(Diags);
- LHS = ParseCastExpression(false);
+ LHS = ParseCastExpression(AnyCastExpr);
}
if (!LHS.isInvalid())
@@ -169,7 +170,7 @@ ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) {
if (Tok.is(tok::kw_co_yield))
return ParseCoyieldExpression();
- ExprResult LHS = ParseCastExpression(/*isUnaryExpression=*/false,
+ ExprResult LHS = ParseCastExpression(AnyCastExpr,
/*isAddressOfOperand=*/false,
isTypeCast);
return ParseRHSOfBinaryExpression(LHS, prec::Assignment);
@@ -202,7 +203,7 @@ Parser::ParseConstantExpressionInExprEvalContext(TypeCastState isTypeCast) {
Sema::ExpressionEvaluationContext::ConstantEvaluated &&
"Call this function only if your ExpressionEvaluationContext is "
"already ConstantEvaluated");
- ExprResult LHS(ParseCastExpression(false, false, isTypeCast));
+ ExprResult LHS(ParseCastExpression(AnyCastExpr, false, isTypeCast));
ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
return Actions.ActOnConstantExpression(Res);
}
@@ -220,7 +221,7 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) {
ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) {
EnterExpressionEvaluationContext ConstantEvaluated(
Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
- ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
+ ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));
ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
return Actions.ActOnCaseExpr(CaseLoc, Res);
}
@@ -234,13 +235,141 @@ ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) {
ExprResult Parser::ParseConstraintExpression() {
EnterExpressionEvaluationContext ConstantEvaluated(
Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
- ExprResult LHS(ParseCastExpression(/*isUnaryExpression=*/false));
+ ExprResult LHS(ParseCastExpression(AnyCastExpr));
ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr));
- if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get()))
+ if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get())) {
+ Actions.CorrectDelayedTyposInExpr(Res);
return ExprError();
+ }
return Res;
}
+/// \brief Parse a constraint-logical-and-expression.
+///
+/// \verbatim
+/// C++2a[temp.constr.decl]p1
+/// constraint-logical-and-expression:
+/// primary-expression
+/// constraint-logical-and-expression '&&' primary-expression
+///
+/// \endverbatim
+ExprResult
+Parser::ParseConstraintLogicalAndExpression(bool IsTrailingRequiresClause) {
+ EnterExpressionEvaluationContext ConstantEvaluated(
+ Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+ bool NotPrimaryExpression = false;
+ auto ParsePrimary = [&] () {
+ ExprResult E = ParseCastExpression(PrimaryExprOnly,
+ /*isAddressOfOperand=*/false,
+ /*isTypeCast=*/NotTypeCast,
+ /*isVectorLiteral=*/false,
+ &NotPrimaryExpression);
+ if (E.isInvalid())
+ return ExprError();
+ auto RecoverFromNonPrimary = [&] (ExprResult E, bool Note) {
+ E = ParsePostfixExpressionSuffix(E);
+ // Use InclusiveOr, the precedence just after '&&' to not parse the
+ // next arguments to the logical and.
+ E = ParseRHSOfBinaryExpression(E, prec::InclusiveOr);
+ if (!E.isInvalid())
+ Diag(E.get()->getExprLoc(),
+ Note
+ ? diag::note_unparenthesized_non_primary_expr_in_requires_clause
+ : diag::err_unparenthesized_non_primary_expr_in_requires_clause)
+ << FixItHint::CreateInsertion(E.get()->getBeginLoc(), "(")
+ << FixItHint::CreateInsertion(
+ PP.getLocForEndOfToken(E.get()->getEndLoc()), ")")
+ << E.get()->getSourceRange();
+ return E;
+ };
+
+ if (NotPrimaryExpression ||
+ // Check if the following tokens must be a part of a non-primary
+ // expression
+ getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
+ /*CPlusPlus11=*/true) > prec::LogicalAnd ||
+ // Postfix operators other than '(' (which will be checked for in
+ // CheckConstraintExpression).
+ Tok.isOneOf(tok::period, tok::plusplus, tok::minusminus) ||
+ (Tok.is(tok::l_square) && !NextToken().is(tok::l_square))) {
+ E = RecoverFromNonPrimary(E, /*Note=*/false);
+ if (E.isInvalid())
+ return ExprError();
+ NotPrimaryExpression = false;
+ }
+ bool PossibleNonPrimary;
+ bool IsConstraintExpr =
+ Actions.CheckConstraintExpression(E.get(), Tok, &PossibleNonPrimary,
+ IsTrailingRequiresClause);
+ if (!IsConstraintExpr || PossibleNonPrimary) {
+ // Atomic constraint might be an unparenthesized non-primary expression
+ // (such as a binary operator), in which case we might get here (e.g. in
+ // 'requires 0 + 1 && true' we would now be at '+', and parse and ignore
+ // the rest of the addition expression). Try to parse the rest of it here.
+ if (PossibleNonPrimary)
+ E = RecoverFromNonPrimary(E, /*Note=*/!IsConstraintExpr);
+ Actions.CorrectDelayedTyposInExpr(E);
+ return ExprError();
+ }
+ return E;
+ };
+ ExprResult LHS = ParsePrimary();
+ if (LHS.isInvalid())
+ return ExprError();
+ while (Tok.is(tok::ampamp)) {
+ SourceLocation LogicalAndLoc = ConsumeToken();
+ ExprResult RHS = ParsePrimary();
+ if (RHS.isInvalid()) {
+ Actions.CorrectDelayedTyposInExpr(LHS);
+ return ExprError();
+ }
+ ExprResult Op = Actions.ActOnBinOp(getCurScope(), LogicalAndLoc,
+ tok::ampamp, LHS.get(), RHS.get());
+ if (!Op.isUsable()) {
+ Actions.CorrectDelayedTyposInExpr(RHS);
+ Actions.CorrectDelayedTyposInExpr(LHS);
+ return ExprError();
+ }
+ LHS = Op;
+ }
+ return LHS;
+}
+
+/// \brief Parse a constraint-logical-or-expression.
+///
+/// \verbatim
+/// C++2a[temp.constr.decl]p1
+/// constraint-logical-or-expression:
+/// constraint-logical-and-expression
+/// constraint-logical-or-expression '||'
+/// constraint-logical-and-expression
+///
+/// \endverbatim
+ExprResult
+Parser::ParseConstraintLogicalOrExpression(bool IsTrailingRequiresClause) {
+ ExprResult LHS(ParseConstraintLogicalAndExpression(IsTrailingRequiresClause));
+ if (!LHS.isUsable())
+ return ExprError();
+ while (Tok.is(tok::pipepipe)) {
+ SourceLocation LogicalOrLoc = ConsumeToken();
+ ExprResult RHS =
+ ParseConstraintLogicalAndExpression(IsTrailingRequiresClause);
+ if (!RHS.isUsable()) {
+ Actions.CorrectDelayedTyposInExpr(LHS);
+ return ExprError();
+ }
+ ExprResult Op = Actions.ActOnBinOp(getCurScope(), LogicalOrLoc,
+ tok::pipepipe, LHS.get(), RHS.get());
+ if (!Op.isUsable()) {
+ Actions.CorrectDelayedTyposInExpr(RHS);
+ Actions.CorrectDelayedTyposInExpr(LHS);
+ return ExprError();
+ }
+ LHS = Op;
+ }
+ return LHS;
+}
+
bool Parser::isNotExpressionStart() {
tok::TokenKind K = Tok.getKind();
if (K == tok::l_brace || K == tok::r_brace ||
@@ -414,7 +543,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
} else if (getLangOpts().CPlusPlus && NextTokPrec <= prec::Conditional)
RHS = ParseAssignmentExpression();
else
- RHS = ParseCastExpression(false);
+ RHS = ParseCastExpression(AnyCastExpr);
if (RHS.isInvalid()) {
// FIXME: Errors generated by the delayed typo correction should be
@@ -519,22 +648,24 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
}
}
-/// Parse a cast-expression, or, if \p isUnaryExpression is true,
-/// parse a unary-expression.
+/// Parse a cast-expression, unary-expression or primary-expression, based
+/// on \p ExprType.
///
/// \p isAddressOfOperand exists because an id-expression that is the
/// operand of address-of gets special treatment due to member pointers.
///
-ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
+ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
bool isAddressOfOperand,
TypeCastState isTypeCast,
- bool isVectorLiteral) {
+ bool isVectorLiteral,
+ bool *NotPrimaryExpression) {
bool NotCastExpr;
- ExprResult Res = ParseCastExpression(isUnaryExpression,
+ ExprResult Res = ParseCastExpression(ParseKind,
isAddressOfOperand,
NotCastExpr,
isTypeCast,
- isVectorLiteral);
+ isVectorLiteral,
+ NotPrimaryExpression);
if (NotCastExpr)
Diag(Tok, diag::err_expected_expression);
return Res;
@@ -759,11 +890,12 @@ class CastExpressionIdValidator final : public CorrectionCandidateCallback {
/// '__is_rvalue_expr'
/// \endverbatim
///
-ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
+ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
bool isAddressOfOperand,
bool &NotCastExpr,
TypeCastState isTypeCast,
- bool isVectorLiteral) {
+ bool isVectorLiteral,
+ bool *NotPrimaryExpression) {
ExprResult Res;
tok::TokenKind SavedKind = Tok.getKind();
auto SavedType = PreferredType;
@@ -782,11 +914,21 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// ParsePostfixExpressionSuffix.
switch (SavedKind) {
case tok::l_paren: {
- // If this expression is limited to being a unary-expression, the parent can
+ // If this expression is limited to being a unary-expression, the paren can
// not start a cast expression.
- ParenParseOption ParenExprType =
- (isUnaryExpression && !getLangOpts().CPlusPlus) ? CompoundLiteral
- : CastExpr;
+ ParenParseOption ParenExprType;
+ switch (ParseKind) {
+ case CastParseKind::UnaryExprOnly:
+ if (!getLangOpts().CPlusPlus)
+ ParenExprType = CompoundLiteral;
+ LLVM_FALLTHROUGH;
+ case CastParseKind::AnyCastExpr:
+ ParenExprType = ParenParseOption::CastExpr;
+ break;
+ case CastParseKind::PrimaryExprOnly:
+ ParenExprType = FoldExpr;
+ break;
+ }
ParsedType CastTy;
SourceLocation RParenLoc;
Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
@@ -861,8 +1003,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
if (TryAnnotateTypeOrScopeToken())
return ExprError();
assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super));
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
-
+ return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast,
+ isVectorLiteral, NotPrimaryExpression);
+
case tok::identifier: { // primary-expression: identifier
// unqualified-id: identifier
// constant: enumeration-constant
@@ -949,8 +1092,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
= RevertibleTypeTraits.find(II);
if (Known != RevertibleTypeTraits.end()) {
Tok.setKind(Known->second);
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, isTypeCast);
+ return ParseCastExpression(ParseKind, isAddressOfOperand,
+ NotCastExpr, isTypeCast,
+ isVectorLiteral, NotPrimaryExpression);
}
}
@@ -961,7 +1105,10 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
if (TryAnnotateTypeOrScopeToken())
return ExprError();
if (!Tok.is(tok::identifier))
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
+ return ParseCastExpression(ParseKind, isAddressOfOperand,
+ NotCastExpr, isTypeCast,
+ isVectorLiteral,
+ NotPrimaryExpression);
}
}
@@ -1076,8 +1223,10 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
Tok.is(tok::r_paren) ? nullptr : &Replacement);
if (!Res.isInvalid() && Res.isUnset()) {
UnconsumeToken(Replacement);
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, isTypeCast);
+ return ParseCastExpression(ParseKind, isAddressOfOperand,
+ NotCastExpr, isTypeCast,
+ /*isVectorLiteral=*/false,
+ NotPrimaryExpression);
}
if (!Res.isInvalid() && Tok.is(tok::less))
checkPotentialAngleBracket(Res);
@@ -1122,12 +1271,16 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw___builtin_FILE:
case tok::kw___builtin_FUNCTION:
case tok::kw___builtin_LINE:
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
return ParseBuiltinPrimaryExpression();
case tok::kw___null:
return Actions.ActOnGNUNullExpr(ConsumeToken());
case tok::plusplus: // unary-expression: '++' unary-expression [C99]
case tok::minusminus: { // unary-expression: '--' unary-expression [C99]
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
// C++ [expr.unary] has:
// unary-expression:
// ++ cast-expression
@@ -1140,7 +1293,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// One special case is implicitly handled here: if the preceding tokens are
// an ambiguous cast expression, such as "(T())++", then we recurse to
// determine whether the '++' is prefix or postfix.
- Res = ParseCastExpression(!getLangOpts().CPlusPlus,
+ Res = ParseCastExpression(getLangOpts().CPlusPlus ?
+ UnaryExprOnly : AnyCastExpr,
/*isAddressOfOperand*/false, NotCastExpr,
NotTypeCast);
if (NotCastExpr) {
@@ -1156,10 +1310,12 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return Res;
}
case tok::amp: { // unary-expression: '&' cast-expression
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
// Special treatment because of member pointers
SourceLocation SavedLoc = ConsumeToken();
PreferredType.enterUnary(Actions, Tok.getLocation(), tok::amp, SavedLoc);
- Res = ParseCastExpression(false, true);
+ Res = ParseCastExpression(AnyCastExpr, true);
if (!Res.isInvalid())
Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
return Res;
@@ -1172,17 +1328,21 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::exclaim: // unary-expression: '!' cast-expression
case tok::kw___real: // unary-expression: '__real' cast-expression [GNU]
case tok::kw___imag: { // unary-expression: '__imag' cast-expression [GNU]
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
SourceLocation SavedLoc = ConsumeToken();
PreferredType.enterUnary(Actions, Tok.getLocation(), SavedKind, SavedLoc);
- Res = ParseCastExpression(false);
+ Res = ParseCastExpression(AnyCastExpr);
if (!Res.isInvalid())
Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
return Res;
}
case tok::kw_co_await: { // unary-expression: 'co_await' cast-expression
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
SourceLocation CoawaitLoc = ConsumeToken();
- Res = ParseCastExpression(false);
+ Res = ParseCastExpression(AnyCastExpr);
if (!Res.isInvalid())
Res = Actions.ActOnCoawaitExpr(getCurScope(), CoawaitLoc, Res.get());
return Res;
@@ -1190,9 +1350,11 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU]
// __extension__ silences extension warnings in the subexpression.
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
ExtensionRAIIObject O(Diags); // Use RAII to do this.
SourceLocation SavedLoc = ConsumeToken();
- Res = ParseCastExpression(false);
+ Res = ParseCastExpression(AnyCastExpr);
if (!Res.isInvalid())
Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
return Res;
@@ -1209,8 +1371,12 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression
// unary-expression: '__builtin_omp_required_simd_align' '(' type-name ')'
case tok::kw___builtin_omp_required_simd_align:
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
return ParseUnaryExprOrTypeTraitExpression();
case tok::ampamp: { // unary-expression: '&&' identifier
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
SourceLocation AmpAmpLoc = ConsumeToken();
if (Tok.isNot(tok::identifier))
return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
@@ -1229,15 +1395,23 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw_dynamic_cast:
case tok::kw_reinterpret_cast:
case tok::kw_static_cast:
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
Res = ParseCXXCasts();
break;
case tok::kw___builtin_bit_cast:
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
Res = ParseBuiltinBitCast();
break;
case tok::kw_typeid:
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
Res = ParseCXXTypeid();
break;
case tok::kw___uuidof:
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
Res = ParseCXXUuidof();
break;
case tok::kw_this:
@@ -1302,6 +1476,10 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return ExprError();
}
+ // Everything henceforth is a postfix-expression.
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
+
if (SavedKind == tok::kw_typename) {
// postfix-expression: typename-specifier '(' expression-list[opt] ')'
// typename-specifier braced-init-list
@@ -1338,8 +1516,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
if (TryAnnotateTypeOrScopeToken())
return ExprError();
if (!Tok.is(tok::annot_cxxscope))
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, isTypeCast);
+ return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr,
+ isTypeCast, isVectorLiteral,
+ NotPrimaryExpression);
Token Next = NextToken();
if (Next.is(tok::annot_template_id)) {
@@ -1352,8 +1531,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
ParseOptionalCXXScopeSpecifier(SS, nullptr,
/*EnteringContext=*/false);
AnnotateTemplateIdTokenAsType();
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, isTypeCast);
+ return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr,
+ isTypeCast, isVectorLiteral,
+ NotPrimaryExpression);
}
}
@@ -1369,8 +1549,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// translate it into a type and continue parsing as a cast
// expression.
AnnotateTemplateIdTokenAsType();
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, isTypeCast);
+ return ParseCastExpression(ParseKind, isAddressOfOperand,
+ NotCastExpr, isTypeCast, isVectorLiteral,
+ NotPrimaryExpression);
}
// Fall through to treat the template-id as an id-expression.
@@ -1387,15 +1568,22 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
if (TryAnnotateTypeOrScopeToken())
return ExprError();
if (!Tok.is(tok::coloncolon))
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
+ return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast,
+ isVectorLiteral, NotPrimaryExpression);
// ::new -> [C++] new-expression
// ::delete -> [C++] delete-expression
SourceLocation CCLoc = ConsumeToken();
- if (Tok.is(tok::kw_new))
+ if (Tok.is(tok::kw_new)) {
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
return ParseCXXNewExpression(true, CCLoc);
- if (Tok.is(tok::kw_delete))
+ }
+ if (Tok.is(tok::kw_delete)) {
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
return ParseCXXDeleteExpression(true, CCLoc);
+ }
// This is not a type name or scope specifier, it is an invalid expression.
Diag(CCLoc, diag::err_expected_expression);
@@ -1403,12 +1591,18 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
}
case tok::kw_new: // [C++] new-expression
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
return ParseCXXNewExpression(false, Tok.getLocation());
case tok::kw_delete: // [C++] delete-expression
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
return ParseCXXDeleteExpression(false, Tok.getLocation());
case tok::kw_noexcept: { // [C++0x] 'noexcept' '(' expression ')'
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
Diag(Tok, diag::warn_cxx98_compat_noexcept_expr);
SourceLocation KeyLoc = ConsumeToken();
BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -1437,13 +1631,19 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw___array_rank:
case tok::kw___array_extent:
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
return ParseArrayTypeTrait();
case tok::kw___is_lvalue_expr:
case tok::kw___is_rvalue_expr:
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
return ParseExpressionTrait();
case tok::at: {
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
SourceLocation AtLoc = ConsumeToken();
return ParseObjCAtExpression(AtLoc);
}
@@ -1465,8 +1665,13 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// expression, or we have something that doesn't appear to be a lambda.
// If we're in the last case, we fall back to ParseObjCMessageExpression.
Res = TryParseLambdaExpression();
- if (!Res.isInvalid() && !Res.get())
+ if (!Res.isInvalid() && !Res.get()) {
+ // We assume Objective-C++ message expressions are not
+ // primary-expressions.
+ if (NotPrimaryExpression)
+ *NotPrimaryExpression = true;
Res = ParseObjCMessageExpression();
+ }
break;
}
Res = ParseLambdaExpression();
@@ -1486,6 +1691,11 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// are compiling for OpenCL, we need to return an error as this implies
// that the address of the function is being taken, which is illegal in CL.
+ if (ParseKind == PrimaryExprOnly)
+ // This is strictly a primary-expression - no postfix-expr pieces should be
+ // parsed.
+ return Res;
+
// These can be followed by postfix-expr pieces.
PreferredType = SavedType;
Res = ParsePostfixExpressionSuffix(Res);
@@ -1929,7 +2139,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
return ExprError();
}
- Operand = ParseCastExpression(true/*isUnaryExpression*/);
+ Operand = ParseCastExpression(UnaryExprOnly);
} else {
// If it starts with a '(', we know that it is either a parenthesized
// type-name, or it is a unary-expression that starts with a compound
@@ -2474,8 +2684,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
RParenLoc = T.getCloseLocation();
PreferredType.enterTypeCast(Tok.getLocation(), Ty.get().get());
- ExprResult SubExpr = ParseCastExpression(/*isUnaryExpression=*/false);
-
+ ExprResult SubExpr = ParseCastExpression(AnyCastExpr);
+
if (Ty.isInvalid() || SubExpr.isInvalid())
return ExprError();
@@ -2555,7 +2765,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// Parse the cast-expression that follows it next.
// isVectorLiteral = true will make sure we don't parse any
// Postfix expression yet
- Result = ParseCastExpression(/*isUnaryExpression=*/false,
+ Result = ParseCastExpression(/*isUnaryExpression=*/AnyCastExpr,
/*isAddressOfOperand=*/false,
/*isTypeCast=*/IsTypeCast,
/*isVectorLiteral=*/true);
@@ -2607,7 +2817,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
PreferredType.enterTypeCast(Tok.getLocation(), CastTy.get());
// Parse the cast-expression that follows it next.
// TODO: For cast expression with CastTy.
- Result = ParseCastExpression(/*isUnaryExpression=*/false,
+ Result = ParseCastExpression(/*isUnaryExpression=*/AnyCastExpr,
/*isAddressOfOperand=*/false,
/*isTypeCast=*/IsTypeCast);
if (!Result.isInvalid()) {