Commit Graph
110 Commits
Author SHA1 Message Date
Lucile Rose Nihlen bc1ae703c3 return 0 from Run when it doesn't specify a return value (#7180)
https://carbon.compiler-explorer.com/z/88K9Kh5Wo shows the program
exiting with a garbage value copied from uninitialized memory.

This PR modifies `lower` to detect if the function lowered is the
entry point and doesn't specify a return type. If so, it emits
different LLVM IR to return int32 0, and modifies the lowered
function signature to match the int32 return type.
2026-05-08 19:00:47 +00:00
Richard Smith bc06f6c5ec Mangle the signature decl when mangling a thunk. (#7177)
Fixes mangling collisions when two thunks with the same name (eg, `Op`)
are created in the same context, which in turn would lead to LLVM
verifier failures and miscompiles.

To support this, add a new value store to track a little more
information about thunks beyond what's in the `Function`.
2026-05-07 21:58:29 +00:00
Nicholas Bishop 1bc329af14 Support calling Carbon destructors from C++ (#7143)
A destructor is added to the C++ class definition in
`CarbonExternalASTSource::CompleteType`. The destructor calls a Carbon
function that calls the `Destroy` operator.
2026-05-04 20:28:58 +00:00
Dana Jansens f8dd4d85bf Do not treat impls in different scopes as redeclarations (#7161)
An impl in a different scope, with the same parameters, will overlap and
get diagnosed for that later by the [prioritization
rule](https://docs.carbon-lang.dev/docs/design/generics/details.html#prioritization-rule),
if they are not in a match_first block. But they are not considered as
redeclarations.

See [proposal
p5366](https://github.com/carbon-language/carbon-lang/blob/62b94f79322039acc3fc8e175896a64a32df470e/proposals/p5366.md)
for the rule.
2026-05-04 19:11:51 +00:00
David Blaikie 071ab9f532 Import dynamic-ness of a C++ class (#7141) 2026-05-01 22:53:44 +00:00
Nicholas Bishop f3f039516e Support accessing Carbon class fields from C++ (#7119)
When any field of a Carbon class is access from C++ for the first time,
all fields are exported as `clang::FieldDecl`s (this is necessary
because clang fields have an internal index that is initialized on first
use).

`ClangDeclStore` now provides bidirectional mapping. This allows looking
up a `ClangDeclId` by `InstId`, so when Carbon class fields are exported
they can be looked up that way.
2026-04-29 20:07:10 +00:00
Richard Smith 0124aae041 Import non-const rvalue references as var parameters. (#7125)
When importing a C++ function with an rvalue reference parameter, we
previously produced a Carbon value parameter. This would lead to the
toolchain believing it could pass the address of a non-expiring object
to the function, which would lead to a use-after-move.

Instead, we now map non-const rvalue reference parameters to Carbon
`var` parameters. This forces the object passed into C++ to be unique
and owned by the call. While that's not an exact match for C++ rvalue
reference parameters, given that it provides "always move" not
"conditionally move", it's the closest match we have at the moment.
2026-04-29 00:28:00 +00:00
Dana Jansens 554b1b8d10 Remove SymbolicBindingType (#7114)
This inst was meant to support tracking the depth of a `.Self` facet,
but we have now implemented substitution of `.Self` in facet type
identification, and in eval of where expressions, without needing to
track the depth.

See history here:
-
[2025-06-30](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.4qd5dkyfn2k3)
-
[2025-07-07](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.7urbxcq23olv)
- #6026
2026-04-27 19:04:59 +00:00
Nicholas Bishop 67648b4d49 Remove "__cpp_thunk" from thunk name for exported functions (#7092)
This makes the behavior consistent between methods and regular
functions, and fixes the behavior with `using` aliases (see new
`using.carbon` test).

As requested in
https://github.com/carbon-language/carbon-lang/pull/7078#discussion_r3121104954.
2026-04-22 18:05:02 +00:00
Nicholas Bishop 33d534ab31 Support calling Carbon methods from C++ (#7078)
The FunctionDecl created for calling the Carbon thunk now takes a `self`
parameter for non-static methods, and the C++ thunk now passes an extra
argument for that `self` parameter when needed.

The CXXMethodDecl thunk created for calling methods now sets the storage
class appropriate depending on whether the method is static or not.

To reduce the number of parameters being passed around to thunk-building
functions, added a `FunctionInfo` struct and pass that around instead.
2026-04-22 15:09:33 +00:00
Richard Smith f91990aa87 Override Clang class layout for Carbon class types. (#7071)
Use the Carbon-determined size and alignment for Carbon-defined classes,
rather than allowing Clang to work one out for itself using the C++
rules.
2026-04-17 00:03:29 +00:00
Nicholas Bishop 114cf401c2 Support C++ calling Carbon functions with non-() return type (#7051)
For calling non-`()` functions, the Carbon->Carbon thunk now takes an
extra reference parameter and writes the target function's return value
out to that parameter. (At the SemIR level this is how returns already
work, but adding this extra reference parameter is needed so that the
function is lowered correctly.) The C++ thunk now creates a local
variable to be initialized by the Carbon thunk, and then returns that
value to the original C++ caller.
2026-04-16 00:29:38 +00:00
Richard Smith be0c07dc7e Give Carbon -> C++ thunks internal linkage. (#7040)
Also declare them `inline` since we're putting the `always_inline`
attribute on them. Use the `internal_linkage` attribute rather than
`SC_Static` since it's a more precise mechanism and matches what we do
for static member functions in reverse interop (where `SC_Static` means
something else and would not give the function internal linkage).
2026-04-08 21:14:30 +00:00
Richard Smith b74e0d1260 Superficial support for exporting complete class types to C++. (#7029)
We don't yet populate the bases or fields, so the class types show up as
empty classes in C++ for now. But we do allow calls to static member
functions.
2026-04-08 19:29:25 +00:00
Nicholas Bishop 0635f4628f Add support for C++ calling Carbon functions with parameters (#7024)
This works by generating two thunks, one in C++ and one in Carbon. For
example, given this input:
```c++
// Carbon:
fn Callme(f: f32) {}

// C++:
void F() {
  // This will call `Callme__cpp_thunk`
  Carbon::Callme(1.0);
}
```

These functions are generated:
```c++
// Carbon:
fn Callme__carbon_thunk(ref f: f32) {
  // Call the target function.
  Callme(f);
}

// C++:

// C++ declaration for the Carbon thunk.
void Callme__carbon_thunk(float& f);

void Callme__cpp_thunk(float f) {
  // Call the Carbon thunk with args passed by reference.
  Callme__carbon_thunk(f);
}
```

For now, all arguments are passed by reference, even if they are simple
types like pointers or i32.

Functions with non-void return types are not supported yet.
2026-04-07 23:25:57 +00:00
Richard Smith 05ba1d7356 Add a conversion impl from T* to const T* (#7010)
This is already allowed as a builtin conversion, but the impl allows the
generics system to know about it, so that conversions like
`Optional(T*)` to `Optional(const T*)` are allowed. This in turn allows
a C++ `T*` to be implicitly converted to a C++ `const T*` in Carbon
code.
2026-04-03 22:07:53 +00:00
Richard Smith 81ed4d829d Perform CppThunkRef conversion as part of category conversion. (#7020)
Instead of recursing back into Convert, make CppThunkRef conversion just
add an extra step to category conversion, performing a copy conversion
followed by an ephemeral reference binding conversion.
2026-04-02 23:39:25 +00:00
Jon Ross-Perkinsandjonmeow 9266ced4e3 Improve CanDestroyType to handle remaining cases (#6943)
This is only fixing the decision about *whether* to produce a witness.
Implementation of the witness is still a TODO, though where a body is
generated, it should also precisely reflect where one _needs_ to be
generated.

Note the tests:

- toolchain/lower/testdata/function/generic/import_core_witness.carbon
- toolchain/lower/testdata/function/generic/import_unused_def.carbon

These tests can probably be produced _without_ Core.Destroy, but I found
the essence of them while trying to build //examples with Core.Destroy
and a simpler minimization wasn't striking me.

Assisted-by: Google Antigravity with Gemini

---------

Co-authored-by: jonmeow <jperkins@google.com>
2026-04-02 22:54:58 +00:00
Richard Smith dfac728571 Fix pointer sizes in debug info. (#7002)
The size is in bits, so 8 is an unlikely value. Also, don't hardcode a
size, ask the data layout for it.
2026-04-01 16:35:12 +00:00
Richard Smith 8b59e85b16 Add support for inline Cpp declarations. (#6994)
For #6830, add support for inline C++ fragments as a declaration rather
than as a packaging directive. For now, this uses `inline Cpp
<string-literal>;` as syntax. The prior `import Cpp inline
<string-literal>;` is left alone for the time being. We can decide
separately whether to remove that.

`inline Cpp` requires that there was at least one `import Cpp`. It's not
clear to me if that's the right design long-term, but it seems
reasonable for now.

Assisted-by: Gemini via Google Antigravity
2026-03-31 22:27:43 +00:00
Nicholas Bishop 396756c151 Handle Temporary values when const-evaling AcquireValue (#6992)
This will be used for const-evaling functions. Splitting into a separate
commit since it touches a lot of test files, and a couple fail_todo
tests are no longer failing.
2026-03-31 15:50:54 +00:00
Nicholas Bishop bf6a14ac39 Support Temporary constants (#6983)
Evaluate `Temporary` constants to a `Temporary` with the `storage` field
set to `None`.
2026-03-30 19:07:46 +00:00
Nicholas Bishop 1ef35e8299 Fix name mangling for Carbon functions called from C++ (#6984)
Since this requires using the `Mangler` class from `toolchain/check`,
moved it from `toolchain/lower` to `toolchain/sem_ir`.

The mangled name is then attached to the `FunctionDecl` with an
`AsmLabelAttr`.
2026-03-27 22:52:11 +00:00
Nicholas Bishop 85da6cae01 Support calling simple Carbon functions from C++ (#6967)
For now, only functions with no parameters and a `()` return type are
supported.
2026-03-26 18:14:39 +00:00
Richard Smith 37b238fa28 Make C++ types impl Core.Default. (#6962)
C++ classes that are default-constructible now implement `Core.Default`
by calling the default constructor.
2026-03-25 21:07:24 +00:00
David Blaikie 415cd6f8f0 Reverse Interop: Class declarations (#6955)
Generate class declarations for Carbon classes referenced from C++

Based on #6940, review from eb62070a01
onwards
2026-03-25 04:50:08 +00:00
Geoff Romer e0c6800ab3 Reverse nesting structure of parameter patterns (#6930)
See
[here](https://docs.google.com/document/d/1rWcueFwIfZox6GKVGxiUG4cBzjrZ6djXiIDGyJDtrE4/edit?tab=t.0#heading=h.7mi143mdhr2h)
for an overview of the changes and their rationale.

Assisted-by: Gemini 3.1 Pro via Antigravity
2026-03-23 20:38:20 +00:00
Richard SmithandGeoff Romer ce50f181f1 Add an interface for initialization of vars without an explicit initializer (#6934)
When a `var` is not explicitly given an initializer, initialize it in
one of two ways:

* If its type implements the new interface `Core.Default`, call
`Core.Default.Op` to initialize it.
* Otherwise, if its type implements `UnformedInit`, leave it in an
unformed state. For now, this is always an uninitialized state, but that
will change in the future.
* If neither of those apply, the `var` declaration is ill-formed.

This is a step towards implementing leads decision #6739 and proposals
#257 and #5913.

Assisted-by: Gemini 3.1 Pro via Antigravity

---------

Co-authored-by: Geoff Romer <gromer@google.com>
2026-03-19 23:46:06 +00:00
Richard Smith 2e5b195813 Make {} as Class an initializing expression. (#6882)
Previously we forced a temporary materialization, resulting in it being
treated as an ephemeral reference expression. This change allows

```carbon
var x: Class = {} as Class;
```

even when `Class` is not copyable.
2026-03-11 20:21:21 +00:00
Jon Ross-Perkins 70c401f85f Updates the llvm-raw commit to HEAD as of 2026-03-09 (#6879)
Test changes are the result of autoupdate_testdata.py

Assisted-by: Google Antigravity with Gemini
2026-03-11 14:47:40 +00:00
Dana JansensandChandler Carruth 744b1290cf Roll LLVM b20d7d02..6811a83c815 (#6844)
Roll LLVM to `6811a83c81500ee373adfc0d9978ff9625a4cf1c`.

This includes https://github.com/llvm/llvm-project/pull/183831 which
moved the functionality of `finish()` on `DiagnosticConsumer`s into the
destructors, and removed the `finish()` method. So, our callers to
`finish()` are migrated to cause the destructor to run at that time
instead.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2026-03-09 15:00:21 +00:00
Richard SmithandCarbon Infra Bot 15680ba101 Support calling functions with explicit template arguments. (#6814)
Treat the initial sequence ofarguments in a call to a C++ function up to
and including the last argument that is a type or template as being the
explicit template arguments for the call, rather than rejecting them
because they can't be converted to the parameter types.

Implements the current direction on leads issue #6768, except that no
syntax for explicitly annotating an argument as being a template
argument is provided.

---------

Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
2026-03-03 00:26:33 +00:00
Geoff RomerandJon Ross-Perkins 6dba8ee111 Remove index fields from ParamPatterns (#6815)
This is a step toward removing the index from `InitForm`, so that equal
form values always have equal representations.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2026-03-03 00:19:47 +00:00
Jon Ross-Perkins b14015602b Make Destroy.Op functions able to have a body (#6729)
This is iterating on how `Destroy.Op` generates, to start adding body
capabilities. This changes the way the signature is created, and adds a
`CoreWitness` function kind so that mangling can prevent name
collisions. The result is that what _was_ `DestroyOp` is now
`Core.Destroy.Op` or, as can be seen in
toolchain/lower/testdata/interop/cpp/nullptr.carbon,
`_COp.<hash>:core.Destroy.Core` where `:core` is indicating that it's a
core witness (taking a note from `:thunk`).

Assisted-by: Google Antigravity with Gemini 3 Flash
2026-03-02 17:57:31 +00:00
little KitchenandRichard Smith 8edd5eb9a1 fix: reject {} initialization for non-aggregate C++ classes (#6675)
## Summary

Fixes the toolchain incorrectly allowing `{}` initialization for
non-aggregate C++ classes.

## Problem

When importing an empty C++ class, the toolchain was treating it as a
Carbon empty struct, which allowed initialization from `{}`. This is
incorrect for non-aggregate classes (e.g., those with user-declared
constructors).

```carbon
import Cpp inline '''
struct X { X(); };  // non-aggregate (has user-declared constructor)
''';

fn Make() {
  var x: Cpp.X = {};  // incorrectly accepted, should be rejected
}
```

## Solution

Added a check for `clang_def->isAggregate()` in `ImportClassObjectRepr`
so that only aggregate classes get the empty struct representation.

**Before:**
```cpp
if (clang_def->isEmpty() && !clang_def->getNumBases()) {
```

**After:**
```cpp
if (clang_def->isEmpty() && !clang_def->getNumBases() &&
    clang_def->isAggregate()) {
```

## Testing

Added test file
`toolchain/check/testdata/interop/cpp/class/non_aggregate_init.carbon`
with:
- Non-aggregate class (`struct X { X(); }`) - should reject `{}`
initialization
- Aggregate class (`struct Y {}`) - should accept `{}` initialization

Note: I couldn't run tests locally due to clang version requirements
(needs >= 19, have 17). The CI should validate the changes.

Closes #6669

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-02-24 18:19:50 +00:00
Chandler Carruth 375a736c42 Update LLVM to a more recent commit (#6771)
This includes the major version bump and some changes to output in
various tests.
2026-02-23 20:30:55 +00:00
Prabhat Sachdeva a5a4c756a7 Only treat top-level Run in Main as the entry point (#6757)
Fix IsEntryPoint to only recognize `Run` as the program entry point when
it is declared at package scope in the `Main` package, not when it
appears inside a namespace or via C++ interop.

Closes #6755
2026-02-18 22:17:15 +00:00
Richard Smith 773837e1bb Ask Clang to emit C++ global variables. (#6748)
Don't emit them ourselves. This was leading to our emitted variable
being renamed away from the proper symbol name, leading to link errors.

Fixes #6742.
2026-02-14 03:07:48 +00:00
Jon Ross-Perkins 64e3fab43a Skip C++ types when generating Destroy witnesses (#6732)
This TODO had been written before C++ types were generating destroy
implementations, which is resolved now.

Assisted-by: Google Antigravity with Gemini 3 Flash
2026-02-14 00:43:11 +00:00
Jon Ross-Perkins 74969cab04 Generate non-final Destroy witnesses for symbolics (#6731)
This is related to #6727, but is generally a necessary fix even without
that issue. I'm not adding a specific test of #6727 because it should
also be covered by the tests in #6726.

Assisted-by: Google Antigravity with Gemini 3 Flash
2026-02-13 17:46:50 +00:00
Geoff RomerandRichard Smith e5b05a1fac ExprCategory for guaranteed-in-place initializing expressions (#6623)
The primary change in this PR is to split the `Initializing` expression
category into separate `ReprInitializing` and `InPlaceInitializing`
categories, depending on whether initialization uses the types
initializing representation, or is guaranteed to be in place. It also
rationalizes and documents the SemIR-level semantics of those categories
(including where #5545's "ephemeral entire reference" category will
fit), and introduces two new inst kinds to close gaps exposed in the
process.

Some additional secondary changes:
- Consistently format the storage arguments of initializers with `to`,
regardless of whether initialization is in-place, and document the `to`
notation.
- Rename some inst kinds and functions, and restructure some of the
code, for clarity and consistency with the new documentation.
- Resolve a TODO to handle more category conversions in
`CategoryConverter`, in order to make it easier to reason about category
conversions.

See #6588 and the review history of this PR for background.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-02-04 02:27:12 +00:00
Richard Smith c0b24047dd Interop support for initialization via std::initializer_list. (#6672)
Add a new builtin function `cpp.std.initializer_list.make` that takes an
array and returns a `std::initializer_list`, initialized to refer to
that array. When C++ initialization wants to perform a
`std::initializer_list`-from-array construction, synthesize a
declaration of a matching builtin function and use that to perform the
initialization.

Ideally we would specify this conversion as an impl of `ImplicitAs` in
the prelude instead of hardcoding it in the interop layer, but
unfortunately that's not currently possible, for various reasons -- we
can't make the conversion form-generic, we can't deduce the array length
from the initializer, and we can't deduce against the arguments of
imported C++ class templates yet -- so for now synthesizing a builtin
function on demand is the best we can do.

Assisted-by: Gemini 3 Pro via Antigravity
2026-01-30 22:24:18 +00:00
Richard Smith e69c3fd978 Support list initialization of C++ classes that is performed via a constructor call. (#6660)
The general strategy here is to import the constructor with a signature
that directly matches the argument. The intent is that the imported
function will eventually be usable directly as the `ImplicitAs.Convert`
function in a generated `impl`.

For initialization from a tuple, for example `(1, 2)`, we import the
selected constructor with a signature that takes a tuple pattern:

  `fn Class.Class((a: i32, b: i32)) -> Class;`

In order to support that, this PR also adds support in general for tuple
patterns in function signatures. It turns out the implementation was
already very close to allowing this.

Assisted-by: Gemini 3 Pro via Antigravity
2026-01-27 22:04:21 +00:00
Richard Smith 093d5072db Add support for using C++ user-defined conversions via interop (#6646)
When performing an implicit conversion to or from a C++ class type, look
for a C++ implicit conversion, and if that conversion involves a
function call (to a constructor or conversion function), call that
function to perform the conversion.

Note that this is just a first pass at supporting implicit conversions.
There are a lot of other things that can happen in a C++ implicit
conversion, such as aggregate initialization or `std::initializer_list`
initialization that aren't handled here. In addition, we intentionally
leave all standard conversions to Carbon to perform, so that we will
reject conversions such as `i32 -> unsigned` that C++ would select but
Carbon considers to be invalid.

Also support `as` conversions. These are treated analogously, but
perform direct-initialization instead of copy-initialization, so they
also find `explicit` constructors and conversion functions.

In order to give good diagnostics, also track the original C++ source
location for imported C++ functions on the imported version of the
function.

Assisted-by: Gemini 3 Pro via Antigravity
2026-01-25 04:51:25 +00:00
David Blaikie 773b7136ef Use a single llvm::Module for C++ interop and Carbon IRGen (#6595)
Some module metadata changed - because rather than linking one module
with one module metadata value (eg: PIC Level 0, or unspecified) and one
module with a different one (PIC level 2, in clang) - we use Clang's
Module as-is, no merging required, so Clang's module metadata sticks
rather than being merged with default values from Carbon.

Also tweaked the name we use for Clang's module name so it matches the
carbon file name.

Otherwise the IR changes seem to be just reorderings - C++ interop goes
first, then Carbon, rather than the other way around.
2026-01-17 00:15:53 +00:00
Geoff RomerandCarbon Infra Bot 95eb7b16bb Expose C++ reference returns as Carbon reference returns (#6618)
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
2026-01-16 18:08:42 +00:00
David Blaikie f1f6005d4a Perform Clang IRGen during check (#6569)
Background:
https://docs.google.com/document/d/1wi85FRiWh4X9A-gCYMVGKR40-q5fM6-3JaSpePk-XCY/edit?usp=sharing
And specifically this work is essentially an alternative to #5543

Clang's code generation is implemented through an ASTListener
(clang::CodeGenerator) that is attached throughout Clang's
parsing/sema/code
generation phases and acts on Clang AST incrementally throughout that
process.

Prior to this patch, Carbon has only created the CodeGenerator during
Carbon's
`lower` phase, missing out on key callbacks that would be made by Clang
during
`check`. Some of these issues were addressed by #6237 and #6483 - but
there were
still remaining cases where the delayed processing lead to missing
functionality.

With #6483 much of the Clang code that made multithreaded complexity of
#5543 is
no longer present, and we have access to the point of ASTListener
registration
so we can register the CodeGenerator there and consume its resulting
llvm::Module during lower.

Examples of some of the bugs this addresses are seen in the linked doc,
and
checked in as tests in this change in
`clang_code_generator_callbacks.carbon`

An indicental bug that's also fixed, and caused all the other test case
churn,
is that the `CodeGenerator` created during `lower` wasn't getting passed
the
Clang `CodeGenOpts` and was creating its own default - so, most notably,
optimization flags were not respected. This meant that the LLVM IR from
Clang
was always -O0 style IR (optnone, no inlinehint, no TBAA, etc). With
this
change, now the Clang IRGen gets the real `CodeGenOpts` and respects
optimization/other flags specified there.

This is only meant to be a rough proof of concept - I'm totally open to
reworking this in any way (even quite substantially) if folks have ideas
about
how this should be implemented most generally/elegantly/etc.
2026-01-14 00:54:37 +00:00
Richard Smith 31919afa24 Allow conversion between T* and Cpp.void*. (#6575)
Support an implicit conversion from `T*` to `Cpp.void*` and to `const
Cpp.void*`, and an `unsafe as` conversion in the opposite direction.

In order to support C++ calls taking and returning `void*` (which get
mapped to Carbon `Optional(Cpp.void*)`, also support conversions from
`Optional(T)` to `Optional(U)` if there's a conversion from `T` to `U`.

Fix a bug in `OptionalStorage` for `T*` where its `HasValue` was exactly
backwards.
2026-01-12 16:32:15 +00:00
Richard Smith 935ccce2a6 Fix lowering of imported global variables. (#6567)
*   When a C++ static data member is imported, evaluate its address to a
    constant like we would for a namespace-scope variable.
*   When an imported variable is used in a way that doesn't require its
    type to be complete, emit the variable with an opaque type instead
    of skipping it (and potentially crashing later).
2026-01-11 19:22:43 +00:00
Richard Smith 7cf7d8697b Add testing for interop with C++ inline and thread_local variables. (#6568)
Inline variables already work fine; thread_local variables need more
work.
2026-01-09 01:31:27 +00:00