Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Unified Diff: src/scopes.cc

Issue 968263002: [strong] Fix scoping related errors for methods. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: code review (arv@) Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/scopes.cc
diff --git a/src/scopes.cc b/src/scopes.cc
index 97a89431f39e1e824acda5d8d3a85c46df568c3c..4e7b14b46fac6bc4385cc230ab93d6383f7e73ff 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -798,6 +798,8 @@ static const char* Header(ScopeType scope_type) {
case BLOCK_SCOPE: return "block";
case WITH_SCOPE: return "with";
case ARROW_SCOPE: return "arrow";
+ case CLASS_SCOPE:
+ return "class";
rossberg 2015/03/04 10:39:27 Nit: format like others.
marja 2015/03/04 11:14:38 clang-format wants it this way :/ Instead, formatt
rossberg 2015/03/04 12:39:33 I wish we would just fracking nuke this clang-form
}
UNREACHABLE();
return NULL;
@@ -1070,29 +1072,7 @@ bool Scope::ResolveVariable(CompilationInfo* info, VariableProxy* proxy,
case BOUND:
// We found a variable binding.
if (is_strong(language_mode())) {
- // Check for declaration-after use (for variables) in strong mode. Note
- // that we can only do this in the case where we have seen the
- // declaration. And we always allow referencing functions (for now).
-
- // If both the use and the declaration are inside an eval scope
- // (possibly indirectly), or one of them is, we need to check whether
- // they are inside the same eval scope or different
- // ones.
-
- // TODO(marja,rossberg): Detect errors across different evals (depends
- // on the future of eval in strong mode).
- const Scope* eval_for_use = NearestOuterEvalScope();
- const Scope* eval_for_declaration =
- var->scope()->NearestOuterEvalScope();
-
- if (proxy->position() != RelocInfo::kNoPosition &&
- proxy->position() < var->initializer_position() &&
- !var->is_function() && eval_for_use == eval_for_declaration) {
- DCHECK(proxy->end_position() != RelocInfo::kNoPosition);
- ReportMessage(proxy->position(), proxy->end_position(),
- "strong_use_before_declaration", proxy->raw_name());
- return false;
- }
+ if (!CheckStrongModeDeclaration(proxy, var)) return false;
}
break;
@@ -1137,6 +1117,50 @@ bool Scope::ResolveVariable(CompilationInfo* info, VariableProxy* proxy,
}
+bool Scope::CheckStrongModeDeclaration(VariableProxy* proxy, Variable* var) {
+ // Check for declaration-after use (for variables) in strong mode. Note that
+ // we can only do this in the case where we have seen the declaration. And we
+ // always allow referencing functions (for now).
+
+ // If both the use and the declaration are inside an eval scope (possibly
+ // indirectly), or one of them is, we need to check whether they are inside
+ // the same eval scope or different ones.
+
+ // TODO(marja,rossberg): Detect errors across different evals (depends on the
+ // future of eval in strong mode).
+ const Scope* eval_for_use = NearestOuterEvalScope();
+ const Scope* eval_for_declaration = var->scope()->NearestOuterEvalScope();
+
+ // Allow referencing the class name from methods, even though the initializer
+ // position for class names is only after the body. Note that the only
+ // variable declared in the class scope is the class name.
+ bool legal_class_name_reference = false;
+ if (var->scope()->is_class_scope()) {
+ // Referencing the class name is only allowed inside methods of that class.
+ Scope* scope = this;
+ bool found_method_scope = false;
+ while (scope && !found_method_scope && scope != var->scope()) {
+ if (scope->is_function_scope() && scope->outer_scope_ == var->scope()) {
+ found_method_scope = true;
rossberg 2015/03/04 10:39:27 Can't we simplify the logic by returning true here
marja 2015/03/04 11:14:38 Done.
+ break;
+ }
+ scope = scope->outer_scope();
+ }
+ legal_class_name_reference = found_method_scope;
+ }
+
+ if (proxy->position() != RelocInfo::kNoPosition &&
+ proxy->position() < var->initializer_position() && !var->is_function() &&
+ eval_for_use == eval_for_declaration && !legal_class_name_reference) {
+ DCHECK(proxy->end_position() != RelocInfo::kNoPosition);
+ ReportMessage(proxy->position(), proxy->end_position(),
+ "strong_use_before_declaration", proxy->raw_name());
+ return false;
+ }
+ return true;
+}
+
+
bool Scope::ResolveVariablesRecursively(CompilationInfo* info,
AstNodeFactory* factory) {
DCHECK(info->script_scope()->is_script_scope());
@@ -1201,7 +1225,8 @@ bool Scope::MustAllocate(Variable* var) {
if ((var->is_this() || var->is_new_target() || !var->raw_name()->IsEmpty()) &&
(var->has_forced_context_allocation() || scope_calls_eval_ ||
inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() ||
- is_block_scope() || is_module_scope() || is_script_scope())) {
+ is_block_scope() || is_class_scope() || is_module_scope() ||
+ is_script_scope())) {
var->set_is_used();
if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned();
}
@@ -1223,7 +1248,10 @@ bool Scope::MustAllocateInContext(Variable* var) {
if (has_forced_context_allocation()) return true;
if (var->mode() == TEMPORARY) return false;
if (var->mode() == INTERNAL) return true;
- if (is_catch_scope() || is_block_scope() || is_module_scope()) return true;
+ if (is_catch_scope() || is_block_scope() || is_class_scope() ||
+ is_module_scope()) {
+ return true;
+ }
if (is_script_scope() && IsLexicalVariableMode(var->mode())) return true;
return var->has_forced_context_allocation() ||
scope_calls_eval_ ||

Powered by Google App Engine
This is Rietveld 408576698