Commit Graph
75 Commits
Author SHA1 Message Date
Jon Ross-Perkins 2c6d9c7f66 Rename type's GetInstId to GetTypeInstId, reflecting returned type (#6708)
Discussed briefly [on
Discord](https://discord.com/channels/655572317891461132/655578254970716160/1470442830118912265),
done to reduce confusion.

Assisted-by: Google Antigravity with Gemini 3 Flash
2026-02-09 22:00:21 +00:00
Jon Ross-Perkins f0e04c89c3 Share more function logic between custom/thunk/C++ functions. (#6690)
I need to do more work on the custom witness functions. This is trying
to make it easier to see the differences between the approaches before I
resume work there (e.g. this helps flag a possible reason I was having
trouble switching definitions when it came to generics, I think those
are mishandled right now).

This changes the thunk test because it was doing
`CheckFunctionDefinitionSignature` in a different order from
`handle_function.cpp`, and I think `handle_function.cpp` is more
canonical here (changing that affects tests with defined functions).

Assisted-by: Google Antigravity with Gemini 3 Flash
2026-02-05 18:44:55 +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
05ea0e77d9 Map structs and tuples to initializer lists in C++ overload resolution. (#6620)
When performing C++ overload resolution with an argument that is of
Carbon struct or tuple type, form a braced initializer list as the
placeholder argument. Note that this only affects overload resolution;
no new support for actually converting structs or tuples to C++ types is
added. In particular, while this does allow an empty class to be
initialized from `{}`, it does not allow a non-empty C++ class to be
initialized from a struct, as that is not yet supported in general.

---------

Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
Co-authored-by: Geoff Romer <gromer@google.com>
2026-01-21 19:10:10 +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
Richard SmithandGeoff Romer de0ad6730f Fix crash if a member of std::string_view is found in a derived class. (#6604)
Members of `std::string_view` can't be accessed directly, because that
type maps into Carbon's `str` type (`Core.String`), so member access
doesn't find the C++ members. But they can be named via qualified name
lookup into a derived type. That crashed because we didn't expect the
non-Cpp type `Core.String` to be the parent of a Cpp-imported member.

Plus add some more test coverage for related cases (not involving `str`)
that already worked.

---------

Co-authored-by: Geoff Romer <gromer@google.com>
2026-01-15 22:36:18 +00:00
Chandler Carruth 9861c31476 Update LLVM to a recent commit (#6599)
This brings some fixes:
- The handling of `zlib` and `zstd` are much cleaner
- Three of our patches are no longer needed

This also includes the fixes from #6562

It also moves us from `zlib` to `zlib-ng` which is a much better basis
for what we want, and likely makes our toolchain faster when generating
debug info at least.

It fixes another API change in terms of which headers provide the
`createInvocation` we use.

Lastly, it cleans up the deps test to correctly recognize the wrappers
for `zlib-ng` and `zstd`, as well as improving the documentation for why
we allow dependencies on them.
2026-01-14 21:58:48 +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
Geoff Romer a2737a3189 Add Call param patterns to Function (#6586) 2026-01-13 19:30:15 +00:00
Richard Smith ead7803d60 Simplify importing of C++ global variables. (#6565)
Remove the unnecessary two-phase creation of variables in C++ import. We
don't need to create a placeholder and overwrite it here, so stop doing
so.

Also, add the patterns to the imports table and don't create a
NameBindingDecl. The NameBindingDecl would never be used for anything.
This matches what we do when importing a Carbon variable, and improves
the formatted SemIR output.
2026-01-09 00:16:27 +00:00
Geoff Romer 11d407b4a0 Add form to Function (#6561)
... and use the form to implement support for `ref` returns.
2026-01-08 18:55:53 +00:00
Geoff Romer b72bfb918b Allocate CallParamIndexes eagerly (#6540)
This approach is more robust because there's no intermediate state where
the `ParamPattern` insts have been created, but don't yet have their
final values.
2026-01-05 19:38:52 +00:00
Richard Smith 531d063596 When importing a trivial destructor from C++, produce a no_op builtin. (#6531)
This avoids us trying to produce a reference to the C++ destructor,
which Clang won't emit because it believes it's unnecessary. This
previously led to link errors.

Fixe #6502.
2025-12-23 05:30:29 +00:00
Richard Smith 6b28213b36 Add interop support for naming and "calling" C++ templates. (#6474)
Expose C++ class templates, variable templates, alias templates, and
concepts as callable values in Carbon, and map calls to them into
template-id formation, mirroring how Carbon generics behave. For now,
only type template parameters are supported; non-type and template
template parameters produce a TODO error.
2025-12-15 17:45:01 +00:00
Richard SmithandJon Ross-Perkins a8eca2ece6 Delay finishing the C++ translation unit until we reach the real EOF. (#6489)
Instead of parsing a complete C++ translation unit and then interacting
with the translation unit further after the fact, delay finishing the
translation unit until we finish the Carbon check phase. This fixes some
issues where we would produce duplicated or incorrect diagnostics at the
end of the C++ translation unit, particularly for unused declarations.
Now we're in control of how we parse the translation unit, also disable
parsing of C++20 modules if the syntax appears within `import Cpp
inline` code.

Keep the same clang parser alive throughout check, and use it instead of
building a new one when parsing macros. This resolves issues where the
translation unit scope was destroyed too early, resulting in unqualified
lookup within macros being unable to find global scope entities.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-12-13 00:56:30 +00:00
Jon Ross-Perkins c0b335b87f Add well-known identifier caching (#6486)
I'm doing this because I figured it'd be an incremental improvement for
all the operator lookups that we do. Even to the extent that we've
discussed witness caching, I think it'll still apply. It does add one
more step to adding new interfaces (before, you'd just write the string,
now you add it to the def file and reference it).

I'll claim it makes GetClangOperatorKind a lot friendlier to read/edit,
nevermind removing the string comparisons. :)
2025-12-11 21:41:47 +00:00
Richard Smith 6114df59ee Factor out a Check::CppContext holding C++-specific check state (#6482)
* Move `Sema` access from `CppFile` into `CppContext`.
* Move the mangle context from `SemIR::File` into `CppContext`.
* Move source location mapping state from `Context` into `CppContext`.

Also factor out the `GenerateAst` function that builds the `CppContext`
and `CppFile` into its own file.
2025-12-10 18:55:22 +00:00
Geoff Romer bf45b1cbf5 Refactor function return type representation (#6463)
This separates the return type from the return pattern, and replaces the
return pattern with a block of return patterns. This is a step toward
support for `ref` returns (where there's no corresponding return
pattern) and compund-form returns (where there may be multiple return
patterns).
2025-12-10 18:34:23 +00:00
Richard Smith c7cd24e1b2 Support for calling C++ destructors. (#6453)
Synthesize an impl of `Destroy` for C++ classes in response to impl
lookup.
2025-12-09 21:03:27 +00:00
Richard SmithandJon Ross-Perkins d208e950c7 Encapsulate clang::ASTUnit in SemIR::CppFile. (#6459)
This intends to avoid proliferation of dependencies on the exact API of
`clang::ASTUnit`, and would enable us to more easily switch to a
different approach that gives us more control over the construction of
the Clang AST.

Also remove some unnecessary tracking of the `CppFile` and instead
always retrieve it from the `SemIR::File`.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-12-04 21:05:40 +00:00
372f632d9d Implement support for copying C++ classes. (#6434)
When performing impl lookup for `Core.Copy` for a C++ class type, look
for a copy constructor. If we find one, synthesize an impl witness that
calls the constructor.

This adds initial support for impl lookup to delegate to the C++ interop
logic for queries involving C++ types. For now, we don't implement the
rules from #6166 that compare a synthesized type structure for the C++
impl against the best Carbon type structure, but the framework for
building that support is established here.

Currently there is no caching of the lookup here, and we build unique
`ImplWitnessTable`s for each lookup, which leads to each impl lookup
producing a distinct facet value. This results in some errors in generic
contexts; this will be addressed in follow-up changes. This PR aims only
to support the non-generic case.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
2025-12-02 02:52:23 +00:00
Ivana Ivanovska 108e39e095 Fix SemIR printout for string literals in macros (#6440)
Added SemIR printout for string literals in macros in the tests. Removed
adding the inst in the imports to make the printout succeed.

Part of #6303
2025-11-28 16:34:25 +00:00
Boaz Brickner bef92cf881 Add CppCompat.ULong32, CppCompat.LongLong64 and CppCompat.ULongLong64 (#6386)
This extends #6364 to allow having:
* `Cpp.unsigned_long` as a distinct type when `unsigned long` is 32
bits.
* `Cpp.long_long` and `Cpp.unsigned_long_long` as distinct types when
`long` and `unsigned long` are 64 bits.

Similarly to #6364, we only support implicit conversions from the
matching literal type (`u32`, `i64` and `u64`).

See #6275 for rationale.

Part of #5263.
2025-11-26 16:51:22 +00:00
Ivana Ivanovska 109e39c75c Add support for nullptr literals in macros (#6426)
Adding support for macros that evaluate to nullptr literal.

Demo:

```c++
// macros.h
void foo(int a[2]);
#define MyNullPtr nullptr
```
```c++
// macros.cpp
void foo(int a[2]) {
  if (!a) {
    printf("array a is nullptr\n");
    return;
  }
  printf("a[0] = %d \n", a[0]);
}
```

```c++
// main.carbon

library "Main";

import Cpp library "macros.h";

fn Run() -> i32 {
  Cpp.foo(Cpp.MyNullPtr);
  return 0;
}
```

```
$ clang -c macros.cpp;
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link macros.o main.o \--output=demo_carbon
$ ./demo_carbon
array a is nullptr
```

Part of #6303
2025-11-24 21:03:35 +00:00
Ivana Ivanovska 7be6538aec Add support for character literals in macros (#6419)
Adding support for macros with character literals.

Part of #6303
2025-11-24 13:54:17 +00:00
Ivana Ivanovska 093700b274 Add support for boolean literals in macros (#6418)
Adding support for macros with boolean literals.

Demo:

```c++
// main.carbon

library "Main";

import Core library "io";

import Cpp inline '''
  #define M_TRUE true
''';

fn Run() -> i32 {
  let a: bool = Cpp.M_TRUE;
  if (a) {
    Core.Print(1);
  } else {
    Core.Print(0);
  }
  return 0;
}
```

```
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link main.o \--output=demo_carbon
$ ./demo_carbon
1
```

Part of #6303
2025-11-24 10:40:57 +00:00
Richard Smith 13fbe3c1f3 Allow interop with classes with virtual base classes. (#6413)
For now, treat such classes as being final, since we can't correctly
derive from them.

This removes the last category of C++ class that we are entirely unable
to interop with, and is a prerequisite for interop with C++ iostreams
(which have a virtual base class).
2025-11-21 16:45:38 +00:00
Ivana Ivanovska 8866e39085 Add support for string literals in macros (#6408)
Adding support for macros with string literals.

Part of #6303
2025-11-21 12:33:18 +00:00
Ivana Ivanovska 994e6c904d Add support for macros with floating-point literals (#6391)
Adding support for floating-point literals in macros.

Part of #6303
2025-11-20 12:49:43 +00:00
Richard Smith 0678501038 Replace builtin CppVoidType with a prelude type. (#6403)
Following #6357, map C++ `void` to a prelude class type
`Core.CppCompat.VoidBase`, not to a builtin type. This is mostly just
moving logic around, but does notably change `Cpp.void` from being an
incomplete type to being a complete-but-abstract type.

Also change `NullptrT` to be an adapter for `void*` instead of `()*`, to
follow the approved design.

Implicit conversions to `void` and to `void*` are still absent.

Part of #6280.
2025-11-19 20:40:17 +00:00
Ivana Ivanovska 315b0ac241 Refactor identifier lookup in cpp/import.cpp (#6383)
Following up on the
[comment](https://github.com/carbon-language/carbon-lang/pull/6326#discussion_r2512160370)
from PR #6326, refactoring the identifier lookup to be only once,
instead of both in `LookupMacro` and `ClangLookupName`.

Part of #6303
2025-11-19 13:38:07 +00:00
Chandler Carruth 13bb660f7f Update LLVM and update APIs (#6147)
This also updates the patch file for compiler-rt as upstream has changed
a bit. No functional change.
2025-11-15 03:37:13 +00:00
Boaz Brickner bc734bb768 C++ Interop: Add Core.CppCompat.Long32 as a distinct type for Cpp.long when long is 32 bits (#6364)
For now, only support implicit conversions from and to `i32`.

See #6275 for rationale.

Part of #5263.
2025-11-14 23:26:43 +00:00
Boaz Brickner 2ad26487b6 C++ Interop: Don't crash when trying to call a C++ function with undeduced return type (#6363)
This crashed on trying to build a C++ thunk because the error wasn't
propagated.

Part of #5436.
2025-11-13 20:53:03 +00:00
Jon Ross-Perkins 877179d6d9 Refactor addition of imported locations and placeholders (#6354)
- Makes a little more use of `MakeImportedLocIdAndInst` instead of
`UncheckedLoc`
- Requires use of `MakeImportedLocIdAndInst` with `ImportIRInstId`;
previously optional
- Relevant `if constexpr` moves to `AddPlaceholderImportedInst`, but is
more narrowly scoped there.
- Refactors out `AddPlaceholderImportedInstInNoBlock` to reduce how many
spots do an explicit `imports().push_back(...)`

I'd also considered removing `MakeImportedLocIdAndInst` where possible,
but went this route so that changes to the expected parse node wouldn't
affect callers. When it's required, `MakeImportedLocIdAndInst` is always
there; when it's conditionally present, changing `Parse::NodeId` between
enforceable and not-enforceable would require refactoring any callsites
that assumed one or the other.
2025-11-13 18:34:13 +00:00
Geoff Romer 0873777237 Import C++ ref parameters as ref parameters (#6360) 2025-11-13 17:04:58 +00:00
Richard Smith 86b02ee8af Interop support for nullptr and nullptr_t. (#6353)
Add a `Core.CppCompat.NullptrT` type that C++'s `nullptr_t` maps into.
Map `nullptr` to an uninitialized constant of that type -- `nullptr`
doesn't actually have any defined bits within it, despite having the
same representation as `void*`.
2025-11-12 23:23:48 +00:00
Ivana Ivanovska 3b0dad9dd5 Add support for simple object-like macros (#6326)
Adds support for object-like macros with a single replacement
numeric-literal kind token. Only macros that evaluate to an integer
constant are supported for now. When detected at name lookup, they are
imported as a constant integer value in Carbon.

Demo:

```c++
// --- macros.h

#define CONFIG_VALUE 2
```

``` c++
// main.carbon
library "Main";

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

fn Run() {
    let a: i32 = Cpp.CONFIG_VALUE;
    Core.Print(a);
}
```

```c++
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link main.o \--output=demo_carbon
$ ./demo_carbon
2
```

Part of #6303
2025-11-11 11:24:20 +00:00
Boaz Brickner b54f2dd592 Support import Cpp; to import Cpp namespace for using C++ builtins (#6320)
This allows writing
```
import Cpp;
```

Instead of writing
```
import Cpp inline "";
```

Part of #6330.
2025-11-06 08:45:28 +00:00
Boaz Brickner ae50e0f623 Propagate location to CppOverloadSetValue instructions (#6317)
Part of #5915.
2025-11-05 16:53:04 +00:00
Boaz Brickner 805600de43 C++ Interop: Preserve non-nullability when mapping const non-nullable pointers (#6293)
For non-nullable const pointers, we need to keep the non-nullability.

This is done by preserving non-nullability when mapping qualifiers.
2025-11-04 18:25:22 +00:00
Boaz Brickner d3762f9723 Remove unused ImportCppId and list of Cpp imports in File (#6290)
See discussion:
https://discord.com/channels/655572317891461132/655578254970716160/1432518191350808659

Part of #5245.
2025-10-30 18:03:34 +00:00
Boaz Brickner fc8db6ac5c C++ Interop: Add a test that demonstrates that const non nullable pointers are wrongly mapped to nullable (optional) pointers (#6284)
Part of #5772.
2025-10-29 09:12:25 +00:00
Boaz Brickner 4d4d720ff0 C++ Interop: Support getting void* from C++ functions and passing void* it to C++ function (#6279)
This defines `Cpp.void` as a custom type.
`Cpp.void*` is mapped to C++ `void*`.

Not supported yet: Conversions from and to other pointer types.

C++ Interop Demo:

```carbon
// main.carbon

library "Main";

import Core library "io";

import Cpp inline '''
#include <cstdio>

auto GetPointer() -> void* _Nonnull {
  static int x = 8;
  return &x;
}

auto GetValue(void* _Nonnull ptr) -> int {
  return *static_cast<int*>(ptr);
}
''';

fn Run() -> i32 {
  let ptr: Cpp.void* = Cpp.GetPointer();
  Core.Print(Cpp.GetValue(ptr));
  return 0;
}
```

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

Part of #6280.
2025-10-29 09:03:53 +00:00
Richard Smith 6011040481 Rework handling of C++ references. (#6268)
For now, map C++ reference types to const-qualified Carbon pointer types
rather than picking between a (non-const) pointer or a value type. This
fixes misbehavior in lowering for reference members in classes and
reference return types.

Update the special-case handling for references as function parameters
so that it continues to map const reference parameters to Carbon
pass-by-value, and unify the code paths for `self` parameters and other
parameters, which were mostly doing the same thing but had some subtle
differences.

Add references to the list of types that we can pass to and from C++
directly, without needing an additional layer of thunks.
2025-10-28 00:33:26 +00:00
Richard Smith a1a35c207e Unify "needs thunk" logic. (#6277)
Remove duplication between determining whether a parameter needs custom
thunk mapping and whether a function needs a thunk. Now a function needs
a thunk if any parameter or the return type does.

This fixes some inconsistencies; previously:
- We would not require a thunk when passing an `unsigned int`, but if we
  had a thunk we'd pass `unsigned int` indirectly.
- We would always require a thunk for an enum parameter, even though
  we'd actually pass it directly if its underlying type is a 32- or
  64-bit integer.
- We would require a thunk for a nullable pointer, even though
  we arrange for all pointer types to have the same ABI in Carbon and
  C++, including nullable pointers / Optional(T*).

This also causes us to use a thunk for rvalue reference return types,
which we used to miscompile.

Depends on #6276.
2025-10-27 22:49:29 +00:00
Geoff Romer 09710d102f Separate binding insts for refs and values (#6235)
This resolves a TODO in `expr_info.cpp` by using the inst kind rather
than the bound value to track the binding's category.

Since we're churning all the `bind_name` insts in testdata anyway, I'm
also taking this opportunity to align the inst naming with the design's
terminology, by calling these insts "bindings" (this aspect of the PR is
dependent on #6231 resolving an ambiguity in that terminology). For
consistency we'll need to rename several other insts as well (see the
TODO on `RefBinding`); I'm deferring that to a separate PR to minimize
the review load, but I think those name changes are in-scope for this
review.
2025-10-23 01:46:24 +00:00
Boaz Brickner 840562feb3 C++ Interop: Fix access calculation to handle private member of base classes correctly (#6238)
Always take into account both the lookup access specifier and the
declaration. When set, lookup access specifier takes precedence. When
not set, we have two use cases:
1. This is not a record member, so no access is specified at all. Treat
this as public.
2. This is a record member of a base class. Treat this as private.
[Reference](https://github.com/llvm/llvm-project/blob/4b1d7827c07381610ad4fa7bd9d1a9659008b963/clang/include/clang/AST/DeclCXX.h#L1724).

Also, deduplicate access mapping between import and overload resolution.

Background:
https://github.com/carbon-language/carbon-lang/pull/6221#issuecomment-3407981790

Part of #5859.
2025-10-21 08:12:57 +00:00
Richard Smith 304d2056cc Map nullable C++ pointer types to Core.Optional(T*). (#6230) 2025-10-16 20:52:32 +00:00