Skip to content

[BUG] Certain combination of inout member func, as and non-last non-moved use doesn't compile UFCS #414

Open
@realgdman

Description

@realgdman

Cpp1 compilation fails on exact combination: inout this member function, cast with as, and non-last use without std::move.

Code to Reproduce

S: type = {
	const_foo: (this) = { std::cout << "const foo \n"; }
	mut_foo: (inout this) = { std::cout << "foo \n"; }
}

test_const_foo: () = {
	s: S =();
	(s as S).const_foo(); //ok, CPP2_UFCS_0(const_foo, (cpp2::as_<S>(s)));
	(s as S).const_foo(); //ok, CPP2_UFCS_0(const_foo, (cpp2::as_<S>(std::move(s))));
}

test_mut_foo: () = {
	s: S =();
	(s as S).mut_foo(); //BAD CPP2_UFCS_0(mut_foo, (cpp2::as_<S>(s)));
	(s as S).mut_foo(); //ok, CPP2_UFCS_0(mut_foo, (cpp2::as_<S>(std::move(s))));
}

Command lines
cppfront/cppfront $1.cpp2 -p
clang++-15 -Icppfront/include $1.cpp -std=c++20 -o $1

Expected result - what you expected to happen
Compiled code or diagnostic on wrong usage

Actual result/error

derivedufcs.cpp2:14:14: error: use of undeclared identifier 'mut_foo'
 CPP2_UFCS_0(mut_foo, (cpp2::as_<S>(s)));
             ^
derivedufcs.cpp2:14:2: note: in instantiation of function template specialization 'test_mut_foo()::(anonymous class)::operator()<const S &>' requested here
 CPP2_UFCS_0(mut_foo, (cpp2::as_<S>(s)));
 ^
cppfront/include/cpp2util.h:695:2: note: expanded from macro 'CPP2_UFCS_0'                                            
}(PARAM1)
 ^
1 error generated. 

Additional context
I encountered this writing bigger example, so didn't figured out root cause yet.
But I reduced it to combination of 3 elements. Removing any 1 of them make it work.

  1. Using s.foo() instead of (s as S).foo(), but that's what I was testing in first place. But cpp2::as_ template could be first suspect.
  2. Removing inout on member function (proved by const_foo compiling without problem)
  3. Removing one use. It is working on last use move, but failing on regular use.
    Last one I found important, since last use getting special treatment, and tests usually do something only once, so they usually test last-use move, and not regular one.

Also it's totally possible that I just wrote something silly, and this is expected for this combination.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions