| Index: tools/gn/parse_tree.cc
|
| diff --git a/tools/gn/parse_tree.cc b/tools/gn/parse_tree.cc
|
| index bc50f201c2c617b0aca54df87ab6a6c1a0297c84..4015fd1f353149acfd0d610b5f7eddc3cf52c608 100644
|
| --- a/tools/gn/parse_tree.cc
|
| +++ b/tools/gn/parse_tree.cc
|
| @@ -53,6 +53,38 @@ const AccessorNode* AccessorNode::AsAccessor() const {
|
| }
|
|
|
| Value AccessorNode::Execute(Scope* scope, Err* err) const {
|
| + if (index_)
|
| + return ExecuteArrayAccess(scope, err);
|
| + else if (member_)
|
| + return ExecuteScopeAccess(scope, err);
|
| + NOTREACHED();
|
| + return Value();
|
| +}
|
| +
|
| +LocationRange AccessorNode::GetRange() const {
|
| + if (index_)
|
| + return LocationRange(base_.location(), index_->GetRange().end());
|
| + else if (member_)
|
| + return LocationRange(base_.location(), member_->GetRange().end());
|
| + NOTREACHED();
|
| + return LocationRange();
|
| +}
|
| +
|
| +Err AccessorNode::MakeErrorDescribing(const std::string& msg,
|
| + const std::string& help) const {
|
| + return Err(GetRange(), msg, help);
|
| +}
|
| +
|
| +void AccessorNode::Print(std::ostream& out, int indent) const {
|
| + out << IndentFor(indent) << "ACCESSOR\n";
|
| + out << IndentFor(indent + 1) << base_.value() << "\n";
|
| + if (index_)
|
| + index_->Print(out, indent + 1);
|
| + else if (member_)
|
| + member_->Print(out, indent + 1);
|
| +}
|
| +
|
| +Value AccessorNode::ExecuteArrayAccess(Scope* scope, Err* err) const {
|
| Value index_value = index_->Execute(scope, err);
|
| if (err->has_error())
|
| return Value();
|
| @@ -91,19 +123,46 @@ Value AccessorNode::Execute(Scope* scope, Err* err) const {
|
| return base_value->list_value()[index_sizet];
|
| }
|
|
|
| -LocationRange AccessorNode::GetRange() const {
|
| - return LocationRange(base_.location(), index_->GetRange().end());
|
| -}
|
| -
|
| -Err AccessorNode::MakeErrorDescribing(const std::string& msg,
|
| - const std::string& help) const {
|
| - return Err(GetRange(), msg, help);
|
| -}
|
| +Value AccessorNode::ExecuteScopeAccess(Scope* scope, Err* err) const {
|
| + // We jump through some hoops here since ideally a.b will count "b" as
|
| + // accessed in the given scope. The value "a" might be in some normal nested
|
| + // scope and we can modify it, but it might also be inherited from the
|
| + // readonly root scope and we can't do used variable tracking on it. (It's
|
| + // not legal to const cast it away since the root scope will be in readonly
|
| + // mode and being accessed from multiple threads without locking.) So this
|
| + // code handles both cases.
|
| + const Value* result = NULL;
|
| +
|
| + // Look up the value in the scope named by "base_".
|
| + Value* mutable_base_value = scope->GetMutableValue(base_.value(), true);
|
| + if (mutable_base_value) {
|
| + // Common case: base value is mutable so we can track variable accesses
|
| + // for unused value warnings.
|
| + if (!mutable_base_value->VerifyTypeIs(Value::SCOPE, err))
|
| + return Value();
|
| + result = mutable_base_value->scope_value()->GetValue(
|
| + member_->value().value(), true);
|
| + } else {
|
| + // Fall back to see if the value is on a read-only scope.
|
| + const Value* const_base_value = scope->GetValue(base_.value(), true);
|
| + if (const_base_value) {
|
| + // Read only value, don't try to mark the value access as a "used" one.
|
| + if (!const_base_value->VerifyTypeIs(Value::SCOPE, err))
|
| + return Value();
|
| + result =
|
| + const_base_value->scope_value()->GetValue(member_->value().value());
|
| + } else {
|
| + *err = Err(base_, "Undefined identifier.");
|
| + return Value();
|
| + }
|
| + }
|
|
|
| -void AccessorNode::Print(std::ostream& out, int indent) const {
|
| - out << IndentFor(indent) << "ACCESSOR\n";
|
| - out << IndentFor(indent + 1) << base_.value() << "\n";
|
| - index_->Print(out, indent + 1);
|
| + if (!result) {
|
| + *err = Err(member_.get(), "No value named \"" +
|
| + member_->value().value() + "\" in scope \"" + base_.value() + "\"");
|
| + return Value();
|
| + }
|
| + return *result;
|
| }
|
|
|
| // BinaryOpNode ---------------------------------------------------------------
|
|
|