230 lines
11 KiB
Diff
230 lines
11 KiB
Diff
|
From cdf3e81ff49b200213d67d65558f2919222b60ab Mon Sep 17 00:00:00 2001
|
||
|
From: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com>
|
||
|
Date: Mon, 16 Dec 2019 11:39:11 +0000
|
||
|
Subject: [PATCH] BookmarkModelMerger: Move RemoteTreeNode declaration to header.
|
||
|
|
||
|
This fixes the build with libstdc++ after commit 8f5dad93e58 ("Fix CHECK
|
||
|
failure due to untracked local nodes"):
|
||
|
|
||
|
/usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/bits/stl_pair.h:215:11: error: field has incomplete type 'sync_bookmarks::BookmarkModelMerger::RemoteTreeNode'
|
||
|
_T2 second; /// @c second is a copy of the second object
|
||
|
^
|
||
|
/usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/ext/aligned_buffer.h:91:28: note: in instantiation of template class 'std::pair<const std::__cxx11::basic_string<char>, sync_bookmarks::BookmarkModelMerger::RemoteTreeNode>' requested here
|
||
|
: std::aligned_storage<sizeof(_Tp), __alignof__(_Tp)>
|
||
|
^
|
||
|
/usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/bits/hashtable_policy.h:233:43: note: in instantiation of template class '__gnu_cxx::__aligned_buffer<std::pair<const std::__cxx11::basic_string<char>, sync_bookmarks::BookmarkModelMerger::RemoteTreeNode> >' requested here
|
||
|
__gnu_cxx::__aligned_buffer<_Value> _M_storage;
|
||
|
^
|
||
|
/usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/bits/hashtable_policy.h:264:39: note: in instantiation of template class 'std::__detail::_Hash_node_value_base<std::pair<const std::__cxx11::basic_string<char>, sync_bookmarks::BookmarkModelMerger::RemoteTreeNode> >' requested here
|
||
|
struct _Hash_node<_Value, true> : _Hash_node_value_base<_Value>
|
||
|
^
|
||
|
/usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/bits/hashtable_policy.h:2028:25: note: in instantiation of template class 'std::__detail::_Hash_node<std::pair<const std::__cxx11::basic_string<char>, sync_bookmarks::BookmarkModelMerger::RemoteTreeNode>, true>' requested here
|
||
|
rebind_traits<typename __node_type::value_type>;
|
||
|
^
|
||
|
/usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/bits/hashtable.h:184:15: note: in instantiation of template class 'std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<const std::__cxx11::basic_string<char>, sync_bookmarks::BookmarkModelMerger::RemoteTreeNode>, true> > >
|
||
|
' requested here
|
||
|
private __detail::_Hashtable_alloc<
|
||
|
^
|
||
|
/usr/lib/gcc/x86_64-redhat-linux/9/../../../../include/c++/9/bits/unordered_map.h:105:18: note: in instantiation of template class 'std::_Hashtable<std::__cxx11::basic_string<char>, std::pair<const std::__cxx11::basic_string<char>, sync_bookmarks::BookmarkModelMerger::RemoteTreeNode>, std::allocator<std::pair<con
|
||
|
st std::__cxx11::basic_string<char>, sync_bookmarks::BookmarkModelMerger::RemoteTreeNode> >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char> >, std::hash<std::string>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__deta
|
||
|
il::_Hashtable_traits<true, false, true> >' requested here
|
||
|
_Hashtable _M_h;
|
||
|
^
|
||
|
../../components/sync_bookmarks/bookmark_model_merger.h:146:22: note: in instantiation of template class 'std::unordered_map<std::__cxx11::basic_string<char>, sync_bookmarks::BookmarkModelMerger::RemoteTreeNode, std::hash<std::string>, std::equal_to<std::__cxx11::basic_string<char> >, std::allocator<std::pair<con
|
||
|
st std::__cxx11::basic_string<char>, sync_bookmarks::BookmarkModelMerger::RemoteTreeNode> > >' requested here
|
||
|
const RemoteForest remote_forest_;
|
||
|
^
|
||
|
../../components/sync_bookmarks/bookmark_model_merger.h:53:9: note: forward declaration of 'sync_bookmarks::BookmarkModelMerger::RemoteTreeNode'
|
||
|
class RemoteTreeNode;
|
||
|
^
|
||
|
|
||
|
Essentially, the problem is that libstdc++'s std::unordered_map<T, U>
|
||
|
implementation requires both T and U to be fully declared. I raised the
|
||
|
problem in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92770, and GCC's
|
||
|
position is that we are relying on undefined behavior according to the C++
|
||
|
standard (https://eel.is/c++draft/requirements#res.on.functions-2.5).
|
||
|
|
||
|
Bug: 957519
|
||
|
Change-Id: Ife7e435e516932a795bfbe05b2c910c3272878f0
|
||
|
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1960156
|
||
|
Commit-Queue: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com>
|
||
|
Reviewed-by: Mikel Astiz <mastiz@chromium.org>
|
||
|
Auto-Submit: Raphael Kubo da Costa <raphael.kubo.da.costa@intel.com>
|
||
|
Cr-Commit-Position: refs/heads/master@{#725070}
|
||
|
---
|
||
|
|
||
|
diff --git a/components/sync_bookmarks/bookmark_model_merger.cc b/components/sync_bookmarks/bookmark_model_merger.cc
|
||
|
index eae153ef..579848e 100644
|
||
|
--- a/components/sync_bookmarks/bookmark_model_merger.cc
|
||
|
+++ b/components/sync_bookmarks/bookmark_model_merger.cc
|
||
|
@@ -5,7 +5,6 @@
|
||
|
#include "components/sync_bookmarks/bookmark_model_merger.h"
|
||
|
|
||
|
#include <algorithm>
|
||
|
-#include <memory>
|
||
|
#include <set>
|
||
|
#include <string>
|
||
|
#include <utility>
|
||
|
@@ -205,66 +204,44 @@
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
-class BookmarkModelMerger::RemoteTreeNode final {
|
||
|
- public:
|
||
|
- // Constructs a tree given |update| as root and recursively all descendants by
|
||
|
- // traversing |*updates_per_parent_id|. |update| and |updates_per_parent_id|
|
||
|
- // must not be null. All updates |*updates_per_parent_id| must represent valid
|
||
|
- // updates. Updates corresponding from descendant nodes are moved away from
|
||
|
- // |*updates_per_parent_id|.
|
||
|
- static RemoteTreeNode BuildTree(
|
||
|
- std::unique_ptr<syncer::UpdateResponseData> update,
|
||
|
- UpdatesPerParentId* updates_per_parent_id);
|
||
|
+BookmarkModelMerger::RemoteTreeNode::RemoteTreeNode() = default;
|
||
|
|
||
|
- ~RemoteTreeNode() = default;
|
||
|
+BookmarkModelMerger::RemoteTreeNode::~RemoteTreeNode() = default;
|
||
|
|
||
|
- // Allow moves, useful during construction.
|
||
|
- RemoteTreeNode(RemoteTreeNode&&) = default;
|
||
|
- RemoteTreeNode& operator=(RemoteTreeNode&&) = default;
|
||
|
+BookmarkModelMerger::RemoteTreeNode::RemoteTreeNode(
|
||
|
+ BookmarkModelMerger::RemoteTreeNode&&) = default;
|
||
|
+BookmarkModelMerger::RemoteTreeNode& BookmarkModelMerger::RemoteTreeNode::
|
||
|
+operator=(BookmarkModelMerger::RemoteTreeNode&&) = default;
|
||
|
|
||
|
- const syncer::EntityData& entity() const { return *update_->entity; }
|
||
|
- int64_t response_version() const { return update_->response_version; }
|
||
|
+void BookmarkModelMerger::RemoteTreeNode::EmplaceSelfAndDescendantsByGUID(
|
||
|
+ std::unordered_map<std::string, const RemoteTreeNode*>*
|
||
|
+ guid_to_remote_node_map) const {
|
||
|
+ DCHECK(guid_to_remote_node_map);
|
||
|
|
||
|
- // Direct children nodes, sorted by ascending unique position. These are
|
||
|
- // guaranteed to be valid updates (e.g. IsValidBookmarkSpecifics()).
|
||
|
- const std::vector<RemoteTreeNode>& children() const { return children_; }
|
||
|
+ const std::string& guid = entity().specifics.bookmark().guid();
|
||
|
+ if (!guid.empty()) {
|
||
|
+ DCHECK(base::IsValidGUID(guid));
|
||
|
|
||
|
- // Recursively emplaces all GUIDs (this node and descendants) into
|
||
|
- // |*guid_to_remote_node_map|, which must not be null.
|
||
|
- void EmplaceSelfAndDescendantsByGUID(
|
||
|
- std::unordered_map<std::string, const RemoteTreeNode*>*
|
||
|
- guid_to_remote_node_map) const {
|
||
|
- DCHECK(guid_to_remote_node_map);
|
||
|
-
|
||
|
- const std::string& guid = entity().specifics.bookmark().guid();
|
||
|
- if (!guid.empty()) {
|
||
|
- DCHECK(base::IsValidGUID(guid));
|
||
|
-
|
||
|
- // Duplicate GUIDs have been sorted out before.
|
||
|
- bool success = guid_to_remote_node_map->emplace(guid, this).second;
|
||
|
- DCHECK(success);
|
||
|
- }
|
||
|
-
|
||
|
- for (const RemoteTreeNode& child : children_) {
|
||
|
- child.EmplaceSelfAndDescendantsByGUID(guid_to_remote_node_map);
|
||
|
- }
|
||
|
+ // Duplicate GUIDs have been sorted out before.
|
||
|
+ bool success = guid_to_remote_node_map->emplace(guid, this).second;
|
||
|
+ DCHECK(success);
|
||
|
}
|
||
|
|
||
|
- private:
|
||
|
- static bool UniquePositionLessThan(const RemoteTreeNode& lhs,
|
||
|
- const RemoteTreeNode& rhs) {
|
||
|
- const syncer::UniquePosition a_pos =
|
||
|
- syncer::UniquePosition::FromProto(lhs.entity().unique_position);
|
||
|
- const syncer::UniquePosition b_pos =
|
||
|
- syncer::UniquePosition::FromProto(rhs.entity().unique_position);
|
||
|
- return a_pos.LessThan(b_pos);
|
||
|
+ for (const RemoteTreeNode& child : children_) {
|
||
|
+ child.EmplaceSelfAndDescendantsByGUID(guid_to_remote_node_map);
|
||
|
}
|
||
|
+}
|
||
|
|
||
|
- RemoteTreeNode() = default;
|
||
|
-
|
||
|
- std::unique_ptr<syncer::UpdateResponseData> update_;
|
||
|
- std::vector<RemoteTreeNode> children_;
|
||
|
-};
|
||
|
+// static
|
||
|
+bool BookmarkModelMerger::RemoteTreeNode::UniquePositionLessThan(
|
||
|
+ const RemoteTreeNode& lhs,
|
||
|
+ const RemoteTreeNode& rhs) {
|
||
|
+ const syncer::UniquePosition a_pos =
|
||
|
+ syncer::UniquePosition::FromProto(lhs.entity().unique_position);
|
||
|
+ const syncer::UniquePosition b_pos =
|
||
|
+ syncer::UniquePosition::FromProto(rhs.entity().unique_position);
|
||
|
+ return a_pos.LessThan(b_pos);
|
||
|
+}
|
||
|
|
||
|
// static
|
||
|
BookmarkModelMerger::RemoteTreeNode
|
||
|
diff --git a/components/sync_bookmarks/bookmark_model_merger.h b/components/sync_bookmarks/bookmark_model_merger.h
|
||
|
index 9b59200..bf0783ec 100644
|
||
|
--- a/components/sync_bookmarks/bookmark_model_merger.h
|
||
|
+++ b/components/sync_bookmarks/bookmark_model_merger.h
|
||
|
@@ -5,6 +5,7 @@
|
||
|
#ifndef COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_MODEL_MERGER_H_
|
||
|
#define COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_MODEL_MERGER_H_
|
||
|
|
||
|
+#include <memory>
|
||
|
#include <string>
|
||
|
#include <unordered_map>
|
||
|
#include <vector>
|
||
|
@@ -50,7 +51,52 @@
|
||
|
|
||
|
private:
|
||
|
// Internal representation of a remote tree, composed of nodes.
|
||
|
- class RemoteTreeNode;
|
||
|
+ class RemoteTreeNode final {
|
||
|
+ private:
|
||
|
+ using UpdatesPerParentId =
|
||
|
+ std::unordered_map<base::StringPiece,
|
||
|
+ syncer::UpdateResponseDataList,
|
||
|
+ base::StringPieceHash>;
|
||
|
+
|
||
|
+ public:
|
||
|
+ // Constructs a tree given |update| as root and recursively all descendants
|
||
|
+ // by traversing |*updates_per_parent_id|. |update| and
|
||
|
+ // |updates_per_parent_id| must not be null. All updates
|
||
|
+ // |*updates_per_parent_id| must represent valid updates. Updates
|
||
|
+ // corresponding from descendant nodes are moved away from
|
||
|
+ // |*updates_per_parent_id|.
|
||
|
+ static RemoteTreeNode BuildTree(
|
||
|
+ std::unique_ptr<syncer::UpdateResponseData> update,
|
||
|
+ UpdatesPerParentId* updates_per_parent_id);
|
||
|
+
|
||
|
+ ~RemoteTreeNode();
|
||
|
+
|
||
|
+ // Allow moves, useful during construction.
|
||
|
+ RemoteTreeNode(RemoteTreeNode&&);
|
||
|
+ RemoteTreeNode& operator=(RemoteTreeNode&&);
|
||
|
+
|
||
|
+ const syncer::EntityData& entity() const { return *update_->entity; }
|
||
|
+ int64_t response_version() const { return update_->response_version; }
|
||
|
+
|
||
|
+ // Direct children nodes, sorted by ascending unique position. These are
|
||
|
+ // guaranteed to be valid updates (e.g. IsValidBookmarkSpecifics()).
|
||
|
+ const std::vector<RemoteTreeNode>& children() const { return children_; }
|
||
|
+
|
||
|
+ // Recursively emplaces all GUIDs (this node and descendants) into
|
||
|
+ // |*guid_to_remote_node_map|, which must not be null.
|
||
|
+ void EmplaceSelfAndDescendantsByGUID(
|
||
|
+ std::unordered_map<std::string, const RemoteTreeNode*>*
|
||
|
+ guid_to_remote_node_map) const;
|
||
|
+
|
||
|
+ private:
|
||
|
+ static bool UniquePositionLessThan(const RemoteTreeNode& lhs,
|
||
|
+ const RemoteTreeNode& rhs);
|
||
|
+
|
||
|
+ RemoteTreeNode();
|
||
|
+
|
||
|
+ std::unique_ptr<syncer::UpdateResponseData> update_;
|
||
|
+ std::vector<RemoteTreeNode> children_;
|
||
|
+ };
|
||
|
|
||
|
// A forest composed of multiple trees where the root of each tree represents
|
||
|
// a permanent node, keyed by server-defined unique tag of the root.
|