Commit 1f1af42d authored by caitpotter88's avatar caitpotter88 Committed by Commit bot

[parser] parenthesized Literals are not valid AssignmentPatterns

Encode "parenthesized" status of parenthesized Expressions to prevent
them from being treated as Patterns.

BUG=v8:4657, v8:811
LOG=N
R=rossberg@chromium.org, adamk@chromium.org, littledan@chromium.org

Review URL: https://codereview.chromium.org/1570793002

Cr-Commit-Position: refs/heads/master@{#33190}
parent 23235b5f
...@@ -365,6 +365,14 @@ class Expression : public AstNode { ...@@ -365,6 +365,14 @@ class Expression : public AstNode {
BailoutId id() const { return BailoutId(local_id(0)); } BailoutId id() const { return BailoutId(local_id(0)); }
TypeFeedbackId test_id() const { return TypeFeedbackId(local_id(1)); } TypeFeedbackId test_id() const { return TypeFeedbackId(local_id(1)); }
// Parenthesized expressions in the form `( Expression )`.
void set_is_parenthesized() {
bit_field_ = ParenthesizedField::update(bit_field_, true);
}
bool is_parenthesized() const {
return ParenthesizedField::decode(bit_field_);
}
protected: protected:
Expression(Zone* zone, int pos) Expression(Zone* zone, int pos)
: AstNode(pos), : AstNode(pos),
...@@ -387,6 +395,8 @@ class Expression : public AstNode { ...@@ -387,6 +395,8 @@ class Expression : public AstNode {
int base_id_; int base_id_;
Bounds bounds_; Bounds bounds_;
class ToBooleanTypesField : public BitField16<uint16_t, 0, 9> {}; class ToBooleanTypesField : public BitField16<uint16_t, 0, 9> {};
class ParenthesizedField
: public BitField16<bool, ToBooleanTypesField::kNext, 1> {};
uint16_t bit_field_; uint16_t bit_field_;
// Ends with 16-bit field; deriving classes in turn begin with // Ends with 16-bit field; deriving classes in turn begin with
// 16-bit fields for optimum packing efficiency. // 16-bit fields for optimum packing efficiency.
......
...@@ -1365,6 +1365,7 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, ...@@ -1365,6 +1365,7 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
Expect(Token::RPAREN, CHECK_OK); Expect(Token::RPAREN, CHECK_OK);
if (peek() != Token::ARROW) { if (peek() != Token::ARROW) {
ValidateExpression(classifier, CHECK_OK); ValidateExpression(classifier, CHECK_OK);
expr->set_is_parenthesized();
} }
return expr; return expr;
} }
...@@ -2041,7 +2042,8 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, int flags, ...@@ -2041,7 +2042,8 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, int flags,
ExpressionClassifier::CoverInitializedNameProduction); ExpressionClassifier::CoverInitializedNameProduction);
bool maybe_pattern = bool maybe_pattern =
expression->IsObjectLiteral() || expression->IsArrayLiteral(); (expression->IsObjectLiteral() || expression->IsArrayLiteral()) &&
!expression->is_parenthesized();
if (!Token::IsAssignmentOp(peek())) { if (!Token::IsAssignmentOp(peek())) {
// Parsed conditional expression only (no assignment). // Parsed conditional expression only (no assignment).
......
...@@ -2366,7 +2366,9 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context, ...@@ -2366,7 +2366,9 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
} }
} }
bool is_pattern = pattern->IsObjectLiteral() || pattern->IsArrayLiteral(); bool is_pattern =
(pattern->IsObjectLiteral() || pattern->IsArrayLiteral()) &&
!pattern->is_parenthesized();
Scanner::Location variable_loc = scanner()->location(); Scanner::Location variable_loc = scanner()->location();
const AstRawString* single_name = const AstRawString* single_name =
......
...@@ -591,7 +591,8 @@ PreParser::Statement PreParser::ParseVariableDeclarations( ...@@ -591,7 +591,8 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
} }
} }
is_pattern = pattern.IsObjectLiteral() || pattern.IsArrayLiteral(); is_pattern = (pattern.IsObjectLiteral() || pattern.IsArrayLiteral()) &&
!pattern.is_parenthesized();
bool is_for_iteration_variable = bool is_for_iteration_variable =
var_context == kForStatement && var_context == kForStatement &&
......
...@@ -279,6 +279,12 @@ class PreParserExpression { ...@@ -279,6 +279,12 @@ class PreParserExpression {
int position() const { return RelocInfo::kNoPosition; } int position() const { return RelocInfo::kNoPosition; }
void set_function_token_position(int position) {} void set_function_token_position(int position) {}
// Parenthesized expressions in the form `( Expression )`.
void set_is_parenthesized() {
code_ = ParenthesizedField::update(code_, true);
}
bool is_parenthesized() const { return ParenthesizedField::decode(code_); }
private: private:
enum Type { enum Type {
kExpression, kExpression,
...@@ -306,6 +312,13 @@ class PreParserExpression { ...@@ -306,6 +312,13 @@ class PreParserExpression {
// The first three bits are for the Type. // The first three bits are for the Type.
typedef BitField<Type, 0, 3> TypeField; typedef BitField<Type, 0, 3> TypeField;
// The high order bit applies only to nodes which would inherit from the
// Expression ASTNode --- This is by necessity, due to the fact that
// Expression nodes may be represented as multiple Types, not exclusively
// through kExpression.
// TODO(caitp, adamk): clean up PreParserExpression bitfields.
typedef BitField<bool, 31, 1> ParenthesizedField;
// The rest of the bits are interpreted depending on the value // The rest of the bits are interpreted depending on the value
// of the Type field, so they can share the storage. // of the Type field, so they can share the storage.
typedef BitField<ExpressionType, TypeField::kNext, 3> ExpressionTypeField; typedef BitField<ExpressionType, TypeField::kNext, 3> ExpressionTypeField;
......
...@@ -7043,6 +7043,21 @@ TEST(DestructuringAssignmentNegativeTests) { ...@@ -7043,6 +7043,21 @@ TEST(DestructuringAssignmentNegativeTests) {
"[...x,]", "[...x,]",
"[x, y, ...z = 1]", "[x, y, ...z = 1]",
"[...z = 1]", "[...z = 1]",
// v8:4657
"({ x: x4, x: (x+=1e4) })",
"(({ x: x4, x: (x+=1e4) }))",
"({ x: x4, x: (x+=1e4) } = {})",
"(({ x: x4, x: (x+=1e4) } = {}))",
"(({ x: x4, x: (x+=1e4) }) = {})",
"({ x: y } = {})",
"(({ x: y } = {}))",
"(({ x: y }) = {})",
"([a])",
"(([a]))",
"([a] = [])",
"(([a] = []))",
"(([a]) = [])",
NULL}; NULL};
// clang-format on // clang-format on
static const ParserFlag always_flags[] = { static const ParserFlag always_flags[] = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment