Commit Graph
4383 Commits
Author SHA1 Message Date
Chandler CarruthandJon Ross-Perkins 3ec0bcb4fd Improve building of generated sources for ClangD (#6046)
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>
2025-09-15 16:43:02 +00:00
Ivana Ivanovska 12ddfb9c7c [Carbon/C++ interop] Add support for C++ overloaded functions (#5891)
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
2025-09-15 12:29:49 +00:00
Richard Smith 20ac6b9270 Remove logging prints from advent example. (#6057)
Make this example just print the answer like the other tests do. This
makes automated testing of these examples easier.
v0.0.0-0.nightly.2025.09.15 v0.0.0-0.nightly.2025.09.14 v0.0.0-0.nightly.2025.09.13
2025-09-13 01:23:35 +00:00
Elliott KaltandRichard Smith f4bd6e42f9 Replace impl fn with override fn (#6008)
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>
2025-09-12 23:27:02 +00:00
Jon Ross-PerkinsandRichard Smith 973d721916 Some more edits to EnumBase and EnumMaskBase (#6054)
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>
2025-09-12 22:59:37 +00:00
Jon Ross-Perkins 1d19fa3954 Disable clang-tidy action in favor of clangd-tidy (#6037)
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.
2025-09-12 20:10:14 +00:00
Jon Ross-Perkins 6cc5d7ed2a Add an EnumMaskBase type (#6053)
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.
2025-09-12 18:04:10 +00:00
Boaz Brickner 508a88e2a9 C++ inteop: Set type source info for a generated C++ thunk function (#6049)
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.
2025-09-12 07:11:36 +00:00
Richard Smith d60900cbeb Remove special case for returning value expressions by copy (#6052)
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.
v0.0.0-0.nightly.2025.09.12
2025-09-12 00:13:33 +00:00
Dana Jansens 896ef4da0e Include the Name when dumping an instruction with a name (#6051)
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>)
```
2025-09-11 18:50:35 +00:00
Boaz Brickner 34805543a1 Sort functions in import_cpp.cpp per import_cpp.h (#6048)
Context:
https://github.com/carbon-language/carbon-lang/pull/5891#discussion_r2247678242
2025-09-11 12:58:26 +00:00
Chandler Carruth 4776f3230b Disable the modernize headers clang-tidy check (#6045)
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.
2025-09-11 07:52:50 +00:00
Richard SmithandGeoff Romer 1ec8ac7ef9 Add Copy interface and use it for making copies. (#6034)
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>
v0.0.0-0.nightly.2025.09.11
2025-09-10 23:55:55 +00:00
Dana Jansens 91722ae21a Stop round tripping through an InstId to get the ConstantId of a TypeId (#6044)
TypeId and ConstantId are easily interchangeable, and there's no need to
go through InstId, which is more complicated.
2025-09-10 22:16:29 +00:00
Richard Smith e8cd229e74 When performing an impl lookup, only import impls for related interfaces. (#6040)
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
2025-09-10 21:40:27 +00:00
Chandler CarruthandDana Jansens 1c6e859a50 Many improvements to the filesystem library (#6000)
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>
2025-09-10 20:21:51 +00:00
Jon Ross-Perkins e45d304340 Remove unused EnumBase macros (#6043)
These were used by explorer code.
2025-09-10 19:13:16 +00:00
Jon Ross-Perkins b0d93c2393 Use enumerated values in formatter (#6042)
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.
2025-09-10 18:40:48 +00:00
Jon Ross-Perkins 0da91115cd Run clangd-tidy for the merge queue (#6041)
Necessary for switching off clang-tidy, just forgot about this
(temporarily switched back enforcement).
2025-09-10 17:59:11 +00:00
Dana Jansens ed43fd2c1c Give the BindSymbolicName for .Self in a binding pattern a FacetType type (#6036)
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.
2025-09-10 17:57:08 +00:00
Boaz Brickner d6fbe3c663 C++ interop: Support importing operators defined in namespaces (#6024)
C++ Interop Demo:

```c++
// my_number.h

namespace MyNamespace {

class MyNumber {
 public:
  explicit MyNumber(int value) : value_(value) {}
  auto value() const -> int { return value_; }

 private:
  int value_;
};

auto operator+(MyNumber lhs, MyNumber rhs) -> MyNumber;

}  // namespace MyNamespace
```

```c++
// my_number.cpp

#include "my_number.h"

namespace MyNamespace {

auto operator+(MyNumber lhs, MyNumber rhs) -> MyNumber {
  return MyNumber(lhs.value() + rhs.value());
}

}  // namespace MyNamespace
```

```carbon
// main.carbon

library "Main";

import Core library "io";
import Cpp library "my_number.h";

fn Run() -> i32 {
  let n1: Cpp.MyNamespace.MyNumber = Cpp.MyNamespace.MyNumber.MyNumber(5);
  Core.Print(n1.value());
  let n2: Cpp.MyNamespace.MyNumber = Cpp.MyNamespace.MyNumber.MyNumber(7);
  Core.Print(n2.value());
  let n3: Cpp.MyNamespace.MyNumber = n1 + n2;
  Core.Print(n3.value());
  return 0;
}
```

Before this change:
```
$ bazel-bin/toolchain/carbon compile main.carbon
main.carbon:13:38: error: cannot access member of interface `Core.AddWith(Cpp.MyNamespace.MyNumber)` in type `Cpp.MyNamespace.MyNumber` that does not implement that interface
  let n3: Cpp.MyNamespace.MyNumber = n1 + n2;
                                     ^~~~~~~
```

With this change:

```shell
$ clang -c my_number.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link my_number.o main.o --output=demo
$ ./demo
5
7
12
```

Part of https://github.com/carbon-language/carbon-lang/issues/5995.
2025-09-10 14:03:09 +00:00
Jon Ross-Perkins 3f799bd987 Use explicit(false) for implicit construction (#6039)
Echoing what was added in #5608, updating existing uses. Unfortunately
there's divergent behavior for operators versus constructors, so keeping
the nolint on those.
2025-09-10 13:47:59 +00:00
Jon Ross-Perkins b74fdf52de Use typename on templates for consistency. (#6038)
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`.
2025-09-10 13:44:36 +00:00
Jon Ross-Perkins 0518fdebbc Fix potential fingerprint conflict in constraints (#6033)
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`.
v0.0.0-0.nightly.2025.09.10
2025-09-09 21:44:03 +00:00
Boaz Brickner 56adfa20ce C++ interop: Add a test for calling an operator on an inner class (#6030)
This currently works and I'd like to keep it that way when adding
operators in namespace support.

Part of #5995.
2025-09-09 13:06:55 +00:00
Dana Jansens 1dbf000905 Avoid python stack traces when hitting ^C in autoupdate (#6004)
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.
v0.0.0-0.nightly.2025.09.09
2025-09-08 21:17:36 +00:00
Dana Jansens b92e23962a Use a FixedSizeValueStore<CheckIRId> in Lower::Context (#6021)
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.
2025-09-08 17:33:54 +00:00
Dana Jansens 64139e5d65 Stop using Map for the cache in InstFingerprinter (#6019)
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.
2025-09-08 16:15:10 +00:00
Boaz Brickner 471b394c6d C++ interop: Support unary operators (#6020)
Newly supported: `-`.
Partially supported due to lack of reference support: `++` (prefix),
`--` (prefix).
Not supported due to lack of Carbon support to call them correctly: `+`,
`++` (postfix), `--` (postfix), `~`, `!`, `&`, `*`, `->`.

Also (for consistency):
* Add the operator declarations to unsupported binary operators tests.
* Logical operators and the unary `operator&` (address of) are expected
to be called by explicitly calling `operatorX`.

C++ Interop Demo:

```c++
// my_number.h

class MyNumber {
 public:
  explicit MyNumber(int value) : value_(value) {}
  auto value() const -> int { return value_; }

 private:
  int value_;
};

auto operator++(MyNumber operand) -> MyNumber;
auto operator--(MyNumber operand) -> MyNumber;
auto operator-(MyNumber operand) -> MyNumber;
```

```c++
// my_number.cpp

#include "my_number.h"

auto operator++(MyNumber operand) -> MyNumber {
  return MyNumber(operand.value() + 1);
}

auto operator--(MyNumber operand) -> MyNumber {
  return MyNumber(operand.value() - 1);
}

auto operator-(MyNumber operand) -> MyNumber {
  return MyNumber(-operand.value());
}
```

```carbon
// main.carbon

library "Main";

import Core library "io";
import Cpp library "my_number.h";

fn Run() -> i32 {
  var num: Cpp.MyNumber = Cpp.MyNumber.MyNumber(14);
  Core.Print(num.value());
  ++num;
  Core.Print(num.value());
  --num;
  Core.Print(num.value());
  num = -num;
  Core.Print(num.value());
  return 0;
}
```

```shell
$ clang -c my_number.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link my_number.o main.o --output=demo
$ ./demo
14
14
14
-14
```

Part of https://github.com/carbon-language/carbon-lang/issues/5995.
2025-09-08 15:39:08 +00:00
Chandler Carruth 049abc638d Update LLVM to pick up new compiler-rt build rules (#6023)
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.
2025-09-08 14:51:23 +00:00
Boaz Brickner b88b53e7e3 C++ interop: Add support for importing globals (#6005)
This supports importing globals in the global scope and within
namespaces, and support for class static data members.

C++ Interop Demo:

```c++
// my_global.h

extern int my_global;
void inc_my_global();
```

```c++
// my_global.cpp

#include "my_global.h"

int my_global = 5;

void inc_my_global() {
  ++my_global;
}
```

```carbon
// main.carbon

library "Main";

import Core library "io";
import Cpp library "my_global.h";

fn Run() -> i32 {
  Core.Print(Cpp.my_global);
  Cpp.inc_my_global();
  Core.Print(Cpp.my_global);
  return 0;
}
```

```shell
$ clang -c my_global.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link my_global.o main.o --output=demo
$ ./demo
5
6
```

Part of #6006.
2025-09-08 08:34:55 +00:00
Boaz Brickner 321891cd8e Hello world C++ interop example (#5991)
Based on #5920.
Added commented out better examples and clarified what is missing to
support them.
Added `tags` support to `carbon_binary` (based on #5967) to set the
`BUILD` rule to manual until we can find `cstdio` in macos.

```shell
$ bazel run examples/interop/cpp:hello_world
...
Hello world!
```
2025-09-08 07:44:29 +00:00
Chandler Carruth 0691d4827c Update LLVM (#6022)
Notably, this updates past a major AST refactoring and tries to apply
those changes across the toolchain.
v0.0.0-0.nightly.2025.09.08 v0.0.0-0.nightly.2025.09.07
2025-09-06 08:36:10 +00:00
Boaz Brickner ee42b2db93 C++ interop: Support more binary operators (#6017)
Already supported: `+`.
Newly supported: `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, `>>`, `==`,
`!=`, `<`, `>`, `<=`, `>=`.
Partially supported due to lack of reference support: `+=`, `-=`, `*=`,
`/=`, `%=`, `&=`, `|=`, `^=`.
Not supported due to lack of reference support: `<<=`, `>>=`.
Not supported (I think Carbon doesn't want overloading these): `&&`,
`||`.

C++ Interop Demo:

```c++
// my_number.h

class MyNumber {
 public:
  explicit MyNumber(int value) : value_(value) {}
  auto value() const -> int { return value_; }
  void set_value(int value) { value_ = value; }

 private:
  int value_;
};

// Arithmetic
auto operator+(MyNumber lhs, MyNumber rhs) -> MyNumber;
auto operator-(MyNumber lhs, MyNumber rhs) -> MyNumber;
auto operator*(MyNumber lhs, MyNumber rhs) -> MyNumber;
auto operator/(MyNumber lhs, MyNumber rhs) -> MyNumber;
auto operator%(MyNumber lhs, MyNumber rhs) -> MyNumber;

// Bitwise
auto operator&(MyNumber lhs, MyNumber rhs) -> MyNumber;
auto operator|(MyNumber lhs, MyNumber rhs) -> MyNumber;
auto operator^(MyNumber lhs, MyNumber rhs) -> MyNumber;
auto operator<<(MyNumber lhs, int shift) -> MyNumber;
auto operator>>(MyNumber lhs, int shift) -> MyNumber;

// Compound Arithmetic
auto operator+=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull;
auto operator-=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull;
auto operator*=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull;
auto operator/=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull;
auto operator%=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull;

// Compound Bitwise
auto operator&=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull;
auto operator|=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull;
auto operator^=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull;

// Relational
auto operator==(MyNumber lhs, MyNumber rhs) -> bool;
auto operator!=(MyNumber lhs, MyNumber rhs) -> bool;
auto operator<(MyNumber lhs, MyNumber rhs) -> bool;
auto operator>(MyNumber lhs, MyNumber rhs) -> bool;
auto operator<=(MyNumber lhs, MyNumber rhs) -> bool;
auto operator>=(MyNumber lhs, MyNumber rhs) -> bool;
```

```c++
// my_number.cpp

#include "my_number.h"

// Arithmetic
auto operator+(MyNumber lhs, MyNumber rhs) -> MyNumber {
  return MyNumber(lhs.value() + rhs.value());
}
auto operator-(MyNumber lhs, MyNumber rhs) -> MyNumber {
  return MyNumber(lhs.value() - rhs.value());
}
auto operator*(MyNumber lhs, MyNumber rhs) -> MyNumber {
  return MyNumber(lhs.value() * rhs.value());
}
auto operator/(MyNumber lhs, MyNumber rhs) -> MyNumber {
  return MyNumber(lhs.value() / rhs.value());
}
auto operator%(MyNumber lhs, MyNumber rhs) -> MyNumber {
  return MyNumber(lhs.value() % rhs.value());
}

// Bitwise
auto operator&(MyNumber lhs, MyNumber rhs) -> MyNumber {
  return MyNumber(lhs.value() & rhs.value());
}
auto operator|(MyNumber lhs, MyNumber rhs) -> MyNumber {
  return MyNumber(lhs.value() | rhs.value());
}
auto operator^(MyNumber lhs, MyNumber rhs) -> MyNumber {
  return MyNumber(lhs.value() ^ rhs.value());
}
auto operator<<(MyNumber lhs, int shift) -> MyNumber {
  return MyNumber(lhs.value() << shift);
}
auto operator>>(MyNumber lhs, int shift) -> MyNumber {
  return MyNumber(lhs.value() >> shift);
}

// Compound Arithmetic
auto operator+=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull {
  return &(*lhs = *lhs + rhs);
}
auto operator-=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull {
  return &(*lhs = *lhs - rhs);
}
auto operator*=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull {
  return &(*lhs = *lhs * rhs);
}
auto operator/=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull {
  return &(*lhs = *lhs / rhs);
}
auto operator%=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull {
  return &(*lhs = *lhs % rhs);
}

// Compound Bitwise
auto operator&=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull {
  return &(*lhs = *lhs & rhs);
}
auto operator|=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull {
  return &(*lhs = *lhs | rhs);
}
auto operator^=(MyNumber* _Nonnull lhs, MyNumber rhs) -> MyNumber* _Nonnull {
  return &(*lhs = *lhs ^ rhs);
}

// Relational
auto operator==(MyNumber lhs, MyNumber rhs) -> bool {
  return lhs.value() == rhs.value();
}
auto operator!=(MyNumber lhs, MyNumber rhs) -> bool {
  return lhs.value() != rhs.value();
}
auto operator<(MyNumber lhs, MyNumber rhs) -> bool {
  return lhs.value() < rhs.value();
}
auto operator>(MyNumber lhs, MyNumber rhs) -> bool {
  return lhs.value() > rhs.value();
}
auto operator<=(MyNumber lhs, MyNumber rhs) -> bool {
  return lhs.value() <= rhs.value();
}
auto operator>=(MyNumber lhs, MyNumber rhs) -> bool {
  return lhs.value() >= rhs.value();
}
```

```carbon
// main.carbon

library "Main";

import Core library "io";
import Cpp library "my_number.h";

fn PrintBool(b: bool) {
  if (b) {
    Core.Print(1);
  } else {
    Core.Print(0);
  }
}

fn Run() -> i32 {
  // Arithmetic
  var num1: Cpp.MyNumber = Cpp.MyNumber.MyNumber(14);
  var num2: Cpp.MyNumber = Cpp.MyNumber.MyNumber(5);
  Core.Print(num1.value());
  Core.Print(num2.value());
  Core.Print((num1 + num2).value());
  Core.Print((num1 - num2).value());
  Core.Print((num1 * num2).value());
  Core.Print((num1 / num2).value());
  Core.Print((num1 % num2).value());

  // Bitwise
  var bits1: Cpp.MyNumber = Cpp.MyNumber.MyNumber(12);
  var bits2: Cpp.MyNumber = Cpp.MyNumber.MyNumber(10);
  Core.Print(bits1.value());
  Core.Print(bits2.value());
  Core.Print((bits1 & bits2).value());
  Core.Print((bits1 | bits2).value());
  Core.Print((bits1 ^ bits2).value());
  Core.Print((bits1 << 2).value());
  Core.Print((bits1 >> 1).value());

  // Compound Arithmetic
  var c: Cpp.MyNumber = Cpp.MyNumber.MyNumber(100);
  Core.Print(c.value());
  &c += Cpp.MyNumber.MyNumber(10);
  Core.Print(c.value());
  &c -= Cpp.MyNumber.MyNumber(20);
  Core.Print(c.value());
  &c *= Cpp.MyNumber.MyNumber(2);
  Core.Print(c.value());
  &c /= Cpp.MyNumber.MyNumber(6);
  Core.Print(c.value());
  &c %= Cpp.MyNumber.MyNumber(9);
  Core.Print(c.value());

  // Compound Bitwise
  &c |= Cpp.MyNumber.MyNumber(12);
  Core.Print(c.value());
  &c &= Cpp.MyNumber.MyNumber(7);
  Core.Print(c.value());
  &c ^= Cpp.MyNumber.MyNumber(10);
  Core.Print(c.value());

  // Relational
  var rel1: Cpp.MyNumber = Cpp.MyNumber.MyNumber(20);
  var rel2: Cpp.MyNumber = Cpp.MyNumber.MyNumber(30);
  var rel3: Cpp.MyNumber = Cpp.MyNumber.MyNumber(20);
  Core.Print(rel1.value());
  Core.Print(rel2.value());
  Core.Print(rel3.value());
  PrintBool(rel1 == rel3);
  PrintBool(rel1 != rel2);
  PrintBool(rel1 < rel2);
  PrintBool(rel2 > rel1);
  PrintBool(rel1 <= rel3);
  PrintBool(rel1 >= rel2);

  return 0;
}
```

```shell
$ clang -c my_number.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link my_number.o main.o --output=demo
$ ./demo
14
5
19
9
70
2
4
12
10
8
14
6
48
6
100
110
90
180
30
3
15
7
13
20
30
20
1
1
1
1
1
0
```

Part of https://github.com/carbon-language/carbon-lang/issues/5995.
v0.0.0-0.nightly.2025.09.06
2025-09-05 13:03:10 +00:00
Richard Smith db0a00d713 Fix double-destruction of temporaries. (#6010)
Attach the cleanup to the `Temporary` instruction instead of to the
`TemporaryStorage` instruction. We create `TemporaryStorage`
instructions speculatively when creating an initializing expression, and
may overwrite those instructions with other instructions if it turns out
that a temporary is not required. Instead, wait until we finalize the
temporary and create a `Temporary` instruction to register the cleanup.
v0.0.0-0.nightly.2025.09.05
2025-09-04 19:19:59 +00:00
Richard Smith f943f31e41 Allow a value of type MaybeUnformed(T) to convert to T with unsafe as (#6014)
We already allowed this for reference expressions; this extends the
support to also cover value expressions. This requires a little more
work because the value representation of `T` and `MaybeUnformed(T)`
don't necessarily match in general.
2025-09-04 19:10:28 +00:00
Richard Smith 51cb078da4 Support lowering of functions with variable binding parameters. (#6012)
Fix a crash when attempting to lower a function with a variable binding
as a parameter. This is a narrowly-targeted fix, and not the right
longer-term approach; more complex patterns as function parameters will
still fail and likely crash.
2025-09-04 15:02:37 +00:00
Jon Ross-Perkins 74a8d51d78 Add test name to all file_test errors (#6011)
Common case is going to be like:

```
Running tests with 64 thread(s)

Autoupdate can't discard non-CHECK lines inside conflicts:

......................!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!..!!!!!!!!!!!!!!!!!!!!.
```

->

```
Running tests with 64 thread(s)

toolchain/check/testdata/as/unsafe_as.carbon: Autoupdate can't discard non-CHECK lines inside conflicts:

......................!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!..!!!!!!!!!!!!!!!!!!!!.
```

(i.e., the conflict line was blank)

One error had the test name, I'm dropping it here, meaning:

```
................................................................................
Missing AUTOUPDATE/NOAUTOUPDATE setting: toolchain/codegen/testdata/assembly/basic.carbon
................................................................................
```

->

```
................................................................................
toolchain/codegen/testdata/assembly/basic.carbon: Missing AUTOUPDATE/NOAUTOUPDATE setting
................................................................................
```

For single-threaded runs, at the top there's already:

```
  } else if (single_threaded) {
    std::unique_lock<std::mutex> lock(output_mutex);
    llvm::errs() << "\nTEST: " << test.test_name << ' ';
  }
```
2025-09-04 14:54:47 +00:00
Dana JansensandJon Ross-Perkins 70f104aa40 Always import canonical instructions except for exceptional Decl cases (#6009)
There are a few instructions that import in multiple phases, which
receive the `const_id` and use it to construct multiple constants until
building the final constant value. These include
`AssociatedConstantDecl`, `FunctionDecl`, and `InterfaceDecl`.

Other instructions just construct a constant value in a single attempt,
once all their dependencies are imported. For these instruction types,
avoid importing the non-canonical instruction. Always get the canonical
constant instruction and import that.

Since the constant value of an instruction can have a very different
structure than its non-canonical value, this ensures import has a
consistent structure to work with, by only working with canonical values
as much as possible.

The `VtableDecl` and `VtablePtr` were set up to pass along `const_id`
but do not actually require multiple phases, so they have been changed
to stop passing along the unused (and always empty) `const_id`.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
v0.0.0-0.nightly.2025.09.04
2025-09-03 22:36:27 +00:00
Richard Smith cb5e2e1597 Improve support for qualification conversions. (#5999)
* Treat `MaybeUnformed` and `partial` as qualifiers, like `const`.
* Allow pointer conversions to add qualifiers.
* Allow unsafe pointer conversions to remove qualifiers.
* Allow conversions on non-reference expressions to drop `const`.
* Allow unsafe conversions on any expression to drop `const`.
* Allow unsafe conversions on non-initializing expressions to drop
  `partial`. For initializing expressions, we should initialize the
  vptr when dropping `partial`; this is not yet supported so we reject.
* Allow conversions on reference expressions to add `MaybeUnformed`.
* Allow unsafe conversions on reference expressions to drop
  `MaybeUnformed`. For non-reference expressions, additional work is
  required, because the value / initializing representation may not
  match between `T` and `MaybeUnformed(T)`, so those are rejected for
  now.
2025-09-03 21:00:12 +00:00
Richard Smithandjosh11b 10fab24451 Add example showing basic interop with C++ RE2 library (#5967)
Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
2025-09-03 20:41:48 +00:00
Boaz Brickner 870c5380a0 C++ interop: Support importing binary operator+ (#5996)
Triggered by calling a binary operator with LHS being an imported C++
class type.

Not supported (yet):
* Multiple overloads.
* Other operators.

C++ Interop Demo:

```c++
// hello_world.h

class C {
 public:
  C(int x) : x_(x) {}
  auto x() const -> int { return x_; }

 private:
  int x_ = 0; 
};

auto operator+ (C c1, C c2) -> C;
```

```c++
// hello_world.cpp

#include "hello_world.h"

#include <cstdio>

auto operator+ (C c1, C c2) -> C {
  printf("Adding %d with %d\n", c1.x(), c2.x());
  return C(c1.x() + c2.x());
}
```

```carbon
// main.carbon

library "Main";

import Cpp library "hello_world.h";

fn Run() -> i32 {
  let c1 : Cpp.C = Cpp.C.C(7);
  let c2 : Cpp.C = Cpp.C.C(8);
  let c3 : Cpp.C = c1 + c2;
  let c4 : Cpp.C = c3 + c2;
  return 0;
}

```

```shell
$ clang -c hello_world.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link hello_world.o main.o --output=demo
$ ./demo
Adding 7 with 8
Adding 15 with 8
```

Part of #5995.
2025-09-03 12:01:20 +00:00
Elliott Kalt 58de34e534 Decouple associated constants from let (#5973)
Decouples associated constants from being special cased in let handlers.
Enforces associated constant grammar restrictions in parsing instead of
checking.

Closes #5411
v0.0.0-0.nightly.2025.09.03
2025-09-02 23:15:26 +00:00
Richard Smith 0e6dd7e701 Add MaybeUnformed(T) type. (#5989)
This type has the same object representation as `T`, but always uses a
pointer type as its value representation. No other semantics are
provided for it yet.
2025-09-02 20:50:49 +00:00
Richard SmithandDana Jansens 4483d1e5a7 Recover better from invalid C++ classes. (#5992)
When importing a class definition, don't ask for the class layout if the
definition is invalid. Avoids an assertion failure in Clang.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2025-09-02 19:32:35 +00:00
Dana Jansens 00d0eb85e2 Remove redundant if condition after #5971 (#6003)
PR #5971 added this same condition as an early-out earlier in the
PerformBuiltinConversion function.
2025-09-02 19:28:54 +00:00
Boaz Brickner b5d86fdb6f Properly dump SemIR for inline C++ imports (#6001)
Dumping SemIR crashed on inline C++ imports and this outputs `import Cpp
inline` instead.
Followup of #5904.
v0.0.0-0.nightly.2025.09.02 v0.0.0-0.nightly.2025.09.01 v0.0.0-0.nightly.2025.08.31 v0.0.0-0.nightly.2025.08.30
2025-08-29 21:36:10 +00:00
Boaz Brickner 8adb3570ac C++ Interop: Add support for char (#5988)
Added tests for different character types.
`char` is currently not in primitives prelude, so had to use full
prelude.

C++ Interop Demo:

```carbon
// main.carbon

library "Main";

import Cpp inline '''
auto output_char(char c) -> void {
  printf("%c", c);
}
''';

fn Run() -> i32 {
  let msg: array(Core.Char, 13) =
      ('H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\n');
  for (c: Core.Char in msg) {
    Cpp.output_char(c);
  }
  return 0;
}
```

```shell
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link main.o --output=demo
$ ./demo
Hello world!
```

Part of https://github.com/carbon-language/carbon-lang/issues/5263.
v0.0.0-0.nightly.2025.08.29
2025-08-29 01:11:24 +00:00
Richard Smith 50e5476ee3 Add support for unsafe as operator to the toolchain. (#5993)
Following the direction of #5913, add support for parsing an `unsafe as`
operator. For now, we allow one additional conversion using `unsafe as`
beyond the conversions supported by `as`: we permit pointer conversions
that remove qualifiers, such as `const T*` -> `T*`.
2025-08-28 23:00:53 +00:00
David Blaikie 1d0f30df3a Fix a use of an imported InstId used where a local InstId is required (#5998)
Found by WIP validation for this type of issue ongoing in #5997

I'm not entirely sure how the one test update falls out of this change -
but it is from the same test that I originally reduced the problem from,
which is reassuring.

The reduced test case I investigated the issue with was this:
`a.carbon`:
```
library "lib";
interface I1(Other:! type) {
   let Result:! type;
}
```
`b.carbon`:
```
import library "lib";
class T1 { }
impl T1 as I1(Self) where .Result = Self { }
```
The SemIR dump diff looked like this:
```
89c89
<   %Main.import_ref.b6f = import_ref Main//lib, inst28 [no loc], unloaded
---
>   %Main.import_ref.b6f = import_ref Main//lib, inst27 [no loc], unloaded
96c96
<   %Main.import_ref.f7b: @I1.%I1.type (%I1.type.e87) = import_ref Main//lib, inst28 [no loc], loaded [symbolic = @I1.%Self (constants.%Self.c47)]
---
>   %Main.import_ref.f7b: @I1.%I1.type (%I1.type.e87) = import_ref Main//lib, inst27 [no loc], loaded [symbolic = @I1.%Self (constants.%Self.c47)]
```
Which is a difference, but given the `inst28`/`inst27` don't appear
anywhere else than these two lines, it doesn't give a terribly
meaningful diff/story about what changed - but perhaps it's
sufficient...

Not sure if this test ^ is sufficiently more interesting than the diff
update already in this patch. If so, happy to add the above as a new
test case.

Open to ideas.
2025-08-28 20:02:26 +00:00