diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -95,6 +95,8 @@ /// Describes a module or submodule. class Module { public: + Module(const Module &) = default; + /// The name of this module. std::string Name; diff --git a/llvm/include/llvm/ADT/IterableTraits.h b/llvm/include/llvm/ADT/IterableTraits.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/ADT/IterableTraits.h @@ -0,0 +1,55 @@ +//===- IterableTraits.h - A trait to identify iterables ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ITERABLETRAITS_H +#define LLVM_ADT_ITERABLETRAITS_H + +#include +#include + +namespace llvm { + +namespace detail { + +template auto is_forward_iterator(...) -> std::false_type; + +template +auto is_forward_iterator(int) -> decltype( + std::next(std::declval()), + std::integral_constant< + bool, + std::is_convertible() != std::declval()), + bool>::value && + !std::is_void())>::value && + std::is_copy_constructible::value && true>{}); + +} // namespace detail + +// A convenient trait to check whether a type provides the forward iterator +// semantic. +template +struct is_forward_iterator : decltype(detail::is_forward_iterator(0)) {}; + +namespace detail { + +template auto is_range_iterable(...) -> std::false_type; + +template ()))>> +auto is_range_iterable(char) -> decltype(std::begin(std::declval()), // + std::end(std::declval()), // + llvm::is_forward_iterator{}); +} // namespace detail + +// A convenient trait to check whether a type provides the begin / end semantic. +template +struct is_range_iterable : decltype(detail::is_range_iterable(0)) {}; + +} // namespace llvm + +#endif // LLVM_ADT_ITERABLETRAITS_H diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h --- a/llvm/include/llvm/ADT/SmallVector.h +++ b/llvm/include/llvm/ADT/SmallVector.h @@ -13,7 +13,7 @@ #ifndef LLVM_ADT_SMALLVECTOR_H #define LLVM_ADT_SMALLVECTOR_H -#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/IterableTraits.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" @@ -1188,10 +1188,13 @@ this->append(S, E); } - template - explicit SmallVector(const iterator_range &R) + template + explicit SmallVector( + Iterable &&Range, + std::enable_if_t::value, bool> = true) : SmallVectorImpl(N) { - this->append(R.begin(), R.end()); + this->append(std::begin(std::forward(Range)), + std::end(std::forward(Range))); } SmallVector(std::initializer_list IL) : SmallVectorImpl(N) { diff --git a/llvm/tools/llvm-xray/xray-converter.cpp b/llvm/tools/llvm-xray/xray-converter.cpp --- a/llvm/tools/llvm-xray/xray-converter.cpp +++ b/llvm/tools/llvm-xray/xray-converter.cpp @@ -158,6 +158,8 @@ // A structure that allows building a dictionary of stack ids for the Chrome // trace event format. struct StackIdData { + StackIdData(const StackIdData &) = default; + // Each Stack of function calls has a unique ID. unsigned id; diff --git a/llvm/unittests/ADT/CMakeLists.txt b/llvm/unittests/ADT/CMakeLists.txt --- a/llvm/unittests/ADT/CMakeLists.txt +++ b/llvm/unittests/ADT/CMakeLists.txt @@ -41,6 +41,7 @@ IntEqClassesTest.cpp IntervalMapTest.cpp IntrusiveRefCntPtrTest.cpp + IterableTraitsTest.cpp IteratorTest.cpp MappedIteratorTest.cpp MapVectorTest.cpp diff --git a/llvm/unittests/ADT/IterableTraitsTest.cpp b/llvm/unittests/ADT/IterableTraitsTest.cpp new file mode 100644 --- /dev/null +++ b/llvm/unittests/ADT/IterableTraitsTest.cpp @@ -0,0 +1,62 @@ +//===- IterableTraitsTest.cpp - Unit tests for is_range_iterable ----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/IterableTraits.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" +#include "gtest/gtest.h" +#include +#include +#include + +namespace llvm { + +class ForwardDeclared; + +TEST(IteratorRangeTest, IsForwardIterator) { + EXPECT_FALSE(is_forward_iterator::value); + EXPECT_TRUE(is_forward_iterator::value); + EXPECT_TRUE(is_forward_iterator::value); + EXPECT_TRUE(is_forward_iterator::value); + using ForwardList = std::forward_list; + EXPECT_TRUE(is_forward_iterator::value); + EXPECT_TRUE(is_forward_iterator::value); +} + +TEST(IteratorRangeTest, IsIterableCArray) { + int Data[4]; + EXPECT_TRUE( + is_range_iterable>::value); +} + +TEST(IteratorRangeTest, IsIterableVector) { + using Vector = std::vector; + EXPECT_TRUE(is_range_iterable::value); +} + +TEST(IteratorRangeTest, IsIterableArray) { + using Array = std::array; + EXPECT_TRUE(is_range_iterable::value); +} + +TEST(IteratorRangeTest, IsIterableSmallVector) { + using SVector = SmallVector; + EXPECT_TRUE(is_range_iterable::value); +} + +TEST(IteratorRangeTest, IsIterableRange) { + using Range = iterator_range; + EXPECT_TRUE(is_range_iterable::value); +} + +TEST(IteratorRangeTest, NonIterableTypes) { + EXPECT_FALSE(is_range_iterable::value); + EXPECT_FALSE(is_range_iterable::value); +} + +} // namespace llvm diff --git a/llvm/unittests/ADT/SmallVectorTest.cpp b/llvm/unittests/ADT/SmallVectorTest.cpp --- a/llvm/unittests/ADT/SmallVectorTest.cpp +++ b/llvm/unittests/ADT/SmallVectorTest.cpp @@ -226,6 +226,22 @@ this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3); } +// Constructor test. +TYPED_TEST(SmallVectorTest, ConstructorIterableCArrayTest) { + SCOPED_TRACE("ConstructorTest"); + int arr[] = {1, 2, 3}; + this->theVector = SmallVector(arr); + this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3); +} + +// Constructor test. +TYPED_TEST(SmallVectorTest, ConstructorIterableVectorTest) { + SCOPED_TRACE("ConstructorTest"); + std::vector vec = {1, 2, 3}; + this->theVector = SmallVector(vec); + this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3); +} + // New vector test. TYPED_TEST(SmallVectorTest, EmptyVectorTest) { SCOPED_TRACE("EmptyVectorTest");