Clang: Fix set_union bug

std::set_union in libC++ is broken for move iterators. We has to use
temporarily our own implementation which can be removed if we move to a
newer version of XCode.

Task-number: QTCREATORBUG-22246
Change-Id: I8fccc8aab5f8af738aa2e589ba65924363cd818d
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
Marco Bubke
2019-04-02 18:29:13 +02:00
parent dce3e9708c
commit eb53b183ba
5 changed files with 103 additions and 29 deletions

View File

@@ -25,6 +25,8 @@
#include "generatedfiles.h" #include "generatedfiles.h"
#include <utils/algorithm.h>
namespace ClangBackEnd { namespace ClangBackEnd {
void GeneratedFiles::update(V2::FileContainers &&fileContainers) void GeneratedFiles::update(V2::FileContainers &&fileContainers)
@@ -32,16 +34,16 @@ void GeneratedFiles::update(V2::FileContainers &&fileContainers)
V2::FileContainers unionFileContainers; V2::FileContainers unionFileContainers;
unionFileContainers.reserve(m_fileContainers.size() + fileContainers.size()); unionFileContainers.reserve(m_fileContainers.size() + fileContainers.size());
auto compare = [] (const V2::FileContainer &first, const V2::FileContainer &second) { auto compare = [](const V2::FileContainer &first, const V2::FileContainer &second) {
return first.filePath < second.filePath; return first.filePath < second.filePath;
}; };
std::set_union(std::make_move_iterator(fileContainers.begin()), Utils::set_union(std::make_move_iterator(fileContainers.begin()),
std::make_move_iterator(fileContainers.end()), std::make_move_iterator(fileContainers.end()),
std::make_move_iterator(m_fileContainers.begin()), std::make_move_iterator(m_fileContainers.begin()),
std::make_move_iterator(m_fileContainers.end()), std::make_move_iterator(m_fileContainers.end()),
std::back_inserter(unionFileContainers), std::back_inserter(unionFileContainers),
compare); compare);
m_fileContainers = std::move(unionFileContainers); m_fileContainers = std::move(unionFileContainers);
} }
@@ -55,12 +57,12 @@ void GeneratedFiles::update(const V2::FileContainers &fileContainers)
return first.filePath < second.filePath; return first.filePath < second.filePath;
}; };
std::set_union(fileContainers.begin(), Utils::set_union(fileContainers.begin(),
fileContainers.end(), fileContainers.end(),
std::make_move_iterator(m_fileContainers.begin()), std::make_move_iterator(m_fileContainers.begin()),
std::make_move_iterator(m_fileContainers.end()), std::make_move_iterator(m_fileContainers.end()),
std::back_inserter(unionFileContainers), std::back_inserter(unionFileContainers),
compare); compare);
m_fileContainers = std::move(unionFileContainers); m_fileContainers = std::move(unionFileContainers);
} }

View File

@@ -862,4 +862,70 @@ std::make_signed_t<typename Container::size_type> ssize(Container container)
{ {
return static_cast<std::make_signed_t<typename Container::size_type>>(container.size()); return static_cast<std::make_signed_t<typename Container::size_type>>(container.size());
} }
template<typename Compare>
struct CompareIter
{
Compare compare;
explicit constexpr CompareIter(Compare compare)
: compare(std::move(compare))
{}
template<typename Iterator1, typename Iterator2>
constexpr bool operator()(Iterator1 it1, Iterator2 it2)
{
return bool(compare(*it1, *it2));
}
};
template<typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>
OutputIterator set_union_impl(InputIterator1 first1,
InputIterator1 last1,
InputIterator2 first2,
InputIterator2 last2,
OutputIterator result,
Compare comp)
{
auto compare = CompareIter<Compare>(comp);
while (first1 != last1 && first2 != last2) {
if (compare(first1, first2)) {
*result = *first1;
++first1;
} else if (compare(first2, first1)) {
*result = *first2;
++first2;
} else {
*result = *first1;
++first1;
++first2;
}
++result;
}
return std::copy(first2, last2, std::copy(first1, last1, result));
}
template<typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>
OutputIterator set_union(InputIterator1 first1,
InputIterator1 last1,
InputIterator2 first2,
InputIterator2 last2,
OutputIterator result,
Compare comp)
{
return Utils::set_union_impl(first1, last1, first2, last2, result, comp);
}
template<typename InputIterator1, typename InputIterator2, typename OutputIterator>
OutputIterator set_union(InputIterator1 first1,
InputIterator1 last1,
InputIterator2 first2,
InputIterator2 last2,
OutputIterator result)
{
return Utils::set_union_impl(
first1, last1, first2, last2, result, std::less<typename InputIterator1::value_type>{});
}
} // namespace Utils } // namespace Utils

View File

@@ -30,6 +30,8 @@
#include <progresscounter.h> #include <progresscounter.h>
#include <sqlitetransaction.h> #include <sqlitetransaction.h>
#include <utils/algorithm.h>
namespace ClangBackEnd { namespace ClangBackEnd {
void PchTaskQueue::addPchTasks(PchTasks &&newPchTasks, PchTasks &destination) void PchTaskQueue::addPchTasks(PchTasks &&newPchTasks, PchTasks &destination)
@@ -42,12 +44,12 @@ void PchTaskQueue::addPchTasks(PchTasks &&newPchTasks, PchTasks &destination)
PchTasks mergedPchTasks; PchTasks mergedPchTasks;
mergedPchTasks.reserve(destination.size() + newPchTasks.size()); mergedPchTasks.reserve(destination.size() + newPchTasks.size());
std::set_union(std::make_move_iterator(newPchTasks.begin()), Utils::set_union(std::make_move_iterator(newPchTasks.begin()),
std::make_move_iterator(newPchTasks.end()), std::make_move_iterator(newPchTasks.end()),
std::make_move_iterator(destination.begin()), std::make_move_iterator(destination.begin()),
std::make_move_iterator(destination.end()), std::make_move_iterator(destination.end()),
std::back_inserter(mergedPchTasks), std::back_inserter(mergedPchTasks),
compare); compare);
destination = std::move(mergedPchTasks); destination = std::move(mergedPchTasks);

View File

@@ -27,6 +27,8 @@
#include "pchtaskqueueinterface.h" #include "pchtaskqueueinterface.h"
#include <utils/algorithm.h>
namespace ClangBackEnd { namespace ClangBackEnd {
void PchTasksMerger::mergeTasks(PchTaskSets &&taskSets, void PchTasksMerger::mergeTasks(PchTaskSets &&taskSets,
@@ -48,11 +50,11 @@ Result merge(Container &&first, Container &&second)
Result result; Result result;
result.reserve(first.size() + second.size()); result.reserve(first.size() + second.size());
std::set_union(std::make_move_iterator(first.begin()), Utils::set_union(std::make_move_iterator(first.begin()),
std::make_move_iterator(first.end()), std::make_move_iterator(first.end()),
std::make_move_iterator(second.begin()), std::make_move_iterator(second.begin()),
std::make_move_iterator(second.end()), std::make_move_iterator(second.end()),
std::back_inserter(result)); std::back_inserter(result));
return result; return result;
} }

View File

@@ -27,6 +27,8 @@
#include <projectpartcontainer.h> #include <projectpartcontainer.h>
#include <utils/algorithm.h>
#include <functional> #include <functional>
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -48,11 +50,11 @@ struct ArgumentsEntry
ProjectPartIds mergedIds; ProjectPartIds mergedIds;
mergedIds.reserve(ids.size() + newIds.size()); mergedIds.reserve(ids.size() + newIds.size());
std::set_union(std::make_move_iterator(ids.begin()), Utils::set_union(std::make_move_iterator(ids.begin()),
std::make_move_iterator(ids.end()), std::make_move_iterator(ids.end()),
std::make_move_iterator(newIds.begin()), std::make_move_iterator(newIds.begin()),
std::make_move_iterator(newIds.end()), std::make_move_iterator(newIds.end()),
std::back_inserter(mergedIds)); std::back_inserter(mergedIds));
ids = std::move(mergedIds); ids = std::move(mergedIds);
} }