summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/clang/lib/Parse/ParseExpr.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
committerpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
commitb773203fb58f3ef282fb69c832d8710cab5bc82d (patch)
treee75913f147570fbd75169647b144df85b88a038c /gnu/llvm/tools/clang/lib/Parse/ParseExpr.cpp
parenttweak errno in previous (diff)
downloadwireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.tar.xz
wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.zip
Import LLVM 7.0.1 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Parse/ParseExpr.cpp')
-rw-r--r--gnu/llvm/tools/clang/lib/Parse/ParseExpr.cpp344
1 files changed, 191 insertions, 153 deletions
diff --git a/gnu/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/gnu/llvm/tools/clang/lib/Parse/ParseExpr.cpp
index 1b8865edb79..2a65eec8a0f 100644
--- a/gnu/llvm/tools/clang/lib/Parse/ParseExpr.cpp
+++ b/gnu/llvm/tools/clang/lib/Parse/ParseExpr.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Provides the Expression parsing implementation.
+/// Provides the Expression parsing implementation.
///
/// Expressions in C99 basically consist of a bunch of binary operators with
/// unary operators and other random stuff at the leaves.
@@ -32,7 +32,7 @@
#include "llvm/ADT/SmallVector.h"
using namespace clang;
-/// \brief Simple precedence-based parser for binary/ternary operators.
+/// Simple precedence-based parser for binary/ternary operators.
///
/// Note: we diverge from the C99 grammar when parsing the assignment-expression
/// production. C99 specifies that the LHS of an assignment operator should be
@@ -156,7 +156,7 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
return ParseRHSOfBinaryExpression(LHS, prec::Comma);
}
-/// \brief Parse an expr that doesn't include (top-level) commas.
+/// Parse an expr that doesn't include (top-level) commas.
ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
@@ -175,7 +175,7 @@ ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) {
return ParseRHSOfBinaryExpression(LHS, prec::Assignment);
}
-/// \brief Parse an assignment expression where part of an Objective-C message
+/// Parse an assignment expression where part of an Objective-C message
/// send has already been parsed.
///
/// In this case \p LBracLoc indicates the location of the '[' of the message
@@ -217,7 +217,15 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) {
return ParseConstantExpressionInExprEvalContext(isTypeCast);
}
-/// \brief Parse a constraint-expression.
+ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) {
+ EnterExpressionEvaluationContext ConstantEvaluated(
+ Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+ ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
+ ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
+ return Actions.ActOnCaseExpr(CaseLoc, Res);
+}
+
+/// Parse a constraint-expression.
///
/// \verbatim
/// constraint-expression: [Concepts TS temp.constr.decl p1]
@@ -246,30 +254,6 @@ bool Parser::isNotExpressionStart() {
return isKnownToBeDeclarationSpecifier();
}
-/// We've parsed something that could plausibly be intended to be a template
-/// name (\p LHS) followed by a '<' token, and the following code can't possibly
-/// be an expression. Determine if this is likely to be a template-id and if so,
-/// diagnose it.
-bool Parser::diagnoseUnknownTemplateId(ExprResult LHS, SourceLocation Less) {
- TentativeParsingAction TPA(*this);
- // FIXME: We could look at the token sequence in a lot more detail here.
- if (SkipUntil(tok::greater, tok::greatergreater, tok::greatergreatergreater,
- StopAtSemi | StopBeforeMatch)) {
- TPA.Commit();
-
- SourceLocation Greater;
- ParseGreaterThanInTemplateList(Greater, true, false);
- Actions.diagnoseExprIntendedAsTemplateName(getCurScope(), LHS,
- Less, Greater);
- return true;
- }
-
- // There's no matching '>' token, this probably isn't supposed to be
- // interpreted as a template-id. Parse it as an (ill-formed) comparison.
- TPA.Revert();
- return false;
-}
-
bool Parser::isFoldOperator(prec::Level Level) const {
return Level > prec::Unknown && Level != prec::Conditional &&
Level != prec::Spaceship;
@@ -279,7 +263,7 @@ bool Parser::isFoldOperator(tok::TokenKind Kind) const {
return isFoldOperator(getBinOpPrecedence(Kind, GreaterThanIsOperator, true));
}
-/// \brief Parse a binary expression that starts with \p LHS and has a
+/// Parse a binary expression that starts with \p LHS and has a
/// precedence of at least \p MinPrec.
ExprResult
Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
@@ -302,6 +286,14 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
if (OpToken.is(tok::caretcaret)) {
return ExprError(Diag(Tok, diag::err_opencl_logical_exclusive_or));
}
+
+ // If we're potentially in a template-id, we may now be able to determine
+ // whether we're actually in one or not.
+ if (OpToken.isOneOf(tok::comma, tok::greater, tok::greatergreater,
+ tok::greatergreatergreater) &&
+ checkPotentialAngleBracketDelimiter(OpToken))
+ return ExprError();
+
// Bail out when encountering a comma followed by a token which can't
// possibly be the start of an expression. For instance:
// int f() { return 1, }
@@ -313,16 +305,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
return LHS;
}
- // If a '<' token is followed by a type that can be a template argument and
- // cannot be an expression, then this is ill-formed, but might be intended
- // to be a template-id.
- if (OpToken.is(tok::less) && Actions.mightBeIntendedToBeTemplateName(LHS) &&
- (isKnownToBeDeclarationSpecifier() ||
- Tok.isOneOf(tok::greater, tok::greatergreater,
- tok::greatergreatergreater)) &&
- diagnoseUnknownTemplateId(LHS, OpToken.getLocation()))
- return ExprError();
-
// If the next token is an ellipsis, then this is a fold-expression. Leave
// it alone so we can handle it in the paren expression.
if (isFoldOperator(NextTokPrec) && Tok.is(tok::ellipsis)) {
@@ -336,7 +318,17 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
// Special case handling for the ternary operator.
ExprResult TernaryMiddle(true);
if (NextTokPrec == prec::Conditional) {
- if (Tok.isNot(tok::colon)) {
+ if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
+ // Parse a braced-init-list here for error recovery purposes.
+ SourceLocation BraceLoc = Tok.getLocation();
+ TernaryMiddle = ParseBraceInitializer();
+ if (!TernaryMiddle.isInvalid()) {
+ Diag(BraceLoc, diag::err_init_list_bin_op)
+ << /*RHS*/ 1 << PP.getSpelling(OpToken)
+ << Actions.getExprRange(TernaryMiddle.get());
+ TernaryMiddle = ExprError();
+ }
+ } else if (Tok.isNot(tok::colon)) {
// Don't parse FOO:BAR as if it were a typo for FOO::BAR.
ColonProtectionRAIIObject X(*this);
@@ -345,11 +337,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
// In particular, the RHS of the '?' is 'expression', not
// 'logical-OR-expression' as we might expect.
TernaryMiddle = ParseExpression();
- if (TernaryMiddle.isInvalid()) {
- Actions.CorrectDelayedTyposInExpr(LHS);
- LHS = ExprError();
- TernaryMiddle = nullptr;
- }
} else {
// Special case handling of "X ? Y : Z" where Y is empty:
// logical-OR-expression '?' ':' conditional-expression [GNU]
@@ -357,6 +344,12 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
Diag(Tok, diag::ext_gnu_conditional_expr);
}
+ if (TernaryMiddle.isInvalid()) {
+ Actions.CorrectDelayedTyposInExpr(LHS);
+ LHS = ExprError();
+ TernaryMiddle = nullptr;
+ }
+
if (!TryConsumeToken(tok::colon, ColonLoc)) {
// Otherwise, we're missing a ':'. Assume that this was a typo that
// the user forgot. If we're not in a macro expansion, we can suggest
@@ -448,7 +441,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
// is okay, to bind exactly as tightly. For example, compile A=B=C=D as
// A=(B=(C=D)), where each paren is a level of recursion here.
// The function takes ownership of the RHS.
- RHS = ParseRHSOfBinaryExpression(RHS,
+ RHS = ParseRHSOfBinaryExpression(RHS,
static_cast<prec::Level>(ThisPrec + !isRightAssoc));
RHSIsInitList = false;
@@ -469,6 +462,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
if (ThisPrec == prec::Assignment) {
Diag(OpToken, diag::warn_cxx98_compat_generalized_initializer_lists)
<< Actions.getExprRange(RHS.get());
+ } else if (ColonLoc.isValid()) {
+ Diag(ColonLoc, diag::err_init_list_bin_op)
+ << /*RHS*/1 << ":"
+ << Actions.getExprRange(RHS.get());
+ LHS = ExprError();
} else {
Diag(OpToken, diag::err_init_list_bin_op)
<< /*RHS*/1 << PP.getSpelling(OpToken)
@@ -513,7 +511,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
}
}
-/// \brief Parse a cast-expression, or, if \p isUnaryExpression is true,
+/// Parse a cast-expression, or, if \p isUnaryExpression is true,
/// parse a unary-expression.
///
/// \p isAddressOfOperand exists because an id-expression that is the
@@ -570,7 +568,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
};
}
-/// \brief Parse a cast-expression, or, if \pisUnaryExpression is true, parse
+/// Parse a cast-expression, or, if \pisUnaryExpression is true, parse
/// a unary-expression.
///
/// \p isAddressOfOperand exists because an id-expression that is the operand
@@ -619,6 +617,8 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
/// [GNU] '__FUNCTION__'
/// [MS] '__FUNCDNAME__'
/// [MS] 'L__FUNCTION__'
+/// [MS] '__FUNCSIG__'
+/// [MS] 'L__FUNCSIG__'
/// [GNU] '__PRETTY_FUNCTION__'
/// [GNU] '(' compound-statement ')'
/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
@@ -656,14 +656,14 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
///
/// id-expression: [C++ 5.1]
/// unqualified-id
-/// qualified-id
+/// qualified-id
///
/// unqualified-id: [C++ 5.1]
/// identifier
/// operator-function-id
/// conversion-function-id
-/// '~' class-name
-/// template-id
+/// '~' class-name
+/// template-id
///
/// new-expression: [C++ 5.3.4]
/// '::'[opt] 'new' new-placement[opt] new-type-id
@@ -729,7 +729,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
/// '__trivially_copyable'
///
/// binary-type-trait:
-/// [GNU] '__is_base_of'
+/// [GNU] '__is_base_of'
/// [MS] '__is_convertible_to'
/// '__is_convertible'
/// '__is_same'
@@ -789,6 +789,10 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// We have parsed the cast-expression and no postfix-expr pieces are
// following.
return Res;
+ case FoldExpr:
+ // We only parsed a fold-expression. There might be postfix-expr pieces
+ // afterwards; parse them now.
+ break;
}
break;
@@ -807,7 +811,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw_false:
Res = ParseCXXBoolLiteral();
break;
-
+
case tok::kw___objc_yes:
case tok::kw___objc_no:
return ParseObjCBoolLiteral();
@@ -820,6 +824,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
assert(Res.get() == nullptr && "Stray primary-expression annotation?");
Res = getExprAnnotation(Tok);
ConsumeAnnotationToken();
+ if (!Res.isInvalid() && Tok.is(tok::less))
+ checkPotentialAngleBracket(Res);
break;
case tok::kw___super:
@@ -829,7 +835,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return ExprError();
assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super));
return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
-
+
case tok::identifier: { // primary-expression: identifier
// unqualified-id: identifier
// constant: enumeration-constant
@@ -951,14 +957,14 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return ExprError();
}
// Allow either an identifier or the keyword 'class' (in C++).
- if (Tok.isNot(tok::identifier) &&
+ if (Tok.isNot(tok::identifier) &&
!(getLangOpts().CPlusPlus && Tok.is(tok::kw_class))) {
Diag(Tok, diag::err_expected_property_name);
return ExprError();
}
IdentifierInfo &PropertyName = *Tok.getIdentifierInfo();
SourceLocation PropertyLoc = ConsumeToken();
-
+
Res = Actions.ActOnClassPropertyRefExpr(II, PropertyName,
ILoc, PropertyLoc);
break;
@@ -967,7 +973,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// In an Objective-C method, if we have "super" followed by an identifier,
// the token sequence is ill-formed. However, if there's a ':' or ']' after
// that identifier, this is probably a message send with a missing open
- // bracket. Treat it as such.
+ // bracket. Treat it as such.
if (getLangOpts().ObjC1 && &II == Ident_super && !InMessageExpression &&
getCurScope()->isInObjcMethodScope() &&
((Tok.is(tok::identifier) &&
@@ -977,17 +983,17 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
nullptr);
break;
}
-
+
// If we have an Objective-C class name followed by an identifier
// and either ':' or ']', this is an Objective-C class message
// send that's missing the opening '['. Recovery
// appropriately. Also take this path if we're performing code
// completion after an Objective-C class name.
- if (getLangOpts().ObjC1 &&
- ((Tok.is(tok::identifier) && !InMessageExpression) ||
+ if (getLangOpts().ObjC1 &&
+ ((Tok.is(tok::identifier) && !InMessageExpression) ||
Tok.is(tok::code_completion))) {
const Token& Next = NextToken();
- if (Tok.is(tok::code_completion) ||
+ if (Tok.is(tok::code_completion) ||
Next.is(tok::colon) || Next.is(tok::r_square))
if (ParsedType Typ = Actions.getTypeName(II, ILoc, getCurScope()))
if (Typ.get()->isObjCObjectOrInterfaceType()) {
@@ -999,24 +1005,24 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
unsigned DiagID;
DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ,
Actions.getASTContext().getPrintingPolicy());
-
+
Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
- TypeResult Ty = Actions.ActOnTypeName(getCurScope(),
+ TypeResult Ty = Actions.ActOnTypeName(getCurScope(),
DeclaratorInfo);
if (Ty.isInvalid())
break;
- Res = ParseObjCMessageExpressionBody(SourceLocation(),
- SourceLocation(),
+ Res = ParseObjCMessageExpressionBody(SourceLocation(),
+ SourceLocation(),
Ty.get(), nullptr);
break;
}
}
-
+
// Make sure to pass down the right value for isAddressOfOperand.
if (isAddressOfOperand && isPostfixExpressionSuffixStart())
isAddressOfOperand = false;
-
+
// Function designators are allowed to be undeclared (C99 6.5.1p2), so we
// need to know whether or not this identifier is a function designator or
// not.
@@ -1039,11 +1045,13 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
isAddressOfOperand, std::move(Validator),
/*IsInlineAsmIdentifier=*/false,
Tok.is(tok::r_paren) ? nullptr : &Replacement);
- if (!Res.isInvalid() && !Res.get()) {
+ if (!Res.isInvalid() && Res.isUnset()) {
UnconsumeToken(Replacement);
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
NotCastExpr, isTypeCast);
}
+ if (!Res.isInvalid() && Tok.is(tok::less))
+ checkPotentialAngleBracket(Res);
break;
}
case tok::char_constant: // constant: character-constant
@@ -1059,6 +1067,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw___FUNCDNAME__: // primary-expression: __FUNCDNAME__ [MS]
case tok::kw___FUNCSIG__: // primary-expression: __FUNCSIG__ [MS]
case tok::kw_L__FUNCTION__: // primary-expression: L__FUNCTION__ [MS]
+ case tok::kw_L__FUNCSIG__: // primary-expression: L__FUNCSIG__ [MS]
case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
ConsumeToken();
@@ -1170,7 +1179,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
if (getCurScope()->getFnParent() == nullptr)
return ExprError(Diag(Tok, diag::err_address_of_label_outside_fn));
-
+
Diag(AmpAmpLoc, diag::ext_gnu_address_of_label);
LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
Tok.getLocation());
@@ -1224,6 +1233,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::annot_decltype:
case tok::kw_char:
case tok::kw_wchar_t:
+ case tok::kw_char8_t:
case tok::kw_char16_t:
case tok::kw_char32_t:
case tok::kw_bool:
@@ -1374,7 +1384,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
T.consumeClose();
if (!Result.isInvalid())
- Result = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(),
+ Result = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(),
Result.get(), T.getCloseLocation());
return Result;
}
@@ -1383,7 +1393,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw_##Spelling:
#include "clang/Basic/TokenKinds.def"
return ParseTypeTrait();
-
+
case tok::kw___array_rank:
case tok::kw___array_extent:
return ParseArrayTypeTrait();
@@ -1391,7 +1401,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw___is_lvalue_expr:
case tok::kw___is_rvalue_expr:
return ParseExpressionTrait();
-
+
case tok::at: {
SourceLocation AtLoc = ConsumeToken();
return ParseObjCAtExpression(AtLoc);
@@ -1449,7 +1459,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return Res;
}
-/// \brief Once the leading part of a postfix-expression is parsed, this
+/// Once the leading part of a postfix-expression is parsed, this
/// method parses any suffixes that apply.
///
/// \verbatim
@@ -1479,16 +1489,16 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
case tok::code_completion:
if (InMessageExpression)
return LHS;
-
+
Actions.CodeCompletePostfixExpression(getCurScope(), LHS);
cutOffParsing();
return ExprError();
-
+
case tok::identifier:
// If we see identifier: after an expression, and we're not already in a
// message send, then this is probably a message send with a missing
// opening bracket '['.
- if (getLangOpts().ObjC1 && !InMessageExpression &&
+ if (getLangOpts().ObjC1 && !InMessageExpression &&
(NextToken().is(tok::colon) || NextToken().is(tok::r_square))) {
LHS = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),
nullptr, LHS.get());
@@ -1610,8 +1620,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (!LHS.isInvalid()) {
ExprResult ECResult = Actions.ActOnCUDAExecConfigExpr(getCurScope(),
- OpenLoc,
- ExecConfigExprs,
+ OpenLoc,
+ ExecConfigExprs,
CloseLoc);
if (ECResult.isInvalid())
LHS = ExprError();
@@ -1625,7 +1635,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
ExprVector ArgExprs;
CommaLocsTy CommaLocs;
-
+
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteCall(getCurScope(), LHS.get(), None);
cutOffParsing();
@@ -1665,7 +1675,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
PT.consumeClose();
LHS = ExprError();
} else {
- assert((ArgExprs.size() == 0 ||
+ assert((ArgExprs.size() == 0 ||
ArgExprs.size()-1 == CommaLocs.size())&&
"Unexpected number of commas!");
LHS = Actions.ActOnCallExpr(getCurScope(), LHS.get(), Loc,
@@ -1686,8 +1696,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
CXXScopeSpec SS;
ParsedType ObjectType;
bool MayBePseudoDestructor = false;
+ Expr* OrigLHS = !LHS.isInvalid() ? LHS.get() : nullptr;
+
if (getLangOpts().CPlusPlus && !LHS.isInvalid()) {
- Expr *Base = LHS.get();
+ Expr *Base = OrigLHS;
const Type* BaseType = Base->getType().getTypePtrOrNull();
if (BaseType && Tok.is(tok::l_paren) &&
(BaseType->isFunctionType() ||
@@ -1704,7 +1716,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (LHS.isInvalid())
break;
- ParseOptionalCXXScopeSpecifier(SS, ObjectType,
+ ParseOptionalCXXScopeSpecifier(SS, ObjectType,
/*EnteringContext=*/false,
&MayBePseudoDestructor);
if (SS.isNotEmpty())
@@ -1712,18 +1724,32 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
}
if (Tok.is(tok::code_completion)) {
+ tok::TokenKind CorrectedOpKind =
+ OpKind == tok::arrow ? tok::period : tok::arrow;
+ ExprResult CorrectedLHS(/*IsInvalid=*/true);
+ if (getLangOpts().CPlusPlus && OrigLHS) {
+ const bool DiagsAreSuppressed = Diags.getSuppressAllDiagnostics();
+ Diags.setSuppressAllDiagnostics(true);
+ CorrectedLHS = Actions.ActOnStartCXXMemberReference(
+ getCurScope(), OrigLHS, OpLoc, CorrectedOpKind, ObjectType,
+ MayBePseudoDestructor);
+ Diags.setSuppressAllDiagnostics(DiagsAreSuppressed);
+ }
+
+ Expr *Base = LHS.get();
+ Expr *CorrectedBase = CorrectedLHS.get();
+
// Code completion for a member access expression.
- if (Expr *Base = LHS.get())
- Actions.CodeCompleteMemberReferenceExpr(
- getCurScope(), Base, OpLoc, OpKind == tok::arrow,
- ExprStatementTokLoc == Base->getLocStart());
+ Actions.CodeCompleteMemberReferenceExpr(
+ getCurScope(), Base, CorrectedBase, OpLoc, OpKind == tok::arrow,
+ Base && ExprStatementTokLoc == Base->getLocStart());
cutOffParsing();
return ExprError();
}
if (MayBePseudoDestructor && !LHS.isInvalid()) {
- LHS = ParseCXXPseudoDestructor(LHS.get(), OpLoc, OpKind, SS,
+ LHS = ParseCXXPseudoDestructor(LHS.get(), OpLoc, OpKind, SS,
ObjectType);
break;
}
@@ -1744,27 +1770,29 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
// 'class' as if it were an identifier.
//
// This hack allows property access to the 'class' method because it is
- // such a common method name. For other C++ keywords that are
+ // such a common method name. For other C++ keywords that are
// Objective-C method names, one must use the message send syntax.
IdentifierInfo *Id = Tok.getIdentifierInfo();
SourceLocation Loc = ConsumeToken();
Name.setIdentifier(Id, Loc);
- } else if (ParseUnqualifiedId(SS,
- /*EnteringContext=*/false,
+ } else if (ParseUnqualifiedId(SS,
+ /*EnteringContext=*/false,
/*AllowDestructorName=*/true,
/*AllowConstructorName=*/
- getLangOpts().MicrosoftExt,
+ getLangOpts().MicrosoftExt,
/*AllowDeductionGuide=*/false,
- ObjectType, TemplateKWLoc, Name)) {
+ ObjectType, &TemplateKWLoc, Name)) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
LHS = ExprError();
}
-
+
if (!LHS.isInvalid())
- LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc,
+ LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc,
OpKind, SS, TemplateKWLoc, Name,
CurParsedObjCImpl ? CurParsedObjCImpl->Dcl
: nullptr);
+ if (!LHS.isInvalid() && Tok.is(tok::less))
+ checkPotentialAngleBracket(LHS);
break;
}
case tok::plusplus: // postfix-expression: postfix-expression '++'
@@ -1854,7 +1882,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
ParenParseOption ExprType = CastExpr;
SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
- Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
+ Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
false, CastTy, RParenLoc);
CastRange = SourceRange(LParenLoc, RParenLoc);
@@ -1868,7 +1896,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
if (getLangOpts().CPlusPlus || OpTok.isNot(tok::kw_typeof)) {
// GNU typeof in C requires the expression to be parenthesized. Not so for
// sizeof/alignof or in C++. Therefore, the parenthesized expression is
- // the start of a unary-expression, but doesn't include any postfix
+ // the start of a unary-expression, but doesn't include any postfix
// pieces. Parse these now if present.
if (!Operand.isInvalid())
Operand = ParsePostfixExpressionSuffix(Operand.get());
@@ -1881,7 +1909,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
}
-/// \brief Parse a sizeof or alignof expression.
+/// Parse a sizeof or alignof expression.
///
/// \verbatim
/// unary-expression: [C99 6.5.3]
@@ -1934,7 +1962,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
} else {
Diag(Tok, diag::err_sizeof_parameter_pack);
}
-
+
if (!Name)
return ExprError();
@@ -1943,7 +1971,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
Sema::ReuseLambdaContextDecl);
return Actions.ActOnSizeofParameterPackExpr(getCurScope(),
- OpTok.getLocation(),
+ OpTok.getLocation(),
*Name, NameLoc,
RParenLoc);
}
@@ -2178,15 +2206,15 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
TypeResult DestTy = ParseTypeName();
if (DestTy.isInvalid())
return ExprError();
-
+
// Attempt to consume the r-paren.
if (Tok.isNot(tok::r_paren)) {
Diag(Tok, diag::err_expected) << tok::r_paren;
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
-
- Res = Actions.ActOnAsTypeExpr(Expr.get(), DestTy.get(), StartLoc,
+
+ Res = Actions.ActOnAsTypeExpr(Expr.get(), DestTy.get(), StartLoc,
ConsumeParen());
break;
}
@@ -2207,15 +2235,15 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
TypeResult DestTy = ParseTypeName();
if (DestTy.isInvalid())
return ExprError();
-
+
// Attempt to consume the r-paren.
if (Tok.isNot(tok::r_paren)) {
Diag(Tok, diag::err_expected) << tok::r_paren;
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
-
- Res = Actions.ActOnConvertVectorExpr(Expr.get(), DestTy.get(), StartLoc,
+
+ Res = Actions.ActOnConvertVectorExpr(Expr.get(), DestTy.get(), StartLoc,
ConsumeParen());
break;
}
@@ -2270,7 +2298,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
CastTy = nullptr;
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteOrdinaryName(getCurScope(),
+ Actions.CodeCompleteOrdinaryName(getCurScope(),
ExprType >= CompoundLiteral? Sema::PCC_ParenthesizedExpression
: Sema::PCC_Expression);
cutOffParsing();
@@ -2294,7 +2322,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
}
BridgeCast = false;
}
-
+
// None of these cases should fall through with an invalid Result
// unless they've already reported an error.
if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
@@ -2348,16 +2376,16 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
<< FixItHint::CreateReplacement(BridgeKeywordLoc,
"__bridge_retained");
}
-
+
TypeResult Ty = ParseTypeName();
T.consumeClose();
ColonProtection.restore();
RParenLoc = T.getCloseLocation();
ExprResult SubExpr = ParseCastExpression(/*isUnaryExpression=*/false);
-
+
if (Ty.isInvalid() || SubExpr.isInvalid())
return ExprError();
-
+
return Actions.ActOnObjCBridgedCast(getCurScope(), OpenLoc, Kind,
BridgeKeywordLoc, Ty.get(),
RParenLoc, SubExpr.get());
@@ -2383,8 +2411,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
ParseSpecifierQualifierList(DS);
Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
ParseDeclarator(DeclaratorInfo);
-
- // If our type is followed by an identifier and either ':' or ']', then
+
+ // If our type is followed by an identifier and either ':' or ']', then
// this is probably an Objective-C message send where the leading '[' is
// missing. Recover as if that were the case.
if (!DeclaratorInfo.isInvalidType() && Tok.is(tok::identifier) &&
@@ -2395,10 +2423,10 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
InMessageExpressionRAIIObject InMessage(*this, false);
Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
}
- Result = ParseObjCMessageExpressionBody(SourceLocation(),
- SourceLocation(),
+ Result = ParseObjCMessageExpressionBody(SourceLocation(),
+ SourceLocation(),
Ty.get(), nullptr);
- } else {
+ } else {
// Match the ')'.
T.consumeClose();
ColonProtection.restore();
@@ -2475,7 +2503,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// Reject the cast of super idiom in ObjC.
if (Tok.is(tok::identifier) && getLangOpts().ObjC1 &&
- Tok.getIdentifierInfo() == Ident_super &&
+ Tok.getIdentifierInfo() == Ident_super &&
getCurScope()->isInObjcMethodScope() &&
GetLookAheadToken(1).isNot(tok::period)) {
Diag(Tok.getLocation(), diag::err_illegal_super_cast)
@@ -2490,7 +2518,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
/*isTypeCast=*/IsTypeCast);
if (!Result.isInvalid()) {
Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc,
- DeclaratorInfo, CastTy,
+ DeclaratorInfo, CastTy,
RParenLoc, Result.get());
}
return Result;
@@ -2499,8 +2527,9 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
return ExprError();
}
- } else if (Tok.is(tok::ellipsis) &&
+ } else if (ExprType >= FoldExpr && Tok.is(tok::ellipsis) &&
isFoldOperator(NextToken().getKind())) {
+ ExprType = FoldExpr;
return ParseFoldExpression(ExprResult(), T);
} else if (isTypeCast) {
// Parse the expression-list.
@@ -2512,9 +2541,11 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
if (!ParseSimpleExpressionList(ArgExprs, CommaLocs)) {
// FIXME: If we ever support comma expressions as operands to
// fold-expressions, we'll need to allow multiple ArgExprs here.
- if (ArgExprs.size() == 1 && isFoldOperator(Tok.getKind()) &&
- NextToken().is(tok::ellipsis))
+ if (ExprType >= FoldExpr && ArgExprs.size() == 1 &&
+ isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) {
+ ExprType = FoldExpr;
return ParseFoldExpression(ArgExprs[0], T);
+ }
ExprType = SimpleExpr;
Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),
@@ -2529,10 +2560,13 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// expressions are parsed correctly.
Result = Actions.CorrectDelayedTyposInExpr(Result);
}
- ExprType = SimpleExpr;
- if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis))
+ if (ExprType >= FoldExpr && isFoldOperator(Tok.getKind()) &&
+ NextToken().is(tok::ellipsis)) {
+ ExprType = FoldExpr;
return ParseFoldExpression(Result, T);
+ }
+ ExprType = SimpleExpr;
// Don't build a paren expression unless we actually match a ')'.
if (!Result.isInvalid() && Tok.is(tok::r_paren))
@@ -2688,13 +2722,13 @@ ExprResult Parser::ParseGenericSelectionExpression() {
if (T.getCloseLocation().isInvalid())
return ExprError();
- return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc,
+ return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc,
T.getCloseLocation(),
ControllingExpr.get(),
Types, Exprs);
}
-/// \brief Parse A C++1z fold-expression after the opening paren and optional
+/// Parse A C++1z fold-expression after the opening paren and optional
/// left-hand-side expression.
///
/// \verbatim
@@ -2791,7 +2825,7 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
Expr = ParseAssignmentExpression();
if (Tok.is(tok::ellipsis))
- Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());
+ Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());
if (Expr.isInvalid()) {
SkipUntil(tok::comma, tok::r_paren, StopBeforeMatch);
SawError = true;
@@ -2802,7 +2836,10 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
if (Tok.isNot(tok::comma))
break;
// Move to the next argument, remember where the comma was.
+ Token Comma = Tok;
CommaLocs.push_back(ConsumeToken());
+
+ checkPotentialAngleBracketDelimiter(Comma);
}
if (SawError) {
// Ensure typos get diagnosed when errors were encountered while parsing the
@@ -2837,7 +2874,10 @@ Parser::ParseSimpleExpressionList(SmallVectorImpl<Expr*> &Exprs,
return false;
// Move to the next argument, remember where the comma was.
+ Token Comma = Tok;
CommaLocs.push_back(ConsumeToken());
+
+ checkPotentialAngleBracketDelimiter(Comma);
}
}
@@ -2852,7 +2892,7 @@ void Parser::ParseBlockId(SourceLocation CaretLoc) {
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type);
return cutOffParsing();
}
-
+
// Parse the specifier-qualifier-list piece.
DeclSpec DS(AttrFactory);
ParseSpecifierQualifierList(DS);
@@ -2929,33 +2969,31 @@ ExprResult Parser::ParseBlockLiteralExpression() {
ParseBlockId(CaretLoc);
} else {
// Otherwise, pretend we saw (void).
- ParsedAttributes attrs(AttrFactory);
SourceLocation NoLoc;
- ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/true,
- /*IsAmbiguous=*/false,
- /*RParenLoc=*/NoLoc,
- /*ArgInfo=*/nullptr,
- /*NumArgs=*/0,
- /*EllipsisLoc=*/NoLoc,
- /*RParenLoc=*/NoLoc,
- /*TypeQuals=*/0,
- /*RefQualifierIsLvalueRef=*/true,
- /*RefQualifierLoc=*/NoLoc,
- /*ConstQualifierLoc=*/NoLoc,
- /*VolatileQualifierLoc=*/NoLoc,
- /*RestrictQualifierLoc=*/NoLoc,
- /*MutableLoc=*/NoLoc,
- EST_None,
- /*ESpecRange=*/SourceRange(),
- /*Exceptions=*/nullptr,
- /*ExceptionRanges=*/nullptr,
- /*NumExceptions=*/0,
- /*NoexceptExpr=*/nullptr,
- /*ExceptionSpecTokens=*/nullptr,
- /*DeclsInPrototype=*/None,
- CaretLoc, CaretLoc,
- ParamInfo),
- attrs, CaretLoc);
+ ParamInfo.AddTypeInfo(
+ DeclaratorChunk::getFunction(/*HasProto=*/true,
+ /*IsAmbiguous=*/false,
+ /*RParenLoc=*/NoLoc,
+ /*ArgInfo=*/nullptr,
+ /*NumArgs=*/0,
+ /*EllipsisLoc=*/NoLoc,
+ /*RParenLoc=*/NoLoc,
+ /*TypeQuals=*/0,
+ /*RefQualifierIsLvalueRef=*/true,
+ /*RefQualifierLoc=*/NoLoc,
+ /*ConstQualifierLoc=*/NoLoc,
+ /*VolatileQualifierLoc=*/NoLoc,
+ /*RestrictQualifierLoc=*/NoLoc,
+ /*MutableLoc=*/NoLoc, EST_None,
+ /*ESpecRange=*/SourceRange(),
+ /*Exceptions=*/nullptr,
+ /*ExceptionRanges=*/nullptr,
+ /*NumExceptions=*/0,
+ /*NoexceptExpr=*/nullptr,
+ /*ExceptionSpecTokens=*/nullptr,
+ /*DeclsInPrototype=*/None, CaretLoc,
+ CaretLoc, ParamInfo),
+ CaretLoc);
MaybeParseGNUAttributes(ParamInfo);