parent
41b87b039a
commit
f4a1a5cfc0
@ -0,0 +1,324 @@
|
|||||||
|
diff -up chromium-74.0.3729.169/base/values.cc.2f28731 chromium-74.0.3729.169/base/values.cc
|
||||||
|
--- chromium-74.0.3729.169/base/values.cc.2f28731 2019-05-31 15:03:32.200591044 -0400
|
||||||
|
+++ chromium-74.0.3729.169/base/values.cc 2019-05-31 15:13:39.546036829 -0400
|
||||||
|
@@ -12,6 +12,7 @@
|
||||||
|
#include <ostream>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
+#include "base/bit_cast.h"
|
||||||
|
#include "base/json/json_writer.h"
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "base/memory/ptr_util.h"
|
||||||
|
@@ -36,6 +37,9 @@ static_assert(std::is_standard_layout<Va
|
||||||
|
"base::Value should be a standard-layout C++ class in order "
|
||||||
|
"to avoid undefined behaviour in its implementation!");
|
||||||
|
|
||||||
|
+static_assert(sizeof(Value::DoubleStorage) == sizeof(double),
|
||||||
|
+ "The double and DoubleStorage types should have the same size");
|
||||||
|
+
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const char* const kTypeNames[] = {"null", "boolean", "integer", "double",
|
||||||
|
@@ -110,8 +114,6 @@ Value::Value(Value&& that) noexcept {
|
||||||
|
InternalMoveConstructFrom(std::move(that));
|
||||||
|
}
|
||||||
|
|
||||||
|
-Value::Value() noexcept : type_(Type::NONE) {}
|
||||||
|
-
|
||||||
|
Value::Value(Type type) : type_(type) {
|
||||||
|
// Initialize with the default value.
|
||||||
|
switch (type_) {
|
||||||
|
@@ -125,7 +127,7 @@ Value::Value(Type type) : type_(type) {
|
||||||
|
int_value_ = 0;
|
||||||
|
return;
|
||||||
|
case Type::DOUBLE:
|
||||||
|
- double_value_ = 0.0;
|
||||||
|
+ double_value_ = bit_cast<DoubleStorage>(0.0);
|
||||||
|
return;
|
||||||
|
case Type::STRING:
|
||||||
|
new (&string_value_) std::string();
|
||||||
|
@@ -149,21 +151,16 @@ Value::Value(Type type) : type_(type) {
|
||||||
|
CHECK(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
-Value::Value(bool in_bool)
|
||||||
|
- : bool_type_(Type::BOOLEAN),
|
||||||
|
- bool_value_(in_bool) {}
|
||||||
|
-
|
||||||
|
-Value::Value(int in_int)
|
||||||
|
- : int_type_(Type::INTEGER),
|
||||||
|
- int_value_(in_int) {}
|
||||||
|
+Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {}
|
||||||
|
+
|
||||||
|
+Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {}
|
||||||
|
|
||||||
|
Value::Value(double in_double)
|
||||||
|
- : double_type_(Type::DOUBLE),
|
||||||
|
- double_value_(in_double) {
|
||||||
|
- if (!std::isfinite(double_value_)) {
|
||||||
|
+ : type_(Type::DOUBLE), double_value_(bit_cast<DoubleStorage>(in_double)) {
|
||||||
|
+ if (!std::isfinite(in_double)) {
|
||||||
|
NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
|
||||||
|
<< "values cannot be represented in JSON";
|
||||||
|
- double_value_ = 0.0;
|
||||||
|
+ double_value_ = bit_cast<DoubleStorage>(0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -172,8 +169,7 @@ Value::Value(const char* in_string) : Va
|
||||||
|
Value::Value(StringPiece in_string) : Value(std::string(in_string)) {}
|
||||||
|
|
||||||
|
Value::Value(std::string&& in_string) noexcept
|
||||||
|
- : string_type_(Type::STRING),
|
||||||
|
- string_value_(std::move(in_string)) {
|
||||||
|
+ : type_(Type::STRING), string_value_(std::move(in_string)) {
|
||||||
|
DCHECK(IsStringUTF8(string_value_));
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -182,19 +178,15 @@ Value::Value(const char16* in_string16)
|
||||||
|
Value::Value(StringPiece16 in_string16) : Value(UTF16ToUTF8(in_string16)) {}
|
||||||
|
|
||||||
|
Value::Value(const std::vector<char>& in_blob)
|
||||||
|
- : binary_type_(Type::BINARY),
|
||||||
|
- binary_value_(in_blob.begin(), in_blob.end()) {}
|
||||||
|
+ : type_(Type::BINARY), binary_value_(in_blob.begin(), in_blob.end()) {}
|
||||||
|
|
||||||
|
Value::Value(base::span<const uint8_t> in_blob)
|
||||||
|
- : binary_type_(Type::BINARY),
|
||||||
|
- binary_value_(in_blob.begin(), in_blob.end()) {}
|
||||||
|
+ : type_(Type::BINARY), binary_value_(in_blob.begin(), in_blob.end()) {}
|
||||||
|
|
||||||
|
Value::Value(BlobStorage&& in_blob) noexcept
|
||||||
|
- : binary_type_(Type::BINARY),
|
||||||
|
- binary_value_(std::move(in_blob)) {}
|
||||||
|
+ : type_(Type::BINARY), binary_value_(std::move(in_blob)) {}
|
||||||
|
|
||||||
|
-Value::Value(const DictStorage& in_dict)
|
||||||
|
- : dict_type_(Type::DICTIONARY), dict_() {
|
||||||
|
+Value::Value(const DictStorage& in_dict) : type_(Type::DICTIONARY), dict_() {
|
||||||
|
dict_.reserve(in_dict.size());
|
||||||
|
for (const auto& it : in_dict) {
|
||||||
|
dict_.try_emplace(dict_.end(), it.first,
|
||||||
|
@@ -203,18 +195,16 @@ Value::Value(const DictStorage& in_dict)
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::Value(DictStorage&& in_dict) noexcept
|
||||||
|
- : dict_type_(Type::DICTIONARY),
|
||||||
|
- dict_(std::move(in_dict)) {}
|
||||||
|
+ : type_(Type::DICTIONARY), dict_(std::move(in_dict)) {}
|
||||||
|
|
||||||
|
-Value::Value(const ListStorage& in_list) : list_type_(Type::LIST), list_() {
|
||||||
|
+Value::Value(const ListStorage& in_list) : type_(Type::LIST), list_() {
|
||||||
|
list_.reserve(in_list.size());
|
||||||
|
for (const auto& val : in_list)
|
||||||
|
list_.emplace_back(val.Clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::Value(ListStorage&& in_list) noexcept
|
||||||
|
- : list_type_(Type::LIST),
|
||||||
|
- list_(std::move(in_list)) {}
|
||||||
|
+ : type_(Type::LIST), list_(std::move(in_list)) {}
|
||||||
|
|
||||||
|
Value& Value::operator=(Value&& that) noexcept {
|
||||||
|
InternalCleanup();
|
||||||
|
@@ -223,6 +213,10 @@ Value& Value::operator=(Value&& that) no
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
+double Value::AsDoubleInternal() const {
|
||||||
|
+ return bit_cast<double>(double_value_);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
Value Value::Clone() const {
|
||||||
|
switch (type_) {
|
||||||
|
case Type::NONE:
|
||||||
|
@@ -232,7 +226,7 @@ Value Value::Clone() const {
|
||||||
|
case Type::INTEGER:
|
||||||
|
return Value(int_value_);
|
||||||
|
case Type::DOUBLE:
|
||||||
|
- return Value(double_value_);
|
||||||
|
+ return Value(AsDoubleInternal());
|
||||||
|
case Type::STRING:
|
||||||
|
return Value(string_value_);
|
||||||
|
case Type::BINARY:
|
||||||
|
@@ -277,7 +271,7 @@ int Value::GetInt() const {
|
||||||
|
|
||||||
|
double Value::GetDouble() const {
|
||||||
|
if (is_double())
|
||||||
|
- return double_value_;
|
||||||
|
+ return AsDoubleInternal();
|
||||||
|
if (is_int())
|
||||||
|
return int_value_;
|
||||||
|
CHECK(false);
|
||||||
|
@@ -342,9 +336,10 @@ base::Optional<double> Value::FindDouble
|
||||||
|
const Value* result = FindKey(key);
|
||||||
|
if (result) {
|
||||||
|
if (result->is_int())
|
||||||
|
- return base::make_optional(static_cast<double>(result->int_value_));
|
||||||
|
- if (result->is_double())
|
||||||
|
- return base::make_optional(result->double_value_);
|
||||||
|
+ return static_cast<double>(result->int_value_);
|
||||||
|
+ if (result->is_double()) {
|
||||||
|
+ return result->AsDoubleInternal();
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
return base::nullopt;
|
||||||
|
}
|
||||||
|
@@ -548,7 +543,7 @@ bool Value::GetAsInteger(int* out_value)
|
||||||
|
|
||||||
|
bool Value::GetAsDouble(double* out_value) const {
|
||||||
|
if (out_value && is_double()) {
|
||||||
|
- *out_value = double_value_;
|
||||||
|
+ *out_value = AsDoubleInternal();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (out_value && is_int()) {
|
||||||
|
@@ -643,7 +638,7 @@ bool operator==(const Value& lhs, const
|
||||||
|
case Value::Type::INTEGER:
|
||||||
|
return lhs.int_value_ == rhs.int_value_;
|
||||||
|
case Value::Type::DOUBLE:
|
||||||
|
- return lhs.double_value_ == rhs.double_value_;
|
||||||
|
+ return lhs.AsDoubleInternal() == rhs.AsDoubleInternal();
|
||||||
|
case Value::Type::STRING:
|
||||||
|
return lhs.string_value_ == rhs.string_value_;
|
||||||
|
case Value::Type::BINARY:
|
||||||
|
@@ -688,7 +683,7 @@ bool operator<(const Value& lhs, const V
|
||||||
|
case Value::Type::INTEGER:
|
||||||
|
return lhs.int_value_ < rhs.int_value_;
|
||||||
|
case Value::Type::DOUBLE:
|
||||||
|
- return lhs.double_value_ < rhs.double_value_;
|
||||||
|
+ return lhs.AsDoubleInternal() < rhs.AsDoubleInternal();
|
||||||
|
case Value::Type::STRING:
|
||||||
|
return lhs.string_value_ < rhs.string_value_;
|
||||||
|
case Value::Type::BINARY:
|
||||||
|
diff -up chromium-74.0.3729.169/base/values.h.2f28731 chromium-74.0.3729.169/base/values.h
|
||||||
|
--- chromium-74.0.3729.169/base/values.h.2f28731 2019-05-31 15:13:48.418868163 -0400
|
||||||
|
+++ chromium-74.0.3729.169/base/values.h 2019-05-31 15:17:06.015112057 -0400
|
||||||
|
@@ -77,12 +77,13 @@ class Value;
|
||||||
|
// base::Value dict(base::Value::Type::DICTIONARY);
|
||||||
|
// dict.SetKey("mykey", base::Value(foo));
|
||||||
|
// return dict;
|
||||||
|
-// }
|
||||||
|
class BASE_EXPORT Value {
|
||||||
|
public:
|
||||||
|
using BlobStorage = std::vector<uint8_t>;
|
||||||
|
using DictStorage = flat_map<std::string, std::unique_ptr<Value>>;
|
||||||
|
using ListStorage = std::vector<Value>;
|
||||||
|
+ // See technical note below explaining why this is used.
|
||||||
|
+ using DoubleStorage = struct { alignas(4) char v[sizeof(double)]; };
|
||||||
|
|
||||||
|
enum class Type : unsigned char {
|
||||||
|
NONE = 0,
|
||||||
|
@@ -111,7 +112,10 @@ class BASE_EXPORT Value {
|
||||||
|
static std::unique_ptr<Value> ToUniquePtrValue(Value val);
|
||||||
|
|
||||||
|
Value(Value&& that) noexcept;
|
||||||
|
- Value() noexcept; // A null value.
|
||||||
|
+ Value() noexcept {} // A null value
|
||||||
|
+ // Fun fact: using '= default' above instead of '{}' does not work because
|
||||||
|
+ // the compiler complains that the default constructor was deleted since
|
||||||
|
+ // the inner union contains fields with non-default constructors.
|
||||||
|
|
||||||
|
// Value's copy constructor and copy assignment operator are deleted. Use this
|
||||||
|
// to obtain a deep copy explicitly.
|
||||||
|
@@ -379,82 +383,29 @@ class BASE_EXPORT Value {
|
||||||
|
size_t EstimateMemoryUsage() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
- // Technical note:
|
||||||
|
- // The naive way to implement a tagged union leads to wasted bytes
|
||||||
|
- // in the object on CPUs like ARM ones, which impose an 8-byte alignment
|
||||||
|
- // for double values. I.e. if one does something like:
|
||||||
|
- //
|
||||||
|
- // struct TaggedValue {
|
||||||
|
- // int type_; // size = 1, align = 4
|
||||||
|
- // union {
|
||||||
|
- // bool bool_value_; // size = 1, align = 1
|
||||||
|
- // int int_value_; // size = 4, align = 4
|
||||||
|
- // double double_value_; // size = 8, align = 8
|
||||||
|
- // std::string string_value_; // size = 12, align = 4 (32-bit)
|
||||||
|
- // };
|
||||||
|
- // };
|
||||||
|
- //
|
||||||
|
- // The end result is that the union will have an alignment of 8, and a size
|
||||||
|
- // of 16, due to 4 extra padding bytes following |string_value_| to respect
|
||||||
|
- // the alignment requirement.
|
||||||
|
- //
|
||||||
|
- // As a consequence, the struct TaggedValue will have a size of 24 bytes,
|
||||||
|
- // due to the size of the union (16), the size of |type_| (4) and 4 bytes
|
||||||
|
- // of padding between |type_| and the union to respect its alignment.
|
||||||
|
- //
|
||||||
|
- // This means 8 bytes of unused memory per instance on 32-bit ARM!
|
||||||
|
- //
|
||||||
|
- // To reclaim these, a union of structs is used instead, in order to ensure
|
||||||
|
- // that |double_value_| below is always located at an offset that is a
|
||||||
|
- // multiple of 8, relative to the start of the overall data structure.
|
||||||
|
- //
|
||||||
|
- // Each struct must declare its own |type_| field, which must have a different
|
||||||
|
- // name, to appease the C++ compiler.
|
||||||
|
- //
|
||||||
|
- // Using this technique sizeof(base::Value) == 16 on 32-bit ARM instead
|
||||||
|
- // of 24, without losing any information. Results are unchanged for x86,
|
||||||
|
- // x86_64 and arm64 (16, 32 and 32 bytes respectively).
|
||||||
|
+ // Special case for doubles, which are aligned to 8 bytes on some
|
||||||
|
+ // 32-bit architectures. In this case, a simple declaration as a
|
||||||
|
+ // double member would make the whole union 8 byte-aligned, which
|
||||||
|
+ // would also force 4 bytes of wasted padding space before it in
|
||||||
|
+ // the Value layout.
|
||||||
|
+ //
|
||||||
|
+ // To override this, store the value as an array of 32-bit integers, and
|
||||||
|
+ // perform the appropriate bit casts when reading / writing to it.
|
||||||
|
+ Type type_ = Type::NONE;
|
||||||
|
+
|
||||||
|
union {
|
||||||
|
- struct {
|
||||||
|
- // TODO(crbug.com/646113): Make these private once DictionaryValue and
|
||||||
|
- // ListValue are properly inlined.
|
||||||
|
- Type type_ : 8;
|
||||||
|
- };
|
||||||
|
- struct {
|
||||||
|
- Type bool_type_ : 8;
|
||||||
|
- bool bool_value_;
|
||||||
|
- };
|
||||||
|
- struct {
|
||||||
|
- Type int_type_ : 8;
|
||||||
|
- int int_value_;
|
||||||
|
- };
|
||||||
|
- struct {
|
||||||
|
- Type double_type_ : 8;
|
||||||
|
- // Subtle: On architectures that require it, the compiler will ensure
|
||||||
|
- // that |double_value_|'s offset is a multiple of 8 (e.g. 32-bit ARM).
|
||||||
|
- // See technical note above to understand why it is important.
|
||||||
|
- double double_value_;
|
||||||
|
- };
|
||||||
|
- struct {
|
||||||
|
- Type string_type_ : 8;
|
||||||
|
- std::string string_value_;
|
||||||
|
- };
|
||||||
|
- struct {
|
||||||
|
- Type binary_type_ : 8;
|
||||||
|
- BlobStorage binary_value_;
|
||||||
|
- };
|
||||||
|
- struct {
|
||||||
|
- Type dict_type_ : 8;
|
||||||
|
- DictStorage dict_;
|
||||||
|
- };
|
||||||
|
- struct {
|
||||||
|
- Type list_type_ : 8;
|
||||||
|
- ListStorage list_;
|
||||||
|
- };
|
||||||
|
+ bool bool_value_;
|
||||||
|
+ int int_value_;
|
||||||
|
+ DoubleStorage double_value_;
|
||||||
|
+ std::string string_value_;
|
||||||
|
+ BlobStorage binary_value_;
|
||||||
|
+ DictStorage dict_;
|
||||||
|
+ ListStorage list_;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class ValuesTest_SizeOfValue_Test;
|
||||||
|
+ double AsDoubleInternal() const;
|
||||||
|
void InternalMoveConstructFrom(Value&& that);
|
||||||
|
void InternalCleanup();
|
||||||
|
|
@ -0,0 +1,12 @@
|
|||||||
|
diff -up chromium-74.0.3729.169/base/values.h.gentoo3 chromium-74.0.3729.169/base/values.h
|
||||||
|
--- chromium-74.0.3729.169/base/values.h.gentoo3 2019-05-31 14:02:13.019800039 -0400
|
||||||
|
+++ chromium-74.0.3729.169/base/values.h 2019-05-31 14:02:32.531380130 -0400
|
||||||
|
@@ -84,7 +84,7 @@ class BASE_EXPORT Value {
|
||||||
|
using DictStorage = flat_map<std::string, std::unique_ptr<Value>>;
|
||||||
|
using ListStorage = std::vector<Value>;
|
||||||
|
|
||||||
|
- enum class Type {
|
||||||
|
+ enum class Type : unsigned char {
|
||||||
|
NONE = 0,
|
||||||
|
BOOLEAN,
|
||||||
|
INTEGER,
|
@ -0,0 +1,75 @@
|
|||||||
|
From c2c467f69fc00d353879d7add5f2c04a6acabbb1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: David 'Digit' Turner <digit@google.com>
|
||||||
|
Date: Wed, 20 Mar 2019 21:41:09 +0000
|
||||||
|
Subject: [PATCH] base: Value::FindDoubleKey() converts integers to doubles
|
||||||
|
|
||||||
|
Ensure that FindDoubleKey() can return the value of an
|
||||||
|
INTEGER key as a double. This is consistent with the behaviour
|
||||||
|
of Value::GetDouble() which will auto-convert INTEGER values
|
||||||
|
to doubles.
|
||||||
|
|
||||||
|
BUG=646113
|
||||||
|
R=dcheng@chromium.org,jdoerrie@chromium.org,sdefresne@chromium.org,hidehiko@chromium.org
|
||||||
|
|
||||||
|
Change-Id: I2c08cb91b6cfd5db268a182ffffe16682d848008
|
||||||
|
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1529017
|
||||||
|
Reviewed-by: Sylvain Defresne <sdefresne@chromium.org>
|
||||||
|
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||||
|
Commit-Queue: David Turner <digit@chromium.org>
|
||||||
|
Cr-Commit-Position: refs/heads/master@{#642680}
|
||||||
|
---
|
||||||
|
base/values.cc | 10 ++++++++--
|
||||||
|
base/values.h | 2 ++
|
||||||
|
base/values_unittest.cc | 2 +-
|
||||||
|
3 files changed, 11 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/base/values.cc b/base/values.cc
|
||||||
|
index 035aa2350cde..69d66ff8ab00 100644
|
||||||
|
--- a/base/values.cc
|
||||||
|
+++ b/base/values.cc
|
||||||
|
@@ -339,8 +339,14 @@ base::Optional<int> Value::FindIntKey(StringPiece key) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
base::Optional<double> Value::FindDoubleKey(StringPiece key) const {
|
||||||
|
- const Value* result = FindKeyOfType(key, Type::DOUBLE);
|
||||||
|
- return result ? base::make_optional(result->double_value_) : base::nullopt;
|
||||||
|
+ const Value* result = FindKey(key);
|
||||||
|
+ if (result) {
|
||||||
|
+ if (result->is_int())
|
||||||
|
+ return base::make_optional(static_cast<double>(result->int_value_));
|
||||||
|
+ if (result->is_double())
|
||||||
|
+ return base::make_optional(result->double_value_);
|
||||||
|
+ }
|
||||||
|
+ return base::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string* Value::FindStringKey(StringPiece key) const {
|
||||||
|
diff --git a/base/values.h b/base/values.h
|
||||||
|
index e31cadd83102..6f2cd3cc3d79 100644
|
||||||
|
--- a/base/values.h
|
||||||
|
+++ b/base/values.h
|
||||||
|
@@ -200,6 +200,8 @@ class BASE_EXPORT Value {
|
||||||
|
// function's name.
|
||||||
|
base::Optional<bool> FindBoolKey(StringPiece key) const;
|
||||||
|
base::Optional<int> FindIntKey(StringPiece key) const;
|
||||||
|
+ // Note FindDoubleKey() will auto-convert INTEGER keys to their double
|
||||||
|
+ // value, for consistency with GetDouble().
|
||||||
|
base::Optional<double> FindDoubleKey(StringPiece key) const;
|
||||||
|
|
||||||
|
// |FindStringKey| returns |nullptr| if value is not found or not a string.
|
||||||
|
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
|
||||||
|
index b23fd8332491..7c545c09d947 100644
|
||||||
|
--- a/base/values_unittest.cc
|
||||||
|
+++ b/base/values_unittest.cc
|
||||||
|
@@ -674,7 +674,7 @@ TEST(ValuesTest, FindDoubleKey) {
|
||||||
|
const Value dict(std::move(storage));
|
||||||
|
EXPECT_EQ(base::nullopt, dict.FindDoubleKey("null"));
|
||||||
|
EXPECT_EQ(base::nullopt, dict.FindDoubleKey("bool"));
|
||||||
|
- EXPECT_EQ(base::nullopt, dict.FindDoubleKey("int"));
|
||||||
|
+ EXPECT_NE(base::nullopt, dict.FindDoubleKey("int"));
|
||||||
|
EXPECT_NE(base::nullopt, dict.FindDoubleKey("double"));
|
||||||
|
EXPECT_EQ(base::nullopt, dict.FindDoubleKey("string"));
|
||||||
|
EXPECT_EQ(base::nullopt, dict.FindDoubleKey("blob"));
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -0,0 +1,587 @@
|
|||||||
|
From e1b1f3a5f273c8da533fad495b9de316e2c83c9b Mon Sep 17 00:00:00 2001
|
||||||
|
From: jdoerrie <jdoerrie@chromium.org>
|
||||||
|
Date: Sat, 16 Mar 2019 04:08:01 +0000
|
||||||
|
Subject: [PATCH] [base] Add Dead Type to base::Value
|
||||||
|
|
||||||
|
This change adds a temporary DEAD type to base::Value which should help
|
||||||
|
to track down use-after-free bugs. Furthermore, this change also removes
|
||||||
|
the now unneeded is_alive_ flag.
|
||||||
|
|
||||||
|
Bug: 859477, 941404
|
||||||
|
Change-Id: I9b7a2f3cbb0b22d7e3ed35b2453537419f3f7e55
|
||||||
|
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1478897
|
||||||
|
Reviewed-by: Pavol Marko <pmarko@chromium.org>
|
||||||
|
Reviewed-by: Tao Bai <michaelbai@chromium.org>
|
||||||
|
Reviewed-by: Thomas Anderson <thomasanderson@chromium.org>
|
||||||
|
Reviewed-by: Mike Pinkerton <pinkerton@chromium.org>
|
||||||
|
Reviewed-by: Bill Budge <bbudge@chromium.org>
|
||||||
|
Reviewed-by: Ken Rockot <rockot@google.com>
|
||||||
|
Reviewed-by: Steven Bennetts <stevenjb@chromium.org>
|
||||||
|
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||||
|
Reviewed-by: David Turner <digit@chromium.org>
|
||||||
|
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
|
||||||
|
Cr-Commit-Position: refs/heads/master@{#641404}
|
||||||
|
---
|
||||||
|
base/json/json_writer.cc | 5 ++
|
||||||
|
base/values.cc | 68 ++++++++++++-------
|
||||||
|
base/values.h | 23 ++-----
|
||||||
|
base/values_unittest.cc | 10 ++-
|
||||||
|
.../ui/cocoa/applescript/apple_event_util.mm | 10 +++
|
||||||
|
chromeos/network/onc/variable_expander.cc | 6 ++
|
||||||
|
.../core/browser/android/policy_converter.cc | 11 ++-
|
||||||
|
.../core/common/policy_loader_win_unittest.cc | 8 ++-
|
||||||
|
.../policy/core/common/policy_test_utils.cc | 5 ++
|
||||||
|
.../policy/core/common/registry_dict.cc | 4 ++
|
||||||
|
.../gin_java_script_to_java_types_coercion.cc | 8 ++-
|
||||||
|
ipc/ipc_message_utils.cc | 11 ++-
|
||||||
|
mojo/public/cpp/base/values_mojom_traits.h | 7 +-
|
||||||
|
.../ppb_x509_certificate_private_shared.cc | 2 +
|
||||||
|
14 files changed, 127 insertions(+), 51 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/base/json/json_writer.cc b/base/json/json_writer.cc
|
||||||
|
index 376a459f9a46..cd020e7fa0c0 100644
|
||||||
|
--- a/base/json/json_writer.cc
|
||||||
|
+++ b/base/json/json_writer.cc
|
||||||
|
@@ -179,6 +179,11 @@ bool JSONWriter::BuildJSONString(const Value& node, size_t depth) {
|
||||||
|
// Successful only if we're allowed to omit it.
|
||||||
|
DLOG_IF(ERROR, !omit_binary_values_) << "Cannot serialize binary value.";
|
||||||
|
return omit_binary_values_;
|
||||||
|
+
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case Value::Type::DEAD:
|
||||||
|
+ CHECK(false);
|
||||||
|
+ return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(crbug.com/859477): Revert to NOTREACHED() after root cause is found.
|
||||||
|
diff --git a/base/values.cc b/base/values.cc
|
||||||
|
index 0c002551b317..035aa2350cde 100644
|
||||||
|
--- a/base/values.cc
|
||||||
|
+++ b/base/values.cc
|
||||||
|
@@ -90,8 +90,6 @@ std::unique_ptr<Value> CopyWithoutEmptyChildren(const Value& node) {
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
-constexpr uint16_t Value::kMagicIsAlive;
|
||||||
|
-
|
||||||
|
// static
|
||||||
|
std::unique_ptr<Value> Value::CreateWithCopiedBuffer(const char* buffer,
|
||||||
|
size_t size) {
|
||||||
|
@@ -112,9 +110,9 @@ Value::Value(Value&& that) noexcept {
|
||||||
|
InternalMoveConstructFrom(std::move(that));
|
||||||
|
}
|
||||||
|
|
||||||
|
-Value::Value() noexcept : type_(Type::NONE), is_alive_(kMagicIsAlive) {}
|
||||||
|
+Value::Value() noexcept : type_(Type::NONE) {}
|
||||||
|
|
||||||
|
-Value::Value(Type type) : type_(type), is_alive_(kMagicIsAlive) {
|
||||||
|
+Value::Value(Type type) : type_(type) {
|
||||||
|
// Initialize with the default value.
|
||||||
|
switch (type_) {
|
||||||
|
case Type::NONE:
|
||||||
|
@@ -141,22 +139,26 @@ Value::Value(Type type) : type_(type), is_alive_(kMagicIsAlive) {
|
||||||
|
case Type::LIST:
|
||||||
|
new (&list_) ListStorage();
|
||||||
|
return;
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case Type::DEAD:
|
||||||
|
+ CHECK(false);
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // TODO(crbug.com/859477): Revert to NOTREACHED() after root cause is found.
|
||||||
|
+ CHECK(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::Value(bool in_bool)
|
||||||
|
: bool_type_(Type::BOOLEAN),
|
||||||
|
- bool_is_alive_(kMagicIsAlive),
|
||||||
|
bool_value_(in_bool) {}
|
||||||
|
|
||||||
|
Value::Value(int in_int)
|
||||||
|
: int_type_(Type::INTEGER),
|
||||||
|
- int_is_alive_(kMagicIsAlive),
|
||||||
|
int_value_(in_int) {}
|
||||||
|
|
||||||
|
Value::Value(double in_double)
|
||||||
|
: double_type_(Type::DOUBLE),
|
||||||
|
- double_is_alive_(kMagicIsAlive),
|
||||||
|
double_value_(in_double) {
|
||||||
|
if (!std::isfinite(double_value_)) {
|
||||||
|
NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
|
||||||
|
@@ -171,7 +173,6 @@ Value::Value(StringPiece in_string) : Value(std::string(in_string)) {}
|
||||||
|
|
||||||
|
Value::Value(std::string&& in_string) noexcept
|
||||||
|
: string_type_(Type::STRING),
|
||||||
|
- string_is_alive_(kMagicIsAlive),
|
||||||
|
string_value_(std::move(in_string)) {
|
||||||
|
DCHECK(IsStringUTF8(string_value_));
|
||||||
|
}
|
||||||
|
@@ -182,21 +183,18 @@ Value::Value(StringPiece16 in_string16) : Value(UTF16ToUTF8(in_string16)) {}
|
||||||
|
|
||||||
|
Value::Value(const std::vector<char>& in_blob)
|
||||||
|
: binary_type_(Type::BINARY),
|
||||||
|
- binary_is_alive_(kMagicIsAlive),
|
||||||
|
binary_value_(in_blob.begin(), in_blob.end()) {}
|
||||||
|
|
||||||
|
Value::Value(base::span<const uint8_t> in_blob)
|
||||||
|
: binary_type_(Type::BINARY),
|
||||||
|
- binary_is_alive_(kMagicIsAlive),
|
||||||
|
binary_value_(in_blob.begin(), in_blob.end()) {}
|
||||||
|
|
||||||
|
Value::Value(BlobStorage&& in_blob) noexcept
|
||||||
|
: binary_type_(Type::BINARY),
|
||||||
|
- binary_is_alive_(kMagicIsAlive),
|
||||||
|
binary_value_(std::move(in_blob)) {}
|
||||||
|
|
||||||
|
Value::Value(const DictStorage& in_dict)
|
||||||
|
- : dict_type_(Type::DICTIONARY), dict_is_alive_(kMagicIsAlive), dict_() {
|
||||||
|
+ : dict_type_(Type::DICTIONARY), dict_() {
|
||||||
|
dict_.reserve(in_dict.size());
|
||||||
|
for (const auto& it : in_dict) {
|
||||||
|
dict_.try_emplace(dict_.end(), it.first,
|
||||||
|
@@ -206,11 +204,9 @@ Value::Value(const DictStorage& in_dict)
|
||||||
|
|
||||||
|
Value::Value(DictStorage&& in_dict) noexcept
|
||||||
|
: dict_type_(Type::DICTIONARY),
|
||||||
|
- dict_is_alive_(kMagicIsAlive),
|
||||||
|
dict_(std::move(in_dict)) {}
|
||||||
|
|
||||||
|
-Value::Value(const ListStorage& in_list)
|
||||||
|
- : list_type_(Type::LIST), list_is_alive_(kMagicIsAlive), list_() {
|
||||||
|
+Value::Value(const ListStorage& in_list) : list_type_(Type::LIST), list_() {
|
||||||
|
list_.reserve(in_list.size());
|
||||||
|
for (const auto& val : in_list)
|
||||||
|
list_.emplace_back(val.Clone());
|
||||||
|
@@ -218,7 +214,6 @@ Value::Value(const ListStorage& in_list)
|
||||||
|
|
||||||
|
Value::Value(ListStorage&& in_list) noexcept
|
||||||
|
: list_type_(Type::LIST),
|
||||||
|
- list_is_alive_(kMagicIsAlive),
|
||||||
|
list_(std::move(in_list)) {}
|
||||||
|
|
||||||
|
Value& Value::operator=(Value&& that) noexcept {
|
||||||
|
@@ -246,15 +241,21 @@ Value Value::Clone() const {
|
||||||
|
return Value(dict_);
|
||||||
|
case Type::LIST:
|
||||||
|
return Value(list_);
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case Type::DEAD:
|
||||||
|
+ CHECK(false);
|
||||||
|
+ return Value();
|
||||||
|
}
|
||||||
|
|
||||||
|
- NOTREACHED();
|
||||||
|
+ // TODO(crbug.com/859477): Revert to NOTREACHED() after root cause is found.
|
||||||
|
+ CHECK(false);
|
||||||
|
return Value();
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::~Value() {
|
||||||
|
InternalCleanup();
|
||||||
|
- is_alive_ = 0;
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ type_ = Type::DEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
@@ -654,9 +655,14 @@ bool operator==(const Value& lhs, const Value& rhs) {
|
||||||
|
});
|
||||||
|
case Value::Type::LIST:
|
||||||
|
return lhs.list_ == rhs.list_;
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case Value::Type::DEAD:
|
||||||
|
+ CHECK(false);
|
||||||
|
+ return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- NOTREACHED();
|
||||||
|
+ // TODO(crbug.com/859477): Revert to NOTREACHED() after root cause is found.
|
||||||
|
+ CHECK(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -693,9 +699,14 @@ bool operator<(const Value& lhs, const Value& rhs) {
|
||||||
|
});
|
||||||
|
case Value::Type::LIST:
|
||||||
|
return lhs.list_ < rhs.list_;
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case Value::Type::DEAD:
|
||||||
|
+ CHECK(false);
|
||||||
|
+ return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- NOTREACHED();
|
||||||
|
+ // TODO(crbug.com/859477): Revert to NOTREACHED() after root cause is found.
|
||||||
|
+ CHECK(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -733,7 +744,6 @@ size_t Value::EstimateMemoryUsage() const {
|
||||||
|
|
||||||
|
void Value::InternalMoveConstructFrom(Value&& that) {
|
||||||
|
type_ = that.type_;
|
||||||
|
- is_alive_ = that.is_alive_;
|
||||||
|
|
||||||
|
switch (type_) {
|
||||||
|
case Type::NONE:
|
||||||
|
@@ -759,12 +769,17 @@ void Value::InternalMoveConstructFrom(Value&& that) {
|
||||||
|
case Type::LIST:
|
||||||
|
new (&list_) ListStorage(std::move(that.list_));
|
||||||
|
return;
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case Type::DEAD:
|
||||||
|
+ CHECK(false);
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // TODO(crbug.com/859477): Revert to NOTREACHED() after root cause is found.
|
||||||
|
+ CHECK(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Value::InternalCleanup() {
|
||||||
|
- CHECK_EQ(is_alive_, kMagicIsAlive);
|
||||||
|
-
|
||||||
|
switch (type_) {
|
||||||
|
case Type::NONE:
|
||||||
|
case Type::BOOLEAN:
|
||||||
|
@@ -785,7 +800,14 @@ void Value::InternalCleanup() {
|
||||||
|
case Type::LIST:
|
||||||
|
list_.~ListStorage();
|
||||||
|
return;
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case Type::DEAD:
|
||||||
|
+ CHECK(false);
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // TODO(crbug.com/859477): Revert to NOTREACHED() after root cause is found.
|
||||||
|
+ CHECK(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////// DictionaryValue ////////////////////
|
||||||
|
diff --git a/base/values.h b/base/values.h
|
||||||
|
index 429ef1dfdebd..e31cadd83102 100644
|
||||||
|
--- a/base/values.h
|
||||||
|
+++ b/base/values.h
|
||||||
|
@@ -92,7 +92,9 @@ class BASE_EXPORT Value {
|
||||||
|
STRING,
|
||||||
|
BINARY,
|
||||||
|
DICTIONARY,
|
||||||
|
- LIST
|
||||||
|
+ LIST,
|
||||||
|
+ // TODO(crbug.com/859477): Remove once root cause is found.
|
||||||
|
+ DEAD
|
||||||
|
// Note: Do not add more types. See the file-level comment above for why.
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -375,10 +377,6 @@ class BASE_EXPORT Value {
|
||||||
|
size_t EstimateMemoryUsage() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
- // Magic IsAlive signature to debug double frees.
|
||||||
|
- // TODO(crbug.com/859477): Remove once root cause is found.
|
||||||
|
- static constexpr uint16_t kMagicIsAlive = 0x2f19;
|
||||||
|
-
|
||||||
|
// Technical note:
|
||||||
|
// The naive way to implement a tagged union leads to wasted bytes
|
||||||
|
// in the object on CPUs like ARM ones, which impose an 8-byte alignment
|
||||||
|
@@ -408,8 +406,8 @@ class BASE_EXPORT Value {
|
||||||
|
// that |double_value_| below is always located at an offset that is a
|
||||||
|
// multiple of 8, relative to the start of the overall data structure.
|
||||||
|
//
|
||||||
|
- // Each struct must declare its own |type_| and |is_alive_| field, which
|
||||||
|
- // must have a different name, to appease the C++ compiler.
|
||||||
|
+ // Each struct must declare its own |type_| field, which must have a different
|
||||||
|
+ // name, to appease the C++ compiler.
|
||||||
|
//
|
||||||
|
// Using this technique sizeof(base::Value) == 16 on 32-bit ARM instead
|
||||||
|
// of 24, without losing any information. Results are unchanged for x86,
|
||||||
|
@@ -419,24 +417,17 @@ class BASE_EXPORT Value {
|
||||||
|
// TODO(crbug.com/646113): Make these private once DictionaryValue and
|
||||||
|
// ListValue are properly inlined.
|
||||||
|
Type type_ : 8;
|
||||||
|
-
|
||||||
|
- // IsAlive member to debug double frees.
|
||||||
|
- // TODO(crbug.com/859477): Remove once root cause is found.
|
||||||
|
- uint16_t is_alive_ = kMagicIsAlive;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
Type bool_type_ : 8;
|
||||||
|
- uint16_t bool_is_alive_;
|
||||||
|
bool bool_value_;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
Type int_type_ : 8;
|
||||||
|
- uint16_t int_is_alive_;
|
||||||
|
int int_value_;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
Type double_type_ : 8;
|
||||||
|
- uint16_t double_is_alive_;
|
||||||
|
// Subtle: On architectures that require it, the compiler will ensure
|
||||||
|
// that |double_value_|'s offset is a multiple of 8 (e.g. 32-bit ARM).
|
||||||
|
// See technical note above to understand why it is important.
|
||||||
|
@@ -444,22 +435,18 @@ class BASE_EXPORT Value {
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
Type string_type_ : 8;
|
||||||
|
- uint16_t string_is_alive_;
|
||||||
|
std::string string_value_;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
Type binary_type_ : 8;
|
||||||
|
- uint16_t binary_is_alive_;
|
||||||
|
BlobStorage binary_value_;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
Type dict_type_ : 8;
|
||||||
|
- uint16_t dict_is_alive_;
|
||||||
|
DictStorage dict_;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
Type list_type_ : 8;
|
||||||
|
- uint16_t list_is_alive_;
|
||||||
|
ListStorage list_;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
|
||||||
|
index 0a641bcc7ef4..b23fd8332491 100644
|
||||||
|
--- a/base/values_unittest.cc
|
||||||
|
+++ b/base/values_unittest.cc
|
||||||
|
@@ -20,17 +20,20 @@
|
||||||
|
#include "base/strings/string16.h"
|
||||||
|
#include "base/strings/string_piece.h"
|
||||||
|
#include "base/strings/utf_string_conversions.h"
|
||||||
|
+#include "build/build_config.h"
|
||||||
|
#include "testing/gmock/include/gmock/gmock.h"
|
||||||
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
|
||||||
|
namespace base {
|
||||||
|
|
||||||
|
+// Test is currently incorrect on Windows x86.
|
||||||
|
+#if !defined(OS_WIN) || !defined(ARCH_CPU_X86)
|
||||||
|
TEST(ValuesTest, SizeOfValue) {
|
||||||
|
// Ensure that base::Value is as small as possible, i.e. that there is
|
||||||
|
// no wasted space after the inner value due to alignment constraints.
|
||||||
|
- // Distinguish between the 'header' that includes |type_| and |is_alive_|
|
||||||
|
- // and the inner value that follows it, which can be a bool, int, double,
|
||||||
|
- // string, blob, list or dict.
|
||||||
|
+ // Distinguish between the 'header' that includes |type_| and and the inner
|
||||||
|
+ // value that follows it, which can be a bool, int, double, string, blob, list
|
||||||
|
+ // or dict.
|
||||||
|
#define INNER_TYPES_LIST(X) \
|
||||||
|
X(bool, bool_value_) \
|
||||||
|
X(int, int_value_) \
|
||||||
|
@@ -61,6 +64,7 @@ TEST(ValuesTest, SizeOfValue) {
|
||||||
|
LOG(INFO) << "max_inner_struct_limit=" << max_inner_struct_limit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
TEST(ValuesTest, TestNothrow) {
|
||||||
|
static_assert(std::is_nothrow_move_constructible<Value>::value,
|
||||||
|
diff --git a/chrome/browser/ui/cocoa/applescript/apple_event_util.mm b/chrome/browser/ui/cocoa/applescript/apple_event_util.mm
|
||||||
|
index 16d685607ced..25a59338ee73 100644
|
||||||
|
--- a/chrome/browser/ui/cocoa/applescript/apple_event_util.mm
|
||||||
|
+++ b/chrome/browser/ui/cocoa/applescript/apple_event_util.mm
|
||||||
|
@@ -96,6 +96,16 @@ NSAppleEventDescriptor* ValueToAppleEventDescriptor(const base::Value* value) {
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case base::Value::Type::DEAD:
|
||||||
|
+ CHECK(false);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ default:
|
||||||
|
+ CHECK(false);
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return descriptor;
|
||||||
|
diff --git a/chromeos/network/onc/variable_expander.cc b/chromeos/network/onc/variable_expander.cc
|
||||||
|
index fd72752c2aa6..cd5bbb238eb3 100644
|
||||||
|
--- a/chromeos/network/onc/variable_expander.cc
|
||||||
|
+++ b/chromeos/network/onc/variable_expander.cc
|
||||||
|
@@ -145,6 +145,12 @@ bool VariableExpander::ExpandValue(base::Value* value) const {
|
||||||
|
// Nothing to do here.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case base::Value::Type::DEAD: {
|
||||||
|
+ CHECK(false);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
return no_error;
|
||||||
|
}
|
||||||
|
diff --git a/components/policy/core/browser/android/policy_converter.cc b/components/policy/core/browser/android/policy_converter.cc
|
||||||
|
index b711a64febc9..9d41ad0d1507 100644
|
||||||
|
--- a/components/policy/core/browser/android/policy_converter.cc
|
||||||
|
+++ b/components/policy/core/browser/android/policy_converter.cc
|
||||||
|
@@ -175,10 +175,17 @@ std::unique_ptr<base::Value> PolicyConverter::ConvertValueToSchema(
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case base::Value::Type::DEAD: {
|
||||||
|
+ CHECK(false);
|
||||||
|
+ return nullptr;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
- NOTREACHED();
|
||||||
|
- return std::unique_ptr<base::Value>();
|
||||||
|
+ // TODO(crbug.com/859477): Revert to NOTREACHED() after root cause is found.
|
||||||
|
+ CHECK(false);
|
||||||
|
+ return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolicyConverter::SetPolicyValue(const std::string& key,
|
||||||
|
diff --git a/components/policy/core/common/policy_loader_win_unittest.cc b/components/policy/core/common/policy_loader_win_unittest.cc
|
||||||
|
index 311e7fb122fc..0377307c5e28 100644
|
||||||
|
--- a/components/policy/core/common/policy_loader_win_unittest.cc
|
||||||
|
+++ b/components/policy/core/common/policy_loader_win_unittest.cc
|
||||||
|
@@ -133,8 +133,14 @@ bool InstallValue(const base::Value& value,
|
||||||
|
|
||||||
|
case base::Value::Type::BINARY:
|
||||||
|
return false;
|
||||||
|
+
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case base::Value::Type::DEAD:
|
||||||
|
+ CHECK(false);
|
||||||
|
+ return false;
|
||||||
|
}
|
||||||
|
- NOTREACHED();
|
||||||
|
+ // TODO(crbug.com/859477): Revert to NOTREACHED() after root cause is found.
|
||||||
|
+ CHECK(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/components/policy/core/common/policy_test_utils.cc b/components/policy/core/common/policy_test_utils.cc
|
||||||
|
index 5af98b47275c..919f004153ec 100644
|
||||||
|
--- a/components/policy/core/common/policy_test_utils.cc
|
||||||
|
+++ b/components/policy/core/common/policy_test_utils.cc
|
||||||
|
@@ -137,6 +137,11 @@ CFPropertyListRef ValueToProperty(const base::Value& value) {
|
||||||
|
// because there's no equivalent JSON type, and policy values can only
|
||||||
|
// take valid JSON values.
|
||||||
|
break;
|
||||||
|
+
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case base::Value::Type::DEAD:
|
||||||
|
+ CHECK(false);
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
diff --git a/components/policy/core/common/registry_dict.cc b/components/policy/core/common/registry_dict.cc
|
||||||
|
index f3ed372bdcb3..696ba7e04abe 100644
|
||||||
|
--- a/components/policy/core/common/registry_dict.cc
|
||||||
|
+++ b/components/policy/core/common/registry_dict.cc
|
||||||
|
@@ -135,6 +135,10 @@ std::unique_ptr<base::Value> ConvertRegistryValue(const base::Value& value,
|
||||||
|
case base::Value::Type::BINARY:
|
||||||
|
// No conversion possible.
|
||||||
|
break;
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case base::Value::Type::DEAD:
|
||||||
|
+ CHECK(false);
|
||||||
|
+ return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(WARNING) << "Failed to convert " << value.type() << " to "
|
||||||
|
diff --git a/content/browser/android/java/gin_java_script_to_java_types_coercion.cc b/content/browser/android/java/gin_java_script_to_java_types_coercion.cc
|
||||||
|
index dabd66ba8c72..84fd5489a414 100644
|
||||||
|
--- a/content/browser/android/java/gin_java_script_to_java_types_coercion.cc
|
||||||
|
+++ b/content/browser/android/java/gin_java_script_to_java_types_coercion.cc
|
||||||
|
@@ -722,8 +722,14 @@ jvalue CoerceJavaScriptValueToJavaValue(JNIEnv* env,
|
||||||
|
case base::Value::Type::BINARY:
|
||||||
|
return CoerceGinJavaBridgeValueToJavaValue(
|
||||||
|
env, value, target_type, coerce_to_string, object_refs, error);
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case base::Value::Type::DEAD:
|
||||||
|
+ CHECK(false);
|
||||||
|
+ return jvalue();
|
||||||
|
}
|
||||||
|
- NOTREACHED();
|
||||||
|
+
|
||||||
|
+ // TODO(crbug.com/859477): Revert to NOTREACHED() after root cause is found.
|
||||||
|
+ CHECK(false);
|
||||||
|
return jvalue();
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/ipc/ipc_message_utils.cc b/ipc/ipc_message_utils.cc
|
||||||
|
index ec04c77c6c18..df6ec39bd663 100644
|
||||||
|
--- a/ipc/ipc_message_utils.cc
|
||||||
|
+++ b/ipc/ipc_message_utils.cc
|
||||||
|
@@ -92,7 +92,7 @@ void WriteValue(base::Pickle* m, const base::Value* value, int recursion) {
|
||||||
|
|
||||||
|
switch (value->type()) {
|
||||||
|
case base::Value::Type::NONE:
|
||||||
|
- break;
|
||||||
|
+ break;
|
||||||
|
case base::Value::Type::BOOLEAN: {
|
||||||
|
bool val;
|
||||||
|
result = value->GetAsBoolean(&val);
|
||||||
|
@@ -147,6 +147,11 @@ void WriteValue(base::Pickle* m, const base::Value* value, int recursion) {
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ default:
|
||||||
|
+ CHECK(false);
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -260,7 +265,9 @@ bool ReadValue(const base::Pickle* m,
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
- return false;
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ CHECK(false);
|
||||||
|
+ return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
diff --git a/mojo/public/cpp/base/values_mojom_traits.h b/mojo/public/cpp/base/values_mojom_traits.h
|
||||||
|
index cdb9bbbd94df..66752b7c90d8 100644
|
||||||
|
--- a/mojo/public/cpp/base/values_mojom_traits.h
|
||||||
|
+++ b/mojo/public/cpp/base/values_mojom_traits.h
|
||||||
|
@@ -86,8 +86,13 @@ struct COMPONENT_EXPORT(MOJO_BASE_SHARED_TRAITS)
|
||||||
|
return mojo_base::mojom::ValueDataView::Tag::DICTIONARY_VALUE;
|
||||||
|
case base::Value::Type::LIST:
|
||||||
|
return mojo_base::mojom::ValueDataView::Tag::LIST_VALUE;
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case base::Value::Type::DEAD:
|
||||||
|
+ CHECK(false);
|
||||||
|
+ return mojo_base::mojom::ValueDataView::Tag::NULL_VALUE;
|
||||||
|
}
|
||||||
|
- NOTREACHED();
|
||||||
|
+ // TODO(crbug.com/859477): Revert to NOTREACHED() after root cause is found.
|
||||||
|
+ CHECK(false);
|
||||||
|
return mojo_base::mojom::ValueDataView::Tag::NULL_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc b/ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc
|
||||||
|
index 6ffff36337e0..7f392d50f718 100644
|
||||||
|
--- a/ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc
|
||||||
|
+++ b/ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc
|
||||||
|
@@ -73,6 +73,8 @@ PP_Var PPB_X509Certificate_Fields::GetFieldAsPPVar(
|
||||||
|
}
|
||||||
|
case base::Value::Type::DICTIONARY:
|
||||||
|
case base::Value::Type::LIST:
|
||||||
|
+ // TODO(crbug.com/859477): Remove after root cause is found.
|
||||||
|
+ case base::Value::Type::DEAD:
|
||||||
|
// Not handled.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -0,0 +1,50 @@
|
|||||||
|
diff -up chromium-74.0.3729.169/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc.glibc229 chromium-74.0.3729.169/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
|
||||||
|
--- chromium-74.0.3729.169/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc.glibc229 2019-05-31 13:45:04.165403187 -0400
|
||||||
|
+++ chromium-74.0.3729.169/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc 2019-05-31 13:45:38.200830150 -0400
|
||||||
|
@@ -162,6 +162,15 @@ ResultExpr EvaluateSyscallImpl(int fs_de
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#if defined(__NR_vfork)
|
||||||
|
+ // vfork() is almost never used as a system call, but some libc versions (e.g.
|
||||||
|
+ // older versions of bionic) might use it in a posix_spawn() implementation,
|
||||||
|
+ // which is used by system();
|
||||||
|
+ if (sysno == __NR_vfork) {
|
||||||
|
+ return Error(EPERM);
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
if (sysno == __NR_futex)
|
||||||
|
return RestrictFutex();
|
||||||
|
|
||||||
|
diff -up chromium-74.0.3729.169/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc.glibc229 chromium-74.0.3729.169/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
|
||||||
|
--- chromium-74.0.3729.169/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc.glibc229 2019-05-31 13:45:54.653553140 -0400
|
||||||
|
+++ chromium-74.0.3729.169/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc 2019-05-31 13:47:19.357675791 -0400
|
||||||
|
@@ -134,7 +134,8 @@ namespace sandbox {
|
||||||
|
#if !defined(OS_NACL_NONSFI)
|
||||||
|
// Allow Glibc's and Android pthread creation flags, crash on any other
|
||||||
|
// thread creation attempts and EPERM attempts to use neither
|
||||||
|
-// CLONE_VM, nor CLONE_THREAD, which includes all fork() implementations.
|
||||||
|
+// CLONE_VM nor CLONE_THREAD (all fork implementations), unless CLONE_VFORK is
|
||||||
|
+// present (as in newer versions of posix_spawn).
|
||||||
|
ResultExpr RestrictCloneToThreadsAndEPERMFork() {
|
||||||
|
const Arg<unsigned long> flags(0);
|
||||||
|
|
||||||
|
@@ -153,8 +154,16 @@ ResultExpr RestrictCloneToThreadsAndEPER
|
||||||
|
AnyOf(flags == kAndroidCloneMask, flags == kObsoleteAndroidCloneMask,
|
||||||
|
flags == kGlibcPthreadFlags);
|
||||||
|
|
||||||
|
+ // The following two flags are the two important flags in any vfork-emulating
|
||||||
|
+ // clone call. EPERM any clone call that contains both of them.
|
||||||
|
+ const uint64_t kImportantCloneVforkFlags = CLONE_VFORK | CLONE_VM;
|
||||||
|
+
|
||||||
|
+ const BoolExpr is_fork_or_clone_vfork =
|
||||||
|
+ AnyOf((flags & (CLONE_VM | CLONE_THREAD)) == 0,
|
||||||
|
+ (flags & kImportantCloneVforkFlags) == kImportantCloneVforkFlags);
|
||||||
|
+
|
||||||
|
return If(IsAndroid() ? android_test : glibc_test, Allow())
|
||||||
|
- .ElseIf((flags & (CLONE_VM | CLONE_THREAD)) == 0, Error(EPERM))
|
||||||
|
+ .ElseIf(is_fork_or_clone_vfork, Error(EPERM))
|
||||||
|
.Else(CrashSIGSYSClone());
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
|||||||
|
Description: try alternative locations for libwidevinecdm.so:
|
||||||
|
- $HOME/.local/lib/ (snap-friendly, see https://launchpad.net/bugs/1738149)
|
||||||
|
- /opt/google/chrome/ (installed by official google chrome package)
|
||||||
|
Author: Olivier Tilloy <olivier.tilloy@canonical.com>
|
||||||
|
|
||||||
|
--- a/chrome/common/chrome_paths.cc
|
||||||
|
+++ b/chrome/common/chrome_paths.cc
|
||||||
|
@@ -377,6 +377,15 @@ bool PathProvider(int key, base::FilePat
|
||||||
|
// TODO(crbug.com/663554): Remove this after component updated CDM is
|
||||||
|
// supported on Linux and ChromeOS.
|
||||||
|
case chrome::FILE_WIDEVINE_CDM:
|
||||||
|
+ base::PathService::Get(base::DIR_HOME, &cur);
|
||||||
|
+ cur = cur.Append(FILE_PATH_LITERAL(".local/lib/libwidevinecdm.so"));
|
||||||
|
+ if (base::PathExists(cur)) {
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ if (base::PathExists(base::FilePath(FILE_PATH_LITERAL("/opt/google/chrome/libwidevinecdm.so")))) {
|
||||||
|
+ cur = base::FilePath(FILE_PATH_LITERAL("/opt/google/chrome/libwidevinecdm.so"));
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
if (!GetComponentDirectory(&cur))
|
||||||
|
return false;
|
||||||
|
cur =
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,38 @@
|
|||||||
|
From 00f47df999c9b19e80fdc01db0ae9ca1b6a12b3a Mon Sep 17 00:00:00 2001
|
||||||
|
From: vasilvv <vasilvv@google.com>
|
||||||
|
Date: Wed, 3 Apr 2019 13:58:53 -0700
|
||||||
|
Subject: [PATCH] GCC: do not delete move constructor of QuicStreamSendBuffer
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
QuicStreamSendBuffer constructor is implicitely required in the
|
||||||
|
initialization of the vector of substreams in QuicCryptoStream.
|
||||||
|
Though clang apparently ignores that, GCC fails to build.
|
||||||
|
|
||||||
|
BUG=chromium:819294
|
||||||
|
|
||||||
|
Originally submitted by José Dapena Paz <jose.dapena@lge.com> at https://quiche-review.googlesource.com/c/quiche/+/2420
|
||||||
|
|
||||||
|
PiperOrigin-RevId: 241800134
|
||||||
|
Change-Id: I4e3c97d6e5895d85340e8c1b740e6196d9104066
|
||||||
|
---
|
||||||
|
quic/core/quic_stream_send_buffer.h | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/quic/core/quic_stream_send_buffer.h b/quic/core/quic_stream_send_buffer.h
|
||||||
|
index e34514b..74e9d0d 100644
|
||||||
|
--- a/net/third_party/quic/core/quic_stream_send_buffer.h
|
||||||
|
+++ b/net/third_party/quic/core/quic_stream_send_buffer.h
|
||||||
|
@@ -62,7 +62,7 @@ class QUIC_EXPORT_PRIVATE QuicStreamSendBuffer {
|
||||||
|
public:
|
||||||
|
explicit QuicStreamSendBuffer(QuicBufferAllocator* allocator);
|
||||||
|
QuicStreamSendBuffer(const QuicStreamSendBuffer& other) = delete;
|
||||||
|
- QuicStreamSendBuffer(QuicStreamSendBuffer&& other) = delete;
|
||||||
|
+ QuicStreamSendBuffer(QuicStreamSendBuffer&& other) = default;
|
||||||
|
~QuicStreamSendBuffer();
|
||||||
|
|
||||||
|
// Save |data_length| of data starts at |iov_offset| in |iov| to send buffer.
|
||||||
|
--
|
||||||
|
2.21.0
|
||||||
|
|
@ -0,0 +1,655 @@
|
|||||||
|
Description: revert https://gn.googlesource.com/gn/+/0d038c2e0a32a528713d3dfaf1f1e0cdfe87fd46, which breaks the chromium build
|
||||||
|
|
||||||
|
--- a/tools/gn/build/gen.py
|
||||||
|
+++ b/tools/gn/build/gen.py
|
||||||
|
@@ -522,6 +522,7 @@ def WriteGNNinja(path, platform, host, o
|
||||||
|
'tools/gn/setup.cc',
|
||||||
|
'tools/gn/source_dir.cc',
|
||||||
|
'tools/gn/source_file.cc',
|
||||||
|
+ 'tools/gn/source_file_type.cc',
|
||||||
|
'tools/gn/standard_out.cc',
|
||||||
|
'tools/gn/string_utils.cc',
|
||||||
|
'tools/gn/substitution_list.cc',
|
||||||
|
--- a/tools/gn/tools/gn/c_tool.h
|
||||||
|
+++ b/tools/gn/tools/gn/c_tool.h
|
||||||
|
@@ -12,6 +12,7 @@
|
||||||
|
#include "tools/gn/label.h"
|
||||||
|
#include "tools/gn/label_ptr.h"
|
||||||
|
#include "tools/gn/scope.h"
|
||||||
|
+#include "tools/gn/source_file_type.h"
|
||||||
|
#include "tools/gn/substitution_list.h"
|
||||||
|
#include "tools/gn/substitution_pattern.h"
|
||||||
|
#include "tools/gn/tool.h"
|
||||||
|
--- a/tools/gn/tools/gn/compile_commands_writer.cc
|
||||||
|
+++ b/tools/gn/tools/gn/compile_commands_writer.cc
|
||||||
|
@@ -122,7 +122,7 @@ void WriteCommand(const Target* target,
|
||||||
|
const CompileFlags& flags,
|
||||||
|
std::vector<OutputFile>& tool_outputs,
|
||||||
|
PathOutput& path_output,
|
||||||
|
- SourceFile::Type source_type,
|
||||||
|
+ SourceFileType source_type,
|
||||||
|
const char* tool_name,
|
||||||
|
EscapeOptions opts,
|
||||||
|
std::string* compile_commands) {
|
||||||
|
@@ -144,16 +144,16 @@ void WriteCommand(const Target* target,
|
||||||
|
} else if (range.type == &CSubstitutionCFlags) {
|
||||||
|
command_out << flags.cflags;
|
||||||
|
} else if (range.type == &CSubstitutionCFlagsC) {
|
||||||
|
- if (source_type == SourceFile::SOURCE_C)
|
||||||
|
+ if (source_type == SOURCE_C)
|
||||||
|
command_out << flags.cflags_c;
|
||||||
|
} else if (range.type == &CSubstitutionCFlagsCc) {
|
||||||
|
- if (source_type == SourceFile::SOURCE_CPP)
|
||||||
|
+ if (source_type == SOURCE_CPP)
|
||||||
|
command_out << flags.cflags_cc;
|
||||||
|
} else if (range.type == &CSubstitutionCFlagsObjC) {
|
||||||
|
- if (source_type == SourceFile::SOURCE_M)
|
||||||
|
+ if (source_type == SOURCE_M)
|
||||||
|
command_out << flags.cflags_objc;
|
||||||
|
} else if (range.type == &CSubstitutionCFlagsObjCc) {
|
||||||
|
- if (source_type == SourceFile::SOURCE_MM)
|
||||||
|
+ if (source_type == SOURCE_MM)
|
||||||
|
command_out << flags.cflags_objcc;
|
||||||
|
} else if (range.type == &SubstitutionLabel ||
|
||||||
|
range.type == &SubstitutionLabelName ||
|
||||||
|
@@ -222,11 +222,9 @@ void CompileCommandsWriter::RenderJSON(c
|
||||||
|
for (const auto& source : target->sources()) {
|
||||||
|
// If this source is not a C/C++/ObjC/ObjC++ source (not header) file,
|
||||||
|
// continue as it does not belong in the compilation database.
|
||||||
|
- SourceFile::Type source_type = source.type();
|
||||||
|
- if (source_type != SourceFile::SOURCE_CPP &&
|
||||||
|
- source_type != SourceFile::SOURCE_C &&
|
||||||
|
- source_type != SourceFile::SOURCE_M &&
|
||||||
|
- source_type != SourceFile::SOURCE_MM)
|
||||||
|
+ SourceFileType source_type = GetSourceFileType(source);
|
||||||
|
+ if (source_type != SOURCE_CPP && source_type != SOURCE_C &&
|
||||||
|
+ source_type != SOURCE_M && source_type != SOURCE_MM)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char* tool_name = Tool::kToolNone;
|
||||||
|
@@ -324,4 +322,4 @@ void CompileCommandsWriter::VisitDeps(co
|
||||||
|
VisitDeps(pair.ptr, visited);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-}
|
||||||
|
+}
|
||||||
|
\ No newline at end of file
|
||||||
|
--- a/tools/gn/tools/gn/general_tool.h
|
||||||
|
+++ b/tools/gn/tools/gn/general_tool.h
|
||||||
|
@@ -11,6 +11,7 @@
|
||||||
|
#include "base/macros.h"
|
||||||
|
#include "tools/gn/label.h"
|
||||||
|
#include "tools/gn/label_ptr.h"
|
||||||
|
+#include "tools/gn/source_file_type.h"
|
||||||
|
#include "tools/gn/substitution_list.h"
|
||||||
|
#include "tools/gn/substitution_pattern.h"
|
||||||
|
#include "tools/gn/tool.h"
|
||||||
|
--- a/tools/gn/tools/gn/header_checker.cc
|
||||||
|
+++ b/tools/gn/tools/gn/header_checker.cc
|
||||||
|
@@ -18,6 +18,7 @@
|
||||||
|
#include "tools/gn/err.h"
|
||||||
|
#include "tools/gn/filesystem_utils.h"
|
||||||
|
#include "tools/gn/scheduler.h"
|
||||||
|
+#include "tools/gn/source_file_type.h"
|
||||||
|
#include "tools/gn/target.h"
|
||||||
|
#include "tools/gn/trace.h"
|
||||||
|
#include "util/worker_pool.h"
|
||||||
|
@@ -151,10 +152,9 @@ void HeaderChecker::RunCheckOverFiles(co
|
||||||
|
|
||||||
|
for (const auto& file : files) {
|
||||||
|
// Only check C-like source files (RC files also have includes).
|
||||||
|
- SourceFile::Type type = file.first.type();
|
||||||
|
- if (type != SourceFile::SOURCE_CPP && type != SourceFile::SOURCE_H &&
|
||||||
|
- type != SourceFile::SOURCE_C && type != SourceFile::SOURCE_M &&
|
||||||
|
- type != SourceFile::SOURCE_MM && type != SourceFile::SOURCE_RC)
|
||||||
|
+ SourceFileType type = GetSourceFileType(file.first);
|
||||||
|
+ if (type != SOURCE_CPP && type != SOURCE_H && type != SOURCE_C &&
|
||||||
|
+ type != SOURCE_M && type != SOURCE_MM && type != SOURCE_RC)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!check_generated_) {
|
||||||
|
--- a/tools/gn/tools/gn/ninja_binary_target_writer.cc
|
||||||
|
+++ b/tools/gn/tools/gn/ninja_binary_target_writer.cc
|
||||||
|
@@ -23,23 +23,22 @@
|
||||||
|
#include "tools/gn/ninja_utils.h"
|
||||||
|
#include "tools/gn/scheduler.h"
|
||||||
|
#include "tools/gn/settings.h"
|
||||||
|
+#include "tools/gn/source_file_type.h"
|
||||||
|
#include "tools/gn/string_utils.h"
|
||||||
|
#include "tools/gn/substitution_writer.h"
|
||||||
|
#include "tools/gn/target.h"
|
||||||
|
|
||||||
|
bool NinjaBinaryTargetWriter::SourceFileTypeSet::CSourceUsed() {
|
||||||
|
- return Get(SourceFile::SOURCE_CPP) || Get(SourceFile::SOURCE_H) ||
|
||||||
|
- Get(SourceFile::SOURCE_C) || Get(SourceFile::SOURCE_M) ||
|
||||||
|
- Get(SourceFile::SOURCE_MM) || Get(SourceFile::SOURCE_RC) ||
|
||||||
|
- Get(SourceFile::SOURCE_S);
|
||||||
|
+ return Get(SOURCE_CPP) || Get(SOURCE_H) || Get(SOURCE_C) || Get(SOURCE_M) ||
|
||||||
|
+ Get(SOURCE_MM) || Get(SOURCE_RC) || Get(SOURCE_S);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NinjaBinaryTargetWriter::SourceFileTypeSet::RustSourceUsed() {
|
||||||
|
- return Get(SourceFile::SOURCE_RS);
|
||||||
|
+ return Get(SOURCE_RS);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NinjaBinaryTargetWriter::SourceFileTypeSet::GoSourceUsed() {
|
||||||
|
- return Get(SourceFile::SOURCE_GO);
|
||||||
|
+ return Get(SOURCE_GO);
|
||||||
|
}
|
||||||
|
|
||||||
|
NinjaBinaryTargetWriter::NinjaBinaryTargetWriter(const Target* target,
|
||||||
|
@@ -50,6 +49,10 @@ NinjaBinaryTargetWriter::NinjaBinaryTarg
|
||||||
|
NinjaBinaryTargetWriter::~NinjaBinaryTargetWriter() = default;
|
||||||
|
|
||||||
|
void NinjaBinaryTargetWriter::Run() {
|
||||||
|
+ SourceFileTypeSet used_types;
|
||||||
|
+ for (const auto& source : target_->sources())
|
||||||
|
+ used_types.Set(GetSourceFileType(source));
|
||||||
|
+
|
||||||
|
NinjaCBinaryTargetWriter writer(target_, out_);
|
||||||
|
writer.Run();
|
||||||
|
}
|
||||||
|
--- a/tools/gn/tools/gn/ninja_binary_target_writer.h
|
||||||
|
+++ b/tools/gn/tools/gn/ninja_binary_target_writer.h
|
||||||
|
@@ -23,12 +23,11 @@ class NinjaBinaryTargetWriter : public N
|
||||||
|
class SourceFileTypeSet {
|
||||||
|
public:
|
||||||
|
SourceFileTypeSet() {
|
||||||
|
- memset(flags_, 0,
|
||||||
|
- sizeof(bool) * static_cast<int>(SourceFile::SOURCE_NUMTYPES));
|
||||||
|
+ memset(flags_, 0, sizeof(bool) * static_cast<int>(SOURCE_NUMTYPES));
|
||||||
|
}
|
||||||
|
|
||||||
|
- void Set(SourceFile::Type type) { flags_[static_cast<int>(type)] = true; }
|
||||||
|
- bool Get(SourceFile::Type type) const {
|
||||||
|
+ void Set(SourceFileType type) { flags_[static_cast<int>(type)] = true; }
|
||||||
|
+ bool Get(SourceFileType type) const {
|
||||||
|
return flags_[static_cast<int>(type)];
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -37,7 +36,7 @@ class NinjaBinaryTargetWriter : public N
|
||||||
|
bool GoSourceUsed();
|
||||||
|
|
||||||
|
private:
|
||||||
|
- bool flags_[static_cast<int>(SourceFile::SOURCE_NUMTYPES)];
|
||||||
|
+ bool flags_[static_cast<int>(SOURCE_NUMTYPES)];
|
||||||
|
};
|
||||||
|
|
||||||
|
NinjaBinaryTargetWriter(const Target* target, std::ostream& out);
|
||||||
|
--- a/tools/gn/tools/gn/ninja_c_binary_target_writer.cc
|
||||||
|
+++ b/tools/gn/tools/gn/ninja_c_binary_target_writer.cc
|
||||||
|
@@ -24,6 +24,7 @@
|
||||||
|
#include "tools/gn/ninja_utils.h"
|
||||||
|
#include "tools/gn/scheduler.h"
|
||||||
|
#include "tools/gn/settings.h"
|
||||||
|
+#include "tools/gn/source_file_type.h"
|
||||||
|
#include "tools/gn/string_utils.h"
|
||||||
|
#include "tools/gn/substitution_writer.h"
|
||||||
|
#include "tools/gn/target.h"
|
||||||
|
@@ -66,27 +67,27 @@ void AddSourceSetObjectFiles(const Targe
|
||||||
|
if (source_set->GetOutputFilesForSource(source, &tool_name, &tool_outputs))
|
||||||
|
obj_files->push_back(tool_outputs[0]);
|
||||||
|
|
||||||
|
- used_types.Set(source.type());
|
||||||
|
+ used_types.Set(GetSourceFileType(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add MSVC precompiled header object files. GCC .gch files are not object
|
||||||
|
// files so they are omitted.
|
||||||
|
if (source_set->config_values().has_precompiled_headers()) {
|
||||||
|
- if (used_types.Get(SourceFile::SOURCE_C)) {
|
||||||
|
+ if (used_types.Get(SOURCE_C)) {
|
||||||
|
const CTool* tool = source_set->toolchain()->GetToolAsC(CTool::kCToolCc);
|
||||||
|
if (tool && tool->precompiled_header_type() == CTool::PCH_MSVC) {
|
||||||
|
GetPCHOutputFiles(source_set, CTool::kCToolCc, &tool_outputs);
|
||||||
|
obj_files->Append(tool_outputs.begin(), tool_outputs.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- if (used_types.Get(SourceFile::SOURCE_CPP)) {
|
||||||
|
+ if (used_types.Get(SOURCE_CPP)) {
|
||||||
|
const CTool* tool = source_set->toolchain()->GetToolAsC(CTool::kCToolCxx);
|
||||||
|
if (tool && tool->precompiled_header_type() == CTool::PCH_MSVC) {
|
||||||
|
GetPCHOutputFiles(source_set, CTool::kCToolCxx, &tool_outputs);
|
||||||
|
obj_files->Append(tool_outputs.begin(), tool_outputs.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- if (used_types.Get(SourceFile::SOURCE_M)) {
|
||||||
|
+ if (used_types.Get(SOURCE_M)) {
|
||||||
|
const CTool* tool =
|
||||||
|
source_set->toolchain()->GetToolAsC(CTool::kCToolObjC);
|
||||||
|
if (tool && tool->precompiled_header_type() == CTool::PCH_MSVC) {
|
||||||
|
@@ -94,7 +95,7 @@ void AddSourceSetObjectFiles(const Targe
|
||||||
|
obj_files->Append(tool_outputs.begin(), tool_outputs.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- if (used_types.Get(SourceFile::SOURCE_MM)) {
|
||||||
|
+ if (used_types.Get(SOURCE_MM)) {
|
||||||
|
const CTool* tool =
|
||||||
|
source_set->toolchain()->GetToolAsC(CTool::kCToolObjCxx);
|
||||||
|
if (tool && tool->precompiled_header_type() == CTool::PCH_MSVC) {
|
||||||
|
@@ -118,7 +119,7 @@ void NinjaCBinaryTargetWriter::Run() {
|
||||||
|
// Figure out what source types are needed.
|
||||||
|
SourceFileTypeSet used_types;
|
||||||
|
for (const auto& source : target_->sources())
|
||||||
|
- used_types.Set(source.type());
|
||||||
|
+ used_types.Set(GetSourceFileType(source));
|
||||||
|
|
||||||
|
WriteCompilerVars(used_types);
|
||||||
|
|
||||||
|
@@ -234,34 +235,31 @@ void NinjaCBinaryTargetWriter::WriteComp
|
||||||
|
target_->config_values().has_precompiled_headers();
|
||||||
|
|
||||||
|
EscapeOptions opts = GetFlagOptions();
|
||||||
|
- if (used_types.Get(SourceFile::SOURCE_S) ||
|
||||||
|
- used_types.Get(SourceFile::SOURCE_ASM)) {
|
||||||
|
+ if (used_types.Get(SOURCE_S) || used_types.Get(SOURCE_ASM)) {
|
||||||
|
WriteOneFlag(target_, &CSubstitutionAsmFlags, false, Tool::kToolNone,
|
||||||
|
&ConfigValues::asmflags, opts, path_output_, out_);
|
||||||
|
}
|
||||||
|
- if (used_types.Get(SourceFile::SOURCE_C) ||
|
||||||
|
- used_types.Get(SourceFile::SOURCE_CPP) ||
|
||||||
|
- used_types.Get(SourceFile::SOURCE_M) ||
|
||||||
|
- used_types.Get(SourceFile::SOURCE_MM)) {
|
||||||
|
+ if (used_types.Get(SOURCE_C) || used_types.Get(SOURCE_CPP) ||
|
||||||
|
+ used_types.Get(SOURCE_M) || used_types.Get(SOURCE_MM)) {
|
||||||
|
WriteOneFlag(target_, &CSubstitutionCFlags, false, Tool::kToolNone,
|
||||||
|
&ConfigValues::cflags, opts, path_output_, out_);
|
||||||
|
}
|
||||||
|
- if (used_types.Get(SourceFile::SOURCE_C)) {
|
||||||
|
+ if (used_types.Get(SOURCE_C)) {
|
||||||
|
WriteOneFlag(target_, &CSubstitutionCFlagsC, has_precompiled_headers,
|
||||||
|
CTool::kCToolCc, &ConfigValues::cflags_c, opts, path_output_,
|
||||||
|
out_);
|
||||||
|
}
|
||||||
|
- if (used_types.Get(SourceFile::SOURCE_CPP)) {
|
||||||
|
+ if (used_types.Get(SOURCE_CPP)) {
|
||||||
|
WriteOneFlag(target_, &CSubstitutionCFlagsCc, has_precompiled_headers,
|
||||||
|
CTool::kCToolCxx, &ConfigValues::cflags_cc, opts, path_output_,
|
||||||
|
out_);
|
||||||
|
}
|
||||||
|
- if (used_types.Get(SourceFile::SOURCE_M)) {
|
||||||
|
+ if (used_types.Get(SOURCE_M)) {
|
||||||
|
WriteOneFlag(target_, &CSubstitutionCFlagsObjC, has_precompiled_headers,
|
||||||
|
CTool::kCToolObjC, &ConfigValues::cflags_objc, opts,
|
||||||
|
path_output_, out_);
|
||||||
|
}
|
||||||
|
- if (used_types.Get(SourceFile::SOURCE_MM)) {
|
||||||
|
+ if (used_types.Get(SOURCE_MM)) {
|
||||||
|
WriteOneFlag(target_, &CSubstitutionCFlagsObjCc, has_precompiled_headers,
|
||||||
|
CTool::kCToolObjCxx, &ConfigValues::cflags_objcc, opts,
|
||||||
|
path_output_, out_);
|
||||||
|
@@ -321,14 +319,14 @@ void NinjaCBinaryTargetWriter::WritePCHC
|
||||||
|
|
||||||
|
const CTool* tool_c = target_->toolchain()->GetToolAsC(CTool::kCToolCc);
|
||||||
|
if (tool_c && tool_c->precompiled_header_type() != CTool::PCH_NONE &&
|
||||||
|
- used_types.Get(SourceFile::SOURCE_C)) {
|
||||||
|
+ used_types.Get(SOURCE_C)) {
|
||||||
|
WritePCHCommand(&CSubstitutionCFlagsC, CTool::kCToolCc,
|
||||||
|
tool_c->precompiled_header_type(), input_dep,
|
||||||
|
order_only_deps, object_files, other_files);
|
||||||
|
}
|
||||||
|
const CTool* tool_cxx = target_->toolchain()->GetToolAsC(CTool::kCToolCxx);
|
||||||
|
if (tool_cxx && tool_cxx->precompiled_header_type() != CTool::PCH_NONE &&
|
||||||
|
- used_types.Get(SourceFile::SOURCE_CPP)) {
|
||||||
|
+ used_types.Get(SOURCE_CPP)) {
|
||||||
|
WritePCHCommand(&CSubstitutionCFlagsCc, CTool::kCToolCxx,
|
||||||
|
tool_cxx->precompiled_header_type(), input_dep,
|
||||||
|
order_only_deps, object_files, other_files);
|
||||||
|
@@ -336,7 +334,7 @@ void NinjaCBinaryTargetWriter::WritePCHC
|
||||||
|
|
||||||
|
const CTool* tool_objc = target_->toolchain()->GetToolAsC(CTool::kCToolObjC);
|
||||||
|
if (tool_objc && tool_objc->precompiled_header_type() == CTool::PCH_GCC &&
|
||||||
|
- used_types.Get(SourceFile::SOURCE_M)) {
|
||||||
|
+ used_types.Get(SOURCE_M)) {
|
||||||
|
WritePCHCommand(&CSubstitutionCFlagsObjC, CTool::kCToolObjC,
|
||||||
|
tool_objc->precompiled_header_type(), input_dep,
|
||||||
|
order_only_deps, object_files, other_files);
|
||||||
|
@@ -345,7 +343,7 @@ void NinjaCBinaryTargetWriter::WritePCHC
|
||||||
|
const CTool* tool_objcxx =
|
||||||
|
target_->toolchain()->GetToolAsC(CTool::kCToolObjCxx);
|
||||||
|
if (tool_objcxx && tool_objcxx->precompiled_header_type() == CTool::PCH_GCC &&
|
||||||
|
- used_types.Get(SourceFile::SOURCE_MM)) {
|
||||||
|
+ used_types.Get(SOURCE_MM)) {
|
||||||
|
WritePCHCommand(&CSubstitutionCFlagsObjCc, CTool::kCToolObjCxx,
|
||||||
|
tool_objcxx->precompiled_header_type(), input_dep,
|
||||||
|
order_only_deps, object_files, other_files);
|
||||||
|
@@ -478,7 +476,7 @@ void NinjaCBinaryTargetWriter::WriteSour
|
||||||
|
deps.resize(0);
|
||||||
|
const char* tool_name = Tool::kToolNone;
|
||||||
|
if (!target_->GetOutputFilesForSource(source, &tool_name, &tool_outputs)) {
|
||||||
|
- if (source.type() == SourceFile::SOURCE_DEF)
|
||||||
|
+ if (GetSourceFileType(source) == SOURCE_DEF)
|
||||||
|
other_files->push_back(source);
|
||||||
|
continue; // No output for this source.
|
||||||
|
}
|
||||||
|
@@ -599,7 +597,7 @@ void NinjaCBinaryTargetWriter::WriteLink
|
||||||
|
const SourceFile* optional_def_file = nullptr;
|
||||||
|
if (!other_files.empty()) {
|
||||||
|
for (const SourceFile& src_file : other_files) {
|
||||||
|
- if (src_file.type() == SourceFile::SOURCE_DEF) {
|
||||||
|
+ if (GetSourceFileType(src_file) == SOURCE_DEF) {
|
||||||
|
optional_def_file = &src_file;
|
||||||
|
implicit_deps.push_back(
|
||||||
|
OutputFile(settings_->build_settings(), src_file));
|
||||||
|
--- a/tools/gn/tools/gn/source_file.cc
|
||||||
|
+++ b/tools/gn/tools/gn/source_file.cc
|
||||||
|
@@ -21,48 +21,18 @@ void AssertValueSourceFileString(const s
|
||||||
|
DCHECK(!EndsWithSlash(s)) << s;
|
||||||
|
}
|
||||||
|
|
||||||
|
-SourceFile::Type GetSourceFileType(const std::string& file) {
|
||||||
|
- base::StringPiece extension = FindExtension(&file);
|
||||||
|
- if (extension == "cc" || extension == "cpp" || extension == "cxx")
|
||||||
|
- return SourceFile::SOURCE_CPP;
|
||||||
|
- if (extension == "h" || extension == "hpp" || extension == "hxx" ||
|
||||||
|
- extension == "hh" || extension == "inc")
|
||||||
|
- return SourceFile::SOURCE_H;
|
||||||
|
- if (extension == "c")
|
||||||
|
- return SourceFile::SOURCE_C;
|
||||||
|
- if (extension == "m")
|
||||||
|
- return SourceFile::SOURCE_M;
|
||||||
|
- if (extension == "mm")
|
||||||
|
- return SourceFile::SOURCE_MM;
|
||||||
|
- if (extension == "rc")
|
||||||
|
- return SourceFile::SOURCE_RC;
|
||||||
|
- if (extension == "S" || extension == "s" || extension == "asm")
|
||||||
|
- return SourceFile::SOURCE_S;
|
||||||
|
- if (extension == "o" || extension == "obj")
|
||||||
|
- return SourceFile::SOURCE_O;
|
||||||
|
- if (extension == "def")
|
||||||
|
- return SourceFile::SOURCE_DEF;
|
||||||
|
- if (extension == "rs")
|
||||||
|
- return SourceFile::SOURCE_RS;
|
||||||
|
- if (extension == "go")
|
||||||
|
- return SourceFile::SOURCE_GO;
|
||||||
|
-
|
||||||
|
- return SourceFile::SOURCE_UNKNOWN;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
-SourceFile::SourceFile() : type_(SOURCE_UNKNOWN) {}
|
||||||
|
+SourceFile::SourceFile() = default;
|
||||||
|
|
||||||
|
SourceFile::SourceFile(const base::StringPiece& p)
|
||||||
|
- : value_(p.data(), p.size()), type_(GetSourceFileType(value_)) {
|
||||||
|
+ : value_(p.data(), p.size()) {
|
||||||
|
DCHECK(!value_.empty());
|
||||||
|
AssertValueSourceFileString(value_);
|
||||||
|
NormalizePath(&value_);
|
||||||
|
}
|
||||||
|
|
||||||
|
-SourceFile::SourceFile(SwapIn, std::string* value)
|
||||||
|
- : type_(GetSourceFileType(*value)) {
|
||||||
|
+SourceFile::SourceFile(SwapIn, std::string* value) {
|
||||||
|
value_.swap(*value);
|
||||||
|
DCHECK(!value_.empty());
|
||||||
|
AssertValueSourceFileString(value_);
|
||||||
|
--- a/tools/gn/tools/gn/source_file.h
|
||||||
|
+++ b/tools/gn/tools/gn/source_file.h
|
||||||
|
@@ -20,28 +20,6 @@ class SourceDir;
|
||||||
|
// ends in one.
|
||||||
|
class SourceFile {
|
||||||
|
public:
|
||||||
|
- // This should be sequential integers starting from 0 so they can be used as
|
||||||
|
- // array indices.
|
||||||
|
- enum Type {
|
||||||
|
- SOURCE_UNKNOWN = 0,
|
||||||
|
- SOURCE_ASM,
|
||||||
|
- SOURCE_C,
|
||||||
|
- SOURCE_CPP,
|
||||||
|
- SOURCE_H,
|
||||||
|
- SOURCE_M,
|
||||||
|
- SOURCE_MM,
|
||||||
|
- SOURCE_S,
|
||||||
|
- SOURCE_RC,
|
||||||
|
- SOURCE_O, // Object files can be inputs, too. Also counts .obj.
|
||||||
|
- SOURCE_DEF,
|
||||||
|
-
|
||||||
|
- SOURCE_RS,
|
||||||
|
- SOURCE_GO,
|
||||||
|
-
|
||||||
|
- // Must be last.
|
||||||
|
- SOURCE_NUMTYPES,
|
||||||
|
- };
|
||||||
|
-
|
||||||
|
enum SwapIn { SWAP_IN };
|
||||||
|
|
||||||
|
SourceFile();
|
||||||
|
@@ -58,7 +36,6 @@ class SourceFile {
|
||||||
|
|
||||||
|
bool is_null() const { return value_.empty(); }
|
||||||
|
const std::string& value() const { return value_; }
|
||||||
|
- Type type() const { return type_; }
|
||||||
|
|
||||||
|
// Returns everything after the last slash.
|
||||||
|
std::string GetName() const;
|
||||||
|
@@ -103,7 +80,6 @@ class SourceFile {
|
||||||
|
friend class SourceDir;
|
||||||
|
|
||||||
|
std::string value_;
|
||||||
|
- Type type_;
|
||||||
|
|
||||||
|
// Copy & assign supported.
|
||||||
|
};
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tools/gn/tools/gn/source_file_type.cc
|
||||||
|
@@ -0,0 +1,37 @@
|
||||||
|
+// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||||
|
+// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
+// found in the LICENSE file.
|
||||||
|
+
|
||||||
|
+#include "tools/gn/source_file_type.h"
|
||||||
|
+
|
||||||
|
+#include "tools/gn/filesystem_utils.h"
|
||||||
|
+#include "tools/gn/source_file.h"
|
||||||
|
+
|
||||||
|
+SourceFileType GetSourceFileType(const SourceFile& file) {
|
||||||
|
+ base::StringPiece extension = FindExtension(&file.value());
|
||||||
|
+ if (extension == "cc" || extension == "cpp" || extension == "cxx")
|
||||||
|
+ return SOURCE_CPP;
|
||||||
|
+ if (extension == "h" || extension == "hpp" || extension == "hxx" ||
|
||||||
|
+ extension == "hh")
|
||||||
|
+ return SOURCE_H;
|
||||||
|
+ if (extension == "c")
|
||||||
|
+ return SOURCE_C;
|
||||||
|
+ if (extension == "m")
|
||||||
|
+ return SOURCE_M;
|
||||||
|
+ if (extension == "mm")
|
||||||
|
+ return SOURCE_MM;
|
||||||
|
+ if (extension == "rc")
|
||||||
|
+ return SOURCE_RC;
|
||||||
|
+ if (extension == "S" || extension == "s" || extension == "asm")
|
||||||
|
+ return SOURCE_S;
|
||||||
|
+ if (extension == "o" || extension == "obj")
|
||||||
|
+ return SOURCE_O;
|
||||||
|
+ if (extension == "def")
|
||||||
|
+ return SOURCE_DEF;
|
||||||
|
+ if (extension == "rs")
|
||||||
|
+ return SOURCE_RS;
|
||||||
|
+ if (extension == "go")
|
||||||
|
+ return SOURCE_GO;
|
||||||
|
+
|
||||||
|
+ return SOURCE_UNKNOWN;
|
||||||
|
+}
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tools/gn/tools/gn/source_file_type.h
|
||||||
|
@@ -0,0 +1,34 @@
|
||||||
|
+// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||||
|
+// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
+// found in the LICENSE file.
|
||||||
|
+
|
||||||
|
+#ifndef TOOLS_GN_SOURCE_FILE_TYPE_H_
|
||||||
|
+#define TOOLS_GN_SOURCE_FILE_TYPE_H_
|
||||||
|
+
|
||||||
|
+class SourceFile;
|
||||||
|
+
|
||||||
|
+// This should be sequential integers starting from 0 so they can be used as
|
||||||
|
+// array indices.
|
||||||
|
+enum SourceFileType {
|
||||||
|
+ SOURCE_UNKNOWN = 0,
|
||||||
|
+ SOURCE_ASM,
|
||||||
|
+ SOURCE_C,
|
||||||
|
+ SOURCE_CPP,
|
||||||
|
+ SOURCE_H,
|
||||||
|
+ SOURCE_M,
|
||||||
|
+ SOURCE_MM,
|
||||||
|
+ SOURCE_S,
|
||||||
|
+ SOURCE_RC,
|
||||||
|
+ SOURCE_O, // Object files can be inputs, too. Also counts .obj.
|
||||||
|
+ SOURCE_DEF,
|
||||||
|
+
|
||||||
|
+ SOURCE_RS,
|
||||||
|
+ SOURCE_GO,
|
||||||
|
+
|
||||||
|
+ // Must be last.
|
||||||
|
+ SOURCE_NUMTYPES,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+SourceFileType GetSourceFileType(const SourceFile& file);
|
||||||
|
+
|
||||||
|
+#endif // TOOLS_GN_SOURCE_FILE_TYPE_H_
|
||||||
|
--- a/tools/gn/tools/gn/target.cc
|
||||||
|
+++ b/tools/gn/tools/gn/target.cc
|
||||||
|
@@ -16,6 +16,7 @@
|
||||||
|
#include "tools/gn/filesystem_utils.h"
|
||||||
|
#include "tools/gn/functions.h"
|
||||||
|
#include "tools/gn/scheduler.h"
|
||||||
|
+#include "tools/gn/source_file_type.h"
|
||||||
|
#include "tools/gn/substitution_writer.h"
|
||||||
|
#include "tools/gn/tool.h"
|
||||||
|
#include "tools/gn/toolchain.h"
|
||||||
|
@@ -486,10 +487,10 @@ bool Target::GetOutputFilesForSource(con
|
||||||
|
outputs->clear();
|
||||||
|
*computed_tool_type = Tool::kToolNone;
|
||||||
|
|
||||||
|
- SourceFile::Type file_type = source.type();
|
||||||
|
- if (file_type == SourceFile::SOURCE_UNKNOWN)
|
||||||
|
+ SourceFileType file_type = GetSourceFileType(source);
|
||||||
|
+ if (file_type == SOURCE_UNKNOWN)
|
||||||
|
return false;
|
||||||
|
- if (file_type == SourceFile::SOURCE_O) {
|
||||||
|
+ if (file_type == SOURCE_O) {
|
||||||
|
// Object files just get passed to the output and not compiled.
|
||||||
|
outputs->push_back(OutputFile(settings()->build_settings(), source));
|
||||||
|
return true;
|
||||||
|
--- a/tools/gn/tools/gn/tool.cc
|
||||||
|
+++ b/tools/gn/tools/gn/tool.cc
|
||||||
|
@@ -261,27 +261,27 @@ std::unique_ptr<Tool> Tool::CreateTool(c
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
-const char* Tool::GetToolTypeForSourceType(SourceFile::Type type) {
|
||||||
|
+const char* Tool::GetToolTypeForSourceType(SourceFileType type) {
|
||||||
|
switch (type) {
|
||||||
|
- case SourceFile::SOURCE_C:
|
||||||
|
+ case SOURCE_C:
|
||||||
|
return CTool::kCToolCc;
|
||||||
|
- case SourceFile::SOURCE_CPP:
|
||||||
|
+ case SOURCE_CPP:
|
||||||
|
return CTool::kCToolCxx;
|
||||||
|
- case SourceFile::SOURCE_M:
|
||||||
|
+ case SOURCE_M:
|
||||||
|
return CTool::kCToolObjC;
|
||||||
|
- case SourceFile::SOURCE_MM:
|
||||||
|
+ case SOURCE_MM:
|
||||||
|
return CTool::kCToolObjCxx;
|
||||||
|
- case SourceFile::SOURCE_ASM:
|
||||||
|
- case SourceFile::SOURCE_S:
|
||||||
|
+ case SOURCE_ASM:
|
||||||
|
+ case SOURCE_S:
|
||||||
|
return CTool::kCToolAsm;
|
||||||
|
- case SourceFile::SOURCE_RC:
|
||||||
|
+ case SOURCE_RC:
|
||||||
|
return CTool::kCToolRc;
|
||||||
|
- case SourceFile::SOURCE_UNKNOWN:
|
||||||
|
- case SourceFile::SOURCE_H:
|
||||||
|
- case SourceFile::SOURCE_O:
|
||||||
|
- case SourceFile::SOURCE_DEF:
|
||||||
|
- case SourceFile::SOURCE_GO:
|
||||||
|
- case SourceFile::SOURCE_RS:
|
||||||
|
+ case SOURCE_UNKNOWN:
|
||||||
|
+ case SOURCE_H:
|
||||||
|
+ case SOURCE_O:
|
||||||
|
+ case SOURCE_DEF:
|
||||||
|
+ case SOURCE_GO:
|
||||||
|
+ case SOURCE_RS:
|
||||||
|
return kToolNone;
|
||||||
|
default:
|
||||||
|
NOTREACHED();
|
||||||
|
--- a/tools/gn/tools/gn/tool.h
|
||||||
|
+++ b/tools/gn/tools/gn/tool.h
|
||||||
|
@@ -12,7 +12,7 @@
|
||||||
|
#include "tools/gn/label.h"
|
||||||
|
#include "tools/gn/label_ptr.h"
|
||||||
|
#include "tools/gn/scope.h"
|
||||||
|
-#include "tools/gn/source_file.h"
|
||||||
|
+#include "tools/gn/source_file_type.h"
|
||||||
|
#include "tools/gn/substitution_list.h"
|
||||||
|
#include "tools/gn/substitution_pattern.h"
|
||||||
|
|
||||||
|
@@ -171,7 +171,7 @@ class Tool {
|
||||||
|
Toolchain* toolchain,
|
||||||
|
Err* err);
|
||||||
|
|
||||||
|
- static const char* GetToolTypeForSourceType(SourceFile::Type type);
|
||||||
|
+ static const char* GetToolTypeForSourceType(SourceFileType type);
|
||||||
|
static const char* GetToolTypeForTargetFinalOutput(const Target* target);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
--- a/tools/gn/tools/gn/toolchain.cc
|
||||||
|
+++ b/tools/gn/tools/gn/toolchain.cc
|
||||||
|
@@ -88,16 +88,16 @@ void Toolchain::ToolchainSetupComplete()
|
||||||
|
setup_complete_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
-const Tool* Toolchain::GetToolForSourceType(SourceFile::Type type) const {
|
||||||
|
+const Tool* Toolchain::GetToolForSourceType(SourceFileType type) const {
|
||||||
|
return GetTool(Tool::GetToolTypeForSourceType(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
-const CTool* Toolchain::GetToolForSourceTypeAsC(SourceFile::Type type) const {
|
||||||
|
+const CTool* Toolchain::GetToolForSourceTypeAsC(SourceFileType type) const {
|
||||||
|
return GetToolAsC(Tool::GetToolTypeForSourceType(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
const GeneralTool* Toolchain::GetToolForSourceTypeAsGeneral(
|
||||||
|
- SourceFile::Type type) const {
|
||||||
|
+ SourceFileType type) const {
|
||||||
|
return GetToolAsGeneral(Tool::GetToolTypeForSourceType(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
--- a/tools/gn/tools/gn/toolchain.h
|
||||||
|
+++ b/tools/gn/tools/gn/toolchain.h
|
||||||
|
@@ -12,6 +12,7 @@
|
||||||
|
#include "tools/gn/item.h"
|
||||||
|
#include "tools/gn/label_ptr.h"
|
||||||
|
#include "tools/gn/scope.h"
|
||||||
|
+#include "tools/gn/source_file_type.h"
|
||||||
|
#include "tools/gn/substitution_type.h"
|
||||||
|
#include "tools/gn/tool.h"
|
||||||
|
#include "tools/gn/value.h"
|
||||||
|
@@ -87,9 +88,9 @@ class Toolchain : public Item {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the tool for compiling the given source file type.
|
||||||
|
- const Tool* GetToolForSourceType(SourceFile::Type type) const;
|
||||||
|
- const CTool* GetToolForSourceTypeAsC(SourceFile::Type type) const;
|
||||||
|
- const GeneralTool* GetToolForSourceTypeAsGeneral(SourceFile::Type type) const;
|
||||||
|
+ const Tool* GetToolForSourceType(SourceFileType type) const;
|
||||||
|
+ const CTool* GetToolForSourceTypeAsC(SourceFileType type) const;
|
||||||
|
+ const GeneralTool* GetToolForSourceTypeAsGeneral(SourceFileType type) const;
|
||||||
|
|
||||||
|
// Returns the tool that produces the final output for the given target type.
|
||||||
|
// This isn't necessarily the tool you would expect. For copy target, this
|
||||||
|
--- a/tools/gn/tools/gn/visual_studio_writer.cc
|
||||||
|
+++ b/tools/gn/tools/gn/visual_studio_writer.cc
|
||||||
|
@@ -24,6 +24,7 @@
|
||||||
|
#include "tools/gn/label_pattern.h"
|
||||||
|
#include "tools/gn/parse_tree.h"
|
||||||
|
#include "tools/gn/path_output.h"
|
||||||
|
+#include "tools/gn/source_file_type.h"
|
||||||
|
#include "tools/gn/standard_out.h"
|
||||||
|
#include "tools/gn/target.h"
|
||||||
|
#include "tools/gn/variables.h"
|
@ -0,0 +1,134 @@
|
|||||||
|
Description: revert https://gn.googlesource.com/gn/+/8730b0feb6b991fa47368566501ab9ccfb453c92, which breaks the chromium build
|
||||||
|
|
||||||
|
--- a/tools/gn/tools/gn/binary_target_generator.cc
|
||||||
|
+++ b/tools/gn/tools/gn/binary_target_generator.cc
|
||||||
|
@@ -68,38 +68,6 @@ void BinaryTargetGenerator::DoRun() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool BinaryTargetGenerator::FillSources() {
|
||||||
|
- bool ret = TargetGenerator::FillSources();
|
||||||
|
- for (std::size_t i = 0; i < target_->sources().size(); ++i) {
|
||||||
|
- const auto& source = target_->sources()[i];
|
||||||
|
- switch (source.type()) {
|
||||||
|
- case SourceFile::SOURCE_CPP:
|
||||||
|
- case SourceFile::SOURCE_H:
|
||||||
|
- case SourceFile::SOURCE_C:
|
||||||
|
- case SourceFile::SOURCE_M:
|
||||||
|
- case SourceFile::SOURCE_MM:
|
||||||
|
- case SourceFile::SOURCE_S:
|
||||||
|
- case SourceFile::SOURCE_ASM:
|
||||||
|
- case SourceFile::SOURCE_O:
|
||||||
|
- // These are allowed.
|
||||||
|
- break;
|
||||||
|
- case SourceFile::SOURCE_RC:
|
||||||
|
- case SourceFile::SOURCE_DEF:
|
||||||
|
- case SourceFile::SOURCE_RS:
|
||||||
|
- case SourceFile::SOURCE_GO:
|
||||||
|
- case SourceFile::SOURCE_UNKNOWN:
|
||||||
|
- case SourceFile::SOURCE_NUMTYPES:
|
||||||
|
- *err_ =
|
||||||
|
- Err(scope_->GetValue(variables::kSources, true)->list_value()[i],
|
||||||
|
- std::string("Only source, header, and object files belong in "
|
||||||
|
- "the sources of a ") +
|
||||||
|
- Target::GetStringForOutputType(target_->output_type()) +
|
||||||
|
- ". " + source.value() + " is not one of the valid types.");
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- return ret;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
bool BinaryTargetGenerator::FillCompleteStaticLib() {
|
||||||
|
if (target_->output_type() == Target::STATIC_LIBRARY) {
|
||||||
|
const Value* value = scope_->GetValue(variables::kCompleteStaticLib, true);
|
||||||
|
--- a/tools/gn/tools/gn/binary_target_generator.h
|
||||||
|
+++ b/tools/gn/tools/gn/binary_target_generator.h
|
||||||
|
@@ -22,7 +22,6 @@ class BinaryTargetGenerator : public Tar
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void DoRun() override;
|
||||||
|
- bool FillSources() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool FillCompleteStaticLib();
|
||||||
|
--- a/tools/gn/tools/gn/source_dir.cc
|
||||||
|
+++ b/tools/gn/tools/gn/source_dir.cc
|
||||||
|
@@ -98,10 +98,10 @@ SourceFile SourceDir::ResolveRelativeFil
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
const std::string& input_string = p.string_value();
|
||||||
|
- if (!ValidateResolveInput<std::string>(true, p, input_string, err))
|
||||||
|
+ if (!ValidateResolveInput<std::string>(true, p, input_string, err)) {
|
||||||
|
return ret;
|
||||||
|
-
|
||||||
|
- ret.SetValue(ResolveRelative(input_string, value_, true, source_root));
|
||||||
|
+ }
|
||||||
|
+ ret.value_ = ResolveRelative(input_string, value_, true, source_root);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
--- a/tools/gn/tools/gn/source_file.cc
|
||||||
|
+++ b/tools/gn/tools/gn/source_file.cc
|
||||||
|
@@ -55,19 +55,18 @@ SourceFile::Type GetSourceFileType(const
|
||||||
|
SourceFile::SourceFile() : type_(SOURCE_UNKNOWN) {}
|
||||||
|
|
||||||
|
SourceFile::SourceFile(const base::StringPiece& p)
|
||||||
|
- : value_(p.data(), p.size()) {
|
||||||
|
+ : value_(p.data(), p.size()), type_(GetSourceFileType(value_)) {
|
||||||
|
DCHECK(!value_.empty());
|
||||||
|
AssertValueSourceFileString(value_);
|
||||||
|
NormalizePath(&value_);
|
||||||
|
- type_ = GetSourceFileType(value_);
|
||||||
|
}
|
||||||
|
|
||||||
|
-SourceFile::SourceFile(SwapIn, std::string* value) {
|
||||||
|
+SourceFile::SourceFile(SwapIn, std::string* value)
|
||||||
|
+ : type_(GetSourceFileType(*value)) {
|
||||||
|
value_.swap(*value);
|
||||||
|
DCHECK(!value_.empty());
|
||||||
|
AssertValueSourceFileString(value_);
|
||||||
|
NormalizePath(&value_);
|
||||||
|
- type_ = GetSourceFileType(value_);
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceFile::~SourceFile() = default;
|
||||||
|
@@ -93,8 +92,3 @@ SourceDir SourceFile::GetDir() const {
|
||||||
|
base::FilePath SourceFile::Resolve(const base::FilePath& source_root) const {
|
||||||
|
return ResolvePath(value_, true, source_root);
|
||||||
|
}
|
||||||
|
-
|
||||||
|
-void SourceFile::SetValue(const std::string& value) {
|
||||||
|
- value_ = value;
|
||||||
|
- type_ = GetSourceFileType(value_);
|
||||||
|
-}
|
||||||
|
--- a/tools/gn/tools/gn/source_file.h
|
||||||
|
+++ b/tools/gn/tools/gn/source_file.h
|
||||||
|
@@ -97,16 +97,11 @@ class SourceFile {
|
||||||
|
return value_ < other.value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
- void swap(SourceFile& other) {
|
||||||
|
- value_.swap(other.value_);
|
||||||
|
- std::swap(type_, other.type_);
|
||||||
|
- }
|
||||||
|
+ void swap(SourceFile& other) { value_.swap(other.value_); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class SourceDir;
|
||||||
|
|
||||||
|
- void SetValue(const std::string& value);
|
||||||
|
-
|
||||||
|
std::string value_;
|
||||||
|
Type type_;
|
||||||
|
|
||||||
|
--- a/tools/gn/tools/gn/target_generator.h
|
||||||
|
+++ b/tools/gn/tools/gn/target_generator.h
|
||||||
|
@@ -47,7 +47,7 @@ class TargetGenerator {
|
||||||
|
|
||||||
|
const BuildSettings* GetBuildSettings() const;
|
||||||
|
|
||||||
|
- virtual bool FillSources();
|
||||||
|
+ bool FillSources();
|
||||||
|
bool FillPublic();
|
||||||
|
bool FillConfigs();
|
||||||
|
bool FillOutputs(bool allow_substitutions);
|
Loading…
Reference in new issue