Skip to content

Commit 11a101a

Browse files
committed
Canonicalize expressions that may be used as constants
Evaluate and canonicalize the parameters to the built-in function identical(a,b) if they are strings. This guarantees that identical(“ab”, “a”+”b”) evaluates to true. Note: when the parser parses “a”+”b”, it doesn’t know whether the expression will be used in a context that may require a constant value. The canonicalization is thus deferred until it is known that it is required. BUG=25024 [email protected] Review URL: https://codereview.chromium.org/1558033002 .
1 parent c0e374d commit 11a101a

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

runtime/vm/parser.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11202,6 +11202,26 @@ AstNode* Parser::ParseStaticCall(const Class& cls,
1120211202
// source.
1120311203
if (!FLAG_warn_on_javascript_compatibility || is_patch_source()) {
1120411204
ASSERT(num_arguments == 2);
11205+
11206+
// If both arguments are constant expressions of type string,
11207+
// evaluate and canonicalize them.
11208+
// This guarantees that identical("ab", "a"+"b") is true.
11209+
// An alternative way to guarantee this would be to introduce
11210+
// an AST node that canonicalizes a value.
11211+
AstNode* arg0 = arguments->NodeAt(0);
11212+
const Instance* val0 = arg0->EvalConstExpr();
11213+
if ((val0 != NULL) && (val0->IsString())) {
11214+
AstNode* arg1 = arguments->NodeAt(1);
11215+
const Instance* val1 = arg1->EvalConstExpr();
11216+
if ((val1 != NULL) && (val1->IsString())) {
11217+
arguments->SetNodeAt(0,
11218+
new(Z) LiteralNode(arg0->token_pos(),
11219+
EvaluateConstExpr(arg0->token_pos(), arg0)));
11220+
arguments->SetNodeAt(1,
11221+
new(Z) LiteralNode(arg1->token_pos(),
11222+
EvaluateConstExpr(arg1->token_pos(), arg1)));
11223+
}
11224+
}
1120511225
return new(Z) ComparisonNode(ident_pos,
1120611226
Token::kEQ_STRICT,
1120711227
arguments->NodeAt(0),

tests/language/const_string_test.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import "package:expect/expect.dart";
66

77
// Exercises compile-time string constants
88

9+
const yz = "y" + "z";
10+
911
main() {
1012
// Constant comparisons are independent of the quotes used.
1113
Expect.isTrue(identical("abcd", 'abcd'));
@@ -34,4 +36,16 @@ main() {
3436
Expect.isTrue(identical('a\'b\'cd', "a" "'b'" 'c' "d"));
3537
Expect.isTrue(identical('a"b"cd', 'a' '"b"' 'c' "d"));
3638
Expect.isTrue(identical("a\"b\"cd", 'a' '"b"' 'c' "d"));
39+
40+
const a = identical("ab", "a" + "b");
41+
Expect.isTrue(a);
42+
43+
const b = identical("xyz", "x" + yz);
44+
Expect.isTrue(b);
45+
46+
const c = identical("12", "1" "2");
47+
Expect.isTrue(c);
48+
49+
const d = identical("zyz", "z$yz");
50+
Expect.isTrue(d);
3751
}

0 commit comments

Comments
 (0)