Commit Graph
70 Commits
Author SHA1 Message Date
Boaz Brickner f0cff612eb Add support for using C++ double type in imported function declarations (#5868)
Carbon only supports f64, so only double can be mapped.

https://github.com/carbon-language/carbon-lang/blob/30f0ddab71bda71f8789080962b1fe8a5938e327/toolchain/check/type.cpp#L54

C++ Interop Demo:

```c++
// hello_world.h

auto hello_world(double x) -> void;
```

```c++
// hello_world.cpp

#include "hello_world.h"

#include <cstdio>

auto hello_world(double x) -> void {
  printf("double: %f\n", x);
}
```

```carbon
// main.carbon

library "Main";

import Cpp library "hello_world.h";

fn Run() -> i32 {
  Cpp.hello_world(0.25);
  return 0;
}
```

```shell
$ clang -c hello_world.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link hello_world.o main.o --output=demo
$ $ ./demo
double: 0.250000
```

Before this change:

```shell
$ bazel-bin/toolchain/carbon compile main.carbon
main.carbon:8:3: error: semantics TODO: `Unsupported: parameter type: double`
  Cpp.hello_world(0.25);
  ^~~~~~~~~~~~~~~
main.carbon:8:3: note: in `Cpp` name lookup for `hello_world`
  Cpp.hello_world(0.25);
  ^~~~~~~~~~~~~~~
```

Part of #5263.
2025-07-30 07:13:59 +00:00
Richard Smith ef475d8197 Import C++ class A final as Carbon final class. (#5866)
Also import unions as final classes, and abstract classes as `abstract
class`es.
2025-07-30 00:41:42 +00:00
Richard Smith 63b441390c Avoid vector copies when building dependent declarations list. (#5862)
Plus a few cleanups for uses of clang APIs.
2025-07-29 14:55:43 +00:00
Boaz Brickner 30f0ddab71 Add support for importing access from C++ to Carbon (#5858)
Better access control with inheritance should come with better
inheritance support (actually importing inheritance).

C++ Interop Demo:

```c++
// hello_world.h

class HelloWorld {
 public:
  static auto Pub() -> void;

 protected:
  static auto Pro() -> void;

 private:
  static auto Pri() -> void;
};
```

```c++
// hello_world.cpp

#include "hello_world.h"

#include <cstdio>

auto HelloWorld::Pub() -> void { printf("Public!\n"); }
auto HelloWorld::Pro() -> void { printf("Protected!\n"); }
auto HelloWorld::Pri() -> void { printf("Private!\n"); }
```

```carbon
// main.carbon

library "Main";

import Cpp library "hello_world.h";

fn Run() -> i32 {
  Cpp.HelloWorld.Pub();
  Cpp.HelloWorld.Pro();
  Cpp.HelloWorld.Pri();
  return 0;
}
```

```shell
$ clang -c hello_world.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
main.carbon:9:3: error: cannot access protected member `Pro` of type `Cpp.HelloWorld`
  Cpp.HelloWorld.Pro();
  ^~~~~~~~~~~~~~~~~~
main.carbon: note: declared here

main.carbon:10:3: error: cannot access private member `Pri` of type `Cpp.HelloWorld`
  Cpp.HelloWorld.Pri();
  ^~~~~~~~~~~~~~~~~~
main.carbon: note: declared here
```

Before this change (no access checks):
```shell
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link hello_world.o main.o --output=demo
$ ./demo
Public!
Protected!
Private!
```

Part of #5859.
2025-07-29 08:25:15 +00:00
Boaz Brickner 6d6e0d0418 Add support for using C++ bool type in imported function declarations. (#5860)
C++ in

C++ Interop Demo:

```c++
// hello_world.h

auto hello_world(bool x) -> bool;
```

```c++
// hello_world.cpp

#include "hello_world.h"

#include <cstdio>

auto hello_world(bool x) -> bool {
  printf("bool: %d\n", x);
  return !x;
}
```

```carbon
// main.carbon

library "Main";

import Cpp library "hello_world.h";

fn Run() -> i32 {
  let x: bool = Cpp.hello_world(false);
  if (x) {
    return 0;
  } else {
    return 1;
  }
}
```

```shell
$ clang -c hello_world.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link hello_world.o main.o --output=demo
$ ./demo
bool: 0
```

Before this change (bool is interpreted as a 1 bit integer):
```shell
$ bazel-bin/toolchain/carbon compile main.carbon
... CRASH! ...
clang/include/clang/AST/Type.h:952: const ExtQualsTypeCommonBase *clang::QualType::getCommonPtr() const: Assertion `!isNull() && "Cannot retrieve a NULL type pointer"' failed.
```

Part of #5263.
2025-07-29 06:56:45 +00:00
Richard Smith 5de47962b0 Support for importing C++ base classes. (#5856)
For now, provide no support for virtual base classes and only minimal
support for multiple inheritance.
2025-07-28 20:56:06 +00:00
Richard Smith 0d74162e2a Support C++ import for anonymous struct and union members. (#5855) 2025-07-28 20:26:24 +00:00
Richard Smith 36f0a73092 Initial support for interop with class/struct/union fields. (#5849)
Add a new type, `custom_layout_type`, representing a struct type whose
size, alignment, and field offsets can be manually controlled. Use this
as the object representation type for imported C++ class types (which
also includes struct and union types), allowing us to model C++ class
type layouts. In passing, also add support for incomplete C++ class
types, mapping them into incomplete Carbon class types.

Map C++ fields into Carbon field declarations, allowing direct access to
C++ fields from Carbon. So far, no support is added for base classes nor
anonymous struct or union declarations; those will be added in
subsequent PRs. Also, we don't map C++ access control into Carbon yet,
so all C++ fields are accessible regardless of their access control.

For now we still use a `struct_type` as the object representation for
empty C++ classes, in order to continue to support our existing tests
that convert `{}` to empty C++ class types. This is temporary and should
be removed once we support interop with C++ class initialization.
2025-07-25 21:09:24 +00:00
Richard Smith c90c6728fd Interop: support all C++ integer types that map to intN_t or uintN_t. (#5836)
Expand support for `int` and `short` to cover all the other `intN_t` and
`uintN_t` types too. We achieve this by asking Clang what the `intN_t` /
`uintN_t` type that it would use for the given bitwidth is, and checking
if that's the type we're trying to map.
2025-07-22 21:29:09 +00:00
Boaz Brickner 68ee3d5021 Use llvm::reverse() instead of pop_back_val() in ImportDeclAndDependencies() (#5831)
This is more explicit and similar to what we do in `MapType()`.
2025-07-18 21:11:12 +00:00
Boaz Brickner 8cb01b54bd Avoid passing name scope id and name id through ImportCXXRecordDecl() and BuildClassDefinition() (#5829)
All this information is calculated based on the Clang declaration.
2025-07-18 20:58:59 +00:00
Boaz Brickner 52976c55fb When importing a declaration, first collect all dependent unimported declarations and import them first (#5821)
This fixes some tests since we now handle record name scopes correctly.

Part of #5533.
2025-07-18 18:01:27 +00:00
Richard SmithandChandler Carruth 553dd6e531 Build the clang::CompilerInvocation in the driver. (#5784)
Add driver flags to specify clang driver arguments.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2025-07-18 16:30:47 +00:00
Boaz Brickner f4f521de7f Explicitly mark as unsupported instead of crashing mapping a parameter record type defined not in a namespace (#5777)
Before this change we crash in this case when trying to use the outer
type.
After this change we diagnose a TODO.
Will add the missing support for this in a separate PR.

Part of #5533.
2025-07-18 02:42:45 +00:00
Richard Smith 9f67fa4b0f Allow interop with templated but non-template functions. (#5809)
For example, this would allow using `std::string::size`, which is
templated because it's a member of the class template
`std::basic_string`, but isn't itself a function template.
2025-07-17 15:04:19 +00:00
Boaz Brickner 4f8d0649d5 When importing a looked up name, reuse previously imported declaration instead of importing the same declaration again (#5789)
Added test coverage to demonstrate name lookup following import of a
type of a function parameter.
SemIR changes show that the same decl isn't imported multiple times.

Part of #5533.
2025-07-16 11:21:49 +00:00
Richard Smith f204bdf094 Basic support for calling class methods imported from C++. (#5796)
Create a `self` parameter when importing a C++ non-static member
function. That seems to be all we need to get basic method calls
working! For now, `const` methods have by-value self parameters, and
non-`const` methods get an `addr self: Self*` parameter.
2025-07-15 16:05:01 +00:00
Richard Smith a6acba9eab Support for importing const-qualified types from C++. (#5794)
Incidentally also supports import of pointers-to-pointers.

Imported const-qualified types aren't especially useful just yet,
because on the Carbon side we don't yet permit conversions from
non-const to const types, so most of the tests still fail, but for
different reasons now.
2025-07-12 02:22:24 +00:00
Richard Smith 26e23eac10 Support import of typedefs. (#5787)
Unify code paths for importing classes by name and importing them
indirectly when their type is referenced. Switch to using the general
type import machinery to import all type declarations, which allows
typedef declarations naming importable types to be used too.

Fix up handling of error cases to consistently only produce an Error
InstId after actually producing an error message, so that we can produce
exactly one diagnostic in failure cases.

Remove TODO error for unions that previously was only produced when
importing them indirectly, not when importing them by name. Import of
unions is exactly as complete / incomplete as import of other class
types, so treating them differently doesn't seem necessary.
2025-07-10 20:46:46 +00:00
Boaz Brickner a5ddc3e3cd Support importing C++ _Nonnull pointers as function parameters or return values (#5773)
We avoid using canonical type before knowing it's not a pointer because
we need the nullability attribute.
No support for pointers to pointers, yet.

C++ Interop Demo:

```c++
// hello_world.h

auto hello_world_param(int* _Nonnull i) -> void;
auto hello_world_return() -> int* _Nonnull;
```

```c++
// hello_world.cpp

#include "hello_world.h"
#include <cstdio>

auto hello_world_param(int* _Nonnull i) -> void {
  printf("hello_world: %d\n", *i);
}

static int x = 5;
auto hello_world_return() -> int* _Nonnull { return &x; }
```

```carbon
// main.carbon

library "Main";

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

fn Run() -> i32 {
  var i: i32 = 10;
  Cpp.hello_world_param(&i);

  let p: i32* = Cpp.hello_world_return();
  Core.Print(*p);

  return 0;
}
```

```shell
$ clang -c hello_world.cpp
$ ./bazel-bin/toolchain/install/prefix_root/bin/carbon compile main.carbon
$ ./bazel-bin/toolchain/install/prefix_root/bin/carbon link hello_world.o main.o --output=demo
$ ./demo
hello_world: 10
5
```

Part of #5772.
2025-07-10 08:00:37 +00:00
Richard SmithandChandler Carruth 3776e464e0 Properly set up C++ include paths and similar environment settings when parsing imported C++. (#5767)
Stop using the clang tooling library to build an ASTUnit; that library
is set up to process clang frontend arguments, assuming that something
has already built frontend arguments from the compiler arguments. It is
also too encapsulated and doesn't let us inspect and modify the compiler
invocation before it's executed.

Instead, build the AST unit directly in two phases:

* FIrst, take a list of clang driver arguments and convert them into a
list of compiler arguments, using `clang::createInvocation`. Internally,
this uses the clang driver to build a frontend invocation, including
building system-specific include paths as needed.
* Then, directly build an ASTUnit from this compiler invocation.

I've factored this so that we can split out the `createInvocation` step,
with the intention that we may want to move it out of check and into the
carbon driver with the rest of the driver-level argument handling, and
we may want to customize some of the clang options before we invoke the
clang frontend with that set of options.

In order to make the invocation reusable, it no longer depends on the
name of the carbon file importing the C++ code. In place of synthesizing
a header file name as `<foo.carbon>.generated.cpp_imports.h`, we now
insert line marker directives into the generated header so that errors
in that header cause Clang to point a diagnostic back at the Carbon
source file itself. This results in a minor improvement in the
diagnostic output: we no longer refer to a nonexistent generated file.
But the snippet still contains text that doesn't match the source code,
so it remains imperfect.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2025-07-09 03:09:43 +00:00
Richard Smith f987504614 Track the location of the Cpp import for use in Clang diagnostics. (#5783)
When diagnosing a problem with C++ code imported from Carbon, include
the location of the specific `import Cpp` statement that imported the
C++ code as part of the backtrace, rather than providing a location in a
generated file that doesn't exist on disk.

Also fix handling in autoupdate of check lines that contain multiple
file name and line number pairs to use the matched file name for
remapping of locations rather than the first file name in the line.
2025-07-09 00:47:21 +00:00
Boaz Brickner 9d0aaa740b When adding an imported C++ name, make sure that its clang::Decl is mapped if import failed (#5769)
When mapping parameter types, we assume that if the `clang::Decl` isn't
mapped, the name wasn't added, so this fixes a bug that triggers a crash
otherwise.

Part of #5533.
2025-07-08 13:12:32 +00:00
Boaz Brickner ff9154b978 Push a decl name scope before calling CalleePatternMatch() (#5771)
Otherwise the return values of different functions collide.

Part of #5063.
2025-07-07 15:02:47 +00:00
Chandler CarruthandGeoff Romer bba037738d Key-type customization in CanonicalValueStore and ClangDecl cleanups (#5743)
The `ClangDecl` struct caused some confusion here -- it is embedding
extra data into a `CanonicalValueStore` that isn't used for lookups or
canonicalization, but is useful to store along side. This changes the
`CanonicalValueStore` to support customized key type for `Lookup` so
that we can provide the more direct API that only takes the relevant
key.

This in turn takes advantage of the support for heterogenous keys in the
underlying `Set` as long as hashing and equality are consistent. We do
need to add support for heterogenous equality comparison with
`clang::Decl*`, but that is fairly easily done now that the
argument-reversed form isn't needed as well.

Lastly, this cleans up the `ClangDecl` customization points to be more
idiomatic by using `operator==` and `CarbonHashValue`. While there, I've
added comments to make it unambiguous why we can use the pointer value
for the underlying `clang::Decl` due to the Clang AST's
address-as-identity model.

Resolves the immediate TODOs around this type.

Future work might involve changing from the current `Add` API to one
more like `Map` and `Set`'s API where a callback is used to create the
object, but that level of API complexity isn't necessarily motivated yet
and can easily be a follow-on if and when its worth doing. The `Add`
code paths *are* working with the `inst_id` in order to create an
instruction if we are importing the Clang declaration. It is the
`Lookup` code paths that never needed to know about the `inst_id` and
became more confusing for having to stub it out in the API.

---------

Co-authored-by: Geoff Romer <gromer@google.com>
2025-06-27 20:30:05 +00:00
Boaz Brickner b90d3b7751 Use Decl::getAsFunction() to cast clang_decl to FunctionDecl (#5737)
This seems like a better practice though has no effect since we don't
support templates yet.

Part of #5436.
2025-06-26 17:14:02 +00:00
Boaz Brickner 4b8ac429a7 Replace isStruct() || isClass() with !isUnion() (#5715)
Follow up of
https://github.com/carbon-language/carbon-lang/pull/5709/files#r2162385549

Part of https://github.com/carbon-language/carbon-lang/issues/5533.
2025-06-24 07:42:51 +00:00
Boaz Brickner 20f44e0a92 Support a C++ class as a parameter or return by value, similar to a C++ struct (#5709)
Add tests for C++ `union`.
Also fix some typos in `class` tests and remove SemIR ranges from tests
that should diagnose an error.

Part of #5533.
2025-06-23 19:30:56 +00:00
Boaz Brickner cc698d78f5 When using a C++ struct as a parameter, map its type to a Carbon class type (#5538)
This doesn't support actually passing the value of the struct, which is
planned to be implemented using thunks.

`ClangDeclId` value is now `ClangDecl` which includes the mapped Carbon
instruction in addition to the Clang declaration. This allows finding
the Carbon instruction for a given Clang declaration, which is necessary
for mapping a Clang struct parameter type to the Carbon class without
doing name lookup. We don't take the instruction as part of the hash
key, as discussed in
[Discord](https://discord.com/channels/655572317891461132/768530752592805919/1380575881050718469).

To map the type, we also need to map namespaces. To avoid recursion for
inner namespaces, we use a vector.

Note that the first commit just changes the order of functions in the
file to make review easier.

C++ Interop Demo (that shows missing behavior):

```c++
// hello_world.h

struct S {
  S(const S&) { x = 1; }
  int x;
};

void hello_world(S s);
```

```c++
// hello_world.cpp

#include "hello_world.h"

#include <cstdio>

void hello_world2(S s) { printf("hello_world2: %d\n", s.x); }

void hello_world(S s) {
  printf("hello_world: %d\n", s.x);
  hello_world2(s);
}
```

```carbon
// main.carbon

library "Main";

import Cpp library "hello_world.h";

fn Run() -> i32 {
  var s : Cpp.S;
  Cpp.hello_world(s);
  return 0;
}
```

```shell
$ clang -c hello_world.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link hello_world.o main.o --output=demo
$ ./demo
hello_world: -1108224096
hello_world2: 1
```

Part of #5533.
2025-06-20 16:51:58 +00:00
Ivana Ivanovska 3d603fced7 Fix C++ function params and return values printed in SemIR (#5468)
Fix `pattern_block_id` and `call_params_id` for C++ function decl
import, to get the correct SemIR printout for the C++ functions i.e.

1) Fill in missing parameter info in the function decls:
```
// CHECK:STDOUT:   %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {
// CHECK:STDOUT:     %a.patt: %pattern_type.2f8 = binding_pattern a [concrete]
// CHECK:STDOUT:     %a.param_patt: %pattern_type.2f8 = value_param_pattern %a.patt, call_param0 [concrete]
// CHECK:STDOUT:   } {
// CHECK:STDOUT:     %a.param: %i16 = value_param call_param0
// CHECK:STDOUT:     %.1: type = splice_block %i16 [concrete = constants.%i16] {
// CHECK:STDOUT:       %int_16: Core.IntLiteral = int_value 16 [concrete = constants.%int_16]
// CHECK:STDOUT:       %i16: type = class_type @Int, @Int(constants.%int_16) [concrete = constants.%i16]
// CHECK:STDOUT:     }
// CHECK:STDOUT:     %a: %i16 = bind_name a, %a.param
// CHECK:STDOUT:   }
```
2) Print the params and return values:

```
// CHECK:STDOUT: fn @foo_short() -> %i16;
```

```
// CHECK:STDOUT: fn @foo(%a.param: %i16);
```

Closes #5449
2025-06-10 17:17:19 +00:00
Boaz Brickner e4c8150f2c Store Clang Decls in a CanonicalValueStore (#5638)
Saves space since in most cases, we only need a `None` 32 bits index
instead of a null 64 bits pointer.

Based on discussions in [Carbon C++ Interop
weekly](https://docs.google.com/document/d/1YlxEOJ0r-o19o19TCJbFl4Ln1U88yn_Vj23y1Hr5vTk/edit?tab=t.0#heading=h.23l56bt5xwlu)
and Discord
([1](https://discord.com/channels/655572317891461132/768530752592805919/1375121180306047106),
[2](https://discord.com/channels/655572317891461132/768530752592805919/1380575881050718469)).

Note: Any `clang::DeclContext` is also a `clang::Decl`.

Part of #4666.
2025-06-10 16:55:29 +00:00
Boaz Brickner ec97ec9664 Use InImport pointing to C++ imports in ConvertLocInFile() instead of adding a separate InCppImport when emitting (#5614)
I believe we will need to eventually add the specific C++ import
information in `LocId`.

This also seems to fix the `LanguageServerDiagnosticInWrongFile` issue
(#5604).

We're still not in the state we want to be according to
https://github.com/carbon-language/carbon-lang/pull/5246#issuecomment-2784301206.
Will look into removing the location part from the `"In file included
from ..."` line.

Part of #5245.
2025-06-10 09:02:45 +00:00
Jon Ross-Perkins 1e9e148c3b Rename the ImportRefs block to Imports (#5618)
I've been mulling the name of this, changing it and updating comments to
try and better reflect the current semantic. "Imports" reflects how
we're currently printing this in SemIR.
2025-06-05 21:24:58 +00:00
Jon Ross-Perkins 9b1a0729a1 Move imported C++ entities to the import block (#5616)
This mirrors how imports work in general, that the imported declarations
shouldn't belong to the first referencing scope (particularly apparent
when referenced across multiple scopes). I think this was just an
oversight here.
2025-06-05 18:44:27 +00:00
josh11bandJosh L 09ca0b8308 Update LLVM (#5605)
Some updates required for
https://github.com/llvm/llvm-project/pull/139584.

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2025-06-04 00:43:40 +00:00
Boaz Brickner 464ee76b9b Fix stack-use-after-scope issue by making LangOptions parameter non temporary (#5586)
The parameter is kept by reference.
Added a test that accesses `LangOptions` and crashes without this fix.

Part of #5176.
2025-06-02 14:28:36 +00:00
Jon Ross-PerkinsandRichard Smith 65c1dcec5f Force -fPIE for compiles (#5521)
In LLVM, CLANG_DEFAULT_PIE_ON_LINUX is
[configurable](https://github.com/llvm/llvm-project/blob/main/clang/test/CMakeLists.txt#L8),
so change lowering to specify a value.

Also, adjust how the target is set so that function_decl.carbon isn't
trying to overload every flag, and so that the target isn't forgotten
elsewhere.

This is fixing issues introduced by #5427; note #5520 is also a related
fix.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-05-22 21:21:46 +00:00
Boaz Brickner 852d0191a9 Add support for importing C++ inline functions (#5427)
This requires:
* Making `FunctionDecl` mutable since generating code
(`HandleTopLevelDecl()`) requires a mutable declaration and since we
manually add `used` attribute to force code generation.
* Passing the file system to `Lower` since it's needed by Clang code
generation.
* Creating an internal Clang LLVM module and link it against the Carbon
LLVM module.

Demo:

```c++
// hello_world.h

extern int puts;
inline void hello_world() {
  ((int (*)(const char*))&puts)("hello world");
}
```

```carbon
// main.carbon

library "Main";

import Cpp library "hello_world.h";

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

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

Based on https://github.com/carbon-language/carbon-lang/pull/5406.

Part of #5405.
2025-05-21 07:02:05 +00:00
Ivana Ivanovska f8443ae09e [Carbon/C++ interop] Add support for C++ type short (#5393)
Added support for `short`/`int16_t`. Both function parameters and return
values this type will be supported.

Demo:

```c++
// hello_short.h

#include <cstdint>
auto foo_short(int16_t a) -> int16_t;
```

```c++
// hello_short.cpp

#include "hello_short.h"
#include <cstdio>

auto foo_short(int16_t a) -> int16_t {
    printf("a = %i \n", a);
    return a;
}
```

```c++
// main.carbon

library "Main";

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

fn Run() -> i32 {
  var a: i16 = 3;
  Cpp.foo_short(a);
  return 0;
}
```

```
$ clang -c hello_short.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link hello_short.o main.o --output=demo
$ ./demo
a = 3 
```

Part of #5263
2025-05-09 08:51:46 +00:00
Jon Ross-Perkins 1b96e40b63 Update LLVM version (#5415)
Fixes a compile failure with the new version, essentially:

```
external/+llvm_project+llvm-project/llvm/include/llvm/Support/FormatVariadicDetails.h:157:1: error: implicit instantiation of undefined template 'llvm::support::detail::missing_format_adapter<clang::LookupResultKind>'
```
2025-05-02 23:07:50 +00:00
Geoff Romer fafb655d39 Separate pattern types from expression types (#5360)
This is a step toward treating patterns as compile-time constants, so
that we can import them more easily.
2025-04-28 16:54:37 +00:00
Boaz Brickner 609ccefd18 Introduce a Clang diagnostic instruction and use it to point to C++ source locations on Clang errors and warnings (#5262)
Introduce `ImportIRId::Cpp` and refer to clang source location in its
`ImportIRInst`.

Part of #5245.
2025-04-25 13:05:45 +00:00
Dana Jansens c38e723dd8 Rename singleton InstId constants to TypeInstId (#5323)
These constant instructions are all TypeInstId already in their type,
and this makes their names match.

Change the name of MakeSingletonInstId as well and update its comment.
2025-04-17 18:57:20 +00:00
Thomas Köppe bf32da8dad Add missing standard library header inclusions (#5316)
Discovered by clang-tidy.
2025-04-17 15:37:57 +00:00
Jon Ross-Perkins 4923445e3a Drop Singleton from ErrorInst::SingletonInstId and similar (#5304)
We frequently want to operate on singletons. Per discussion, drop
`Singleton` to make the code shorter.

This started off as wanting to write `inst_id.is_error()`, but the
dependency relationship between ids.h and singleton_insts.h would
require some kind of delayed evaluation to allow the implementation to
remain in headers (which I suspect is helpful to have for inlining). I
could have added something like `IsErrorInst`, forward declared in ids.h
and defined in singleton_insts.h (which would always be included by
typed_insts.h), but the template approach felt like a decent balance
between (a) removing the boilerplate `::SingletonInstId`, (b)
understandability, (c) still visually mirroring if we immediately return
a singleton, and (d) flexibility for more than just `ErrorInst`. But TBH
I'd probably still have written `is_error()` if it didn't require
addressing the cross-header cycle.

Then I tried `SemIR::InstId::Is<SemIR::ErrorInst>`, which generally
worked with types but generated the complaint that it didn't shorten
*all* singleton uses. So pulling back on `::Is`, and instead just
dropping `Singleton`.
2025-04-15 22:40:29 +00:00
Jon Ross-Perkins 55da026a46 Remove the SemIRLoc typedef (#5299)
Replace SemIRLoc typedef uses with explicitly SemIR::LocId, loc ->
loc_id for consistency.
2025-04-14 14:28:15 +00:00
Dana JansensandRichard Smith cf57c85545 Introduce TypeInstId (#5288)
TypeInstId is an InstId whose constant value has a type of TypeType.
This includes:
- Type value instructions, the `ClassType` or `IntLiteralType`
instructions.
- Constraint value instructions, which are the `FacetType` and
`TypeType` instructions, each of which also have type TypeType.

TypeInstId encodes in the type system that it is safe to convert the
instruction's value to a TypeId, and CHECKs at construction that this
invariant is maintained.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-04-10 22:59:02 +00:00
Richard Smith a74ca9071b Remove all remaining uses of TypeIds as instruction operands. (#5280)
In preparation for shifting from `TypeId`s potentially representing
attached types to always representing unattached types, using
[terminology suggested on
Discord](https://discord.com/channels/655572317891461132/963846118964350976/1359286326779973712).
This change causes us to track slightly more type spelling information
through SemIR.

One change that has significant impact on the SemIR output is that we
now build a `struct_type` instruction in each class representing the
types of the fields, including the spelling used for those types. This
is now no longer always identical to the corresponding canonical
`struct_type` for the object representation, so it's built separately
and owned by the class.

Also remove `TypeBlock` support entirely, as its only use was
representing `TupleType`s, which now use an `InstBlock`.
2025-04-10 20:53:42 +00:00
Boaz Brickner 68111a994c C++ Interop: Basic C++ record (class/struct/union) import support (#5156)
Focus: Calling static C++ function defined in C++ classes.

Limitations:
* Ignores visibility (public / protected / private).
* No support for: dynamic classes, member methods, data members,
declarations without definitions, importing inheritance.

Based on #5142.

C++ Interop Demo with a class:

```c++
// hello_world.h

namespace some_namespace {

class MyClass {
 public:
  static void hello_world();
};

}  // namespace some_namespace
```

```c++
// hello_world.cpp

#include "hello_world.h"

#include <cstdio>

namespace some_namespace {

void MyClass::hello_world() { printf("Hello World!\n"); }

}  // namespace some_namespace
```

```carbon
// main.carbon

library "Main";

import Cpp library "hello_world.h";

fn Run() -> i32 {
  Cpp.some_namespace.MyClass.hello_world();
  return 0;
}
```

```shell
$ clang -c hello_world.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link hello_world.o main.o --output=demo
$ ./demo
Hello World!
```

Part of #5150.
2025-04-10 08:15:12 +00:00
Ivana Ivanovska 7580df8b8a [Carbon/C++ interop] Add support for int function params (#5197)
Added support for `int` function parameters. Currently only
pass-by-value is supported.

```c++
// hello_int.h;

auto foo_int(int a, int b) -> int;
```

```c++
// hello_int.cpp

#include "hello_int.h"
#include <cstdio>

auto foo_int(int a, int b) -> int {
    printf("a = %i \n", a);
    printf("b = %i \n", b);
    return a + b;
}
```
```c++
// main.carbon

library "Main";

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

fn Carbon_foo(b: i32) {
  Core.Print(b);
}

fn Run() -> i32 {
  Carbon_foo(Cpp.foo_int(2, 8));
  return 0;
}
```

```
$ clang -c hello_int.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link hello_int.o main.o --output=demo
$ ./demo
a = 2 
b = 8 
10
```

Part of  #5064
2025-04-09 11:38:39 +00:00