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.cpp412
1 files changed, 339 insertions, 73 deletions
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 1442df046bb93..81e87582c6ade 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -234,7 +234,7 @@ ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) {
/// \endverbatim
ExprResult Parser::ParseConstraintExpression() {
EnterExpressionEvaluationContext ConstantEvaluated(
- Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+ Actions, Sema::ExpressionEvaluationContext::Unevaluated);
ExprResult LHS(ParseCastExpression(AnyCastExpr));
ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr));
if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get())) {
@@ -256,7 +256,7 @@ ExprResult Parser::ParseConstraintExpression() {
ExprResult
Parser::ParseConstraintLogicalAndExpression(bool IsTrailingRequiresClause) {
EnterExpressionEvaluationContext ConstantEvaluated(
- Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+ Actions, Sema::ExpressionEvaluationContext::Unevaluated);
bool NotPrimaryExpression = false;
auto ParsePrimary = [&] () {
ExprResult E = ParseCastExpression(PrimaryExprOnly,
@@ -625,13 +625,31 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
SourceRange(Actions.getExprRange(LHS.get()).getBegin(),
Actions.getExprRange(RHS.get()).getEnd()));
- LHS = Actions.ActOnBinOp(getCurScope(), OpToken.getLocation(),
- OpToken.getKind(), LHS.get(), RHS.get());
+ ExprResult BinOp =
+ Actions.ActOnBinOp(getCurScope(), OpToken.getLocation(),
+ OpToken.getKind(), LHS.get(), RHS.get());
+ if (BinOp.isInvalid())
+ BinOp = Actions.CreateRecoveryExpr(LHS.get()->getBeginLoc(),
+ RHS.get()->getEndLoc(),
+ {LHS.get(), RHS.get()});
+ LHS = BinOp;
} else {
- LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc,
- LHS.get(), TernaryMiddle.get(),
- RHS.get());
+ ExprResult CondOp = Actions.ActOnConditionalOp(
+ OpToken.getLocation(), ColonLoc, LHS.get(), TernaryMiddle.get(),
+ RHS.get());
+ if (CondOp.isInvalid()) {
+ std::vector<clang::Expr *> Args;
+ // TernaryMiddle can be null for the GNU conditional expr extension.
+ if (TernaryMiddle.get())
+ Args = {LHS.get(), TernaryMiddle.get(), RHS.get()};
+ else
+ Args = {LHS.get(), RHS.get()};
+ CondOp = Actions.CreateRecoveryExpr(LHS.get()->getBeginLoc(),
+ RHS.get()->getEndLoc(), Args);
+ }
+
+ LHS = CondOp;
}
// In this case, ActOnBinOp or ActOnConditionalOp performed the
// CorrectDelayedTyposInExpr check.
@@ -756,6 +774,7 @@ class CastExpressionIdValidator final : public CorrectionCandidateCallback {
/// [C++11] user-defined-literal
/// '(' expression ')'
/// [C11] generic-selection
+/// [C++2a] requires-expression
/// '__func__' [C99 6.4.2.2]
/// [GNU] '__FUNCTION__'
/// [MS] '__FUNCDNAME__'
@@ -901,6 +920,11 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
auto SavedType = PreferredType;
NotCastExpr = false;
+ // Are postfix-expression suffix operators permitted after this
+ // cast-expression? If not, and we find some, we'll parse them anyway and
+ // diagnose them.
+ bool AllowSuffix = true;
+
// This handles all of cast-expression, unary-expression, postfix-expression,
// and primary-expression. We handle them together like this for efficiency
// and to simplify handling of an expression starting with a '(' token: which
@@ -910,8 +934,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
// If the parsed tokens consist of a primary-expression, the cases below
// break out of the switch; at the end we call ParsePostfixExpressionSuffix
// to handle the postfix expression suffixes. Cases that cannot be followed
- // by postfix exprs should return without invoking
- // ParsePostfixExpressionSuffix.
+ // by postfix exprs should set AllowSuffix to false.
switch (SavedKind) {
case tok::l_paren: {
// If this expression is limited to being a unary-expression, the paren can
@@ -934,8 +957,11 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
isTypeCast == IsTypeCast, CastTy, RParenLoc);
+ // FIXME: What should we do if a vector literal is followed by a
+ // postfix-expression suffix? Usually postfix operators are permitted on
+ // literals.
if (isVectorLiteral)
- return Res;
+ return Res;
switch (ParenExprType) {
case SimpleExpr: break; // Nothing else to do.
@@ -973,14 +999,31 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
case tok::kw___objc_yes:
case tok::kw___objc_no:
- return ParseObjCBoolLiteral();
+ Res = ParseObjCBoolLiteral();
+ break;
case tok::kw_nullptr:
Diag(Tok, diag::warn_cxx98_compat_nullptr);
- return Actions.ActOnCXXNullPtrLiteral(ConsumeToken());
+ Res = Actions.ActOnCXXNullPtrLiteral(ConsumeToken());
+ break;
+ case tok::annot_uneval_primary_expr:
case tok::annot_primary_expr:
Res = getExprAnnotation(Tok);
+ if (SavedKind == tok::annot_uneval_primary_expr) {
+ if (Expr *E = Res.get()) {
+ if (!E->isTypeDependent() && !E->containsErrors()) {
+ // TransformToPotentiallyEvaluated expects that it will still be in a
+ // (temporary) unevaluated context and then looks through that context
+ // to build it in the surrounding context. So we need to push an
+ // unevaluated context to balance things out.
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::ExpressionEvaluationContext::Unevaluated,
+ Sema::ReuseLambdaContextDecl);
+ Res = Actions.TransformToPotentiallyEvaluated(Res.get());
+ }
+ }
+ }
ConsumeAnnotationToken();
if (!Res.isInvalid() && Tok.is(tok::less))
checkPotentialAngleBracket(Res);
@@ -1005,7 +1048,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super));
return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast,
isVectorLiteral, NotPrimaryExpression);
-
+
case tok::identifier: { // primary-expression: identifier
// unqualified-id: identifier
// constant: enumeration-constant
@@ -1261,7 +1304,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
Res = ParseGenericSelectionExpression();
break;
case tok::kw___builtin_available:
- return ParseAvailabilityCheckExpr(Tok.getLocation());
+ Res = ParseAvailabilityCheckExpr(Tok.getLocation());
+ break;
case tok::kw___builtin_va_arg:
case tok::kw___builtin_offsetof:
case tok::kw___builtin_choose_expr:
@@ -1273,9 +1317,11 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
case tok::kw___builtin_LINE:
if (NotPrimaryExpression)
*NotPrimaryExpression = true;
+ // This parses the complete suffix; we can return early.
return ParseBuiltinPrimaryExpression();
case tok::kw___null:
- return Actions.ActOnGNUNullExpr(ConsumeToken());
+ Res = Actions.ActOnGNUNullExpr(ConsumeToken());
+ break;
case tok::plusplus: // unary-expression: '++' unary-expression [C99]
case tok::minusminus: { // unary-expression: '--' unary-expression [C99]
@@ -1304,9 +1350,14 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
UnconsumeToken(SavedTok);
return ExprError();
}
- if (!Res.isInvalid())
+ if (!Res.isInvalid()) {
+ Expr *Arg = Res.get();
Res = Actions.ActOnUnaryOp(getCurScope(), SavedTok.getLocation(),
- SavedKind, Res.get());
+ SavedKind, Arg);
+ if (Res.isInvalid())
+ Res = Actions.CreateRecoveryExpr(SavedTok.getLocation(),
+ Arg->getEndLoc(), Arg);
+ }
return Res;
}
case tok::amp: { // unary-expression: '&' cast-expression
@@ -1316,8 +1367,13 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
SourceLocation SavedLoc = ConsumeToken();
PreferredType.enterUnary(Actions, Tok.getLocation(), tok::amp, SavedLoc);
Res = ParseCastExpression(AnyCastExpr, true);
- if (!Res.isInvalid())
- Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
+ if (!Res.isInvalid()) {
+ Expr *Arg = Res.get();
+ Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Arg);
+ if (Res.isInvalid())
+ Res = Actions.CreateRecoveryExpr(Tok.getLocation(), Arg->getEndLoc(),
+ Arg);
+ }
return Res;
}
@@ -1333,8 +1389,12 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
SourceLocation SavedLoc = ConsumeToken();
PreferredType.enterUnary(Actions, Tok.getLocation(), SavedKind, SavedLoc);
Res = ParseCastExpression(AnyCastExpr);
- if (!Res.isInvalid())
- Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
+ if (!Res.isInvalid()) {
+ Expr *Arg = Res.get();
+ Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Arg);
+ if (Res.isInvalid())
+ Res = Actions.CreateRecoveryExpr(SavedLoc, Arg->getEndLoc(), Arg);
+ }
return Res;
}
@@ -1373,7 +1433,9 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
case tok::kw___builtin_omp_required_simd_align:
if (NotPrimaryExpression)
*NotPrimaryExpression = true;
- return ParseUnaryExprOrTypeTraitExpression();
+ AllowSuffix = false;
+ Res = ParseUnaryExprOrTypeTraitExpression();
+ break;
case tok::ampamp: { // unary-expression: '&&' identifier
if (NotPrimaryExpression)
*NotPrimaryExpression = true;
@@ -1389,12 +1451,14 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
Tok.getLocation());
Res = Actions.ActOnAddrLabel(AmpAmpLoc, Tok.getLocation(), LD);
ConsumeToken();
- return Res;
+ AllowSuffix = false;
+ break;
}
case tok::kw_const_cast:
case tok::kw_dynamic_cast:
case tok::kw_reinterpret_cast:
case tok::kw_static_cast:
+ case tok::kw_addrspace_cast:
if (NotPrimaryExpression)
*NotPrimaryExpression = true;
Res = ParseCXXCasts();
@@ -1417,10 +1481,12 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
case tok::kw_this:
Res = ParseCXXThis();
break;
-
+ case tok::kw___builtin_unique_stable_name:
+ Res = ParseUniqueStableNameExpression();
+ break;
case tok::annot_typename:
if (isStartOfObjCClassMessageMissingOpenBracket()) {
- ParsedType Type = getTypeAnnotation(Tok);
+ TypeResult Type = getTypeAnnotation(Tok);
// Fake up a Declarator to use with ActOnTypeName.
DeclSpec DS(AttrFactory);
@@ -1457,11 +1523,13 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
case tok::kw_long:
case tok::kw___int64:
case tok::kw___int128:
+ case tok::kw__ExtInt:
case tok::kw_signed:
case tok::kw_unsigned:
case tok::kw_half:
case tok::kw_float:
case tok::kw_double:
+ case tok::kw___bf16:
case tok::kw__Float16:
case tok::kw___float128:
case tok::kw_void:
@@ -1528,9 +1596,10 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
// type, translate it into a type and continue parsing as a
// cast expression.
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, nullptr,
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false,
/*EnteringContext=*/false);
- AnnotateTemplateIdTokenAsType();
+ AnnotateTemplateIdTokenAsType(SS);
return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr,
isTypeCast, isVectorLiteral,
NotPrimaryExpression);
@@ -1548,7 +1617,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
// We have a template-id that we know refers to a type,
// translate it into a type and continue parsing as a cast
// expression.
- AnnotateTemplateIdTokenAsType();
+ CXXScopeSpec SS;
+ AnnotateTemplateIdTokenAsType(SS);
return ParseCastExpression(ParseKind, isAddressOfOperand,
NotCastExpr, isTypeCast, isVectorLiteral,
NotPrimaryExpression);
@@ -1577,12 +1647,16 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
if (Tok.is(tok::kw_new)) {
if (NotPrimaryExpression)
*NotPrimaryExpression = true;
- return ParseCXXNewExpression(true, CCLoc);
+ Res = ParseCXXNewExpression(true, CCLoc);
+ AllowSuffix = false;
+ break;
}
if (Tok.is(tok::kw_delete)) {
if (NotPrimaryExpression)
*NotPrimaryExpression = true;
- return ParseCXXDeleteExpression(true, CCLoc);
+ Res = ParseCXXDeleteExpression(true, CCLoc);
+ AllowSuffix = false;
+ break;
}
// This is not a type name or scope specifier, it is an invalid expression.
@@ -1593,12 +1667,21 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
case tok::kw_new: // [C++] new-expression
if (NotPrimaryExpression)
*NotPrimaryExpression = true;
- return ParseCXXNewExpression(false, Tok.getLocation());
+ Res = ParseCXXNewExpression(false, Tok.getLocation());
+ AllowSuffix = false;
+ break;
case tok::kw_delete: // [C++] delete-expression
if (NotPrimaryExpression)
*NotPrimaryExpression = true;
- return ParseCXXDeleteExpression(false, Tok.getLocation());
+ Res = ParseCXXDeleteExpression(false, Tok.getLocation());
+ AllowSuffix = false;
+ break;
+
+ case tok::kw_requires: // [C++2a] requires-expression
+ Res = ParseRequiresExpression();
+ AllowSuffix = false;
+ break;
case tok::kw_noexcept: { // [C++0x] 'noexcept' '(' expression ')'
if (NotPrimaryExpression)
@@ -1614,32 +1697,36 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
// which is an unevaluated operand, can throw an exception.
EnterExpressionEvaluationContext Unevaluated(
Actions, Sema::ExpressionEvaluationContext::Unevaluated);
- ExprResult Result = ParseExpression();
+ Res = ParseExpression();
T.consumeClose();
- if (!Result.isInvalid())
- Result = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(),
- Result.get(), T.getCloseLocation());
- return Result;
+ if (!Res.isInvalid())
+ Res = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(), Res.get(),
+ T.getCloseLocation());
+ AllowSuffix = false;
+ break;
}
#define TYPE_TRAIT(N,Spelling,K) \
case tok::kw_##Spelling:
#include "clang/Basic/TokenKinds.def"
- return ParseTypeTrait();
+ Res = ParseTypeTrait();
+ break;
case tok::kw___array_rank:
case tok::kw___array_extent:
if (NotPrimaryExpression)
*NotPrimaryExpression = true;
- return ParseArrayTypeTrait();
+ Res = ParseArrayTypeTrait();
+ break;
case tok::kw___is_lvalue_expr:
case tok::kw___is_rvalue_expr:
if (NotPrimaryExpression)
*NotPrimaryExpression = true;
- return ParseExpressionTrait();
+ Res = ParseExpressionTrait();
+ break;
case tok::at: {
if (NotPrimaryExpression)
@@ -1696,6 +1783,41 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
// parsed.
return Res;
+ if (!AllowSuffix) {
+ // FIXME: Don't parse a primary-expression suffix if we encountered a parse
+ // error already.
+ if (Res.isInvalid())
+ return Res;
+
+ switch (Tok.getKind()) {
+ case tok::l_square:
+ case tok::l_paren:
+ case tok::plusplus:
+ case tok::minusminus:
+ // "expected ';'" or similar is probably the right diagnostic here. Let
+ // the caller decide what to do.
+ if (Tok.isAtStartOfLine())
+ return Res;
+
+ LLVM_FALLTHROUGH;
+ case tok::period:
+ case tok::arrow:
+ break;
+
+ default:
+ return Res;
+ }
+
+ // This was a unary-expression for which a postfix-expression suffix is
+ // not permitted by the grammar (eg, a sizeof expression or
+ // new-expression or similar). Diagnose but parse the suffix anyway.
+ Diag(Tok.getLocation(), diag::err_postfix_after_unary_requires_parens)
+ << Tok.getKind() << Res.get()->getSourceRange()
+ << FixItHint::CreateInsertion(Res.get()->getBeginLoc(), "(")
+ << FixItHint::CreateInsertion(PP.getLocForEndOfToken(PrevTokLocation),
+ ")");
+ }
+
// These can be followed by postfix-expr pieces.
PreferredType = SavedType;
Res = ParsePostfixExpressionSuffix(Res);
@@ -1787,8 +1909,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
BalancedDelimiterTracker T(*this, tok::l_square);
T.consumeOpen();
Loc = T.getOpenLocation();
- ExprResult Idx, Length;
- SourceLocation ColonLoc;
+ ExprResult Idx, Length, Stride;
+ SourceLocation ColonLocFirst, ColonLocSecond;
PreferredType.enterSubscript(Actions, Tok.getLocation(), LHS.get());
if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
@@ -1802,10 +1924,22 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
}
if (Tok.is(tok::colon)) {
// Consume ':'
- ColonLoc = ConsumeToken();
- if (Tok.isNot(tok::r_square))
+ ColonLocFirst = ConsumeToken();
+ if (Tok.isNot(tok::r_square) &&
+ (getLangOpts().OpenMP < 50 ||
+ ((Tok.isNot(tok::colon) && getLangOpts().OpenMP >= 50))))
Length = ParseExpression();
}
+ if (getLangOpts().OpenMP >= 50 &&
+ (OMPClauseKind == llvm::omp::Clause::OMPC_to ||
+ OMPClauseKind == llvm::omp::Clause::OMPC_from) &&
+ Tok.is(tok::colon)) {
+ // Consume ':'
+ ColonLocSecond = ConsumeToken();
+ if (Tok.isNot(tok::r_square)) {
+ Stride = ParseExpression();
+ }
+ }
} else
Idx = ParseExpression();
@@ -1815,10 +1949,11 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
Idx = Actions.CorrectDelayedTyposInExpr(Idx);
Length = Actions.CorrectDelayedTyposInExpr(Length);
if (!LHS.isInvalid() && !Idx.isInvalid() && !Length.isInvalid() &&
- Tok.is(tok::r_square)) {
- if (ColonLoc.isValid()) {
- LHS = Actions.ActOnOMPArraySectionExpr(LHS.get(), Loc, Idx.get(),
- ColonLoc, Length.get(), RLoc);
+ !Stride.isInvalid() && Tok.is(tok::r_square)) {
+ if (ColonLocFirst.isValid() || ColonLocSecond.isValid()) {
+ LHS = Actions.ActOnOMPArraySectionExpr(
+ LHS.get(), Loc, Idx.get(), ColonLocFirst, ColonLocSecond,
+ Length.get(), Stride.get(), RLoc);
} else {
LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc,
Idx.get(), RLoc);
@@ -1935,12 +2070,18 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
PT.consumeClose();
LHS = ExprError();
} else {
- assert((ArgExprs.size() == 0 ||
- ArgExprs.size()-1 == CommaLocs.size())&&
- "Unexpected number of commas!");
- LHS = Actions.ActOnCallExpr(getCurScope(), LHS.get(), Loc,
- ArgExprs, Tok.getLocation(),
+ assert(
+ (ArgExprs.size() == 0 || ArgExprs.size() - 1 == CommaLocs.size()) &&
+ "Unexpected number of commas!");
+ Expr *Fn = LHS.get();
+ SourceLocation RParLoc = Tok.getLocation();
+ LHS = Actions.ActOnCallExpr(getCurScope(), Fn, Loc, ArgExprs, RParLoc,
ExecConfig);
+ if (LHS.isInvalid()) {
+ ArgExprs.insert(ArgExprs.begin(), Fn);
+ LHS =
+ Actions.CreateRecoveryExpr(Fn->getBeginLoc(), RParLoc, ArgExprs);
+ }
PT.consumeClose();
}
@@ -1972,15 +2113,22 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
return ParsePostfixExpressionSuffix(Base);
}
- LHS = Actions.ActOnStartCXXMemberReference(getCurScope(), Base,
- OpLoc, OpKind, ObjectType,
+ LHS = Actions.ActOnStartCXXMemberReference(getCurScope(), Base, OpLoc,
+ OpKind, ObjectType,
MayBePseudoDestructor);
- if (LHS.isInvalid())
+ if (LHS.isInvalid()) {
+ // Clang will try to perform expression based completion as a
+ // fallback, which is confusing in case of member references. So we
+ // stop here without any completions.
+ if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
+ return ExprError();
+ }
break;
-
- ParseOptionalCXXScopeSpecifier(SS, ObjectType,
- /*EnteringContext=*/false,
- &MayBePseudoDestructor);
+ }
+ ParseOptionalCXXScopeSpecifier(
+ SS, ObjectType, LHS.get() && LHS.get()->containsErrors(),
+ /*EnteringContext=*/false, &MayBePseudoDestructor);
if (SS.isNotEmpty())
ObjectType = nullptr;
}
@@ -2040,14 +2188,13 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
IdentifierInfo *Id = Tok.getIdentifierInfo();
SourceLocation Loc = ConsumeToken();
Name.setIdentifier(Id, Loc);
- } else if (ParseUnqualifiedId(SS,
- /*EnteringContext=*/false,
- /*AllowDestructorName=*/true,
- /*AllowConstructorName=*/
- getLangOpts().MicrosoftExt &&
- SS.isNotEmpty(),
- /*AllowDeductionGuide=*/false,
- ObjectType, &TemplateKWLoc, Name)) {
+ } else if (ParseUnqualifiedId(
+ SS, ObjectType, LHS.get() && LHS.get()->containsErrors(),
+ /*EnteringContext=*/false,
+ /*AllowDestructorName=*/true,
+ /*AllowConstructorName=*/
+ getLangOpts().MicrosoftExt && SS.isNotEmpty(),
+ /*AllowDeductionGuide=*/false, &TemplateKWLoc, Name)) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
LHS = ExprError();
}
@@ -2057,15 +2204,25 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
OpKind, SS, TemplateKWLoc, Name,
CurParsedObjCImpl ? CurParsedObjCImpl->Dcl
: nullptr);
- if (!LHS.isInvalid() && Tok.is(tok::less))
- checkPotentialAngleBracket(LHS);
+ if (!LHS.isInvalid()) {
+ if (Tok.is(tok::less))
+ checkPotentialAngleBracket(LHS);
+ } else if (OrigLHS && Name.isValid()) {
+ // Preserve the LHS if the RHS is an invalid member.
+ LHS = Actions.CreateRecoveryExpr(OrigLHS->getBeginLoc(),
+ Name.getEndLoc(), {OrigLHS});
+ }
break;
}
case tok::plusplus: // postfix-expression: postfix-expression '++'
case tok::minusminus: // postfix-expression: postfix-expression '--'
if (!LHS.isInvalid()) {
+ Expr *Arg = LHS.get();
LHS = Actions.ActOnPostfixUnaryOp(getCurScope(), Tok.getLocation(),
- Tok.getKind(), LHS.get());
+ Tok.getKind(), Arg);
+ if (LHS.isInvalid())
+ LHS = Actions.CreateRecoveryExpr(Arg->getBeginLoc(),
+ Tok.getLocation(), Arg);
}
ConsumeToken();
break;
@@ -2175,6 +2332,43 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
}
+ExprResult Parser::ParseUniqueStableNameExpression() {
+ assert(Tok.is(tok::kw___builtin_unique_stable_name) &&
+ "Not __bulitin_unique_stable_name");
+
+ SourceLocation OpLoc = ConsumeToken();
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+
+ // typeid expressions are always parenthesized.
+ if (T.expectAndConsume(diag::err_expected_lparen_after,
+ "__builtin_unique_stable_name"))
+ return ExprError();
+
+ if (isTypeIdInParens()) {
+ TypeResult Ty = ParseTypeName();
+ T.consumeClose();
+
+ if (Ty.isInvalid())
+ return ExprError();
+
+ return Actions.ActOnUniqueStableNameExpr(OpLoc, T.getOpenLocation(),
+ T.getCloseLocation(), Ty.get());
+ }
+
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::ExpressionEvaluationContext::Unevaluated);
+ ExprResult Result = ParseExpression();
+
+ if (Result.isInvalid()) {
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return Result;
+ }
+
+ T.consumeClose();
+ return Actions.ActOnUniqueStableNameExpr(OpLoc, T.getOpenLocation(),
+ T.getCloseLocation(), Result.get());
+}
+
/// Parse a sizeof or alignof expression.
///
/// \verbatim
@@ -2556,6 +2750,33 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
return ParsePostfixExpressionSuffix(Res.get());
}
+bool Parser::tryParseOpenMPArrayShapingCastPart() {
+ assert(Tok.is(tok::l_square) && "Expected open bracket");
+ bool ErrorFound = true;
+ TentativeParsingAction TPA(*this);
+ do {
+ if (Tok.isNot(tok::l_square))
+ break;
+ // Consume '['
+ ConsumeBracket();
+ // Skip inner expression.
+ while (!SkipUntil(tok::r_square, tok::annot_pragma_openmp_end,
+ StopAtSemi | StopBeforeMatch))
+ ;
+ if (Tok.isNot(tok::r_square))
+ break;
+ // Consume ']'
+ ConsumeBracket();
+ // Found ')' - done.
+ if (Tok.is(tok::r_paren)) {
+ ErrorFound = false;
+ break;
+ }
+ } while (Tok.isNot(tok::annot_pragma_openmp_end));
+ TPA.Revert();
+ return !ErrorFound;
+}
+
/// ParseParenExpression - This parses the unit that starts with a '(' token,
/// based on what is allowed by ExprType. The actual thing parsed is returned
/// in ExprType. If stopIfCastExpr is true, it will only return the parsed type,
@@ -2580,6 +2801,8 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
/// '(' '...' fold-operator cast-expression ')'
/// '(' cast-expression fold-operator '...'
/// fold-operator cast-expression ')'
+/// [OPENMP] Array shaping operation
+/// '(' '[' expression ']' { '[' expression ']' } cast-expression
/// \endverbatim
ExprResult
Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
@@ -2650,7 +2873,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// If the substmt parsed correctly, build the AST node.
if (!Stmt.isInvalid()) {
- Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.get(), Tok.getLocation());
+ Result = Actions.ActOnStmtExpr(getCurScope(), OpenLoc, Stmt.get(),
+ Tok.getLocation());
} else {
Actions.ActOnStmtExprError();
}
@@ -2685,7 +2909,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
PreferredType.enterTypeCast(Tok.getLocation(), Ty.get().get());
ExprResult SubExpr = ParseCastExpression(AnyCastExpr);
-
+
if (Ty.isInvalid() || SubExpr.isInvalid())
return ExprError();
@@ -2855,6 +3079,38 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),
ArgExprs);
}
+ } else if (getLangOpts().OpenMP >= 50 && OpenMPDirectiveParsing &&
+ ExprType == CastExpr && Tok.is(tok::l_square) &&
+ tryParseOpenMPArrayShapingCastPart()) {
+ bool ErrorFound = false;
+ SmallVector<Expr *, 4> OMPDimensions;
+ SmallVector<SourceRange, 4> OMPBracketsRanges;
+ do {
+ BalancedDelimiterTracker TS(*this, tok::l_square);
+ TS.consumeOpen();
+ ExprResult NumElements =
+ Actions.CorrectDelayedTyposInExpr(ParseExpression());
+ if (!NumElements.isUsable()) {
+ ErrorFound = true;
+ while (!SkipUntil(tok::r_square, tok::r_paren,
+ StopAtSemi | StopBeforeMatch))
+ ;
+ }
+ TS.consumeClose();
+ OMPDimensions.push_back(NumElements.get());
+ OMPBracketsRanges.push_back(TS.getRange());
+ } while (Tok.isNot(tok::r_paren));
+ // Match the ')'.
+ T.consumeClose();
+ RParenLoc = T.getCloseLocation();
+ Result = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
+ if (ErrorFound) {
+ Result = ExprError();
+ } else if (!Result.isInvalid()) {
+ Result = Actions.ActOnOMPArrayShapingExpr(
+ Result.get(), OpenLoc, RParenLoc, OMPDimensions, OMPBracketsRanges);
+ }
+ return Result;
} else {
InMessageExpressionRAIIObject InMessage(*this, false);
@@ -3123,6 +3379,16 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
if (Tok.is(tok::ellipsis))
Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());
+ else if (Tok.is(tok::code_completion)) {
+ // There's nothing to suggest in here as we parsed a full expression.
+ // Instead fail and propogate the error since caller might have something
+ // the suggest, e.g. signature help in function call. Note that this is
+ // performed before pushing the \p Expr, so that signature help can report
+ // current argument correctly.
+ SawError = true;
+ cutOffParsing();
+ break;
+ }
if (Expr.isInvalid()) {
SkipUntil(tok::comma, tok::r_paren, StopBeforeMatch);
SawError = true;