diff --git a/llvm/include/llvm/ADT/FunctionExtras.h b/llvm/include/llvm/ADT/FunctionExtras.h --- a/llvm/include/llvm/ADT/FunctionExtras.h +++ b/llvm/include/llvm/ADT/FunctionExtras.h @@ -89,18 +89,22 @@ // The heuristic used is related to common ABI register passing conventions. // It doesn't have to be exact though, and in one way it is more strict // because we want to still be able to observe either moves *or* copies. - template - using AdjustedParamT = typename std::conditional< - !std::is_reference::value && - llvm::is_trivially_copy_constructible::value && - llvm::is_trivially_move_constructible::value && - IsSizeLessThanThresholdT::value, - T, T &>::type; + template struct AdjustedParamT { + using type = typename std::conditional< + llvm::is_trivially_copy_constructible::value && + llvm::is_trivially_move_constructible::value && + IsSizeLessThanThresholdT::value, + T, T &>::type; + }; + + // This specialization ensures that 'AdjustedParam' does not trigger a + // compile-time error when 'T' is an incomplete type. + template struct AdjustedParamT { using type = T &; }; // The type of the erased function pointer we use as a callback to dispatch to // the stored callable when it is trivial to move and destroy. - using CallPtrT = ReturnT (*)(void *CallableAddr, - AdjustedParamT... Params); + using CallPtrT = ReturnT (*)( + void *CallableAddr, typename AdjustedParamT::type... Params); using MovePtrT = void (*)(void *LHSCallableAddr, void *RHSCallableAddr); using DestroyPtrT = void (*)(void *CallableAddr); @@ -159,7 +163,9 @@ } CallPtrT getTrivialCallback() const { - return CallbackAndInlineFlag.getPointer().template get()->CallPtr; + return CallbackAndInlineFlag.getPointer() + .template get() + ->CallPtr; } NonTrivialCallbacks *getNonTrivialCallbacks() const { @@ -199,7 +205,7 @@ template static ReturnT CallImpl(void *CallableAddr, - AdjustedParamT... Params) { + typename AdjustedParamT::type... Params) { auto &Func = *reinterpret_cast(CallableAddr); return Func(std::forward(Params)...); } diff --git a/llvm/unittests/ADT/FunctionExtrasTest.cpp b/llvm/unittests/ADT/FunctionExtrasTest.cpp --- a/llvm/unittests/ADT/FunctionExtrasTest.cpp +++ b/llvm/unittests/ADT/FunctionExtrasTest.cpp @@ -273,4 +273,11 @@ EXPECT_EQ("string", returns([] { return "hello"; })); } +TEST(UniqueFunctionTest, IncompleteTypes) { + class A; + unique_function IncompleteArguments; + unique_function IncompleteResultReference; + unique_function IncompleteResultPointer; +} + } // anonymous namespace