diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -146,16 +146,14 @@ using std::begin; template -auto adl_begin(ContainerTy &&container) - -> decltype(begin(std::forward(container))) { +decltype(auto) adl_begin(ContainerTy &&container) { return begin(std::forward(container)); } using std::end; template -auto adl_end(ContainerTy &&container) - -> decltype(end(std::forward(container))) { +decltype(auto) adl_end(ContainerTy &&container) { return end(std::forward(container)); } @@ -170,14 +168,12 @@ } // end namespace adl_detail template -auto adl_begin(ContainerTy &&container) - -> decltype(adl_detail::adl_begin(std::forward(container))) { +decltype(auto) adl_begin(ContainerTy &&container) { return adl_detail::adl_begin(std::forward(container)); } template -auto adl_end(ContainerTy &&container) - -> decltype(adl_detail::adl_end(std::forward(container))) { +decltype(auto) adl_end(ContainerTy &&container) { return adl_detail::adl_end(std::forward(container)); } @@ -195,9 +191,7 @@ /// Return a range covering \p RangeOrContainer with the first N elements /// excluded. -template -auto drop_begin(T &&RangeOrContainer, size_t N) -> - iterator_range { +template auto drop_begin(T &&RangeOrContainer, size_t N) { return make_range(std::next(adl_begin(RangeOrContainer), N), adl_end(RangeOrContainer)); } @@ -233,9 +227,7 @@ } template -auto map_range(ContainerTy &&C, FuncTy F) - -> decltype(make_range(map_iterator(C.begin(), F), - map_iterator(C.end(), F))) { +auto map_range(ContainerTy &&C, FuncTy F) { return make_range(map_iterator(C.begin(), F), map_iterator(C.end(), F)); } @@ -262,9 +254,9 @@ // Returns an iterator_range over the given container which iterates in reverse. // Note that the container must have rbegin()/rend() methods for this to work. template -auto reverse(ContainerTy &&C, - typename std::enable_if::value>::type * = - nullptr) -> decltype(make_range(C.rbegin(), C.rend())) { +auto reverse( + ContainerTy &&C, + typename std::enable_if::value>::type * = nullptr) { return make_range(C.rbegin(), C.rend()); } @@ -278,11 +270,9 @@ // Note that the container must have begin()/end() methods which return // bidirectional iterators for this to work. template -auto reverse( - ContainerTy &&C, - typename std::enable_if::value>::type * = nullptr) - -> decltype(make_range(llvm::make_reverse_iterator(std::end(C)), - llvm::make_reverse_iterator(std::begin(C)))) { +auto reverse(ContainerTy &&C, + typename std::enable_if::value>::type * = + nullptr) { return make_range(llvm::make_reverse_iterator(std::end(C)), llvm::make_reverse_iterator(std::begin(C))); } @@ -680,9 +670,8 @@ } template -static auto deref_or_none(const Iter &I, const Iter &End) - -> llvm::Optional::type>::type> { +static auto deref_or_none(const Iter &I, const Iter &End) -> llvm::Optional< + std::remove_const_t>> { if (I == End) return None; return *I; @@ -983,8 +972,7 @@ FuncTy func; template - auto operator()(const T &lhs, const T &rhs) const - -> decltype(func(lhs.first, rhs.first)) { + decltype(auto) operator()(const T &lhs, const T &rhs) const { return func(lhs.first, rhs.first); } }; @@ -1164,8 +1152,7 @@ std::is_same::iterator_category, std::random_access_iterator_tag>::value, - void>::type * = nullptr) - -> decltype(std::distance(Range.begin(), Range.end())) { + void>::type * = nullptr) { return std::distance(Range.begin(), Range.end()); } @@ -1199,27 +1186,26 @@ /// Provide wrappers to std::find which take ranges instead of having to pass /// begin/end explicitly. -template -auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range)) { +template auto find(R &&Range, const T &Val) { return std::find(adl_begin(Range), adl_end(Range), Val); } /// Provide wrappers to std::find_if which take ranges instead of having to pass /// begin/end explicitly. template -auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { +auto find_if(R &&Range, UnaryPredicate P) { return std::find_if(adl_begin(Range), adl_end(Range), P); } template -auto find_if_not(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { +auto find_if_not(R &&Range, UnaryPredicate P) { return std::find_if_not(adl_begin(Range), adl_end(Range), P); } /// Provide wrappers to std::remove_if which take ranges instead of having to /// pass begin/end explicitly. template -auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { +auto remove_if(R &&Range, UnaryPredicate P) { return std::remove_if(adl_begin(Range), adl_end(Range), P); } @@ -1244,17 +1230,14 @@ /// Wrapper function around std::count to count the number of times an element /// \p Element occurs in the given range \p Range. -template -auto count(R &&Range, const E &Element) -> - typename std::iterator_traits::difference_type { +template auto count(R &&Range, const E &Element) { return std::count(adl_begin(Range), adl_end(Range), Element); } /// Wrapper function around std::count_if to count the number of times an /// element satisfying a given predicate occurs in a range. template -auto count_if(R &&Range, UnaryPredicate P) -> - typename std::iterator_traits::difference_type { +auto count_if(R &&Range, UnaryPredicate P) { return std::count_if(adl_begin(Range), adl_end(Range), P); } @@ -1268,36 +1251,32 @@ /// Provide wrappers to std::partition which take ranges instead of having to /// pass begin/end explicitly. template -auto partition(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { +auto partition(R &&Range, UnaryPredicate P) { return std::partition(adl_begin(Range), adl_end(Range), P); } /// Provide wrappers to std::lower_bound which take ranges instead of having to /// pass begin/end explicitly. -template -auto lower_bound(R &&Range, T &&Value) -> decltype(adl_begin(Range)) { +template auto lower_bound(R &&Range, T &&Value) { return std::lower_bound(adl_begin(Range), adl_end(Range), std::forward(Value)); } template -auto lower_bound(R &&Range, T &&Value, Compare C) - -> decltype(adl_begin(Range)) { +auto lower_bound(R &&Range, T &&Value, Compare C) { return std::lower_bound(adl_begin(Range), adl_end(Range), std::forward(Value), C); } /// Provide wrappers to std::upper_bound which take ranges instead of having to /// pass begin/end explicitly. -template -auto upper_bound(R &&Range, T &&Value) -> decltype(adl_begin(Range)) { +template auto upper_bound(R &&Range, T &&Value) { return std::upper_bound(adl_begin(Range), adl_end(Range), std::forward(Value)); } template -auto upper_bound(R &&Range, T &&Value, Compare C) - -> decltype(adl_begin(Range)) { +auto upper_bound(R &&Range, T &&Value, Compare C) { return std::upper_bound(adl_begin(Range), adl_end(Range), std::forward(Value), C); } @@ -1316,7 +1295,7 @@ /// Requires that C is always true below some limit, and always false above it. template ()))> -auto partition_point(R &&Range, Predicate P) -> decltype(adl_begin(Range)) { +auto partition_point(R &&Range, Predicate P) { return std::partition_point(adl_begin(Range), adl_end(Range), P); } @@ -1393,8 +1372,7 @@ // Could be further improved to cope with non-derivable functors and // non-binary functors (should be a variadic template member function // operator()). - template - auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { + template auto operator()(A &lhs, B &rhs) const { assert(lhs); assert(rhs); return func(*lhs, *rhs); @@ -1515,8 +1493,7 @@ namespace detail { template -auto apply_tuple_impl(F &&f, Tuple &&t, std::index_sequence) - -> decltype(std::forward(f)(std::get(std::forward(t))...)) { +decltype(auto) apply_tuple_impl(F &&f, Tuple &&t, std::index_sequence) { return std::forward(f)(std::get(std::forward(t))...); } @@ -1526,10 +1503,7 @@ /// tuple variadically to f as if by calling f(a1, a2, ..., an) and /// return the result. template -auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl( - std::forward(f), std::forward(t), - std::make_index_sequence< - std::tuple_size::type>::value>{})) { +decltype(auto) apply_tuple(F &&f, Tuple &&t) { using Indices = std::make_index_sequence< std::tuple_size::type>::value>; @@ -1573,15 +1547,12 @@ /// Returns a raw pointer that represents the same address as the argument. /// -/// The late bound return should be removed once we move to C++14 to better -/// align with the C++20 declaration. Also, this implementation can be removed -/// once we move to C++20 where it's defined as std::to_addres() +/// This implementation can be removed once we move to C++20 where it's defined +/// as std::to_addres(). /// /// The std::pointer_traits<>::to_address(p) variations of these overloads has /// not been implemented. -template auto to_address(const Ptr &P) -> decltype(P.operator->()) { - return P.operator->(); -} +template auto to_address(const Ptr &P) { return P.operator->(); } template constexpr T *to_address(T *P) { return P; } } // end namespace llvm diff --git a/llvm/include/llvm/ADT/fallible_iterator.h b/llvm/include/llvm/ADT/fallible_iterator.h --- a/llvm/include/llvm/ADT/fallible_iterator.h +++ b/llvm/include/llvm/ADT/fallible_iterator.h @@ -96,12 +96,10 @@ } /// Forward dereference to the underlying iterator. - auto operator*() -> decltype(*std::declval()) { return *I; } + decltype(auto) operator*() { return *I; } /// Forward const dereference to the underlying iterator. - auto operator*() const -> decltype(*std::declval()) { - return *I; - } + decltype(auto) operator*() const { return *I; } /// Forward structure dereference to the underlying iterator (if the /// underlying iterator supports it). diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h b/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h --- a/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBSymbol.h @@ -17,13 +17,11 @@ #include "llvm/Support/Casting.h" #define FORWARD_SYMBOL_METHOD(MethodName) \ - auto MethodName() const->decltype(RawSymbol->MethodName()) { \ - return RawSymbol->MethodName(); \ - } + decltype(auto) MethodName() const { return RawSymbol->MethodName(); } #define FORWARD_CONCRETE_SYMBOL_ID_METHOD_WITH_NAME(ConcreteType, PrivateName, \ PublicName) \ - auto PublicName##Id() const->decltype(RawSymbol->PrivateName##Id()) { \ + decltype(auto) PublicName##Id() const { \ return RawSymbol->PrivateName##Id(); \ } \ std::unique_ptr PublicName() const { \ diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h --- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h @@ -1079,7 +1079,7 @@ std::shared_ptr getSymbolStringPool() const { return SSP; } /// Run the given lambda with the session mutex locked. - template auto runSessionLocked(Func &&F) -> decltype(F()) { + template decltype(auto) runSessionLocked(Func &&F) { std::lock_guard Lock(SessionMutex); return F(); } diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h b/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h --- a/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h @@ -130,8 +130,7 @@ /// Locks the associated ThreadSafeContext and calls the given function /// on the contained Module. - template - auto withModuleDo(Func &&F) -> decltype(F(std::declval())) { + template decltype(auto) withModuleDo(Func &&F) { assert(M && "Can not call on null module"); auto Lock = TSCtx.getLock(); return F(*M); @@ -139,9 +138,7 @@ /// Locks the associated ThreadSafeContext and calls the given function /// on the contained Module. - template - auto withModuleDo(Func &&F) const - -> decltype(F(std::declval())) { + template decltype(auto) withModuleDo(Func &&F) const { auto Lock = TSCtx.getLock(); return F(*M); } diff --git a/llvm/include/llvm/Support/Casting.h b/llvm/include/llvm/Support/Casting.h --- a/llvm/include/llvm/Support/Casting.h +++ b/llvm/include/llvm/Support/Casting.h @@ -382,8 +382,7 @@ } template -LLVM_NODISCARD inline auto unique_dyn_cast(std::unique_ptr &&Val) - -> decltype(cast(Val)) { +LLVM_NODISCARD inline auto unique_dyn_cast(std::unique_ptr &&Val) { return unique_dyn_cast(Val); } @@ -398,8 +397,7 @@ } template -LLVM_NODISCARD inline auto unique_dyn_cast_or_null(std::unique_ptr &&Val) - -> decltype(cast(Val)) { +LLVM_NODISCARD inline auto unique_dyn_cast_or_null(std::unique_ptr &&Val) { return unique_dyn_cast_or_null(Val); } diff --git a/llvm/include/llvm/Support/Errno.h b/llvm/include/llvm/Support/Errno.h --- a/llvm/include/llvm/Support/Errno.h +++ b/llvm/include/llvm/Support/Errno.h @@ -30,8 +30,8 @@ std::string StrError(int errnum); template -inline auto RetryAfterSignal(const FailT &Fail, const Fun &F, - const Args &... As) -> decltype(F(As...)) { +inline decltype(auto) RetryAfterSignal(const FailT &Fail, const Fun &F, + const Args &... As) { decltype(F(As...)) Res; do { errno = 0; diff --git a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp --- a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp @@ -177,8 +177,7 @@ return Distribution(randomGenerator()); } -template -static auto randomElement(const C &Container) -> decltype(Container[0]) { +template static decltype(auto) randomElement(const C &Container) { assert(!Container.empty() && "Can't pick a random element from an empty container)"); return Container[randomIndex(Container.size() - 1)]; diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp --- a/llvm/unittests/ADT/STLExtrasTest.cpp +++ b/llvm/unittests/ADT/STLExtrasTest.cpp @@ -221,9 +221,7 @@ static StringRef apply_one(StringRef S) { return S.drop_back(); } public: - template - auto operator()(Ts &&... Items) - -> decltype(std::make_tuple(apply_one(Items)...)) { + template auto operator()(Ts &&... Items) { return std::make_tuple(apply_one(Items)...); } }; diff --git a/llvm/unittests/Support/FormatVariadicTest.cpp b/llvm/unittests/Support/FormatVariadicTest.cpp --- a/llvm/unittests/Support/FormatVariadicTest.cpp +++ b/llvm/unittests/Support/FormatVariadicTest.cpp @@ -487,9 +487,7 @@ const char *Fmt; explicit format_tuple(const char *Fmt) : Fmt(Fmt) {} - template - auto operator()(Ts &&... Values) const - -> decltype(formatv(Fmt, std::forward(Values)...)) { + template auto operator()(Ts &&... Values) const { return formatv(Fmt, std::forward(Values)...); } }; diff --git a/llvm/utils/unittest/googletest/include/gtest/internal/custom/raw-ostream.h b/llvm/utils/unittest/googletest/include/gtest/internal/custom/raw-ostream.h --- a/llvm/utils/unittest/googletest/include/gtest/internal/custom/raw-ostream.h +++ b/llvm/utils/unittest/googletest/include/gtest/internal/custom/raw-ostream.h @@ -31,8 +31,7 @@ // printable() returns a version of its argument that can be streamed into a // std::ostream. This may be the argument itself, or some other representation. -template -auto printable(const T &V) -> decltype(StreamSwitch::printable(V)) { +template decltype(auto) printable(const T &V) { // We delegate to the trait, to allow partial specialization. return StreamSwitch::printable(V); }