On Fri, 27 Mar 2020 at 16:35, David Blaikie via cfe-commits < cfe-commits@lists.llvm.org> wrote:
> On Thu, Mar 26, 2020 at 8:49 PM Richard Smith <rich...@metafoo.co.uk> > wrote: > >> On Thu, 26 Mar 2020 at 17:07, David Blaikie via cfe-commits < >> cfe-commits@lists.llvm.org> wrote: >> >>> On Thu, Mar 26, 2020 at 3:12 PM Arthur O'Dwyer < >>> arthur.j.odw...@gmail.com> wrote: >>> >>>> I'm not sure, but I do see that the call stack contains a call to >>>> >>>> bool llvm::function_ref<bool (clang::Expr*&, >>>> bool)>::callback_fn<llvm::function_ref<bool (clang::Expr*&, bool)> >>>> const>(long, clang::Expr*&, bool) >>>> >>>> Notice that this is function_ref::callback_fn<T> instantiated with >>>> T=function_ref itself; i.e., we do have a function_ref to a function_ref. >>>> This is the thing I was saying can happen (in my "lamb/sheep" example) but >>>> which I thought should never happen in this codepath. >>>> Here's function_ref's copy constructor: >>>> >>>> >>>> template <typename Callable> >>>> >>>> function_ref(Callable &&callable, >>>> >>>> >>>> std::enable_if_t<!std::is_same<std::remove_reference_t<Callable>, >>>> >>>> function_ref>::value> * = >>>> nullptr) >>>> >>>> : callback(callback_fn<typename >>>> std::remove_reference<Callable>::type>), >>>> >>>> callable(reinterpret_cast<intptr_t>(&callable)) {} >>>> >>>> >>>> I believe that it should be using std::remove_cvref_t, not >>>> std::remove_reference_t, so as not to conflict with the compiler's >>>> implicitly generated copy constructor. >>>> >>>> Thoughts? >>>> >>> >>> Yep, looks like you're on to something here - I still don't understand >>> why calling that function rather than the real trivial copy ctor would be >>> problematic, >>> >> >> OK, so: we're calling the wrong constructor for the inner capture due to >> the implicit 'const' that's added because the outer lambda is not mutable >> (and the fix suggested by Arthur is the right one: we should be using >> remove_cvref_t here not remove_reference_t -- or rather >> std::remove_cv_t<std::remove_reference_t<Callable>>, since we don't require >> C++20 yet). And this means that copying a function_ref from a *const* >> function_ref gives you a new function_ref that refers to the old one, not a >> new function_ref that refers to the same function the old one did. In >> particular, this happens when copying a lambda that captures a function_ref >> by value. >> > > I was only able to hit this with a const rvalue reference - is that > expected, or did I overcomplicate my test case in some way? > No, my analysis was incomplete, sorry. For a const function_ref&, we call the implicit copy constructor rather than the constructor template. const function_ref&& breaks because it isn't an exact match for an implicit copy/move constructor. > (this: "const function_ref<T> a; function_ref<T> b = a;" didn't hit the > converting ctor, it ran the copy ctor as desired. I had to "function_ref<T> > b = static_cast<const function_ref<T> &&>(a);" to tickle it) > > Committed the fix/test in cbce88dd3a9ea7161da3c57749cf03873dc7ea79 - open > to suggestions on simplification of the test case if there is some. Oh, I > might've named the new test case a bit poorly... didn't go back and edit > that after it got more baked. > > >> >> The next part of the puzzle is that llvm::any_of takes its callback by >> value and passes it by value to std::any_of. And inside any_of, in >> libstdc++, the predicate is passed through __pred_iter ( >> https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/predefined_ops.h#L323) >> before being used. That results in building a function_ref referring to >> part of the function parameter in __pred_iter, whose lifetime ends before >> we call it. >> >> With libc++, the predicate is not copied around inside any_of, which is >> why this was only failing on some buildbots. >> >> but I managed to reproduce this locally with GCC 7.5 (seems to be an >>> issue with the 7 series - the buildbot used 7.3) & if I capture by value in >>> both outer and inner lambdas it reproduces, but if I mark the outer lambda >>> as mutable it succeeds (because this would remove the const & not trip over >>> the SFINAE issue you pointed out)... >>> >>> Investigation continues. >>> >>> - Dave >>> >>> >>>> –Arthur >>>> >>>> >>>> >>>> On Thu, Mar 26, 2020 at 5:08 PM David Blaikie <dblai...@gmail.com> >>>> wrote: >>>> >>>>> Hey Richard - could you help try to diagnose what's happening here? >>>>> >>>>> I reverted this patch in: >>>>> https://github.com/llvm/llvm-project/commit/0d0b90105f92f6cd9cc7004d565834f4429183fb >>>>> But that did actually cause buildbot failures, such as these ones: >>>>> http://lab.llvm.org:8011/builders/clang-ppc64be-linux-multistage/builds/24491 >>>>> eg: >>>>> http://lab.llvm.org:8011/builders/clang-ppc64be-linux-multistage/builds/24491/steps/ninja%20check%201/logs/FAIL%3A%20Clang%3A%3Adeclare_variant_mixed_codegen.cpp >>>>> I "fixed" these failures blind by reapplying part of this original >>>>> commit (the lambda capture by reference rather than by value): >>>>> https://github.com/llvm/llvm-project/commit/2ec59a0a40f4ec02e6b2dbe5f12261959c191aa9 >>>>> >>>>> I've stared at this a fair bit and can't spot any undefined behavior, >>>>> but I guess it's probably in there somewhere - and I'm worried that this >>>>> fix is blind, not fully justified & might be hiding some latent issues. >>>>> >>>>> The full buildbot example failure quoted here in case it times >>>>> out/gets deleted on the buildbot itself: >>>>> >>>>> ******************** TEST 'Clang :: >>>>> OpenMP/declare_variant_mixed_codegen.cpp' FAILED ******************** >>>>> Script: >>>>> -- >>>>> : 'RUN: at line 1'; >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang >>>>> -cc1 -internal-isystem >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/lib/clang/11.0.0/include >>>>> -nostdsysteminc -verify -fopenmp -x c++ -triple x86_64-unknown-linux >>>>> -emit-llvm >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/llvm/clang/test/OpenMP/declare_variant_mixed_codegen.cpp >>>>> -fexceptions -fcxx-exceptions -o - -fsanitize-address-use-after-scope | >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/FileCheck >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/llvm/clang/test/OpenMP/declare_variant_mixed_codegen.cpp >>>>> : 'RUN: at line 2'; >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang >>>>> -cc1 -internal-isystem >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/lib/clang/11.0.0/include >>>>> -nostdsysteminc -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-linux >>>>> -fexceptions -fcxx-exceptions -emit-pch -o >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/tools/clang/test/OpenMP/Output/declare_variant_mixed_codegen.cpp.tmp >>>>> -fopenmp-version=50 >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/llvm/clang/test/OpenMP/declare_variant_mixed_codegen.cpp >>>>> : 'RUN: at line 3'; >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang >>>>> -cc1 -internal-isystem >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/lib/clang/11.0.0/include >>>>> -nostdsysteminc -fopenmp -x c++ -triple x86_64-unknown-linux -fexceptions >>>>> -fcxx-exceptions -std=c++11 -include-pch >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/tools/clang/test/OpenMP/Output/declare_variant_mixed_codegen.cpp.tmp >>>>> -verify >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/llvm/clang/test/OpenMP/declare_variant_mixed_codegen.cpp >>>>> -emit-llvm -o - -fopenmp-version=50 | >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/FileCheck >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/llvm/clang/test/OpenMP/declare_variant_mixed_codegen.cpp >>>>> -- >>>>> Exit Code: 2 >>>>> >>>>> Command Output (stderr): >>>>> -- >>>>> Stack dump: >>>>> 0. Program arguments: >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang >>>>> -cc1 -internal-isystem >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/lib/clang/11.0.0/include >>>>> -nostdsysteminc -verify -fopenmp -x c++ -triple x86_64-unknown-linux >>>>> -emit-llvm >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/llvm/clang/test/OpenMP/declare_variant_mixed_codegen.cpp >>>>> -fexceptions -fcxx-exceptions -o - -fsanitize-address-use-after-scope >>>>> 1. >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/llvm/clang/test/OpenMP/declare_variant_mixed_codegen.cpp:38:92: >>>>> at annotation token >>>>> #0 0x0000000012e3ebd0 llvm::sys::PrintStackTrace(llvm::raw_ostream&) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x12e3ebd0) >>>>> #1 0x0000000012e3ece8 PrintStackTraceSignalHandler(void*) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x12e3ece8) >>>>> #2 0x0000000012e3c4e0 llvm::sys::RunSignalHandlers() >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x12e3c4e0) >>>>> #3 0x0000000012e3d3a4 SignalHandler(int) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x12e3d3a4) >>>>> #4 0x00007fffb50f04d8 (linux-vdso64.so.1+0x4d8) >>>>> #5 0x0000000014df41ac bool llvm::function_ref<bool (clang::Expr*&, >>>>> bool)>::callback_fn<llvm::function_ref<bool (clang::Expr*&, bool)> >>>>> const>(long, clang::Expr*&, bool) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x14df41ac) >>>>> #6 0x00007fffff5e7fd0 >>>>> #7 0x0000000014e2bfd0 clang::OMPTraitInfo::OMPTraitSelector* >>>>> std::__find_if<clang::OMPTraitInfo::OMPTraitSelector*, >>>>> __gnu_cxx::__ops::_Iter_pred<clang::OMPTraitInfo::anyScoreOrCondition(llvm::function_ref<bool >>>>> (clang::Expr*&, >>>>> bool)>)::'lambda'(clang::OMPTraitInfo::OMPTraitSet&)::operator()(clang::OMPTraitInfo::OMPTraitSet&) >>>>> const::'lambda'(clang::OMPTraitInfo::OMPTraitSelector&)> >>>>> >(clang::OMPTraitInfo::OMPTraitSelector*, >>>>> clang::OMPTraitInfo::OMPTraitSelector*, >>>>> __gnu_cxx::__ops::_Iter_pred<clang::OMPTraitInfo::anyScoreOrCondition(llvm::function_ref<bool >>>>> (clang::Expr*&, >>>>> bool)>)::'lambda'(clang::OMPTraitInfo::OMPTraitSet&)::operator()(clang::OMPTraitInfo::OMPTraitSet&) >>>>> const::'lambda'(clang::OMPTraitInfo::OMPTraitSelector&)>, >>>>> std::random_access_iterator_tag) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x14e2bfd0) >>>>> #8 0x0000000014e2c118 bool >>>>> llvm::any_of<llvm::SmallVector<clang::OMPTraitInfo::OMPTraitSelector, >>>>> 4u>&, >>>>> clang::OMPTraitInfo::anyScoreOrCondition(llvm::function_ref<bool >>>>> (clang::Expr*&, >>>>> bool)>)::'lambda'(clang::OMPTraitInfo::OMPTraitSet&)::operator()(clang::OMPTraitInfo::OMPTraitSet&) >>>>> const::'lambda'(clang::OMPTraitInfo::OMPTraitSelector&)>(llvm::SmallVector<clang::OMPTraitInfo::OMPTraitSelector, >>>>> 4u>&, clang::OMPTraitInfo::anyScoreOrCondition(llvm::function_ref<bool >>>>> (clang::Expr*&, >>>>> bool)>)::'lambda'(clang::OMPTraitInfo::OMPTraitSet&)::operator()(clang::OMPTraitInfo::OMPTraitSet&) >>>>> const::'lambda'(clang::OMPTraitInfo::OMPTraitSelector&)) (.isra.3726) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x14e2c118) >>>>> #9 0x0000000014e2c2a4 clang::OMPTraitInfo::OMPTraitSet* >>>>> std::__find_if<clang::OMPTraitInfo::OMPTraitSet*, >>>>> __gnu_cxx::__ops::_Iter_pred<clang::OMPTraitInfo::anyScoreOrCondition(llvm::function_ref<bool >>>>> (clang::Expr*&, bool)>)::'lambda'(clang::OMPTraitInfo::OMPTraitSet&)> >>>>> >(clang::OMPTraitInfo::OMPTraitSet*, clang::OMPTraitInfo::OMPTraitSet*, >>>>> __gnu_cxx::__ops::_Iter_pred<clang::OMPTraitInfo::anyScoreOrCondition(llvm::function_ref<bool >>>>> (clang::Expr*&, bool)>)::'lambda'(clang::OMPTraitInfo::OMPTraitSet&)>, >>>>> std::random_access_iterator_tag) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x14e2c2a4) >>>>> #10 0x0000000014e2c368 bool >>>>> llvm::any_of<llvm::SmallVector<clang::OMPTraitInfo::OMPTraitSet, 4u>&, >>>>> clang::OMPTraitInfo::anyScoreOrCondition(llvm::function_ref<bool >>>>> (clang::Expr*&, >>>>> bool)>)::'lambda'(clang::OMPTraitInfo::OMPTraitSet&)>(llvm::SmallVector<clang::OMPTraitInfo::OMPTraitSet, >>>>> 4u>&, clang::OMPTraitInfo::anyScoreOrCondition(llvm::function_ref<bool >>>>> (clang::Expr*&, bool)>)::'lambda'(clang::OMPTraitInfo::OMPTraitSet&)) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x14e2c368) >>>>> #11 0x0000000014e2cc38 >>>>> clang::Sema::checkOpenMPDeclareVariantFunction(clang::OpaquePtr<clang::DeclGroupRef>, >>>>> clang::Expr*, clang::OMPTraitInfo&, clang::SourceRange) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x14e2cc38) >>>>> #12 0x00000000148fc550 >>>>> clang::Parser::ParseOMPDeclareVariantClauses(clang::OpaquePtr<clang::DeclGroupRef>, >>>>> llvm::SmallVector<clang::Token, 4u>&, clang::SourceLocation) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x148fc550) >>>>> #13 0x00000000148fd354 >>>>> clang::Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(clang::AccessSpecifier&, >>>>> clang::Parser::ParsedAttributesWithRange&, bool, clang::TypeSpecifierType, >>>>> clang::Decl*) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x148fd354) >>>>> #14 0x00000000148723c4 >>>>> clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&, >>>>> clang::ParsingDeclSpec*) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x148723c4) >>>>> #15 0x000000001487395c >>>>> clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&, >>>>> bool) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x1487395c) >>>>> #16 0x0000000014866a20 clang::ParseAST(clang::Sema&, bool, bool) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x14866a20) >>>>> #17 0x00000000136f6298 clang::ASTFrontendAction::ExecuteAction() >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x136f6298) >>>>> #18 0x0000000013de8220 clang::CodeGenAction::ExecuteAction() >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x13de8220) >>>>> #19 0x00000000136fcc64 clang::FrontendAction::Execute() >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x136fcc64) >>>>> #20 0x00000000136b71c0 >>>>> clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x136b71c0) >>>>> #21 0x00000000137c9794 >>>>> clang::ExecuteCompilerInvocation(clang::CompilerInstance*) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x137c9794) >>>>> #22 0x00000000109674cc cc1_main(llvm::ArrayRef<char const*>, char >>>>> const*, void*) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x109674cc) >>>>> #23 0x00000000109635b8 ExecuteCC1Tool(llvm::SmallVectorImpl<char >>>>> const*>&) >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x109635b8) >>>>> #24 0x00000000108b838c main >>>>> (/home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/clang+0x108b838c) >>>>> #25 0x00007fffb4a55b10 generic_start_main.isra.0 >>>>> (/lib64/power8/libc.so.6+0x45b10) >>>>> #26 0x00007fffb4a55d38 __libc_start_main >>>>> (/lib64/power8/libc.so.6+0x45d38) >>>>> FileCheck error: '<stdin>' is empty. >>>>> FileCheck command line: >>>>> >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/stage1/bin/FileCheck >>>>> /home/buildbots/ppc64be-clang-multistage-test/clang-ppc64be-multistage/llvm/clang/test/OpenMP/declare_variant_mixed_codegen.cpp >>>>> >>>>> -- >>>>> >>>>> ******************** >>>>> >>>>> On Sun, Mar 22, 2020 at 7:38 PM David Blaikie <dblai...@gmail.com> >>>>> wrote: >>>>> >>>>>> Reverted in 0d0b90105f92f6cd9cc7004d565834f4429183fb & I'll see what >>>>>> happens with the buildbots. >>>>>> >>>>>> On Sun, Mar 22, 2020 at 5:47 PM Johannes Doerfert < >>>>>> johan...@jdoerfert.de> wrote: >>>>>> >>>>>>> >>>>>>> Apologies for the confusion. >>>>>>> >>>>>>> I wrote the commit message after looking into this and I though the >>>>>>> issue was related to the capture by copy in the inner llvm::any_of >>>>>>> and >>>>>>> the reuse in the outer. Looking back at the code I cannot say anymore >>>>>>> how I got that impression. >>>>>>> >>>>>>> If you think the reference is problematic, I'm totally happy to >>>>>>> remove >>>>>>> it. If the windows bots (or any other ones) don't like it we need to >>>>>>> investigate why. As mentioned, I had a problem recreating the problem >>>>>>> locally before. >>>>>>> >>>>>>> Cheers, >>>>>>> Johannes >>>>>>> >>>>>>> >>>>>>> On 3/22/20 1:37 PM, Arthur O'Dwyer wrote: >>>>>>> > On Sun, Mar 22, 2020 at 1:48 PM David Blaikie via cfe-commits < >>>>>>> > cfe-commits@lists.llvm.org> wrote: >>>>>>> > >>>>>>> >> On Sun, Mar 22, 2020 at 10:40 AM Johannes Doerfert >>>>>>> <johan...@jdoerfert.de> >>>>>>> >> wrote: >>>>>>> >> >>>>>>> >>> Some buildbots, I think only Windows buildbots for some reason, >>>>>>> crashed >>>>>>> >>> in this function. >>>>>>> >>> >>>>>>> >>> The reason, as described, is that an `llvm::function_ref` >>>>>>> cannot be >>>>>>> >>> copied and then reused. It just happened to work on almost all >>>>>>> >>> configurations. >>>>>>> >>> >>>>>>> >> >>>>>>> >> That doesn't seem to be accurate, or if it is there's a lot of >>>>>>> mistakes in >>>>>>> >> the codebase - basically every function_ref parameter I can see >>>>>>> in >>>>>>> LLVM is >>>>>>> >> passing by value, not by const ref. The implementation of >>>>>>> >> llvm::function_ref looks quite copyable so long as it doesn't >>>>>>> outlive the >>>>>>> >> functor it is pointing to. >>>>>>> >> >>>>>>> > >>>>>>> > David is correct. llvm::function_ref, like >>>>>>> std::reference_wrapper, is a >>>>>>> > trivially copyable type, and it's designed to be copied. >>>>>>> > Like string_view and reference_wrapper, function_ref is designed >>>>>>> to be >>>>>>> > passed by value. Redundantly passing function_ref *again by >>>>>>> reference* is a >>>>>>> > code smell. >>>>>>> > >>>>>>> > I've also checked the code here, and it looks like there are only >>>>>>> two >>>>>>> > callers of `anyScoreOrCondition` — both in Sema/SemaOpenMP.cpp — >>>>>>> and they >>>>>>> > are both fine. FWIW, I would recommend reverting Johannes' change >>>>>>> and >>>>>>> > seeing if those Windows buildbots are still unhappy (and if so, >>>>>>> why). >>>>>>> > >>>>>>> > >>>>>>> > Btw, one failure mode I'm aware of, but which I believe is NOT >>>>>>> relevant in >>>>>>> > Johannes' case, is that `function_ref`'s converting constructor >>>>>>> behaves >>>>>>> > differently from its copy constructor. >>>>>>> > >>>>>>> > int main() >>>>>>> > >>>>>>> > { >>>>>>> > >>>>>>> > auto lamb = [](){ return 42; }; >>>>>>> > >>>>>>> > auto sheep = [](){ return 43; }; >>>>>>> > >>>>>>> > llvm::function_ref<int()> one = lamb; >>>>>>> > >>>>>>> > >>>>>>> > llvm::function_ref<int()> twoA = one; // twoA refers to >>>>>>> lamb >>>>>>> > >>>>>>> > llvm::function_ref<short()> twoB = one; // twoB refers to >>>>>>> one which >>>>>>> > refers to lamb >>>>>>> > >>>>>>> > >>>>>>> > one = sheep; >>>>>>> > >>>>>>> > >>>>>>> > assert(twoA() == 42); // twoA refers to lamb >>>>>>> > >>>>>>> > assert(twoB() == 43); // twoB refers to one which refers to >>>>>>> sheep >>>>>>> > >>>>>>> > } >>>>>>> > >>>>>>> > That is, if you have a function that takes a parameter of type >>>>>>> > function_ref<A>, and someone passes it an argument of type >>>>>>> function_ref<B>, >>>>>>> > then inside the function your parameter will be referring to that >>>>>>> argument >>>>>>> > itself instead of to its referent. >>>>>>> > However, in Johannes' particular case, we have no function_refs >>>>>>> referring >>>>>>> > to other function_refs. We just make a lambda and take a >>>>>>> function_ref to >>>>>>> > it, the end. So I'm pretty sure this pitfall is irrelevant. >>>>>>> > >>>>>>> > –Arthur >>>>>>> > >>>>>>> >>>>>>> _______________________________________________ >>> cfe-commits mailing list >>> cfe-commits@lists.llvm.org >>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >>> >> _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits