mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 13:31:06 +01:00
Basic check support for adapters. (#3874)
No support is provided yet for converting between a type and an adapter for that type.
This commit is contained in:
@@ -950,6 +950,7 @@ class TypeCompleter {
|
||||
auto BuildValueRepr(SemIR::TypeId type_id, SemIR::Inst inst) const
|
||||
-> SemIR::ValueRepr {
|
||||
CARBON_KIND_SWITCH(inst) {
|
||||
case SemIR::AdaptDecl::Kind:
|
||||
case SemIR::AddrOf::Kind:
|
||||
case SemIR::AddrPattern::Kind:
|
||||
case SemIR::ArrayIndex::Kind:
|
||||
|
||||
@@ -66,6 +66,7 @@ struct DeclState {
|
||||
// The kind of declaration.
|
||||
enum DeclKind : int8_t {
|
||||
FileScope,
|
||||
Adapt,
|
||||
Alias,
|
||||
Base,
|
||||
Class,
|
||||
|
||||
@@ -901,6 +901,7 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
|
||||
}
|
||||
|
||||
// These cases are either not expressions or not constant.
|
||||
case SemIR::AdaptDecl::Kind:
|
||||
case SemIR::AddrPattern::Kind:
|
||||
case SemIR::Assign::Kind:
|
||||
case SemIR::BindName::Kind:
|
||||
|
||||
@@ -9,6 +9,17 @@
|
||||
|
||||
namespace Carbon::Check {
|
||||
|
||||
// If `type_id` is a class type, get its corresponding `SemIR::Class` object.
|
||||
// Otherwise returns `nullptr`.
|
||||
static auto TryGetAsClass(Context& context, SemIR::TypeId type_id)
|
||||
-> SemIR::Class* {
|
||||
auto class_type = context.types().TryGetAs<SemIR::ClassType>(type_id);
|
||||
if (!class_type) {
|
||||
return nullptr;
|
||||
}
|
||||
return &context.classes().Get(class_type->class_id);
|
||||
}
|
||||
|
||||
auto HandleClassIntroducer(Context& context, Parse::ClassIntroducerId node_id)
|
||||
-> bool {
|
||||
// Create an instruction block to hold the instructions created as part of the
|
||||
@@ -172,15 +183,113 @@ auto HandleClassDefinitionStart(Context& context,
|
||||
return true;
|
||||
}
|
||||
|
||||
auto HandleAdaptIntroducer(Context& /*context*/,
|
||||
// Diagnoses a class-specific declaration appearing outside a class.
|
||||
static auto DiagnoseClassSpecificDeclOutsideClass(Context& context,
|
||||
SemIRLoc loc,
|
||||
Lex::TokenKind tok) -> void {
|
||||
CARBON_DIAGNOSTIC(ClassSpecificDeclOutsideClass, Error,
|
||||
"`{0}` declaration can only be used in a class.",
|
||||
Lex::TokenKind);
|
||||
context.emitter().Emit(loc, ClassSpecificDeclOutsideClass, tok);
|
||||
}
|
||||
|
||||
// Returns the declaration of the immediately-enclosing class scope, or
|
||||
// diagonses if there isn't one.
|
||||
static auto GetEnclosingClassOrDiagnose(Context& context, SemIRLoc loc,
|
||||
Lex::TokenKind tok)
|
||||
-> std::optional<SemIR::ClassDecl> {
|
||||
auto class_scope = context.GetCurrentScopeAs<SemIR::ClassDecl>();
|
||||
if (!class_scope) {
|
||||
DiagnoseClassSpecificDeclOutsideClass(context, loc, tok);
|
||||
}
|
||||
return class_scope;
|
||||
}
|
||||
|
||||
// Diagnoses a class-specific declaration that is repeated within a class, but
|
||||
// is not permitted to be repeated.
|
||||
static auto DiagnoseClassSpecificDeclRepeated(Context& context,
|
||||
SemIRLoc new_loc,
|
||||
SemIRLoc prev_loc,
|
||||
Lex::TokenKind tok) -> void {
|
||||
CARBON_DIAGNOSTIC(ClassSpecificDeclRepeated, Error,
|
||||
"Multiple `{0}` declarations in class.{1}", Lex::TokenKind,
|
||||
std::string);
|
||||
const llvm::StringRef extra = tok == Lex::TokenKind::Base
|
||||
? " Multiple inheritance is not permitted."
|
||||
: "";
|
||||
CARBON_DIAGNOSTIC(ClassSpecificDeclPrevious, Note,
|
||||
"Previous `{0}` declaration is here.", Lex::TokenKind);
|
||||
context.emitter()
|
||||
.Build(new_loc, ClassSpecificDeclRepeated, tok, extra.str())
|
||||
.Note(prev_loc, ClassSpecificDeclPrevious, tok)
|
||||
.Emit();
|
||||
}
|
||||
|
||||
auto HandleAdaptIntroducer(Context& context,
|
||||
Parse::AdaptIntroducerId /*node_id*/) -> bool {
|
||||
context.decl_state_stack().Push(DeclState::Adapt);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto HandleAdaptDecl(Context& context, Parse::AdaptDeclId /*node_id*/) -> bool {
|
||||
auto adapted_expr_id = context.node_stack().PopExpr();
|
||||
(void)adapted_expr_id;
|
||||
// TODO: Process the `adapt` declaration.
|
||||
auto HandleAdaptDecl(Context& context, Parse::AdaptDeclId node_id) -> bool {
|
||||
auto [adapted_type_node, adapted_type_expr_id] =
|
||||
context.node_stack().PopExprWithNodeId();
|
||||
|
||||
// Process modifiers. `extend` is permitted, no others are allowed.
|
||||
LimitModifiersOnDecl(context, KeywordModifierSet::Extend,
|
||||
Lex::TokenKind::Adapt);
|
||||
auto modifiers = context.decl_state_stack().innermost().modifier_set;
|
||||
context.decl_state_stack().Pop(DeclState::Adapt);
|
||||
|
||||
auto enclosing_class_decl =
|
||||
GetEnclosingClassOrDiagnose(context, node_id, Lex::TokenKind::Adapt);
|
||||
if (!enclosing_class_decl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto& class_info = context.classes().Get(enclosing_class_decl->class_id);
|
||||
if (class_info.adapt_id.is_valid()) {
|
||||
DiagnoseClassSpecificDeclRepeated(context, node_id, class_info.adapt_id,
|
||||
Lex::TokenKind::Adapt);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto adapted_type_id = ExprAsType(context, node_id, adapted_type_expr_id);
|
||||
adapted_type_id = context.AsCompleteType(adapted_type_id, [&] {
|
||||
CARBON_DIAGNOSTIC(IncompleteTypeInAdaptDecl, Error,
|
||||
"Adapted type `{0}` is an incomplete type.",
|
||||
SemIR::TypeId);
|
||||
return context.emitter().Build(node_id, IncompleteTypeInAdaptDecl,
|
||||
adapted_type_id);
|
||||
});
|
||||
|
||||
// Build a SemIR representation for the declaration.
|
||||
class_info.adapt_id =
|
||||
context.AddInst({node_id, SemIR::AdaptDecl{adapted_type_id}});
|
||||
|
||||
// Extend the class scope with the adapted type's scope if requested.
|
||||
if (!!(modifiers & KeywordModifierSet::Extend)) {
|
||||
auto extended_scope_id = SemIR::NameScopeId::Invalid;
|
||||
if (adapted_type_id == SemIR::TypeId::Error) {
|
||||
// Recover by not extending any scope. We instead set has_error to true
|
||||
// below.
|
||||
} else if (auto* adapted_class_info =
|
||||
TryGetAsClass(context, adapted_type_id)) {
|
||||
extended_scope_id = adapted_class_info->scope_id;
|
||||
CARBON_CHECK(adapted_class_info->scope_id.is_valid())
|
||||
<< "Complete class should have a scope";
|
||||
} else {
|
||||
// TODO: Accept any type that has a scope.
|
||||
context.TODO(node_id, "extending non-class type");
|
||||
}
|
||||
|
||||
auto& class_scope = context.name_scopes().Get(class_info.scope_id);
|
||||
if (extended_scope_id.is_valid()) {
|
||||
class_scope.extended_scopes.push_back(extended_scope_id);
|
||||
} else {
|
||||
class_scope.has_error = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -208,17 +317,6 @@ constexpr BaseInfo BaseInfo::Error = {.type_id = SemIR::TypeId::Error,
|
||||
.scope_id = SemIR::NameScopeId::Invalid};
|
||||
} // namespace
|
||||
|
||||
// If `type_id` is a class type, get its corresponding `SemIR::Class` object.
|
||||
// Otherwise returns `nullptr`.
|
||||
static auto TryGetAsClass(Context& context, SemIR::TypeId type_id)
|
||||
-> SemIR::Class* {
|
||||
auto class_type = context.types().TryGetAs<SemIR::ClassType>(type_id);
|
||||
if (!class_type) {
|
||||
return nullptr;
|
||||
}
|
||||
return &context.classes().Get(class_type->class_id);
|
||||
}
|
||||
|
||||
// Diagnoses an attempt to derive from a final type.
|
||||
static auto DiagnoseBaseIsFinal(Context& context, Parse::NodeId node_id,
|
||||
SemIR::TypeId base_type_id) -> void {
|
||||
@@ -268,7 +366,7 @@ auto HandleBaseDecl(Context& context, Parse::BaseDeclId node_id) -> bool {
|
||||
auto [base_type_node_id, base_type_expr_id] =
|
||||
context.node_stack().PopExprWithNodeId();
|
||||
|
||||
// Process modifiers. `extend` is required, none others are allowed.
|
||||
// Process modifiers. `extend` is required, no others are allowed.
|
||||
LimitModifiersOnDecl(context, KeywordModifierSet::Extend,
|
||||
Lex::TokenKind::Base);
|
||||
auto modifiers = context.decl_state_stack().innermost().modifier_set;
|
||||
@@ -279,25 +377,16 @@ auto HandleBaseDecl(Context& context, Parse::BaseDeclId node_id) -> bool {
|
||||
}
|
||||
context.decl_state_stack().Pop(DeclState::Base);
|
||||
|
||||
auto enclosing_class_decl = context.GetCurrentScopeAs<SemIR::ClassDecl>();
|
||||
auto enclosing_class_decl =
|
||||
GetEnclosingClassOrDiagnose(context, node_id, Lex::TokenKind::Base);
|
||||
if (!enclosing_class_decl) {
|
||||
CARBON_DIAGNOSTIC(BaseOutsideClass, Error,
|
||||
"`base` declaration can only be used in a class.");
|
||||
context.emitter().Emit(node_id, BaseOutsideClass);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto& class_info = context.classes().Get(enclosing_class_decl->class_id);
|
||||
if (class_info.base_id.is_valid()) {
|
||||
CARBON_DIAGNOSTIC(BaseRepeated, Error,
|
||||
"Multiple `base` declarations in class. Multiple "
|
||||
"inheritance is not permitted.");
|
||||
CARBON_DIAGNOSTIC(BasePrevious, Note,
|
||||
"Previous `base` declaration is here.");
|
||||
context.emitter()
|
||||
.Build(node_id, BaseRepeated)
|
||||
.Note(class_info.base_id, BasePrevious)
|
||||
.Emit();
|
||||
DiagnoseClassSpecificDeclRepeated(context, node_id, class_info.base_id,
|
||||
Lex::TokenKind::Base);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -316,6 +405,7 @@ auto HandleBaseDecl(Context& context, Parse::BaseDeclId node_id) -> bool {
|
||||
|
||||
// Add a corresponding field to the object representation of the class.
|
||||
// TODO: Consider whether we want to use `partial T` here.
|
||||
// TODO: Should we diagnose if there are already any fields?
|
||||
context.args_type_info_stack().AddInstId(context.AddInstInNoBlock(
|
||||
{node_id,
|
||||
SemIR::StructTypeField{SemIR::NameId::Base, base_info.type_id}}));
|
||||
@@ -345,9 +435,39 @@ auto HandleClassDefinition(Context& context,
|
||||
context.node_stack().Pop<Parse::NodeKind::ClassDefinitionStart>();
|
||||
context.inst_block_stack().Pop();
|
||||
|
||||
// The class type is now fully defined.
|
||||
// The class type is now fully defined. Compute its object representation.
|
||||
auto& class_info = context.classes().Get(class_id);
|
||||
class_info.object_repr_id = context.GetStructType(fields_id);
|
||||
if (class_info.adapt_id.is_valid()) {
|
||||
class_info.object_repr_id = SemIR::TypeId::Error;
|
||||
if (class_info.base_id.is_valid()) {
|
||||
CARBON_DIAGNOSTIC(AdaptWithBase, Error,
|
||||
"Adapter cannot have a base class.");
|
||||
CARBON_DIAGNOSTIC(AdaptBaseHere, Note, "`base` declaration is here.");
|
||||
context.emitter()
|
||||
.Build(class_info.adapt_id, AdaptWithBase)
|
||||
.Note(class_info.base_id, AdaptBaseHere)
|
||||
.Emit();
|
||||
} else if (!context.inst_blocks().Get(fields_id).empty()) {
|
||||
auto first_field_id = context.inst_blocks().Get(fields_id).front();
|
||||
CARBON_DIAGNOSTIC(AdaptWithFields, Error, "Adapter cannot have fields.");
|
||||
CARBON_DIAGNOSTIC(AdaptFieldHere, Note,
|
||||
"First field declaration is here.");
|
||||
context.emitter()
|
||||
.Build(class_info.adapt_id, AdaptWithFields)
|
||||
.Note(first_field_id, AdaptFieldHere)
|
||||
.Emit();
|
||||
} else {
|
||||
// The object representation of the adapter is the adapted type.
|
||||
// TODO: If the adapted type is a class, should we use its object
|
||||
// representation type instead?
|
||||
class_info.object_repr_id =
|
||||
context.insts()
|
||||
.GetAs<SemIR::AdaptDecl>(class_info.adapt_id)
|
||||
.adapted_type_id;
|
||||
}
|
||||
} else {
|
||||
class_info.object_repr_id = context.GetStructType(fields_id);
|
||||
}
|
||||
|
||||
// The decl_name_stack and scopes are popped by `ProcessNodeIds`.
|
||||
return true;
|
||||
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// AUTOUPDATE
|
||||
|
||||
// --- basic.carbon
|
||||
|
||||
library "basic" api;
|
||||
|
||||
class SomeClass {
|
||||
var a: i32;
|
||||
var b: i32;
|
||||
}
|
||||
|
||||
class SomeClassAdapter {
|
||||
adapt SomeClass;
|
||||
}
|
||||
|
||||
class StructAdapter {
|
||||
adapt {.a: i32, .b: i32};
|
||||
}
|
||||
|
||||
// --- fail_not_extend.carbon
|
||||
|
||||
library "fail_not_extend" api;
|
||||
|
||||
class Adapted {
|
||||
fn F();
|
||||
}
|
||||
|
||||
class AdaptNotExtend {
|
||||
adapt Adapted;
|
||||
}
|
||||
|
||||
fn F(a: AdaptNotExtend) {
|
||||
// `Adapted` is not extended, so lookup for `F` finds nothing.
|
||||
// CHECK:STDERR: fail_not_extend.carbon:[[@LINE+3]]:3: ERROR: Name `F` not found.
|
||||
// CHECK:STDERR: a.F();
|
||||
// CHECK:STDERR: ^~~
|
||||
a.F();
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: --- basic.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %SomeClass: type = class_type @SomeClass [template]
|
||||
// CHECK:STDOUT: %.1: type = unbound_element_type SomeClass, i32 [template]
|
||||
// CHECK:STDOUT: %.2: type = struct_type {.a: i32, .b: i32} [template]
|
||||
// CHECK:STDOUT: %SomeClassAdapter: type = class_type @SomeClassAdapter [template]
|
||||
// CHECK:STDOUT: %.3: type = ptr_type {.a: i32, .b: i32} [template]
|
||||
// CHECK:STDOUT: %StructAdapter: type = class_type @StructAdapter [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .SomeClass = %SomeClass.decl
|
||||
// CHECK:STDOUT: .SomeClassAdapter = %SomeClassAdapter.decl
|
||||
// CHECK:STDOUT: .StructAdapter = %StructAdapter.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %SomeClass.decl: type = class_decl @SomeClass [template = constants.%SomeClass] {}
|
||||
// CHECK:STDOUT: %SomeClassAdapter.decl: type = class_decl @SomeClassAdapter [template = constants.%SomeClassAdapter] {}
|
||||
// CHECK:STDOUT: %StructAdapter.decl: type = class_decl @StructAdapter [template = constants.%StructAdapter] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @SomeClass {
|
||||
// CHECK:STDOUT: %.loc5: <unbound element of class SomeClass> = field_decl a, element0 [template]
|
||||
// CHECK:STDOUT: %.loc6: <unbound element of class SomeClass> = field_decl b, element1 [template]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%SomeClass
|
||||
// CHECK:STDOUT: .a = %.loc5
|
||||
// CHECK:STDOUT: .b = %.loc6
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @SomeClassAdapter {
|
||||
// CHECK:STDOUT: %SomeClass.ref: type = name_ref SomeClass, file.%SomeClass.decl [template = constants.%SomeClass]
|
||||
// CHECK:STDOUT: adapt_decl SomeClass
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%SomeClassAdapter
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @StructAdapter {
|
||||
// CHECK:STDOUT: %.loc14: type = struct_type {.a: i32, .b: i32} [template = constants.%.2]
|
||||
// CHECK:STDOUT: adapt_decl {.a: i32, .b: i32}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%StructAdapter
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_not_extend.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %Adapted: type = class_type @Adapted [template]
|
||||
// CHECK:STDOUT: %.1: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %AdaptNotExtend: type = class_type @AdaptNotExtend [template]
|
||||
// CHECK:STDOUT: %.2: type = tuple_type () [template]
|
||||
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
|
||||
// CHECK:STDOUT: %.4: type = ptr_type Adapted [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .Adapted = %Adapted.decl
|
||||
// CHECK:STDOUT: .AdaptNotExtend = %AdaptNotExtend.decl
|
||||
// CHECK:STDOUT: .F = %F
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %Adapted.decl: type = class_decl @Adapted [template = constants.%Adapted] {}
|
||||
// CHECK:STDOUT: %AdaptNotExtend.decl: type = class_decl @AdaptNotExtend [template = constants.%AdaptNotExtend] {}
|
||||
// CHECK:STDOUT: %F: <function> = fn_decl @F.2 [template] {
|
||||
// CHECK:STDOUT: %AdaptNotExtend.ref: type = name_ref AdaptNotExtend, %AdaptNotExtend.decl [template = constants.%AdaptNotExtend]
|
||||
// CHECK:STDOUT: %a.loc12_6.1: AdaptNotExtend = param a
|
||||
// CHECK:STDOUT: @F.2.%a: AdaptNotExtend = bind_name a, %a.loc12_6.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @Adapted {
|
||||
// CHECK:STDOUT: %F: <function> = fn_decl @F.1 [template] {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%Adapted
|
||||
// CHECK:STDOUT: .F = %F
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @AdaptNotExtend {
|
||||
// CHECK:STDOUT: %Adapted.ref: type = name_ref Adapted, file.%Adapted.decl [template = constants.%Adapted]
|
||||
// CHECK:STDOUT: adapt_decl Adapted
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%AdaptNotExtend
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.1();
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.2(%a: AdaptNotExtend) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %a.ref: AdaptNotExtend = name_ref a, %a
|
||||
// CHECK:STDOUT: %F.ref: <error> = name_ref F, <error> [template = <error>]
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
+314
@@ -0,0 +1,314 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// AUTOUPDATE
|
||||
|
||||
// --- basic.carbon
|
||||
|
||||
library "basic" api;
|
||||
|
||||
class SomeClassAdapter;
|
||||
|
||||
class SomeClass {
|
||||
var a: i32;
|
||||
var b: i32;
|
||||
|
||||
fn StaticMemberFunction();
|
||||
|
||||
fn AdapterMethod[self: SomeClassAdapter]();
|
||||
}
|
||||
|
||||
class SomeClassAdapter {
|
||||
extend adapt SomeClass;
|
||||
}
|
||||
|
||||
fn TestStaticMemberFunction(a: SomeClassAdapter) {
|
||||
a.StaticMemberFunction();
|
||||
}
|
||||
|
||||
fn TestAdapterMethod(a: SomeClassAdapter) {
|
||||
a.AdapterMethod();
|
||||
}
|
||||
|
||||
// --- fail_todo_method_access.carbon
|
||||
|
||||
library "fail_todo_method_access" api;
|
||||
|
||||
class SomeClass {
|
||||
fn F[self: Self]();
|
||||
}
|
||||
|
||||
class SomeClassAdapter {
|
||||
extend adapt SomeClass;
|
||||
}
|
||||
|
||||
fn F(a: SomeClassAdapter) {
|
||||
// CHECK:STDERR: fail_todo_method_access.carbon:[[@LINE+7]]:3: ERROR: Cannot implicitly convert from `SomeClassAdapter` to `SomeClass`.
|
||||
// CHECK:STDERR: a.F();
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_todo_method_access.carbon:[[@LINE-11]]:8: Initializing `self` parameter of method declared here.
|
||||
// CHECK:STDERR: fn F[self: Self]();
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR:
|
||||
a.F();
|
||||
}
|
||||
|
||||
// --- fail_todo_field_access.carbon
|
||||
|
||||
library "fail_todo_field_access" api;
|
||||
|
||||
class SomeClass {
|
||||
var a: i32;
|
||||
var b: i32;
|
||||
}
|
||||
|
||||
class SomeClassAdapter {
|
||||
extend adapt SomeClass;
|
||||
}
|
||||
|
||||
fn F(a: SomeClassAdapter) -> i32 {
|
||||
// CHECK:STDERR: fail_todo_field_access.carbon:[[@LINE+4]]:10: ERROR: Cannot implicitly convert from `SomeClassAdapter` to `SomeClass`.
|
||||
// CHECK:STDERR: return a.b;
|
||||
// CHECK:STDERR: ^~~
|
||||
// CHECK:STDERR:
|
||||
return a.b;
|
||||
}
|
||||
|
||||
// --- fail_todo_adapt_non_class.carbon
|
||||
|
||||
library "fail_todo_adapt_non_class" api;
|
||||
|
||||
class StructAdapter {
|
||||
// CHECK:STDERR: fail_todo_adapt_non_class.carbon:[[@LINE+3]]:3: ERROR: Semantics TODO: `extending non-class type`.
|
||||
// CHECK:STDERR: extend adapt {.a: i32, .b: i32};
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
extend adapt {.a: i32, .b: i32};
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: --- basic.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %SomeClassAdapter: type = class_type @SomeClassAdapter [template]
|
||||
// CHECK:STDOUT: %SomeClass: type = class_type @SomeClass [template]
|
||||
// CHECK:STDOUT: %.1: type = unbound_element_type SomeClass, i32 [template]
|
||||
// CHECK:STDOUT: %.2: type = struct_type {.a: i32, .b: i32} [template]
|
||||
// CHECK:STDOUT: %.3: type = ptr_type {.a: i32, .b: i32} [template]
|
||||
// CHECK:STDOUT: %.4: type = ptr_type SomeClass [template]
|
||||
// CHECK:STDOUT: %.5: type = tuple_type () [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .SomeClassAdapter = %SomeClassAdapter.decl.loc4
|
||||
// CHECK:STDOUT: .SomeClass = %SomeClass.decl
|
||||
// CHECK:STDOUT: .TestStaticMemberFunction = %TestStaticMemberFunction
|
||||
// CHECK:STDOUT: .TestAdapterMethod = %TestAdapterMethod
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %SomeClassAdapter.decl.loc4: type = class_decl @SomeClassAdapter [template = constants.%SomeClassAdapter] {}
|
||||
// CHECK:STDOUT: %SomeClass.decl: type = class_decl @SomeClass [template = constants.%SomeClass] {}
|
||||
// CHECK:STDOUT: %SomeClassAdapter.decl.loc15: type = class_decl @SomeClassAdapter [template = constants.%SomeClassAdapter] {}
|
||||
// CHECK:STDOUT: %TestStaticMemberFunction: <function> = fn_decl @TestStaticMemberFunction [template] {
|
||||
// CHECK:STDOUT: %SomeClassAdapter.ref.loc19: type = name_ref SomeClassAdapter, %SomeClassAdapter.decl.loc4 [template = constants.%SomeClassAdapter]
|
||||
// CHECK:STDOUT: %a.loc19_29.1: SomeClassAdapter = param a
|
||||
// CHECK:STDOUT: @TestStaticMemberFunction.%a: SomeClassAdapter = bind_name a, %a.loc19_29.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %TestAdapterMethod: <function> = fn_decl @TestAdapterMethod [template] {
|
||||
// CHECK:STDOUT: %SomeClassAdapter.ref.loc23: type = name_ref SomeClassAdapter, %SomeClassAdapter.decl.loc4 [template = constants.%SomeClassAdapter]
|
||||
// CHECK:STDOUT: %a.loc23_22.1: SomeClassAdapter = param a
|
||||
// CHECK:STDOUT: @TestAdapterMethod.%a: SomeClassAdapter = bind_name a, %a.loc23_22.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @SomeClassAdapter {
|
||||
// CHECK:STDOUT: %SomeClass.ref: type = name_ref SomeClass, file.%SomeClass.decl [template = constants.%SomeClass]
|
||||
// CHECK:STDOUT: adapt_decl SomeClass
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%SomeClassAdapter
|
||||
// CHECK:STDOUT: extend name_scope2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @SomeClass {
|
||||
// CHECK:STDOUT: %.loc7: <unbound element of class SomeClass> = field_decl a, element0 [template]
|
||||
// CHECK:STDOUT: %.loc8: <unbound element of class SomeClass> = field_decl b, element1 [template]
|
||||
// CHECK:STDOUT: %StaticMemberFunction: <function> = fn_decl @StaticMemberFunction [template] {}
|
||||
// CHECK:STDOUT: %AdapterMethod: <function> = fn_decl @AdapterMethod [template] {
|
||||
// CHECK:STDOUT: %SomeClassAdapter.ref: type = name_ref SomeClassAdapter, file.%SomeClassAdapter.decl.loc4 [template = constants.%SomeClassAdapter]
|
||||
// CHECK:STDOUT: %self.loc12_20.1: SomeClassAdapter = param self
|
||||
// CHECK:STDOUT: %self.loc12_20.2: SomeClassAdapter = bind_name self, %self.loc12_20.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%SomeClass
|
||||
// CHECK:STDOUT: .a = %.loc7
|
||||
// CHECK:STDOUT: .b = %.loc8
|
||||
// CHECK:STDOUT: .StaticMemberFunction = %StaticMemberFunction
|
||||
// CHECK:STDOUT: .AdapterMethod = %AdapterMethod
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @StaticMemberFunction();
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @AdapterMethod[@SomeClass.%self.loc12_20.2: SomeClassAdapter]();
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @TestStaticMemberFunction(%a: SomeClassAdapter) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %a.ref: SomeClassAdapter = name_ref a, %a
|
||||
// CHECK:STDOUT: %StaticMemberFunction.ref: <function> = name_ref StaticMemberFunction, @SomeClass.%StaticMemberFunction [template = @SomeClass.%StaticMemberFunction]
|
||||
// CHECK:STDOUT: %.loc20: init () = call %StaticMemberFunction.ref()
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @TestAdapterMethod(%a: SomeClassAdapter) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %a.ref: SomeClassAdapter = name_ref a, %a
|
||||
// CHECK:STDOUT: %AdapterMethod.ref: <function> = name_ref AdapterMethod, @SomeClass.%AdapterMethod [template = @SomeClass.%AdapterMethod]
|
||||
// CHECK:STDOUT: %.loc24_4: <bound method> = bound_method %a.ref, %AdapterMethod.ref
|
||||
// CHECK:STDOUT: %.loc24_18: init () = call %.loc24_4(%a.ref)
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_method_access.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %SomeClass: type = class_type @SomeClass [template]
|
||||
// CHECK:STDOUT: %.1: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %SomeClassAdapter: type = class_type @SomeClassAdapter [template]
|
||||
// CHECK:STDOUT: %.2: type = tuple_type () [template]
|
||||
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
|
||||
// CHECK:STDOUT: %.4: type = ptr_type SomeClass [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .SomeClass = %SomeClass.decl
|
||||
// CHECK:STDOUT: .SomeClassAdapter = %SomeClassAdapter.decl
|
||||
// CHECK:STDOUT: .F = %F
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %SomeClass.decl: type = class_decl @SomeClass [template = constants.%SomeClass] {}
|
||||
// CHECK:STDOUT: %SomeClassAdapter.decl: type = class_decl @SomeClassAdapter [template = constants.%SomeClassAdapter] {}
|
||||
// CHECK:STDOUT: %F: <function> = fn_decl @F.2 [template] {
|
||||
// CHECK:STDOUT: %SomeClassAdapter.ref: type = name_ref SomeClassAdapter, %SomeClassAdapter.decl [template = constants.%SomeClassAdapter]
|
||||
// CHECK:STDOUT: %a.loc12_6.1: SomeClassAdapter = param a
|
||||
// CHECK:STDOUT: @F.2.%a: SomeClassAdapter = bind_name a, %a.loc12_6.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @SomeClass {
|
||||
// CHECK:STDOUT: %F: <function> = fn_decl @F.1 [template] {
|
||||
// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%SomeClass [template = constants.%SomeClass]
|
||||
// CHECK:STDOUT: %self.loc5_8.1: SomeClass = param self
|
||||
// CHECK:STDOUT: %self.loc5_8.2: SomeClass = bind_name self, %self.loc5_8.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%SomeClass
|
||||
// CHECK:STDOUT: .F = %F
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @SomeClassAdapter {
|
||||
// CHECK:STDOUT: %SomeClass.ref: type = name_ref SomeClass, file.%SomeClass.decl [template = constants.%SomeClass]
|
||||
// CHECK:STDOUT: adapt_decl SomeClass
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%SomeClassAdapter
|
||||
// CHECK:STDOUT: extend name_scope2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.1[@SomeClass.%self.loc5_8.2: SomeClass]();
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.2(%a: SomeClassAdapter) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %a.ref: SomeClassAdapter = name_ref a, %a
|
||||
// CHECK:STDOUT: %F.ref: <function> = name_ref F, @SomeClass.%F [template = @SomeClass.%F]
|
||||
// CHECK:STDOUT: %.loc20_4: <bound method> = bound_method %a.ref, %F.ref
|
||||
// CHECK:STDOUT: %.loc20_6: init () = call %.loc20_4(<invalid>) [template = <error>]
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_field_access.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %SomeClass: type = class_type @SomeClass [template]
|
||||
// CHECK:STDOUT: %.1: type = unbound_element_type SomeClass, i32 [template]
|
||||
// CHECK:STDOUT: %.2: type = struct_type {.a: i32, .b: i32} [template]
|
||||
// CHECK:STDOUT: %SomeClassAdapter: type = class_type @SomeClassAdapter [template]
|
||||
// CHECK:STDOUT: %.3: type = ptr_type {.a: i32, .b: i32} [template]
|
||||
// CHECK:STDOUT: %.4: type = ptr_type SomeClass [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .SomeClass = %SomeClass.decl
|
||||
// CHECK:STDOUT: .SomeClassAdapter = %SomeClassAdapter.decl
|
||||
// CHECK:STDOUT: .F = %F
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %SomeClass.decl: type = class_decl @SomeClass [template = constants.%SomeClass] {}
|
||||
// CHECK:STDOUT: %SomeClassAdapter.decl: type = class_decl @SomeClassAdapter [template = constants.%SomeClassAdapter] {}
|
||||
// CHECK:STDOUT: %F: <function> = fn_decl @F [template] {
|
||||
// CHECK:STDOUT: %SomeClassAdapter.ref: type = name_ref SomeClassAdapter, %SomeClassAdapter.decl [template = constants.%SomeClassAdapter]
|
||||
// CHECK:STDOUT: %a.loc13_6.1: SomeClassAdapter = param a
|
||||
// CHECK:STDOUT: @F.%a: SomeClassAdapter = bind_name a, %a.loc13_6.1
|
||||
// CHECK:STDOUT: %return.var: ref i32 = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @SomeClass {
|
||||
// CHECK:STDOUT: %.loc5: <unbound element of class SomeClass> = field_decl a, element0 [template]
|
||||
// CHECK:STDOUT: %.loc6: <unbound element of class SomeClass> = field_decl b, element1 [template]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%SomeClass
|
||||
// CHECK:STDOUT: .a = %.loc5
|
||||
// CHECK:STDOUT: .b = %.loc6
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @SomeClassAdapter {
|
||||
// CHECK:STDOUT: %SomeClass.ref: type = name_ref SomeClass, file.%SomeClass.decl [template = constants.%SomeClass]
|
||||
// CHECK:STDOUT: adapt_decl SomeClass
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%SomeClassAdapter
|
||||
// CHECK:STDOUT: extend name_scope2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F(%a: SomeClassAdapter) -> i32 {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %a.ref: SomeClassAdapter = name_ref a, %a
|
||||
// CHECK:STDOUT: %b.ref: <unbound element of class SomeClass> = name_ref b, @SomeClass.%.loc6 [template = @SomeClass.%.loc6]
|
||||
// CHECK:STDOUT: %.loc18: i32 = class_element_access <error>, element1 [template = <error>]
|
||||
// CHECK:STDOUT: return <error>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_adapt_non_class.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %StructAdapter: type = class_type @StructAdapter [template]
|
||||
// CHECK:STDOUT: %.1: type = struct_type {.a: i32, .b: i32} [template]
|
||||
// CHECK:STDOUT: %.2: type = ptr_type {.a: i32, .b: i32} [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .StructAdapter = %StructAdapter.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %StructAdapter.decl: type = class_decl @StructAdapter [template = constants.%StructAdapter] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @StructAdapter {
|
||||
// CHECK:STDOUT: %.loc8: type = struct_type {.a: i32, .b: i32} [template = constants.%.1]
|
||||
// CHECK:STDOUT: adapt_decl {.a: i32, .b: i32}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%StructAdapter
|
||||
// CHECK:STDOUT: has_error
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -0,0 +1,256 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// AUTOUPDATE
|
||||
|
||||
// --- fail_not_type.carbon
|
||||
|
||||
library "not_type" api;
|
||||
|
||||
class Bad {
|
||||
// CHECK:STDERR: fail_not_type.carbon:[[@LINE+4]]:3: ERROR: Cannot implicitly convert from `i32` to `type`.
|
||||
// CHECK:STDERR: adapt 100;
|
||||
// CHECK:STDERR: ^~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
adapt 100;
|
||||
}
|
||||
|
||||
// CHECK:STDERR: fail_not_type.carbon:[[@LINE+4]]:18: ERROR: Name `F` not found.
|
||||
// CHECK:STDERR: fn Use(b: Bad) { b.F(); }
|
||||
// CHECK:STDERR: ^~~
|
||||
// CHECK:STDERR:
|
||||
fn Use(b: Bad) { b.F(); }
|
||||
|
||||
// --- fail_extend_not_type.carbon
|
||||
|
||||
library "extend_not_type" api;
|
||||
|
||||
class Bad {
|
||||
// CHECK:STDERR: fail_extend_not_type.carbon:[[@LINE+4]]:3: ERROR: Cannot implicitly convert from `i32` to `type`.
|
||||
// CHECK:STDERR: extend adapt 100;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
extend adapt 100;
|
||||
}
|
||||
|
||||
// No diagnostic here, we don't know what names Bad has.
|
||||
fn Use(b: Bad) { b.F(); }
|
||||
|
||||
// --- fail_repeated.carbon
|
||||
|
||||
library "fail_repeated" api;
|
||||
|
||||
class MultipleAdapts {
|
||||
adapt ();
|
||||
// CHECK:STDERR: fail_repeated.carbon:[[@LINE+7]]:3: ERROR: Multiple `adapt` declarations in class.
|
||||
// CHECK:STDERR: adapt {};
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
// CHECK:STDERR: fail_repeated.carbon:[[@LINE-4]]:3: Previous `adapt` declaration is here.
|
||||
// CHECK:STDERR: adapt ();
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
adapt {};
|
||||
}
|
||||
|
||||
class MultipleAdaptsSameType {
|
||||
adapt ();
|
||||
// CHECK:STDERR: fail_repeated.carbon:[[@LINE+7]]:3: ERROR: Multiple `adapt` declarations in class.
|
||||
// CHECK:STDERR: adapt ();
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
// CHECK:STDERR: fail_repeated.carbon:[[@LINE-4]]:3: Previous `adapt` declaration is here.
|
||||
// CHECK:STDERR: adapt ();
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
adapt ();
|
||||
}
|
||||
|
||||
// --- fail_bad_scope.carbon
|
||||
|
||||
library "fail_bad_scope" api;
|
||||
|
||||
// CHECK:STDERR: fail_bad_scope.carbon:[[@LINE+4]]:1: ERROR: `adapt` declaration can only be used in a class.
|
||||
// CHECK:STDERR: adapt {};
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
adapt {};
|
||||
|
||||
interface I {
|
||||
// CHECK:STDERR: fail_bad_scope.carbon:[[@LINE+4]]:3: ERROR: `adapt` declaration can only be used in a class.
|
||||
// CHECK:STDERR: adapt {};
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
adapt {};
|
||||
}
|
||||
|
||||
class C {
|
||||
interface I {
|
||||
// CHECK:STDERR: fail_bad_scope.carbon:[[@LINE+3]]:5: ERROR: `adapt` declaration can only be used in a class.
|
||||
// CHECK:STDERR: adapt {};
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
adapt {};
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: --- fail_not_type.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %Bad: type = class_type @Bad [template]
|
||||
// CHECK:STDOUT: %.1: i32 = int_literal 100 [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .Bad = %Bad.decl
|
||||
// CHECK:STDOUT: .Use = %Use
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %Bad.decl: type = class_decl @Bad [template = constants.%Bad] {}
|
||||
// CHECK:STDOUT: %Use: <function> = fn_decl @Use [template] {
|
||||
// CHECK:STDOUT: %Bad.ref: type = name_ref Bad, %Bad.decl [template = constants.%Bad]
|
||||
// CHECK:STDOUT: %b.loc16_8.1: Bad = param b
|
||||
// CHECK:STDOUT: @Use.%b: Bad = bind_name b, %b.loc16_8.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @Bad {
|
||||
// CHECK:STDOUT: %.loc9: i32 = int_literal 100 [template = constants.%.1]
|
||||
// CHECK:STDOUT: adapt_decl <error>
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%Bad
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Use(%b: Bad) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %b.ref: Bad = name_ref b, %b
|
||||
// CHECK:STDOUT: %F.ref: <error> = name_ref F, <error> [template = <error>]
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_extend_not_type.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %Bad: type = class_type @Bad [template]
|
||||
// CHECK:STDOUT: %.1: i32 = int_literal 100 [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .Bad = %Bad.decl
|
||||
// CHECK:STDOUT: .Use = %Use
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %Bad.decl: type = class_decl @Bad [template = constants.%Bad] {}
|
||||
// CHECK:STDOUT: %Use: <function> = fn_decl @Use [template] {
|
||||
// CHECK:STDOUT: %Bad.ref: type = name_ref Bad, %Bad.decl [template = constants.%Bad]
|
||||
// CHECK:STDOUT: %b.loc13_8.1: Bad = param b
|
||||
// CHECK:STDOUT: @Use.%b: Bad = bind_name b, %b.loc13_8.1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @Bad {
|
||||
// CHECK:STDOUT: %.loc9: i32 = int_literal 100 [template = constants.%.1]
|
||||
// CHECK:STDOUT: adapt_decl <error>
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%Bad
|
||||
// CHECK:STDOUT: has_error
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Use(%b: Bad) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %b.ref: Bad = name_ref b, %b
|
||||
// CHECK:STDOUT: %F.ref: <error> = name_ref F, <error> [template = <error>]
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_repeated.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %MultipleAdapts: type = class_type @MultipleAdapts [template]
|
||||
// CHECK:STDOUT: %.1: type = tuple_type () [template]
|
||||
// CHECK:STDOUT: %.2: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %MultipleAdaptsSameType: type = class_type @MultipleAdaptsSameType [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .MultipleAdapts = %MultipleAdapts.decl
|
||||
// CHECK:STDOUT: .MultipleAdaptsSameType = %MultipleAdaptsSameType.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %MultipleAdapts.decl: type = class_decl @MultipleAdapts [template = constants.%MultipleAdapts] {}
|
||||
// CHECK:STDOUT: %MultipleAdaptsSameType.decl: type = class_decl @MultipleAdaptsSameType [template = constants.%MultipleAdaptsSameType] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @MultipleAdapts {
|
||||
// CHECK:STDOUT: %.loc5_10.1: () = tuple_literal ()
|
||||
// CHECK:STDOUT: %.loc5_10.2: type = converted %.loc5_10.1, constants.%.1 [template = constants.%.1]
|
||||
// CHECK:STDOUT: adapt_decl ()
|
||||
// CHECK:STDOUT: %.loc13: {} = struct_literal ()
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%MultipleAdapts
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @MultipleAdaptsSameType {
|
||||
// CHECK:STDOUT: %.loc17_10.1: () = tuple_literal ()
|
||||
// CHECK:STDOUT: %.loc17_10.2: type = converted %.loc17_10.1, constants.%.1 [template = constants.%.1]
|
||||
// CHECK:STDOUT: adapt_decl ()
|
||||
// CHECK:STDOUT: %.loc25: () = tuple_literal ()
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%MultipleAdaptsSameType
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_bad_scope.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %.1: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %.2: type = interface_type @I.1 [template]
|
||||
// CHECK:STDOUT: %C: type = class_type @C [template]
|
||||
// CHECK:STDOUT: %.3: type = interface_type @I.2 [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .I = %I.decl
|
||||
// CHECK:STDOUT: .C = %C.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %.loc8: {} = struct_literal ()
|
||||
// CHECK:STDOUT: %I.decl: type = interface_decl @I.1 [template = constants.%.2] {}
|
||||
// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: interface @I.1 {
|
||||
// CHECK:STDOUT: %Self: I = bind_symbolic_name Self [symbolic]
|
||||
// CHECK:STDOUT: %.loc15: {} = struct_literal ()
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = %Self
|
||||
// CHECK:STDOUT: witness = ()
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: interface @I.2 {
|
||||
// CHECK:STDOUT: %Self: I = bind_symbolic_name Self [symbolic]
|
||||
// CHECK:STDOUT: %.loc23: {} = struct_literal ()
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = %Self
|
||||
// CHECK:STDOUT: witness = ()
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C {
|
||||
// CHECK:STDOUT: %I.decl: type = interface_decl @I.2 [template = constants.%.3] {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%C
|
||||
// CHECK:STDOUT: .I = %I.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -0,0 +1,50 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// AUTOUPDATE
|
||||
|
||||
// --- fail_incomplete_type.carbon
|
||||
|
||||
library "incomplete_type" api;
|
||||
|
||||
class Incomplete;
|
||||
|
||||
class AdaptIncomplete {
|
||||
// CHECK:STDERR: fail_incomplete_type.carbon:[[@LINE+6]]:3: ERROR: Adapted type `Incomplete` is an incomplete type.
|
||||
// CHECK:STDERR: adapt Incomplete;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_incomplete_type.carbon:[[@LINE-6]]:1: Class was forward declared here.
|
||||
// CHECK:STDERR: class Incomplete;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
|
||||
adapt Incomplete;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: --- fail_incomplete_type.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %Incomplete: type = class_type @Incomplete [template]
|
||||
// CHECK:STDOUT: %AdaptIncomplete: type = class_type @AdaptIncomplete [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .Incomplete = %Incomplete.decl
|
||||
// CHECK:STDOUT: .AdaptIncomplete = %AdaptIncomplete.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %Incomplete.decl: type = class_decl @Incomplete [template = constants.%Incomplete] {}
|
||||
// CHECK:STDOUT: %AdaptIncomplete.decl: type = class_decl @AdaptIncomplete [template = constants.%AdaptIncomplete] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @Incomplete;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @AdaptIncomplete {
|
||||
// CHECK:STDOUT: %Incomplete.ref: type = name_ref Incomplete, file.%Incomplete.decl [template = constants.%Incomplete]
|
||||
// CHECK:STDOUT: adapt_decl <error>
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%AdaptIncomplete
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -0,0 +1,133 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// AUTOUPDATE
|
||||
|
||||
class B {}
|
||||
|
||||
class C1 {
|
||||
// CHECK:STDERR: fail_adapt_modifiers.carbon:[[@LINE+4]]:3: ERROR: `private` not allowed on `adapt` declaration.
|
||||
// CHECK:STDERR: private adapt B;
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
private adapt B;
|
||||
}
|
||||
|
||||
class C2 {
|
||||
// CHECK:STDERR: fail_adapt_modifiers.carbon:[[@LINE+4]]:3: ERROR: `abstract` not allowed on `adapt` declaration.
|
||||
// CHECK:STDERR: abstract adapt B;
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
abstract adapt B;
|
||||
}
|
||||
|
||||
class C3 {
|
||||
// CHECK:STDERR: fail_adapt_modifiers.carbon:[[@LINE+4]]:3: ERROR: `default` not allowed on `adapt` declaration.
|
||||
// CHECK:STDERR: default adapt B;
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
default adapt B;
|
||||
}
|
||||
|
||||
class C4 {
|
||||
// CHECK:STDERR: fail_adapt_modifiers.carbon:[[@LINE+7]]:10: ERROR: `extend` repeated on declaration.
|
||||
// CHECK:STDERR: extend extend adapt B;
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR: fail_adapt_modifiers.carbon:[[@LINE+4]]:3: `extend` previously appeared here.
|
||||
// CHECK:STDERR: extend extend adapt B;
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR:
|
||||
extend extend adapt B;
|
||||
}
|
||||
|
||||
class C5 {
|
||||
// CHECK:STDERR: fail_adapt_modifiers.carbon:[[@LINE+6]]:10: ERROR: `base` not allowed on declaration with `extend`.
|
||||
// CHECK:STDERR: extend base adapt B;
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_adapt_modifiers.carbon:[[@LINE+3]]:3: `extend` previously appeared here.
|
||||
// CHECK:STDERR: extend base adapt B;
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
extend base adapt B;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: --- fail_adapt_modifiers.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %B: type = class_type @B [template]
|
||||
// CHECK:STDOUT: %.1: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %C1: type = class_type @C1 [template]
|
||||
// CHECK:STDOUT: %.2: type = tuple_type () [template]
|
||||
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
|
||||
// CHECK:STDOUT: %C2: type = class_type @C2 [template]
|
||||
// CHECK:STDOUT: %C3: type = class_type @C3 [template]
|
||||
// CHECK:STDOUT: %C4: type = class_type @C4 [template]
|
||||
// CHECK:STDOUT: %C5: type = class_type @C5 [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .B = %B.decl
|
||||
// CHECK:STDOUT: .C1 = %C1.decl
|
||||
// CHECK:STDOUT: .C2 = %C2.decl
|
||||
// CHECK:STDOUT: .C3 = %C3.decl
|
||||
// CHECK:STDOUT: .C4 = %C4.decl
|
||||
// CHECK:STDOUT: .C5 = %C5.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %B.decl: type = class_decl @B [template = constants.%B] {}
|
||||
// CHECK:STDOUT: %C1.decl: type = class_decl @C1 [template = constants.%C1] {}
|
||||
// CHECK:STDOUT: %C2.decl: type = class_decl @C2 [template = constants.%C2] {}
|
||||
// CHECK:STDOUT: %C3.decl: type = class_decl @C3 [template = constants.%C3] {}
|
||||
// CHECK:STDOUT: %C4.decl: type = class_decl @C4 [template = constants.%C4] {}
|
||||
// CHECK:STDOUT: %C5.decl: type = class_decl @C5 [template = constants.%C5] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @B {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%B
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C1 {
|
||||
// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [template = constants.%B]
|
||||
// CHECK:STDOUT: adapt_decl B
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%C1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C2 {
|
||||
// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [template = constants.%B]
|
||||
// CHECK:STDOUT: adapt_decl B
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%C2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C3 {
|
||||
// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [template = constants.%B]
|
||||
// CHECK:STDOUT: adapt_decl B
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%C3
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C4 {
|
||||
// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [template = constants.%B]
|
||||
// CHECK:STDOUT: adapt_decl B
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%C4
|
||||
// CHECK:STDOUT: extend name_scope2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C5 {
|
||||
// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [template = constants.%B]
|
||||
// CHECK:STDOUT: adapt_decl B
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%C5
|
||||
// CHECK:STDOUT: extend name_scope2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -0,0 +1,195 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// AUTOUPDATE
|
||||
|
||||
// --- fail_adapt_with_base.carbon
|
||||
|
||||
library "fail_adapt_with_base" api;
|
||||
|
||||
base class Base {}
|
||||
|
||||
class AdaptWithBase {
|
||||
// CHECK:STDERR: fail_adapt_with_base.carbon:[[@LINE+3]]:3: ERROR: Adapter cannot have a base class.
|
||||
// CHECK:STDERR: adapt i32;
|
||||
// CHECK:STDERR: ^~~~~~~~~~
|
||||
adapt i32;
|
||||
// CHECK:STDERR: fail_adapt_with_base.carbon:[[@LINE+4]]:3: `base` declaration is here.
|
||||
// CHECK:STDERR: extend base: Base;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
extend base: Base;
|
||||
}
|
||||
|
||||
// --- fail_adapt_with_fields.carbon
|
||||
|
||||
library "fail_adapt_with_fields" api;
|
||||
|
||||
class AdaptWithField {
|
||||
// CHECK:STDERR: fail_adapt_with_fields.carbon:[[@LINE+3]]:3: ERROR: Adapter cannot have fields.
|
||||
// CHECK:STDERR: adapt i32;
|
||||
// CHECK:STDERR: ^~~~~~~~~~
|
||||
adapt i32;
|
||||
// CHECK:STDERR: fail_adapt_with_fields.carbon:[[@LINE+4]]:7: First field declaration is here.
|
||||
// CHECK:STDERR: var n: i32;
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR:
|
||||
var n: i32;
|
||||
}
|
||||
|
||||
class AdaptWithFields {
|
||||
// CHECK:STDERR: fail_adapt_with_fields.carbon:[[@LINE+3]]:3: ERROR: Adapter cannot have fields.
|
||||
// CHECK:STDERR: adapt i32;
|
||||
// CHECK:STDERR: ^~~~~~~~~~
|
||||
adapt i32;
|
||||
// CHECK:STDERR: fail_adapt_with_fields.carbon:[[@LINE+4]]:7: First field declaration is here.
|
||||
// CHECK:STDERR: var a: i32;
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR:
|
||||
var a: i32;
|
||||
var b: i32;
|
||||
var c: i32;
|
||||
}
|
||||
|
||||
// --- fail_adapt_with_base_and_fields.carbon
|
||||
|
||||
library "fail_adapt_with_base_and_fields" api;
|
||||
|
||||
base class Base {}
|
||||
|
||||
class AdaptWithBaseAndFields {
|
||||
extend base: Base;
|
||||
var n: i32;
|
||||
// CHECK:STDERR: fail_adapt_with_base_and_fields.carbon:[[@LINE+6]]:3: ERROR: Adapter cannot have a base class.
|
||||
// CHECK:STDERR: adapt {};
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
// CHECK:STDERR: fail_adapt_with_base_and_fields.carbon:[[@LINE-5]]:3: `base` declaration is here.
|
||||
// CHECK:STDERR: extend base: Base;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~
|
||||
adapt {};
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: --- fail_adapt_with_base.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %Base: type = class_type @Base [template]
|
||||
// CHECK:STDOUT: %.1: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %AdaptWithBase: type = class_type @AdaptWithBase [template]
|
||||
// CHECK:STDOUT: %.2: type = tuple_type () [template]
|
||||
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
|
||||
// CHECK:STDOUT: %.4: type = unbound_element_type AdaptWithBase, Base [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .Base = %Base.decl
|
||||
// CHECK:STDOUT: .AdaptWithBase = %AdaptWithBase.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %Base.decl: type = class_decl @Base [template = constants.%Base] {}
|
||||
// CHECK:STDOUT: %AdaptWithBase.decl: type = class_decl @AdaptWithBase [template = constants.%AdaptWithBase] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @Base {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%Base
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @AdaptWithBase {
|
||||
// CHECK:STDOUT: adapt_decl i32
|
||||
// CHECK:STDOUT: %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
|
||||
// CHECK:STDOUT: %.loc15: <unbound element of class AdaptWithBase> = base_decl Base, element0 [template]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%AdaptWithBase
|
||||
// CHECK:STDOUT: .base = %.loc15
|
||||
// CHECK:STDOUT: extend name_scope2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_adapt_with_fields.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %AdaptWithField: type = class_type @AdaptWithField [template]
|
||||
// CHECK:STDOUT: %.1: type = unbound_element_type AdaptWithField, i32 [template]
|
||||
// CHECK:STDOUT: %AdaptWithFields: type = class_type @AdaptWithFields [template]
|
||||
// CHECK:STDOUT: %.2: type = unbound_element_type AdaptWithFields, i32 [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .AdaptWithField = %AdaptWithField.decl
|
||||
// CHECK:STDOUT: .AdaptWithFields = %AdaptWithFields.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %AdaptWithField.decl: type = class_decl @AdaptWithField [template = constants.%AdaptWithField] {}
|
||||
// CHECK:STDOUT: %AdaptWithFields.decl: type = class_decl @AdaptWithFields [template = constants.%AdaptWithFields] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @AdaptWithField {
|
||||
// CHECK:STDOUT: adapt_decl i32
|
||||
// CHECK:STDOUT: %.loc13: <unbound element of class AdaptWithField> = field_decl n, element0 [template]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%AdaptWithField
|
||||
// CHECK:STDOUT: .n = %.loc13
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @AdaptWithFields {
|
||||
// CHECK:STDOUT: adapt_decl i32
|
||||
// CHECK:STDOUT: %.loc25: <unbound element of class AdaptWithFields> = field_decl a, element0 [template]
|
||||
// CHECK:STDOUT: %.loc26: <unbound element of class AdaptWithFields> = field_decl b, element1 [template]
|
||||
// CHECK:STDOUT: %.loc27: <unbound element of class AdaptWithFields> = field_decl c, element2 [template]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%AdaptWithFields
|
||||
// CHECK:STDOUT: .a = %.loc25
|
||||
// CHECK:STDOUT: .b = %.loc26
|
||||
// CHECK:STDOUT: .c = %.loc27
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_adapt_with_base_and_fields.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %Base: type = class_type @Base [template]
|
||||
// CHECK:STDOUT: %.1: type = struct_type {} [template]
|
||||
// CHECK:STDOUT: %AdaptWithBaseAndFields: type = class_type @AdaptWithBaseAndFields [template]
|
||||
// CHECK:STDOUT: %.2: type = tuple_type () [template]
|
||||
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
|
||||
// CHECK:STDOUT: %.4: type = unbound_element_type AdaptWithBaseAndFields, Base [template]
|
||||
// CHECK:STDOUT: %.5: type = unbound_element_type AdaptWithBaseAndFields, i32 [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .Base = %Base.decl
|
||||
// CHECK:STDOUT: .AdaptWithBaseAndFields = %AdaptWithBaseAndFields.decl
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %Base.decl: type = class_decl @Base [template = constants.%Base] {}
|
||||
// CHECK:STDOUT: %AdaptWithBaseAndFields.decl: type = class_decl @AdaptWithBaseAndFields [template = constants.%AdaptWithBaseAndFields] {}
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @Base {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%Base
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @AdaptWithBaseAndFields {
|
||||
// CHECK:STDOUT: %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
|
||||
// CHECK:STDOUT: %.loc7: <unbound element of class AdaptWithBaseAndFields> = base_decl Base, element0 [template]
|
||||
// CHECK:STDOUT: %.loc8: <unbound element of class AdaptWithBaseAndFields> = field_decl n, element1 [template]
|
||||
// CHECK:STDOUT: %.loc15_10.1: {} = struct_literal ()
|
||||
// CHECK:STDOUT: %.loc15_10.2: type = converted %.loc15_10.1, constants.%.1 [template = constants.%.1]
|
||||
// CHECK:STDOUT: adapt_decl {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%AdaptWithBaseAndFields
|
||||
// CHECK:STDOUT: .base = %.loc7
|
||||
// CHECK:STDOUT: .n = %.loc8
|
||||
// CHECK:STDOUT: extend name_scope2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
+295
@@ -0,0 +1,295 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// AUTOUPDATE
|
||||
|
||||
// --- fail_todo_init_adapt.carbon
|
||||
|
||||
library "fail_todo_init_adapt" api;
|
||||
|
||||
class C {
|
||||
var a: i32;
|
||||
var b: i32;
|
||||
}
|
||||
|
||||
class AdaptC {
|
||||
adapt C;
|
||||
}
|
||||
|
||||
let a: C = {.a = 1, .b = 2};
|
||||
|
||||
// TODO: Allow these as explicit conversions.
|
||||
|
||||
// CHECK:STDERR: fail_todo_init_adapt.carbon:[[@LINE+4]]:17: ERROR: Cannot convert from `C` to `AdaptC` with `as`.
|
||||
// CHECK:STDERR: let b: AdaptC = a as AdaptC;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
let b: AdaptC = a as AdaptC;
|
||||
|
||||
// CHECK:STDERR: fail_todo_init_adapt.carbon:[[@LINE+4]]:12: ERROR: Cannot convert from `AdaptC` to `C` with `as`.
|
||||
// CHECK:STDERR: let c: C = b as C;
|
||||
// CHECK:STDERR: ^~~~~~
|
||||
// CHECK:STDERR:
|
||||
let c: C = b as C;
|
||||
|
||||
fn MakeC() -> C;
|
||||
|
||||
fn MakeAdaptC() -> AdaptC;
|
||||
|
||||
// CHECK:STDERR: fail_todo_init_adapt.carbon:[[@LINE+4]]:17: ERROR: Cannot convert from `C` to `AdaptC` with `as`.
|
||||
// CHECK:STDERR: var d: AdaptC = MakeC() as AdaptC;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
var d: AdaptC = MakeC() as AdaptC;
|
||||
|
||||
// CHECK:STDERR: fail_todo_init_adapt.carbon:[[@LINE+4]]:12: ERROR: Cannot convert from `AdaptC` to `C` with `as`.
|
||||
// CHECK:STDERR: var e: C = MakeAdaptC() as C;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
var e: C = MakeAdaptC() as C;
|
||||
|
||||
// --- fail_not_implicit.carbon
|
||||
|
||||
library "fail_not_implicit" api;
|
||||
|
||||
class C {
|
||||
var a: i32;
|
||||
var b: i32;
|
||||
}
|
||||
|
||||
class AdaptC {
|
||||
adapt C;
|
||||
}
|
||||
|
||||
let a: C = {.a = 1, .b = 2};
|
||||
|
||||
// Cannot implicitly convert between a type and an adapter for the type.
|
||||
|
||||
// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+4]]:1: ERROR: Cannot implicitly convert from `C` to `AdaptC`.
|
||||
// CHECK:STDERR: let b: AdaptC = a;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
let b: AdaptC = a;
|
||||
|
||||
// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+4]]:1: ERROR: Cannot implicitly convert from `AdaptC` to `C`.
|
||||
// CHECK:STDERR: let c: C = b;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
let c: C = b;
|
||||
|
||||
fn MakeC() -> C;
|
||||
|
||||
fn MakeAdaptC() -> AdaptC;
|
||||
|
||||
// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+4]]:1: ERROR: Cannot implicitly convert from `C` to `AdaptC`.
|
||||
// CHECK:STDERR: var d: AdaptC = MakeC();
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
var d: AdaptC = MakeC();
|
||||
|
||||
// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+3]]:1: ERROR: Cannot implicitly convert from `AdaptC` to `C`.
|
||||
// CHECK:STDERR: var e: C = MakeAdaptC();
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~
|
||||
var e: C = MakeAdaptC();
|
||||
|
||||
// CHECK:STDOUT: --- fail_todo_init_adapt.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [template]
|
||||
// CHECK:STDOUT: %.1: type = unbound_element_type C, i32 [template]
|
||||
// CHECK:STDOUT: %.2: type = struct_type {.a: i32, .b: i32} [template]
|
||||
// CHECK:STDOUT: %AdaptC: type = class_type @AdaptC [template]
|
||||
// CHECK:STDOUT: %.3: type = ptr_type {.a: i32, .b: i32} [template]
|
||||
// CHECK:STDOUT: %.4: i32 = int_literal 1 [template]
|
||||
// CHECK:STDOUT: %.5: i32 = int_literal 2 [template]
|
||||
// CHECK:STDOUT: %.6: C = struct_value (%.4, %.5) [template]
|
||||
// CHECK:STDOUT: %.7: type = ptr_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .C = %C.decl
|
||||
// CHECK:STDOUT: .AdaptC = %AdaptC.decl
|
||||
// CHECK:STDOUT: .MakeC = %MakeC
|
||||
// CHECK:STDOUT: .MakeAdaptC = %MakeAdaptC
|
||||
// CHECK:STDOUT: .d = %d
|
||||
// CHECK:STDOUT: .e = %e
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %AdaptC.decl: type = class_decl @AdaptC [template = constants.%AdaptC] {}
|
||||
// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, %C.decl [template = constants.%C]
|
||||
// CHECK:STDOUT: %.loc13_18: i32 = int_literal 1 [template = constants.%.4]
|
||||
// CHECK:STDOUT: %.loc13_26: i32 = int_literal 2 [template = constants.%.5]
|
||||
// CHECK:STDOUT: %.loc13_27.1: {.a: i32, .b: i32} = struct_literal (%.loc13_18, %.loc13_26)
|
||||
// CHECK:STDOUT: %.loc13_27.2: ref C = temporary_storage
|
||||
// CHECK:STDOUT: %.loc13_27.3: ref i32 = class_element_access %.loc13_27.2, element0
|
||||
// CHECK:STDOUT: %.loc13_27.4: init i32 = initialize_from %.loc13_18 to %.loc13_27.3 [template = constants.%.4]
|
||||
// CHECK:STDOUT: %.loc13_27.5: ref i32 = class_element_access %.loc13_27.2, element1
|
||||
// CHECK:STDOUT: %.loc13_27.6: init i32 = initialize_from %.loc13_26 to %.loc13_27.5 [template = constants.%.5]
|
||||
// CHECK:STDOUT: %.loc13_27.7: init C = class_init (%.loc13_27.4, %.loc13_27.6), %.loc13_27.2 [template = constants.%.6]
|
||||
// CHECK:STDOUT: %.loc13_27.8: ref C = temporary %.loc13_27.2, %.loc13_27.7
|
||||
// CHECK:STDOUT: %.loc13_27.9: ref C = converted %.loc13_27.1, %.loc13_27.8
|
||||
// CHECK:STDOUT: %.loc13_27.10: C = bind_value %.loc13_27.9
|
||||
// CHECK:STDOUT: %a: C = bind_name a, %.loc13_27.10
|
||||
// CHECK:STDOUT: %AdaptC.ref.loc21_8: type = name_ref AdaptC, %AdaptC.decl [template = constants.%AdaptC]
|
||||
// CHECK:STDOUT: %a.ref: C = name_ref a, %a
|
||||
// CHECK:STDOUT: %AdaptC.ref.loc21_22: type = name_ref AdaptC, %AdaptC.decl [template = constants.%AdaptC]
|
||||
// CHECK:STDOUT: %b: AdaptC = bind_name b, <error>
|
||||
// CHECK:STDOUT: %C.ref.loc27_8: type = name_ref C, %C.decl [template = constants.%C]
|
||||
// CHECK:STDOUT: %b.ref: AdaptC = name_ref b, %b
|
||||
// CHECK:STDOUT: %C.ref.loc27_17: type = name_ref C, %C.decl [template = constants.%C]
|
||||
// CHECK:STDOUT: %c: C = bind_name c, <error>
|
||||
// CHECK:STDOUT: %MakeC: <function> = fn_decl @MakeC [template] {
|
||||
// CHECK:STDOUT: %C.ref.loc29: type = name_ref C, %C.decl [template = constants.%C]
|
||||
// CHECK:STDOUT: @MakeC.%return: ref C = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %MakeAdaptC: <function> = fn_decl @MakeAdaptC [template] {
|
||||
// CHECK:STDOUT: %AdaptC.ref.loc31: type = name_ref AdaptC, %AdaptC.decl [template = constants.%AdaptC]
|
||||
// CHECK:STDOUT: @MakeAdaptC.%return: ref AdaptC = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %AdaptC.ref.loc37: type = name_ref AdaptC, %AdaptC.decl [template = constants.%AdaptC]
|
||||
// CHECK:STDOUT: %d.var: ref AdaptC = var d
|
||||
// CHECK:STDOUT: %d: ref AdaptC = bind_name d, %d.var
|
||||
// CHECK:STDOUT: %C.ref.loc43: type = name_ref C, %C.decl [template = constants.%C]
|
||||
// CHECK:STDOUT: %e.var: ref C = var e
|
||||
// CHECK:STDOUT: %e: ref C = bind_name e, %e.var
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C {
|
||||
// CHECK:STDOUT: %.loc5: <unbound element of class C> = field_decl a, element0 [template]
|
||||
// CHECK:STDOUT: %.loc6: <unbound element of class C> = field_decl b, element1 [template]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%C
|
||||
// CHECK:STDOUT: .a = %.loc5
|
||||
// CHECK:STDOUT: .b = %.loc6
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @AdaptC {
|
||||
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C]
|
||||
// CHECK:STDOUT: adapt_decl C
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%AdaptC
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @MakeC() -> %return: C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @MakeAdaptC() -> %return: AdaptC;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @__global_init() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %MakeC.ref: <function> = name_ref MakeC, file.%MakeC [template = file.%MakeC]
|
||||
// CHECK:STDOUT: %.loc37_22.1: ref C = temporary_storage
|
||||
// CHECK:STDOUT: %.loc37_22.2: init C = call %MakeC.ref() to %.loc37_22.1
|
||||
// CHECK:STDOUT: %AdaptC.ref: type = name_ref AdaptC, file.%AdaptC.decl [template = constants.%AdaptC]
|
||||
// CHECK:STDOUT: assign file.%d.var, <error>
|
||||
// CHECK:STDOUT: %MakeAdaptC.ref: <function> = name_ref MakeAdaptC, file.%MakeAdaptC [template = file.%MakeAdaptC]
|
||||
// CHECK:STDOUT: %.loc43_22.1: ref AdaptC = temporary_storage
|
||||
// CHECK:STDOUT: %.loc43_22.2: init AdaptC = call %MakeAdaptC.ref() to %.loc43_22.1
|
||||
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C]
|
||||
// CHECK:STDOUT: assign file.%e.var, <error>
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_not_implicit.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [template]
|
||||
// CHECK:STDOUT: %.1: type = unbound_element_type C, i32 [template]
|
||||
// CHECK:STDOUT: %.2: type = struct_type {.a: i32, .b: i32} [template]
|
||||
// CHECK:STDOUT: %AdaptC: type = class_type @AdaptC [template]
|
||||
// CHECK:STDOUT: %.3: type = ptr_type {.a: i32, .b: i32} [template]
|
||||
// CHECK:STDOUT: %.4: i32 = int_literal 1 [template]
|
||||
// CHECK:STDOUT: %.5: i32 = int_literal 2 [template]
|
||||
// CHECK:STDOUT: %.6: C = struct_value (%.4, %.5) [template]
|
||||
// CHECK:STDOUT: %.7: type = ptr_type C [template]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: package: <namespace> = namespace [template] {
|
||||
// CHECK:STDOUT: .Core = %Core
|
||||
// CHECK:STDOUT: .C = %C.decl
|
||||
// CHECK:STDOUT: .AdaptC = %AdaptC.decl
|
||||
// CHECK:STDOUT: .MakeC = %MakeC
|
||||
// CHECK:STDOUT: .MakeAdaptC = %MakeAdaptC
|
||||
// CHECK:STDOUT: .d = %d
|
||||
// CHECK:STDOUT: .e = %e
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Core: <namespace> = namespace [template] {}
|
||||
// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {}
|
||||
// CHECK:STDOUT: %AdaptC.decl: type = class_decl @AdaptC [template = constants.%AdaptC] {}
|
||||
// CHECK:STDOUT: %C.ref.loc13: type = name_ref C, %C.decl [template = constants.%C]
|
||||
// CHECK:STDOUT: %.loc13_18: i32 = int_literal 1 [template = constants.%.4]
|
||||
// CHECK:STDOUT: %.loc13_26: i32 = int_literal 2 [template = constants.%.5]
|
||||
// CHECK:STDOUT: %.loc13_27.1: {.a: i32, .b: i32} = struct_literal (%.loc13_18, %.loc13_26)
|
||||
// CHECK:STDOUT: %.loc13_27.2: ref C = temporary_storage
|
||||
// CHECK:STDOUT: %.loc13_27.3: ref i32 = class_element_access %.loc13_27.2, element0
|
||||
// CHECK:STDOUT: %.loc13_27.4: init i32 = initialize_from %.loc13_18 to %.loc13_27.3 [template = constants.%.4]
|
||||
// CHECK:STDOUT: %.loc13_27.5: ref i32 = class_element_access %.loc13_27.2, element1
|
||||
// CHECK:STDOUT: %.loc13_27.6: init i32 = initialize_from %.loc13_26 to %.loc13_27.5 [template = constants.%.5]
|
||||
// CHECK:STDOUT: %.loc13_27.7: init C = class_init (%.loc13_27.4, %.loc13_27.6), %.loc13_27.2 [template = constants.%.6]
|
||||
// CHECK:STDOUT: %.loc13_27.8: ref C = temporary %.loc13_27.2, %.loc13_27.7
|
||||
// CHECK:STDOUT: %.loc13_27.9: ref C = converted %.loc13_27.1, %.loc13_27.8
|
||||
// CHECK:STDOUT: %.loc13_27.10: C = bind_value %.loc13_27.9
|
||||
// CHECK:STDOUT: %a: C = bind_name a, %.loc13_27.10
|
||||
// CHECK:STDOUT: %AdaptC.ref.loc21: type = name_ref AdaptC, %AdaptC.decl [template = constants.%AdaptC]
|
||||
// CHECK:STDOUT: %a.ref: C = name_ref a, %a
|
||||
// CHECK:STDOUT: %b: AdaptC = bind_name b, <error>
|
||||
// CHECK:STDOUT: %C.ref.loc27: type = name_ref C, %C.decl [template = constants.%C]
|
||||
// CHECK:STDOUT: %b.ref: AdaptC = name_ref b, %b
|
||||
// CHECK:STDOUT: %c: C = bind_name c, <error>
|
||||
// CHECK:STDOUT: %MakeC: <function> = fn_decl @MakeC [template] {
|
||||
// CHECK:STDOUT: %C.ref.loc29: type = name_ref C, %C.decl [template = constants.%C]
|
||||
// CHECK:STDOUT: @MakeC.%return: ref C = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %MakeAdaptC: <function> = fn_decl @MakeAdaptC [template] {
|
||||
// CHECK:STDOUT: %AdaptC.ref.loc31: type = name_ref AdaptC, %AdaptC.decl [template = constants.%AdaptC]
|
||||
// CHECK:STDOUT: @MakeAdaptC.%return: ref AdaptC = var <return slot>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %AdaptC.ref.loc37: type = name_ref AdaptC, %AdaptC.decl [template = constants.%AdaptC]
|
||||
// CHECK:STDOUT: %d.var: ref AdaptC = var d
|
||||
// CHECK:STDOUT: %d: ref AdaptC = bind_name d, %d.var
|
||||
// CHECK:STDOUT: %C.ref.loc42: type = name_ref C, %C.decl [template = constants.%C]
|
||||
// CHECK:STDOUT: %e.var: ref C = var e
|
||||
// CHECK:STDOUT: %e: ref C = bind_name e, %e.var
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C {
|
||||
// CHECK:STDOUT: %.loc5: <unbound element of class C> = field_decl a, element0 [template]
|
||||
// CHECK:STDOUT: %.loc6: <unbound element of class C> = field_decl b, element1 [template]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%C
|
||||
// CHECK:STDOUT: .a = %.loc5
|
||||
// CHECK:STDOUT: .b = %.loc6
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @AdaptC {
|
||||
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C]
|
||||
// CHECK:STDOUT: adapt_decl C
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%AdaptC
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @MakeC() -> %return: C;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @MakeAdaptC() -> %return: AdaptC;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @__global_init() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %MakeC.ref: <function> = name_ref MakeC, file.%MakeC [template = file.%MakeC]
|
||||
// CHECK:STDOUT: %.loc37_22.1: ref C = temporary_storage
|
||||
// CHECK:STDOUT: %.loc37_22.2: init C = call %MakeC.ref() to %.loc37_22.1
|
||||
// CHECK:STDOUT: assign file.%d.var, <error>
|
||||
// CHECK:STDOUT: %MakeAdaptC.ref: <function> = name_ref MakeAdaptC, file.%MakeAdaptC [template = file.%MakeAdaptC]
|
||||
// CHECK:STDOUT: %.loc42_22.1: ref AdaptC = temporary_storage
|
||||
// CHECK:STDOUT: %.loc42_22.2: init AdaptC = call %MakeAdaptC.ref() to %.loc42_22.1
|
||||
// CHECK:STDOUT: assign file.%e.var, <error>
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -183,16 +183,20 @@ CARBON_DIAGNOSTIC_KIND(InvalidBuiltinSignature)
|
||||
CARBON_DIAGNOSTIC_KIND(FunctionExternMismatch)
|
||||
|
||||
// Class checking.
|
||||
CARBON_DIAGNOSTIC_KIND(AdaptWithBase)
|
||||
CARBON_DIAGNOSTIC_KIND(AdaptWithFields)
|
||||
CARBON_DIAGNOSTIC_KIND(AdaptBaseHere)
|
||||
CARBON_DIAGNOSTIC_KIND(AdaptFieldHere)
|
||||
CARBON_DIAGNOSTIC_KIND(BaseIsFinal)
|
||||
CARBON_DIAGNOSTIC_KIND(BaseMissingExtend)
|
||||
CARBON_DIAGNOSTIC_KIND(BaseOutsideClass)
|
||||
CARBON_DIAGNOSTIC_KIND(BasePrevious)
|
||||
CARBON_DIAGNOSTIC_KIND(BaseRepeated)
|
||||
CARBON_DIAGNOSTIC_KIND(ClassForwardDeclaredHere)
|
||||
CARBON_DIAGNOSTIC_KIND(ClassPreviousDefinition)
|
||||
CARBON_DIAGNOSTIC_KIND(ClassRedeclarationDifferentIntroducer)
|
||||
CARBON_DIAGNOSTIC_KIND(ClassRedeclarationDifferentIntroducerPrevious)
|
||||
CARBON_DIAGNOSTIC_KIND(ClassRedefinition)
|
||||
CARBON_DIAGNOSTIC_KIND(ClassSpecificDeclOutsideClass)
|
||||
CARBON_DIAGNOSTIC_KIND(ClassSpecificDeclPrevious)
|
||||
CARBON_DIAGNOSTIC_KIND(ClassSpecificDeclRepeated)
|
||||
CARBON_DIAGNOSTIC_KIND(ClassIncompleteWithinDefinition)
|
||||
CARBON_DIAGNOSTIC_KIND(ConstructionOfAbstractClass)
|
||||
|
||||
@@ -260,6 +264,7 @@ CARBON_DIAGNOSTIC_KIND(NameNotFound)
|
||||
CARBON_DIAGNOSTIC_KIND(NameDeclDuplicate)
|
||||
CARBON_DIAGNOSTIC_KIND(NameDeclPrevious)
|
||||
CARBON_DIAGNOSTIC_KIND(RepeatedConst)
|
||||
CARBON_DIAGNOSTIC_KIND(IncompleteTypeInAdaptDecl)
|
||||
CARBON_DIAGNOSTIC_KIND(IncompleteTypeInBaseDecl)
|
||||
CARBON_DIAGNOSTIC_KIND(IncompleteTypeInConversion)
|
||||
CARBON_DIAGNOSTIC_KIND(IncompleteTypeInFunctionParam)
|
||||
|
||||
@@ -26,6 +26,11 @@ static auto FatalErrorIfEncountered(InstT inst) -> void {
|
||||
<< inst;
|
||||
}
|
||||
|
||||
auto HandleAdaptDecl(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
|
||||
SemIR::AdaptDecl inst) -> void {
|
||||
FatalErrorIfEncountered(inst);
|
||||
}
|
||||
|
||||
auto HandleAddrOf(FunctionContext& context, SemIR::InstId inst_id,
|
||||
SemIR::AddrOf inst) -> void {
|
||||
context.SetLocal(inst_id, context.GetValue(inst.lvalue_id));
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// AUTOUPDATE
|
||||
|
||||
class PairOfInts {
|
||||
var a: i32;
|
||||
var b: i32;
|
||||
}
|
||||
|
||||
class PairAdapter {
|
||||
adapt PairOfInts;
|
||||
}
|
||||
|
||||
fn MakePair() -> PairAdapter {
|
||||
returned var v: PairAdapter;
|
||||
return var;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: ; ModuleID = 'adapt.carbon'
|
||||
// CHECK:STDOUT: source_filename = "adapt.carbon"
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: define void @MakePair(ptr sret({ i32, i32 }) %return) {
|
||||
// CHECK:STDOUT: ret void
|
||||
// CHECK:STDOUT: }
|
||||
+41
-8
@@ -4,26 +4,59 @@
|
||||
//
|
||||
// AUTOUPDATE
|
||||
|
||||
virtual class B
|
||||
// --- fail_virtual_class.carbon
|
||||
|
||||
// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:1: ERROR: `virtual` declarations must either end with a `;` or have a `{ ... }` block for a definition.
|
||||
virtual class B
|
||||
// CHECK:STDERR: fail_virtual_class.carbon:[[@LINE+4]]:1: ERROR: `virtual` declarations must either end with a `;` or have a `{ ... }` block for a definition.
|
||||
// CHECK:STDERR:
|
||||
// CHECK:STDERR: ^
|
||||
// CHECK:STDERR:
|
||||
|
||||
// --- fail_impl_class.carbon
|
||||
|
||||
// CHECK:STDERR: fail_impl_class.carbon:[[@LINE+4]]:1: ERROR: `impl` introducer should be followed by a name.
|
||||
// CHECK:STDERR: impl class
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR:
|
||||
// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+3]]:6: ERROR: `class` introducer should be followed by a name.
|
||||
// CHECK:STDERR: impl class
|
||||
// CHECK:STDERR: ^~~~~
|
||||
impl class
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_modifiers.carbon
|
||||
// --- fail_extend_adapt_base.carbon
|
||||
|
||||
class C {
|
||||
// CHECK:STDERR: fail_extend_adapt_base.carbon:[[@LINE+3]]:16: ERROR: Expected expression.
|
||||
// CHECK:STDERR: extend adapt base B;
|
||||
// CHECK:STDERR: ^~~~
|
||||
extend adapt base B;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_virtual_class.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'ClassIntroducer', text: 'class'},
|
||||
// CHECK:STDOUT: {kind: 'VirtualModifier', text: 'virtual'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'B'},
|
||||
// CHECK:STDOUT: {kind: 'ClassDecl', text: 'impl', has_error: yes, subtree_size: 4},
|
||||
// CHECK:STDOUT: {kind: 'ClassDecl', text: 'B', has_error: yes, subtree_size: 4},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: fail_impl_class.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'ClassIntroducer', text: 'class'},
|
||||
// CHECK:STDOUT: {kind: 'ImplModifier', text: 'impl'},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: '', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'ClassDecl', text: 'class', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ClassDecl', text: 'class', has_error: yes, subtree_size: 4},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: fail_extend_adapt_base.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'ClassIntroducer', text: 'class'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'C'},
|
||||
// CHECK:STDOUT: {kind: 'ClassDefinitionStart', text: '{', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'AdaptIntroducer', text: 'adapt'},
|
||||
// CHECK:STDOUT: {kind: 'ExtendModifier', text: 'extend'},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: 'base', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'AdaptDecl', text: ';', has_error: yes, subtree_size: 4},
|
||||
// CHECK:STDOUT: {kind: 'ClassDefinition', text: '}', subtree_size: 8},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
@@ -56,6 +56,11 @@ struct Class : public Printable<Class> {
|
||||
|
||||
// The following members are accumulated throughout the class definition.
|
||||
|
||||
// The adapted type declaration, if any. Invalid if the class is not an
|
||||
// adapter. This is an AdaptDecl instruction.
|
||||
// TODO: Consider sharing the storage for `adapt_id` and `base_id`. A class
|
||||
// can't have both.
|
||||
InstId adapt_id = InstId::Invalid;
|
||||
// The base class declaration. Invalid if the class has no base class. This is
|
||||
// a BaseDecl instruction.
|
||||
InstId base_id = InstId::Invalid;
|
||||
|
||||
@@ -221,6 +221,7 @@ static auto GetTypePrecedence(InstKind kind) -> int {
|
||||
case PointerType::Kind:
|
||||
return -2;
|
||||
|
||||
case AdaptDecl::Kind:
|
||||
case AddrOf::Kind:
|
||||
case AddrPattern::Kind:
|
||||
case ArrayIndex::Kind:
|
||||
@@ -477,6 +478,7 @@ static auto StringifyTypeExprImpl(const SemIR::File& outer_sem_ir,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AdaptDecl::Kind:
|
||||
case AddrOf::Kind:
|
||||
case AddrPattern::Kind:
|
||||
case ArrayIndex::Kind:
|
||||
@@ -560,6 +562,7 @@ auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory {
|
||||
while (true) {
|
||||
auto untyped_inst = ir->insts().Get(inst_id);
|
||||
CARBON_KIND_SWITCH(untyped_inst) {
|
||||
case AdaptDecl::Kind:
|
||||
case Assign::Kind:
|
||||
case BaseDecl::Kind:
|
||||
case Branch::Kind:
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
// For each instruction kind declared here there is a matching definition in
|
||||
// `typed_insts.h`.
|
||||
CARBON_SEM_IR_INST_KIND(AdaptDecl)
|
||||
CARBON_SEM_IR_INST_KIND(AddrOf)
|
||||
CARBON_SEM_IR_INST_KIND(AddrPattern)
|
||||
CARBON_SEM_IR_INST_KIND(ArrayIndex)
|
||||
|
||||
@@ -44,6 +44,15 @@
|
||||
|
||||
namespace Carbon::SemIR {
|
||||
|
||||
// An adapted type declaration in a class, of the form `adapt T;`.
|
||||
struct AdaptDecl {
|
||||
static constexpr auto Kind =
|
||||
InstKind::AdaptDecl.Define<Parse::AdaptDeclId>("adapt_decl");
|
||||
|
||||
// No type_id; this is not a value.
|
||||
TypeId adapted_type_id;
|
||||
};
|
||||
|
||||
struct AddrOf {
|
||||
// TODO: Make Parse::NodeId more specific.
|
||||
static constexpr auto Kind =
|
||||
|
||||
Reference in New Issue
Block a user