For now this works as follows:
* `T&&` is mapped to a by-value `param: T` parameter.
* `T&` is mapped to an `addr param: T*` parameter.
In either case, we will generate a thunk, which will internally pass the
parameter as a pointer.
Mark C++ functions as used when overload resolution selects them, and
trigger Clang's end-of-TU processing at the end of the Carbon
compilation to perform instantiation and other pending cleanup steps.
We already did the opposite direction; this enables use of `str` in
overload resolution.
Fixes#6062
---------
Co-authored-by: Dana Jansens <danakj@orodu.net>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
When a function template takes a parameter of deduced type, and we
deduce that type to a pointer type because we passed a Carbon pointer as
the argument, don't complain that the deduced type is not nullable. We
still know that it can't be null, because we deduced it from a
non-nullable type.
* Add support for template candidates by calling the suitable
`AddCandidate` function for them.
* Add support for overloading on `*this` qualifiers by calling
`AddMethodCandidate` when appropriate.
* Make mapping from Carbon arguments to Clang arguments a little more
faithful by mapping the Carbon expression category into the Clang value
kind.
This came up because `const T` needs destructor support... This change
makes `impl T as Destroy` and `impl const T as Destroy` distinct type
structures. Right now there's no impl lookup fallback (see
[#6068](https://github.com/carbon-language/carbon-lang/issues/6068)); so
when trying to destroy `const T`, there's no way to have an `impl` for
it to find.
In discussion, `MaybeUnformed` and `partial` have similar challenges, so
I'm covering them together.
In type_structure.h, I'm switching to an enum because it felt like an
easier way to be adding more types. I can switch back if preferred,
though then might take a closer look at the `operator==` because that's
kind of verbose.
When mapping Carbon types to C++ types, check first for the Carbon type
being imported from C++ before checking whether it's an adapter for a
builtin. Enums imported from C++ will be both, and it's important we map
them back to the enum type rather than to their underlying (integer)
type.
Fixes#6061
Add `Dependent` value and initializing representations for types whose
representations are unknown because they are dependent. When generating
SemIR in such cases, use a worst-case initializing representation that
both provides a destination address and also propagates a potential
result value.
Use this to fix incorrect lowering and lowering crashes for specific
functions involving generic types that don't use a copy value
representation.
In lowering, be careful to distinguish between whether the initializing
representation for the generic return type uses a return slot (which
affects whether the SemIR declaration and call have one) and whether the
initializing representation for the specific return type uses a return
slot (which affects whether the LLVM IR declaration and call have one).
This is in support of a goal of changing the blanket `destroy` impl to
use (roughly):
```
private fn CanAggregateDestroy() -> type = "type.can_aggregate_destroy";
// Handles aggregate type destruction.
impl forall [AggregateDestroyT:! CanAggregateDestroy()] AggregateDestroyT as Destroy {
fn Op[addr self: Self*]() = "type.aggregate_destroy";
}
```
That isn't done here because there's still other issues that migrating
raises. What this *does* do is add the builtin functions, and in
particular, support to `FacetTypeInfo` to make `CanAggregateDestroy`
work.
The "special requirement" approach in `FacetTypeInfo` allows us to
support restricting a blanket impl under the current approach of impls.
Maybe we'll find a cleaner approach that can work in the future, but
this fits into the current model by propagating similar to other
requirements. I'm using an enum mask because we have a number of similar
things to add (e.g. copy, move) but I'm not sure we need a full vector.
A few alternatives considered were:
- Supporting syntax more like `where .Self impls
TypeCanAggregateDestroy(.Self, SupportedInterface,
UnsupportedInterface)`. I think it'd be a little cleaner, but requires
better compile-time evaluation in order to assess the type of the call.
Right now it's expected to be a `FacetType` too early to make this work,
and I was concerned about pouring too much more time down this route.
- Providing an actual interface, in particular doing name lookup back
into `Core.` for an interface. This would've added name lookup overhead,
and the question of whether an `impl` exists.
- Generating an interface. This avoids the name lookup, but would still
raise the question of whether an `impl` should also be generated. Work
I've previously done generating interfaces for class destruction also
feels complex to both write and understand (an unfortunate issue).
- Still modeling as an `ImplsConstraint`, for example by defining a
special `InterfaceId::CanAggregateDestroy = -2` similar to what we do on
other ids. I was hesitant because of how this expands the number of
modes of `InterfaceId`, and things for consuming code to watch out for,
for what feels like a relatively niche set of use-cases that are only
interface-like.
---------
Co-authored-by: Dana Jansens <danakj@orodu.net>
We have grown more generation rules, so try to use a regex instead of
listing all of them.
Also, manually add the runfiles C++ library that isn't "generated", but
is symlinked into the source tree only when built.
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
As proposed in [Carbon: C++ interop for overloaded functions and
function
templates](https://docs.google.com/document/d/1KUxumZtNe3mY3TsjW2s_ZADOlAaFlrtsLKHVILtqIaM/edit?tab=t.0),
Clang is used to perform the overload resolution using C++ rules, when
an overloaded C++ set is called from Carbon. Once a function is
selected, it's converted into a Carbon function and called using the
Carbon rules including argument conversions.
A single non-templated function is treated the same way as an overload
set and the same rules apply for its call.
Template functions are not supported yet.
Demo:
a) Non-templated function calls:
```c++
// --- overloads.h
auto foo(int a, short b) -> void;
auto foo(double a) -> void;
auto foo(int a) -> void;
```
```c++
// overloads.cpp
#include "overloads.h"
#include <cstdio>
auto foo(int a, short b) -> void {
printf("hello from foo_int_short(%d, %d) \n", a, b);
}
auto foo(double a) -> void { printf("hello from foo_double(%f) \n", a); }
auto foo(int a) -> void { printf("hello from foo_int(%d) \n", a); }
```
```c++
library "Main";
import Cpp library "overloads.h";
fn Run() -> i32 {
Cpp.foo(1.1 as f64);
return 0;
}
```
```
$ clang -c overloads.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link overloads.o main.o --output=demo
$ ./demo
hello from foo_double(1.100000)
```
b) Constructors:
```c++
// --- constructor_overloads.h
class C {
public:
C();
C(int a, int b);
};
```
```c++
// constructor_overloads.cpp
#include "constructor_overloads.h"
#include <cstdio>
C::C() { printf("hello from C() \n"); }
C::C(int a, int b) { printf("hello from C(%d, %d) \n", a, b); }
```
```c++
library "Main";
import Cpp library "constructor_overloads.h";
fn Run() -> i32 {
let c1: Cpp.C = Cpp.C.C();
let c2: Cpp.C = Cpp.C.C(1, 2);
return 0;
}
```
```
$ clang -c constructor_overloads.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link constructor_overloads.o main.o \--output=demo
$ ./demo
hello from C()
hello from C(1, 2)
```
Follow-ups:
- `Cpp.foo({})` - proper handling of struct literals as call args.
- Fix access for overloaded sets.
- Fix tests:
- Method calls: `error: missing object argument in method call
[MissingObjectInMethodCall]` in tests.
- Fix `toolchain/check/testdata/interop/cpp/import.carbon` test.
- Fix `enums` support.
- Fix `str` -> `std::string_view` mapping.
Part of #5915
This proposal renames the syntax used to mark an overriding definition
of a virtual method from `impl fn` to `override fn` to avoid ambiguity:
besides indicating an overriding virtual function, it can be parsed as
an "impl" declaration when the construct following "impl" begins with a
lambda introduced by "fn".
Closes#5711
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Adds a unit test, and some smaller edits:
- Remove the `=` when defining names, in order to change `}` placement
by clang-format on uses.
- context:
https://github.com/carbon-language/carbon-lang/pull/6053#discussion_r2343423178
- I believe with `EnumBase` that keeping the `=` had been a deliberate
choice, so this PR is intended to confirm that removing it is okay.
- Delete `EnumMaskBase::name`
- context:
https://github.com/carbon-language/carbon-lang/pull/6053#discussion_r2344233707
- We can't just do nothing because `EnumBase::name` uses indexing that's
incompatible with `EnumMaskBase`.
- Some small comment cleanups.
- Tests don't need to be in the `Carbon` namespace anymore, macros work
fine in other namespaces, but it's still the right namespace.
- Documentation on `EnumBase::name` seems to be referring to a prior
structure, wherein we had a macro defining the function instead of the
`Names` array.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Generally seems to be working as intended: clang-tidy has variance from
a few minutes to an hour; clang-tidy hovers around 10 minutes. In this
case, the long tail of slow execution is more visible, partly because
tests will often take close to 10 minutes, if not more.
Branch enforcement should already be switched.
This is a bit of an experiment to see if there's a reasonable way to
write a shared enum type, rather than writing per-case wrappers for
things like `HasTypeQualifiers` or the printing. I think it's a bit
borderline complexity right now, but I'm not sure I can reduce it much
further.
This changes from things like `Internal::EnumClassName##RawEnum` to
`Internal::EnumClassName##Data::RawEnum` so that the enum entries can
have back references to bit shifts without needing to know the
containing type name. Because I'm trying to reduce duplication between
mask and non-mask enums, I did this to non-mask enums too.
This was motivated by #6035 adding another enum mask (which will grow
more entries, and is intended to switch if this is accepted), but I'm
not using that PR as a base here because I didn't want the merge
dependency.
This prevents a null pointer access crash when generating a thunk with
an automatically deduced trivial return type.
In this case, Clang calls `Sema::DeduceFunctionTypeFromReturnExpr()`
which calls `Sema::getReturnTypeLoc()`, which requires this information.
Part of #5514.
When returning a value from a function whose return type has a by-copy
initializing representation, perform initialization like we do when the
return type has an in-place initializing representation. This makes our
SemIR representation more uniform, as the return expression will now
always be an initializing expression rather than a value expression, but
more importantly it means that attempts to return a non-copyable type by
value now fail, even if the type has a by-copy initializing
representation.
This catches a bunch of places where we were returning a value of an
unconstrained template parameter `T:! type`, which we were incorrectly
allowing because we didn't notice it was not copyable. Unfortunately
this then requires quite a few test updates.
Like #6034, this exposes a lowering issue where lowering crashes when
attempting to lower a specific copy operation for certain types; a
couple more tests are temporarily disabled here. An upcoming PR
dependent on this one will fix the issue and re-enable those tests.
If the first argument is an EntityNameId, then dump the name from within
it. In particular this affects dumping BindName and BindSymbolicName.
```
(lldb) dump context non_canonical_query_self_inst_id
inst96: {kind: BindSymbolicName, arg0: entity_name4, arg1: inst<none>, type: type(symbolic_constant35)}
- name: `T`
- type: type(symbolic_constant35): I(.Self) where .Self.(I(.Self).X) = (); {kind: FacetType, arg0: facet_type4, type: type(TypeType)}
- value: symbolic_constant36
- loc: LocId(<none>)
```
Our style guide suggests using `<stdint.h>` and not the `std::`
qualifiers, and this is consistent with other headers like `<time.h>`.
The `clang-tidy` check enforces the reverse pattern, so disable it to
allow us to continue following our style pattern.
Instead of hardcoding which types are copyable, add a `Core.Copy`
interface to perform copying. Move almost all the current copy support
to that interface. Some remaining pieces are still using builtin logic
after this PR:
* For tuples and structs, builtin logic is used to perform elementwise
copies. This also supports copying *adapters of* tuples and structs,
which seems like it may not be desirable, especially for non-extending
adapters. A `Copy` impl is provided for tuples of at most 2 elements, so
that `Core.Copy` constraints are satisfied, but we can't implement this
generally until we have variadics support, and don't yet have a
mechanism to generalize this to structs.
* For `enum` types imported from C++, builtin logic is used to perform a
copy. This is temporary until we have a mechanism to identify these
types from an impl in the prelude.
One lowering test in `toolchain/lower/testdata/class/generic.carbon` is
disabled for now, as it causes a crash in the lowering code due to an
ABI mismatch between the call signature in the lowered declaration of a
specific function and the call that is generated in the specific callee.
Fixing this is a little involved, and will be done in a separate PR.
---------
Co-authored-by: Geoff Romer <gromer@google.com>
This avoids impl lookups involving, say, `Core.Int` pulling in all ~65
impls in "prelude/types/int", which resulted in a lot of unnecessary
importing work, followed by a lot of unnecessary inst namer and inst
formatter work.
Before:
```
Ran 1335 tests in 6186 ms wall time, 146818 ms across threads
Slowest tests:
- toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon: 5611 ms, 5532 ms in Run
- toolchain/check/testdata/interop/cpp/function/operators.carbon: 2034 ms, 1981 ms in Run
- toolchain/check/testdata/primitives/import_symbolic.carbon: 1796 ms, 1786 ms in Run
- toolchain/lower/testdata/operators/arithmetic.carbon: 1729 ms, 1728 ms in Run
- toolchain/lower/testdata/function/generic/call_recursive_sccs_deep.carbon: 1700 ms, 1697 ms in Run
[==========] 1335 tests from 1 test suite ran. (682 ms total)
```
After:
```
Ran 1335 tests in 2419 ms wall time, 109587 ms across threads
Slowest tests:
- toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon: 1748 ms, 1665 ms in Run
- toolchain/check/testdata/interop/cpp/function/operators.carbon: 1106 ms, 1057 ms in Run
- toolchain/lower/testdata/function/generic/call_recursive_diamond.carbon: 1044 ms, 1041 ms in Run
- toolchain/lower/testdata/function/generic/call_recursive_sccs_deep.carbon: 1015 ms, 1012 ms in Run
- toolchain/lower/testdata/operators/arithmetic.carbon: 998 ms, 997 ms in Run
[==========] 1335 tests from 1 test suite ran. (652 ms total)
```
That's still slower than it should be, but a large improvement
nonetheless.
Fixes#6029
This is a collection of improvements to the filesystem library motivated
by using it to build a runtimes cache. It adds several core features:
- Advisory file locking
- Renaming of entries
- Testing for things being open
- File timestamp querying and updating
It also makes several more minor improvements such as improving the
names of functions and making them work in a more predictable fashion.
For example, the functions to read and write an entire file to/from
strings now actually handle the entire file rather than potentially
composing with other reads or writes, and adding the word `File` to
their name makes that more clear. Similarly, directory reading is more
robust in the face of repeatedly reading the same directory, and several
convenience functions were added to handle common patterns of reading
directories.
There is also a small fix to `ostream` uncovered by the tests added
here.
---------
Co-authored-by: Dana Jansens <danakj@orodu.net>
Noticed this was essentially just fetching then discarding the values,
which felt odd to me. I was considering adding an `ids()` function, but
this would leave only 3 spots that'd use it, and the absence seems like
it'll nudge code towards using the value of `enumerate()` when
reasonable.
If it's just `TypeType` then the `BindSymbolicName` appears directly in
type positions, but if it is replaced with another facet value, then we
would need to insert a `FacetAccessType` around it. By giving it a
`FacetType` type, like other `BindSymbolicName`s we make it consistent
and avoid having to introduce extra instructions.
Echoing what was added in #5608, updating existing uses. Unfortunately
there's divergent behavior for operators versus constructors, so keeping
the nolint on those.
They're essentially equivalent, we just typically write `typename`; even
in the examples here, most have other templates in the same file that
use `typename`.
This uses each vector's size as a barrier between lists, to eliminate
the possibility of incidental collisions between entries of different
lists. This is the same as is done inside `AddBlock`.
Currently hitting ^C prints out two stack traces, requiring scrolling up
though multiple screens of scrollback to get back to the autoupdate
results. This primarily shows up when hitting ^C while it's symbolizing
a C++ stack trace.
Now that the total number of IRs is available from SemIR::File, we can
use FixedSizeValueStore to store/look up values mapped from a CheckIRId
instead of a Map, which is demonstrably faster (unsurprisingly, since
it's just a vector index). See #6019.
This replaces a Map with FixedSizeValueStore in Lower::Context for use
in `GetFileContext()`. This function is used in some places that can
become hot, such as `HandleInst()` and `GetType()`. In our current
lowering tests, there's no measurable performance change from this PR,
but based on #6019 we can expect to see one as the amount of
instructions being lowered increases. Using a FixedSizeValueStore when
possible is a better approach than a map, generally.
This takes the debug runtime of
`toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon`
from 4.7s down to about 4s (so 15% faster overall).
There's still lots of room to improve this test which seems to be
hitting lots of pathological behaviour, but InstNamer is 30% of the
runtime, with fingerprinting's `InstFingerprinter::GetOrCompute`
consuming 10% of cycles. We reduce its impact by using a vector of
vectors instead of a Map for the cache of fingerprints. After this
change InstNamer drops below 24% of the runtime.
Also move the instruction name when giving it to `AllocateName` since it
receives std::string by value, though this doesn't show up in the
profile for the test.
This removes the need for a patch and improves on the quality of the
rules significantly. A follow-up PR will use this to apply a number of
fixes to how we build the runtimes.