Commit Graph
254 Commits
Author SHA1 Message Date
Geoff Romer 11eaeeda7d Restructure handling of expressions in patterns (#7445)
Instead of maintaining a stack of pending subpatterns which might or
might not contain expressions, we mark non-nesting regions during
pattern handling that might contain an expression. The implementation
remains largely the same; the difference is that callers are expected to
end a pending expression region as soon as possible, rather than wait
for the end of the subpattern. This makes it possible to emit
non-pattern insts during pattern handling, without the risk that they
will get caught in a pending expression region further up the stack.
2026-07-01 19:15:34 +00:00
Geoff Romer 8158d4ffd4 Basic support for symbolic forms (#7408) 2026-06-25 22:46:48 +00:00
Nicholas Bishop 093dc04db6 Switch back to clang's MultiplexExternalSemaSource (#7416)
The necessary changes were upstreamed, and made available in #7413.
2026-06-25 17:10:06 +00:00
Richard Smith f2d99f31f0 Fix contention between Clang and Carbon over external name lookup. (#7411)
The function to set the visible declarations with a given name
overwrites any existing declarations imported from an AST file, so we
need to avoid calling that for declaration contexts whose names are
managed by Clang to avoid clobbering names imported from modules.

Assisted-by: Gemini via Antigravity
2026-06-24 18:36:59 +00:00
Geoff Romer fee00c6f3c Move FormInfo to SemIR for reuse (#7392) 2026-06-23 19:14:25 +00:00
Nicholas Bishop e5cc550554 Import modified copy of MultiplexExternalSemaSource and drop LLVM patch (#7405)
Copy MultiplexExternalSemaSource.h and MultiplexExternalSemaSource.cpp
from https://github.com/llvm/llvm-project/pull/204458 into
third_party/llvm, and apply a few minor changes to allow them to compile
and pass precommit checks.

This allows
`0011-Add-empty-constructor-and-GetSources-method-to-Multi.patch` to be
removed, which brings Carbon closer to being able to compile on an
unmodified LLVM toolchain.
2026-06-22 19:42:52 +00:00
Christopher Di Bella f55ffe5914 Add Iterate to the list of non-Clang operators (#7369)
This allows us to use non-generic C++ range types in Carbon range-for
loops.
2026-06-17 19:13:33 +00:00
Richard Smith 1106d967df Add support for enum comparisons and bitwise operators (#7356)
If C++ overload resolution selects a builtin operator candidate for an
enum comparison or bitwise operator, provide support for that operator
by generating a corresponding Carbon builtin function. This is
structured to be easily extensible to other C++ builtin overload
candidates if we so choose, but for now the operators defined in the
prelude are doing what we want in most cases.

Bitwise operators on enums produce the same enum type as a result. This
intentionally deviates from C++, where they produce a promoted integral
type.

Assisted-by: Gemini via Antigravity
2026-06-16 19:51:11 +00:00
David Blaikie cf6a89db3f Init vptrs in Carbon initialization of Carbon-derived-from-C++ objects (#7323)
For review convenience, the Clang patch is available as an LLVM Draft PR
here: https://github.com/llvm/llvm-project/pull/202807
2026-06-16 04:50:57 +00:00
Nicholas Bishop f2c94517cc Reland "Fix crash from accessing a Check::Context during lowering (#7335)" (#7359)
In generate_ast.cpp, an `CarbonExternalASTSource` is installed that has
a `Check::Context` pointer. During lowering, this `ExternalASTSource` is
still installed, and using it can cause a crash if the now-invalid
pointer is dereferenced.

Fix by adding a new `ReadOnlyASTSource` in sem_ir, and using that during
lowering.

`CarbonExternalASTSource` now inherits from `ReadOnlyASTSource` to avoid
some code duplication.

In generate_ast.cpp, we now always install a multiplex source, even if
there's only one child source. Clang internally keeps pointers to the
top-level `ExternalASTSource` installed via `setExternalSource`, and
those pointers aren't updated if `setExternalSource` is called again. By
using `MultiplexExternalSemaSource`, we can keep the top-level
`ExternalASTSource` pointer the same, and only update its children.

Using `MultiplexExternalSemaSource` this way requires a new constructor
and a method to modify its child sources; added a new LLVM patch adding
those.

Originally landed in #7335, reverted in #7353 due to ASAN errors.
Changes since original:
* Use LLVM RTTI to make `Lower::Context::Finalize` less brittle.
Add LLVM RTTI to `ReadOnlyASTSource` (and `CarbonExternalASTSource`).
Change Finalize so that instead of just deleting the last multiplex
child source, it erases any multiplex child sources that match
`ReadOnlyASTSource`; this includes `CarbonExternalASTSource` since it's
a subclass.
* Fix ASAN error by updating the `MultiplexExternalSemaSource` earlier
in lowering. It is sometimes accessed during PrepareToLower, so update
it in `Context::GetFileContext` rather than `Context::Finalize`.

Fixes https://github.com/carbon-language/carbon-lang/issues/7142
2026-06-15 20:30:07 +00:00
Nicholas Bishop 40d2d8f68c Revert "Fix crash from accessing a Check::Context during lowering (#7335)" (#7353)
This reverts commit afd679129d.

The commit introduced ASAN errors:

https://github.com/carbon-language/carbon-lang/actions/runs/27436787960/job/81100665405
2026-06-12 23:04:50 +00:00
Nicholas Bishop afd679129d Fix crash from accessing a Check::Context during lowering (#7335)
In generate_ast.cpp, an `CarbonExternalASTSource` is installed that has
a `Check::Context` pointer. During lowering, this `ExternalASTSource` is
still installed, and using it can cause a crash if the now-invalid
pointer is dereferenced.

Fix by adding a new `ReadOnlyASTSource` in sem_ir, and using that during
lowering.

`CarbonExternalASTSource` now inherits from `ReadOnlyASTSource` to avoid
some code duplication.

In generate_ast.cpp, we now always install a multiplex source, even if
there's only one child source. Clang internally keeps pointers to the
top-level `ExternalASTSource` installed via `setExternalSource`, and
those pointers aren't updated if `setExternalSource` is called again. By
using `MultiplexExternalSemaSource`, we can keep the top-level
`ExternalASTSource` pointer the same, and only update its children.

Using `MultiplexExternalSemaSource` this way requires a new constructor
and a method to modify its child sources; added a new LLVM patch adding
those.

https://github.com/carbon-language/carbon-lang/issues/7142
2026-06-12 18:05:19 +00:00
Richard Smith c3fc59b8b9 Don't form a bound method when calling a C++ operator. (#7345)
Because we now support calling a function with a `self` parameter
directly, we can unconditionally call `operator$(lhs, rhs)` rather than
calling `lhs.operator$(rhs)` if the selected operator function happens
to be a member function.

This makes the logic a bit simpler and the SemIR a bit smaller.

We can't do the same for Carbon operators, unfortunately, as we use the
member access to trigger impl lookup.
2026-06-11 21:49:20 +00:00
Chandler Carruthandjosh11b 7871237c15 Move self to the explicit () parameter list (proposal #7016) (#7272)
Implements proposal #7016: `self` moves from the deduced implicit list
(`fn F[self: Self]()`) to the front of the explicit list. Its type may
be written explicitly (`fn F(self: Self)`) or omitted, in which case it
defaults to `Self` (`fn F(self)`, `fn F(ref self)`); `self` in the
implicit list is rejected.

Throughout checking, `self` is modeled as the first explicit parameter.
Because a method is just a function whose first parameter is `self`, it
can also be called as an ordinary function with the receiver passed
explicitly (`Type.M(obj, ...)`), not only as `obj.M(...)`. A new
`SemIR::CallArgParamPatterns` helper chooses the parameters matched
against the explicit arguments, excluding a leading `self` only when it
is supplied as a method-call receiver; arity checking, conversion, and
generic deduction use it. The resulting SemIR and lowering are
unchanged: `self` is still `call_param0`, and witnesses, thunks, and
vtables are unaffected.

An omitted `self` type is parsed as a `SelfBindingPattern` node with no
type expression; checking synthesizes the `Self` type so it behaves
exactly like `self: Self`. However, the exact spelling used must match
between a forward declaration and a definition, following #3763's rules
around declaration matching.

Generated functions, thunks, and C++ interop import/export build `self`
as the first explicit parameter, and the `self`-type override (e.g.
Derived->Base for a virtual override) applies to the explicit `self`.
Placement is validated by new diagnostics: `SelfInImplicitParamList`,
`SelfNotFirstParam`, and `SelfOutsideParamList`. The benchmark source
generator and the documentation adopt the `(self)` shorthand; the
prelude, the examples, and the test data are migrated in the following
commits.

Assisted-by: Claude Code with Claude Opus 4.7

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
2026-06-10 15:30:43 +00:00
Geoff RomerandRichard Smith 85c53fa00c Reimplement derived class thunk in terms of down-casting (#7322)
This helps us move away from the clone-with-modifications approach to
thunking, which gets unwieldy as signatures get more complex.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-06-09 21:10:18 +00:00
Chandler Carruth 7901fb3857 Don't include expensive Clang headers in widely-included headers (#7319)
Fundamentally, this uses forward declarations of Clang types to reduce
the overall compile time cost of Clang headers across the codebase.

Tracing and profiling showed ~2s of every check TU's ~8-12s compile time
going just to parsing Clang frontend and AST headers pulled in via a few
sem_ir and check headers that only use the Clang types by pointer or
reference:

- sem_ir/cpp_file.h (reached via sem_ir/file.h by ~150 TUs) included
clang/Frontend/CompilerInstance.h, clang/CodeGen/ModuleBuilder.h,
clang/AST/Mangle.h, and llvm/IR/Module.h. CppFile's accessors move out
of line to a new cpp_file.cpp and the header now forward-declares the
Clang types.
- check/cpp/context.h (reached via check/context.h by ~100 TUs) included
clang/Frontend/FrontendAction.h and clang/Parse/Parser.h, pulling in
clang's Sema.h and ASTUnit.h.
- sem_ir/clang_decl.h included clang/AST/Decl.h; the three small
functions that need complete Clang types move out of line.
- sem_ir/cpp_overload_set.h included clang/Sema/Overload.h solely for
the three-field OverloadCandidateSet::OperatorRewriteInfo, which is now
mirrored as CppOverloadSet::OperatorRewriteInfo, and clang/AST/Decl.h
solely for a pointer.
- sem_ir/name_scope.h's clang/AST/DeclBase.h include was vestigial.

TUs (and more narrowly included headers) that genuinely use the Clang
definitions now include the Clang headers directly.

Representative compile times (fastbuild, aarch64), combined with the
preceding instantiation-cost changes, relative to trunk:
- check/eval.cpp: 11.85s -> 6.94s (-41%)
- check/handle_operator.cpp: 7.71s -> 3.30s (-57%)
- language_server.cpp: 6.68s -> 3.16s (-53%)
- lower/handle.cpp: 6.75s -> 3.66s (-46%)
- sem_ir/file.cpp: 8.60s -> 6.11s (-29%)
- driver.cpp: 6.68s -> 4.78s (-28%)

Measured full-rebuild impact (316 first-party TUs, fastbuild): -689.5s
CPU, -29.9% relative to trunk.

Assisted-by: Claude
2026-06-07 16:27:22 +00:00
Nicholas Bishop 5e62791ad2 Improve ClangDeclStore ergonomics (#7311)
Change `Lookup` by InstId to return a ClangDecl pointer. All callers
were immediately calling `Get` anyway, so this makes call sites a little
shorter. The other `Lookup` method, by ClangDeclKey, is sometimes called
without calling `Get`, so left that as-is, but renamed to `LookupId`.

Also add a `decl` method to ClangDecl so that the commonly repeated
`clang_decl->key.decl` can be written `clang_decl->decl()`.
2026-06-05 20:49:34 +00:00
Nicholas Bishop 44b17ff436 Set correct C++ access type for fields and static vars (#7312) 2026-06-05 20:07:27 +00:00
David Blaikie b42300cfa3 Ensure exported entities aren't remapped/duplicated (#7304)
This ensures the clang_decls map is used as a cache - without this,
visiting the same entity twice could cause it to be
re-exported/duplicated. See attached test case.
2026-06-05 19:07:33 +00:00
Nicholas BishopandRichard Smith 1aa34d7642 Remove CppGlobalVarStore (#7309)
Replace all uses of CppGlobalVarStore store with ClangDeclStore.

Adding a VarStorage->VarDecl mapping to ClangDeclStore is now done with
the `AddVar` method, which takes an extra `pattern_id` arg. While the
corresponding `ClangDecl` is unchanged from before, the reverse mapping
in `inst_id_to_clang_decl_id_` now uses the `pattern_id` as the key.
This is necessary because in some places the original VarStorage
instructions gets replaced (e.g. by a call to `Convert`). The
`pattern_id` remains stable in those cases.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-06-05 02:07:46 +00:00
David Blaikie 2d87bb02d9 Use clang_decls as the source of truth for function interop mapping (#7303)
Removing the clang_decl_id on SemIR::Function - using only the
clang_decls map to create the association between SemIR::Function and
clang::FunctionDecls.

This adds an `is_external` flag to ClangDecl to indicate whether the
entity originated from Carbon or was imported from another language.
(I'm open to names - I guess for now we mostly use "is this from C++" to
be more specific than "is this external" - eg: NameScope::is_cpp_scope)
2026-06-04 23:16:11 +00:00
Richard Smith 88c191146d Support for float <-> float conversions. (#7279)
Implement support for floating-point <-> floating-point type conversions
as described in https://github.com/carbon-language/carbon-lang/pull/820
and https://github.com/carbon-language/carbon-lang/pull/845.
Value-preserving conversions are implicit; narrowing conversions require
explicit `as`.

Assisted-by: Gemini via Antigravity
2026-06-04 00:33:33 +00:00
Nicholas Bishop f2d0c4d0ae Export Carbon global variables and static vars to C++ (#7298)
Add `ExportVarToCpp`. This checks the `clang_decls` mapping and returns
an existing decl if found. Otherwise, it creates a new `VarDecl` and
adds it to the `clang_decls` mapping.

When lowering, in `FileContext::BuildGlobalVariableDecl`, the
`clang_decls` mapping is used to lookup an existing
`llvm::GlobalVariable` for the instruction. If found, use that rather
than creating a new one to avoid an unwanted second definition in the
llvm IR.
2026-06-03 20:47:54 +00:00
Christopher Di Bella 61ee4edd9c Implement Iterate for types that implement CppRangeForIterate (#7294)
This change adds rudimentary support for C++ ranges in Carbon range-for
loops. Since C++ ranges are exposed through `Core.Iterate`, C++ ranges
have the same limitations as Carbon ranges (e.g. can't return
references).

`Iterate.CursorType` now requires `Destroy`, since types that implement
`CppRangeForIterate` can't be used in range-for loops unless their
cursor type can be verifiably destructible.
2026-06-03 04:51:09 +00:00
Christopher Di Bella d578e4afe7 Remove ref pattern from CppUnsafeDeref (#7293)
Since we can't currently iterate over ranges as references, the
`CppUnsafeDeref` interface can't require types that implement it to take
or return references.
2026-06-03 01:22:07 +00:00
Richard Smith 2952f61095 Support for mapping array types to/from C++. (#7285)
For now, disable the use of array types as by-var paramters and by-init
return types when exporting Carbon functions to C++, as C++ does not
support raw arrays being passed or returned by value.

Assisted-by: Gemini via Antigravity
2026-06-01 21:55:16 +00:00
Nicholas Bishop 682f9fef16 Add FieldStore and fix field initializer imports (#7287)
As suggested in [1], replace `FieldInitializerMap` with a `FieldStore`.
The corresponding `FieldId` is now stored in `FieldDecl`. To make room
for the `FieldId`, the `ElementIndex` is now stored in the `Field`,
along with the initializer.

In import_ref.cpp, resolving `FieldDecl` initializers is now supported,
and in convert.cpp `LoadImportRef` is called to do so. The
`field_initializer_import.carbon` test now passes.

Printing a `FieldDecl` instruction now prints the initializer as well,
if present. See field_initializer.carbon for an example.

[1]:
https://github.com/carbon-language/carbon-lang/pull/7238#discussion_r3283217158
2026-06-01 19:02:01 +00:00
Chandler CarruthandChristopher Di Bella 8a59f2a76b Fix mangling collision for C++ class template specializations (#7269)
Carbon-side thunks (for example the `Copy`/`Destroy` witness thunks
generated for imported C++ types) are mangled by Carbon, and their names
incorporate a fingerprint of the involved types. The instruction
fingerprinter identifies a class only by its name and parent scope,
which is sufficient for Carbon classes but not for imported C++ classes:
different specializations of one class template (and other cases such as
types in anonymous namespaces) share a Carbon name and parent scope. As
a result, the thunks for two distinct specializations could mangle to
the same name, producing a single LLVM function with two definitions and
failing `verifyModule` during lowering.

When fingerprinting a class imported from C++, also include the Clang
mangled name of its type.

Test: toolchain/lower/testdata/interop/cpp/thunks.carbon gains a split
with two specializations of one class template, each requiring a thunk;
their thunks now get distinct mangled names instead of colliding.

Assisted-by: Claude Code

---------

Co-authored-by: Christopher Di Bella <cjdb.ns@gmail.com>
2026-05-30 08:13:00 +00:00
Richard Smith 1a8f2f3b8c Add Core.Destroy support for enums imported from C++ (#7267)
We previously only supported values of enum type, as we did not find a
suitable `Core.Destroy` implementation for enums.
2026-05-29 22:42:12 +00:00
Chandler CarruthandRichard Smith 94d2c1c6d4 Make proposal filenames use 6 digits and include the title (#7245)
We've talked about adding the title to the filename several times over
the years and it seems really valuable. This requires us to compute a
"slug" for the title spelling that can be part of the filename.

Beyond that, we crossed 7000 recently, and so it seems likely that we
will need to add digits sooner rather than later here, so this goes
ahead and moves us to 6 digits so we don't have to adjust again for a
reasonable length of time.

To implement this and ensure we can sustain it going forward this adds a
tool to our pre-commit that validates (and corrects if needed) the
filename.

In order to update everything and keep links working, there are a _lot_
of changes, but the most interesting for direct review are in
`proposals/scripts`.

Assisted-by: Antigravity with Gemini

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-05-29 00:55:04 +00:00
Christopher Di Bella bd7f89b1ad Remove lookup_result and function (#7264)
PR #7230 was automerged before
https://github.com/carbon-language/carbon-lang/pull/7230#pullrequestreview-4348841410
could be applied. This commit actions that feedback.
2026-05-26 22:57:03 +00:00
Christopher Di Bella 64e890c246 Extend CppRangeForIterate to support ADL begin/end (#7230)
`CppRangeForIterate` needs to support finding `begin()`/`end()` as a
pair of methods and as a pair of ADL-findable functions. This change
adds the ADL component, which lets us also diagnose types that don't
implement the interface.

Unlike methods, we apparently have support for overloads when using ADL.
2026-05-22 21:12:06 +00:00
Richard Smith 805b3eebce Fix crash if initializing Clang fails. (#7248)
Flush diagnostics before destroying Clang. If we see an `inline Cpp` and
`Cpp` initialization failed, recover by skipping the inline code rather
than CHECK-failing.
2026-05-21 21:21:50 +00:00
Richard Smith ad97b9e3a5 Basic support for use of C++ modules via interop. (#7241)
Create a multiplex source to pull information from both the AST reader
and from our custom source.

Assisted-by: Gemini via Antigravity
2026-05-21 00:21:54 +00:00
Richard Smith 1231098c14 Fix crash in indirect template instantiation. (#7240)
Provide a source location to the member expression used when a thunk
calls a member function. This ends up being used as the point of
instantiation when the return type triggers a template instantiation;
the absence of this location previously caused assertion failures within
clang.

Assisted-by: Gemini via Antigravity
2026-05-20 23:18:15 +00:00
Richard Smith be70c092fa Add a text mode for fingerprinting. (#7231)
The intent is to add visibility into how the fingerprint is computed, so
that fingerprinting issues and mangling collisions can be more readily
understood and fixed.

Assisted-by: Gemini via Antigravity
2026-05-19 23:16:51 +00:00
Richard Smith b87f848db4 Fix passing mode computation for methods. (#7225)
We were incorrectly computing the index of the Clang implicit conversion
corresponding to method arguments. This led to wrong code and a crash in
lowering due to a calling convention mismatch.

Fixes #7224.

Assisted-by: Gemini via Antigravity
2026-05-18 20:30:23 +00:00
David Blaikie 31db4a0931 Export virtual/abstract/override functions as virtual (#7211)
This provides enough to Clang so it can include these new virtual
functions in the vtable of Carbon types derived from C++ types.
2026-05-18 19:04:33 +00:00
josh11bandJosh L 832d46f01b Update LLVM (#7221)
Assisted-by: Google Antigravity

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2026-05-18 17:06:58 +00:00
David BlaikieandRichard Smith 843323b864 Export virtual functions when exporting a class definition (#7210)
This allows Clang to correctly generate the vtable for the exported
class.

There's still something wrong with new virtual functions in the Carbon
type (left a TODO) - I thought it might be related to not flagging
the CXXMethodDecl as virtual, but my initial experiments don't seem to
back that up, so I'll look into it further separately.

There's also a test regression due to an virtual (well, abstract
specifically, but I think it'd happen with a virtual one too) function
in an abstract class taking `self` by value being rejected since
the abstract class can't be instantiated. Not sure if this is a correct
change - the test's behavior could be preserved by using `ref self`
instnead of `self` in this function. Is that reasonable/expected? Should
we not require a type to be complete when passing by value if we can
compute the value representation without such completeness?

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-05-15 23:53:12 +00:00
Richard Smith dd47e41da6 Fix calls to functions with const T&& parameters. (#7208)
This also fixes passing a value expression to a forwarding reference,
since we currently deduce a `const T&&` parameter in that case.

We were accidentally looking at the type of the thunk parameter (which
is never an rvalue reference) rather than the type of the callee
parameter.
2026-05-14 20:22:32 +00:00
Richard Smith c9d8b59bbd Handle "gaps" in C++ vtables. (#7206)
Not every entry in a C++ vtable corresponds to a function that we want
to import. For the holes, leave a `SemIR::InstId::None` in the vtable.
Also mark vtables that extend a C++ vtable as being non-Carbon-native so
we don't try to lower them (and crash on the `None` entries).

In particular, we leave holes for destructors, since we don't have
destructor declarations on the Carbon side that need to override them.
2026-05-14 00:38:24 +00:00
Richard Smith 917856aff7 Export Carbon classes as base / final / abstract. (#7191)
* For Carbon `base class C`, export as a regular C++ class.
* For Carbon `class C`, export with the C++ `final` keyword attribute.
* For Carbon `abstract C`, mark the destructor as pure virtual in cases
where no member function is abstract, or emit an error if the destructor
is not virtual.

To support the final point, mark the destructor of an exported class as
virtual if it overrides a virtual destructor from the base class.

In passing, fix a crash exporting fields if the class has an invalid
base type.
2026-05-13 17:48:55 +00:00
Richard Smith c33fb9fc48 Support signature mismatch between virtual fn and override fn. (#7198)
For now, hide `override fn`s from name lookup, so that the base class
version is always used, as the derived-class version does not have its
own vptr entry and so would not do the right thing if a further-derived
class adds a new override. This is implemented via a new access kind of
`Hidden`.

When checking the overriding function, pass in the expected `Self` type
and check the `self` parameter against that; the signature that we
generate for the thunk in the derived class is the base class signature
with the `self` parameter's type changed to the derived class.

When we generate a thunk for a virtual function, the thunk is assigned a
`virtual_index`, and the virtual function itself is not. When the thunk
makes a direct call to the virtual function, recognize this situation by
checking for a `virtual_index`, and perform a non-virtual call if there
isn't one.

Assisted-by: Gemini via Antigravity
2026-05-13 17:40:45 +00:00
Dana Jansens 0b47efa57a Don't re-require complete types for extended scopes (#7194)
When an outer type defines an `extend` relationship to an inner type, we
require that inner type to be complete so that we can know that name
lookup can search both scopes as soon as the outer type is complete.

When doing name lookup, we require the type in which we are looking to
be complete. Then, we recursively add extended scopes, but then also
require each of them to be complete again, which inserts
RequireCompleteType instructions into the block doing lookup.

While these new instructions may differ in terms of their specifics,
they are redundant since we already required the type to be complete,
and specifics can not change the completeness of a type. They are also
problematic because a named constraint or interface can extend a scope
with a symbolic specific, by using `Self` as an argument. This inserts a
symbolic instruction into the block doing name lookup, even though that
block may not be generic.
2026-05-13 17:16:02 +00:00
Richard Smith 71ba07239f Support pass-by-move when calling a C++ function taking by value. (#7135)
Previously, we picked a single Carbon parameter pattern for each C++
parameter pattern. This doesn't work well in cases where the Carbon
semantics and the C++ semantics are not perfectly aligned. In
particular, when a parameter is passed by value in C++, that might mean
either pass-by-move (which in Carbon would best be modeled by a `var`
pattern, as no other form of parameter would perform a move) or
pass-by-copy (which in Carbon would best be modeled by a value
parameter, as a `var` parameter would force an extra copy).

After this change, we compute a passing mode for each parameter based on
the implicit conversion sequence from the argument to the parameter as
determined by C++ overload resolution, and use that to determine the
Carbon pattern corresponding to each C++ parameter. This results in
potentially generating multiple different thunks for the same C++
function if it's called in different ways, but we already did that to
handle default arguments and list-initialization. The passing modes are
included in the thunk mangling.

Add a new value store for clang decl signatures, which capture the
information about parameter passing mode as well as the other existing
information about different ways that a C++ function might be imported
to Carbon.

Most of the rules for computing passing modes are the same as before:
const references use pass by value, non-const lvalue references use
pass-by-ref, non-const rvalue references use pass-by-var. But for C++
non-reference parameters, pick between pass-by-value and pass-by-var
based on whether the implicit conversion sequence was effectively
performing a copy. Prefer pass-by-value if either would work and they'd
do the same thing. We still use pass-by-value for const references, even
when the argument is an lvalue and we could pass a reference; we may
want to change this in future.

For virtual functions, we try to pick a worst-case passing mode, as we
can only pick a single signature for what goes in the vtable. Calls to
virtual functions will still use a thunk to C++, allowing variance in
the calling convention at call sites. We don't allow variance in the
overriders as we don't implement support for thunks for virtual
functions yet. We currently use pass-by-value for const reference
parameters here, but that should probably change at some point.

Assisted-by: Gemini via Antigravity
2026-05-13 01:44:07 +00:00
Christopher Di BellaandRichard Smith 2aaa061688 Support detecting begin()/end() methods for range-for loops (#7185)
This commit adds support for range-based for loops using C++ types. It's
currently limited to detecting that `r.begin()` and `r.end()` are
available. We should be able to add full support for methods after #7181
is merged.

Support for ADL is still a work-in-progress, and will be added at a
later time.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-05-12 19:03:55 +00:00
David Blaikie df8b25522e Import C++ vtables (#7174)
This correctly renders the vtable in SemIR, including allowing overrides
in
Carbon-derived-from-C++ classes.

It doesn't work in lowering because clang walks the methods of the
CXXRecordDecl - and we currently don't export anything into the
CXXRecordDecl's methods (we do export the fields) - so that's next.

This also doesn't teach Clang to affirmatively emit the vtable
regardless of the types use in C++ code - or to have Carbon use the
vtable in an object's initialization.
2026-05-11 17:33:08 +00:00
David Blaikie 0f5de499d6 Roundtrip (export/reimport) class declarations (#7182)
Roundtrip (export/reimport) class declarations

The remapping was previously implemented using name_scopes, which aren't
created for class declarations, only definitions - causing the reimport
to import a fresh copy of the type that mismatched with the original (as
seen in the test baseline).

By changing the mapping to use the reverse part of the clang_decls
mapping this should generalize better (& we probably should further
migrate to that mapping). Though it did trip over some issue with
exactly which instruction is used as the key in the clang_decls map -
this change moves towards standardizing on the first decl id of the
class as its map key.
2026-05-11 16:35:47 +00:00
Christopher Di Bella 219d1cdee1 Teach comparison interfaces about C++ operators (#7163) 2026-05-10 21:54:50 +00:00