Commit Graph
14 Commits
Author SHA1 Message Date
Nicholas Bishop 2e61685658 Remove duplicate check for exporting a specific class (#7541)
The check for a specific in `TryMapClassType` is unnecessary;
immediately after it calls `ExportClassToCpp`, which has the same check.
The latter also has a `context.TODO`, which provides a clearer error.

Also improved the `LocId` in `ExportClassToCpp` to use the location of
the first decl rather than the empty location of the class type. This is
the same fix as
https://github.com/carbon-language/carbon-lang/pull/7533, just applied a
little more broadly. This makes the `context.TODO` above point at the
class rather than the start of the source file.
2026-07-21 18:35:20 +00:00
Richard Smith 9ae73d2847 Handle signature mismatch when a Carbon function overrides a C++ virtual function. (#7499)
When a Carbon virtual function overrides a C++ virtual function, we need
to export it with the C++ signature in order for it to work as an
override. Instead of mapping the C++ signature into Carbon and then back
again, use the original C++ signature from the base class as the
signature exported to C++.

Also add documentation explaining how we use thunks in C++ interop,
including in this new virtual function handling logic.
2026-07-15 18:42:03 +00:00
Nicholas Bishop c8fdeef911 Add initial support for exporting generic Carbon functions to C++ (#7462)
This allows C++ to call Carbon functions with generic type parameters,
with some conditions. Example:
```carbon
interface I {
  fn Doit(self);
}
class A {
  impl as I { fn Doit(unused self) {} }
}
class B {
  impl as I { fn Doit(unused self) {} }
}
fn F[T:! I](t: T) {
  t.Doit();
}

inline Cpp '''
void G() {
  Carbon::A a;
  Carbon::B b;
  Carbon::F(a);
  Carbon::F(b);
}
''';
```

The initial support is limited; only explicit parameters are handled
currently.

`CarbonExternalASTSource::GetOrExportFunctionToCpp` now generates a
`clang::FunctionTemplateDecl` for generic Carbon functions. If C++ code
attempts to call that templated function,
`CarbonExternalASTSource::LoadExternalSpecializations` will be called
with the template argument types of that call site. Then we can generate
a specialized thunk for those argument types for C++ to call.
2026-07-08 00:51:21 +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
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 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
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
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
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
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 f31e1685fd Only export each class or namespace to C++ once. (#7042)
Instead of exporting a class or namespace each time a new C++ name
lookup discovers it, track that we have exported the entity on its name
scope, and if a new name lookup finds the same entity, produce the same
clang declaration.
2026-04-13 19:43:44 +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