Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/include/clang/AST/CanonicalType.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ class CanProxyBase {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantArrayType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation)
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/ExprClassification.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,8 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
return Cl::CM_ConstAddrSpace;

// Arrays are not modifiable, only their elements are.
if (CT->isArrayType())
if (CT->isArrayType() &&
!(Ctx.getLangOpts().HLSL && CT->isConstantArrayType()))
return Cl::CM_ArrayType;
// Incomplete types are not modifiable.
if (CT->isIncompleteType())
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5797,11 +5797,26 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
return EmitComplexAssignmentLValue(E);

case TEK_Aggregate:
// If the lang opt is HLSL and the LHS is a constant array
// then we are performing a copy assignment and call a special
// function because EmitAggExprToLValue emits to a temporary LValue
if (getLangOpts().HLSL && E->getLHS()->getType()->isConstantArrayType())
return EmitHLSLArrayAssignLValue(E);

return EmitAggExprToLValue(E);
}
llvm_unreachable("bad evaluation kind");
}

// This function implements trivial copy assignment for HLSL's
// assignable constant arrays.
LValue CodeGenFunction::EmitHLSLArrayAssignLValue(const BinaryOperator *E) {
LValue TrivialAssignmentRHS = EmitLValue(E->getRHS());
LValue LHS = EmitLValue(E->getLHS());
EmitAggregateAssign(LHS, TrivialAssignmentRHS, E->getLHS()->getType());
return LHS;
}

LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E,
llvm::CallBase **CallOrInvoke) {
RValue RV = EmitCallExpr(E, ReturnValueSlot(), CallOrInvoke);
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -4296,6 +4296,7 @@ class CodeGenFunction : public CodeGenTypeCache {
LValue EmitCastLValue(const CastExpr *E);
LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
LValue EmitHLSLArrayAssignLValue(const BinaryOperator *E);
void EmitHLSLOutArgExpr(const HLSLOutArgExpr *E, CallArgList &Args,
QualType Ty);

Expand Down
11 changes: 8 additions & 3 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2232,16 +2232,21 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// just strip the qualifiers because they don't matter.
FromType = FromType.getUnqualifiedType();
} else if (S.getLangOpts().HLSL && FromType->isConstantArrayType() &&
ToType->isArrayParameterType()) {
ToType->isConstantArrayType()) {
// HLSL constant array parameters do not decay, so if the argument is a
// constant array and the parameter is an ArrayParameterType we have special
// handling here.
FromType = S.Context.getArrayParameterType(FromType);
if (ToType->isArrayParameterType()) {
FromType = S.Context.getArrayParameterType(FromType);
SCS.First = ICK_HLSL_Array_RValue;
} else {
SCS.First = ICK_Identity;
}

if (S.Context.getCanonicalType(FromType) !=
S.Context.getCanonicalType(ToType))
return false;

SCS.First = ICK_HLSL_Array_RValue;
SCS.setAllToTypes(ToType);
return true;
} else if (FromType->isArrayType()) {
Expand Down
106 changes: 106 additions & 0 deletions clang/test/AST/HLSL/ArrayAssignable.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump %s | FileCheck %s

// CHECK-LABEL: arr_assign1
// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue '='
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr' 'int[2]'
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr2' 'int[2]'
void arr_assign1() {
int Arr[2] = {0, 1};
int Arr2[2] = {0, 0};
Arr = Arr2;
}

// CHECK-LABEL: arr_assign2
// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue '='
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr' 'int[2]'
// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue '='
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr2' 'int[2]'
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr3' 'int[2]'
void arr_assign2() {
int Arr[2] = {0, 1};
int Arr2[2] = {0, 0};
int Arr3[2] = {2, 2};
Arr = Arr2 = Arr3;
}

// CHECK-LABEL: arr_assign3
// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' lvalue '='
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr' 'int[2][2]'
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr2' 'int[2][2]'
void arr_assign3() {
int Arr[2][2] = {{0, 1}, {2, 3}};
int Arr2[2][2] = {{0, 0}, {1, 1}};
Arr = Arr2;
}

// CHECK-LABEL: arr_assign4
// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int' lvalue '='
// CHECK: ArraySubscriptExpr 0x{{[0-9a-f]+}} {{.*}} 'int' lvalue
// CHECK: ImplicitCastExpr 0x{{[0-9a-f]+}} {{.*}} 'int *' <ArrayToPointerDecay>
// CHECK: ParenExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue
// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue '='
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr' 'int[2]'
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr2' 'int[2]'
// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0
// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 6
void arr_assign4() {
int Arr[2] = {0, 1};
int Arr2[2] = {0, 0};
(Arr = Arr2)[0] = 6;
}

// CHECK-LABEL: arr_assign5
// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int' lvalue '='
// CHECK: ArraySubscriptExpr 0x{{[0-9a-f]+}} {{.*}} 'int' lvalue
// CHECK: ImplicitCastExpr 0x{{[0-9a-f]+}} {{.*}} 'int *' <ArrayToPointerDecay>
// CHECK: ParenExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue
// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue '='
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr' 'int[2]'
// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue '='
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr2' 'int[2]'
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr3' 'int[2]'
// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0
// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 6
void arr_assign5() {
int Arr[2] = {0, 1};
int Arr2[2] = {0, 0};
int Arr3[2] = {3, 4};
(Arr = Arr2 = Arr3)[0] = 6;
}

// CHECK-LABEL: arr_assign6
// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int' lvalue '='
// CHECK: ArraySubscriptExpr 0x{{[0-9a-f]+}} {{.*}} 'int' lvalue
// CHECK: ImplicitCastExpr 0x{{[0-9a-f]+}} {{.*}} 'int *' <ArrayToPointerDecay>
// CHECK: ArraySubscriptExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue
// CHECK: ImplicitCastExpr 0x{{[0-9a-f]+}} {{.*}} 'int (*)[2]' <ArrayToPointerDecay>
// CHECK: ParenExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' lvalue
// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' lvalue '='
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr' 'int[2][2]'
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr2' 'int[2][2]'
// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0
// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0
// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 6
void arr_assign6() {
int Arr[2][2] = {{0, 1}, {2, 3}};
int Arr2[2][2] = {{0, 0}, {1, 1}};
(Arr = Arr2)[0][0] = 6;
}

// CHECK-LABEL: arr_assign7
// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue '='
// CHECK: ArraySubscriptExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]' lvalue
// CHECK: ImplicitCastExpr 0x{{[0-9a-f]+}} {{.*}} 'int (*)[2]' <ArrayToPointerDecay>
// CHECK: ParenExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' lvalue
// CHECK: BinaryOperator 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' lvalue '='
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr' 'int[2][2]'
// CHECK: DeclRefExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2][2]' lvalue Var 0x{{[0-9a-f]+}} 'Arr2' 'int[2][2]'
// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 0
// CHECK: InitListExpr 0x{{[0-9a-f]+}} {{.*}} 'int[2]'
// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 6
// CHECK: IntegerLiteral 0x{{[0-9a-f]+}} {{.*}} 'int' 6
void arr_assign7() {
int Arr[2][2] = {{0, 1}, {2, 3}};
int Arr2[2][2] = {{0, 0}, {1, 1}};
(Arr = Arr2)[0] = {6, 6};
}
120 changes: 120 additions & 0 deletions clang/test/CodeGenHLSL/ArrayAssignable.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --enable-var-scope

// CHECK-LABEL: define void {{.*}}arr_assign1
// CHECK: [[Arr:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: [[Arr2:%.*]] = alloca [2 x i32], align 4
// CHECK-NOT: alloca
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 {{@.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memset.p0.i32(ptr align 4 [[Arr2]], i8 0, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 [[Arr2]], i32 8, i1 false)
// CHECK-NEXT: ret void
void arr_assign1() {
int Arr[2] = {0, 1};
int Arr2[2] = {0, 0};
Arr = Arr2;
}

// CHECK-LABEL: define void {{.*}}arr_assign2
// CHECK: [[Arr:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: [[Arr2:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: [[Arr3:%.*]] = alloca [2 x i32], align 4
// CHECK-NOT: alloca
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 {{@.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memset.p0.i32(ptr align 4 [[Arr2]], i8 0, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr3]], ptr align 4 {{@.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr2]], ptr align 4 [[Arr3]], i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 [[Arr2]], i32 8, i1 false)
// CHECK-NEXT: ret void
void arr_assign2() {
int Arr[2] = {0, 1};
int Arr2[2] = {0, 0};
int Arr3[2] = {3, 4};
Arr = Arr2 = Arr3;
}

// CHECK-LABEL: define void {{.*}}arr_assign3
// CHECK: [[Arr3:%.*]] = alloca [2 x [2 x i32]], align 4
// CHECK-NEXT: [[Arr4:%.*]] = alloca [2 x [2 x i32]], align 4
// CHECK-NOT: alloca
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr3]], ptr align 4 {{@.*}}, i32 16, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr4]], ptr align 4 {{@.*}}, i32 16, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr3]], ptr align 4 [[Arr4]], i32 16, i1 false)
// CHECK-NEXT: ret void
void arr_assign3() {
int Arr2[2][2] = {{0, 0}, {1, 1}};
int Arr3[2][2] = {{1, 1}, {0, 0}};
Arr2 = Arr3;
}

// CHECK-LABEL: define void {{.*}}arr_assign4
// CHECK: [[Arr:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: [[Arr2:%.*]] = alloca [2 x i32], align 4
// CHECK-NOT: alloca
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 {{@.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memset.p0.i32(ptr align 4 [[Arr2]], i8 0, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 [[Arr2]], i32 8, i1 false)
// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[Arr]], i32 0, i32 0
// CHECK-NEXT: store i32 6, ptr [[Idx]], align 4
// CHECK-NEXT: ret void
void arr_assign4() {
int Arr[2] = {0, 1};
int Arr2[2] = {0, 0};
(Arr = Arr2)[0] = 6;
}

// CHECK-LABEL: define void {{.*}}arr_assign5
// CHECK: [[Arr:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: [[Arr2:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: [[Arr3:%.*]] = alloca [2 x i32], align 4
// CHECK-NOT: alloca
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 {{@.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memset.p0.i32(ptr align 4 [[Arr2]], i8 0, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr3]], ptr align 4 {{@.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr2]], ptr align 4 [[Arr3]], i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 [[Arr2]], i32 8, i1 false)
// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[Arr]], i32 0, i32 0
// CHECK-NEXT: store i32 6, ptr [[Idx]], align 4
// CHECK-NEXT: ret void
void arr_assign5() {
int Arr[2] = {0, 1};
int Arr2[2] = {0, 0};
int Arr3[2] = {3, 4};
(Arr = Arr2 = Arr3)[0] = 6;
}

// CHECK-LABEL: define void {{.*}}arr_assign6
// CHECK: [[Arr3:%.*]] = alloca [2 x [2 x i32]], align 4
// CHECK-NEXT: [[Arr4:%.*]] = alloca [2 x [2 x i32]], align 4
// CHECK-NOT: alloca
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr3]], ptr align 4 {{@.*}}, i32 16, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr4]], ptr align 4 {{@.*}}, i32 16, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr3]], ptr align 4 [[Arr4]], i32 16, i1 false)
// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x [2 x i32]], ptr [[Arr3]], i32 0, i32 0
// CHECK-NEXT: [[Idx2:%.*]] = getelementptr inbounds [2 x i32], ptr [[Idx]], i32 0, i32 0
// CHECK-NEXT: store i32 6, ptr [[Idx2]], align 4
// CHECK-NEXT: ret void
void arr_assign6() {
int Arr[2][2] = {{0, 0}, {1, 1}};
int Arr2[2][2] = {{1, 1}, {0, 0}};
(Arr = Arr2)[0][0] = 6;
}

// CHECK-LABEL: define void {{.*}}arr_assign7
// CHECK: [[Arr3:%.*]] = alloca [2 x [2 x i32]], align 4
// CHECK-NEXT: [[Arr4:%.*]] = alloca [2 x [2 x i32]], align 4
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4
// CHECK-NOT: alloca
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr3]], ptr align 4 {{@.*}}, i32 16, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr4]], ptr align 4 {{@.*}}, i32 16, i1 false)
// CHECK-NEXT: store i32 6, ptr [[Tmp]], align 4
// CHECK-NEXT: [[AIE:%.*]] = getelementptr inbounds i32, ptr [[Tmp]], i32 1
// CHECK-NEXT: store i32 6, ptr [[AIE]], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr3]], ptr align 4 [[Arr4]], i32 16, i1 false)
// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x [2 x i32]], ptr [[Arr3]], i32 0, i32 0
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Idx]], ptr align 4 [[Tmp]], i32 8, i1 false)
// CHECK-NEXT: ret void
void arr_assign7() {
int Arr[2][2] = {{0, 1}, {2, 3}};
int Arr2[2][2] = {{0, 0}, {1, 1}};
(Arr = Arr2)[0] = {6, 6};
}
29 changes: 29 additions & 0 deletions clang/test/SemaHLSL/ArrayAssignable_errors.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -verify

void test_wrong_size1() {
int Arr[2] = {0, 1};
int Arr2[3] = {1, 2, 0};
Arr = Arr2;
// expected-error@-1 {{assigning to 'int[2]' from incompatible type 'int[3]'}}
}

void test_wrong_size2() {
int Arr[2] = {0, 1};
int Arr2[3] = {1, 2, 0};
Arr2 = Arr;
// expected-error@-1 {{assigning to 'int[3]' from incompatible type 'int[2]'}}
}

void test_wrong_size3() {
int Arr[2][2] = {{0, 1}, {2, 3}};
int Arr2[2] = {4, 5};
Arr = Arr2;
// expected-error@-1 {{assigning to 'int[2][2]' from incompatible type 'int[2]'}}
}

void test_wrong_size4() {
int Arr[2][2] = {{0, 1}, {2, 3}};
int Arr2[2] = {4, 5};
Arr2 = Arr;
// expected-error@-1 {{assigning to 'int[2]' from incompatible type 'int[2][2]'}}
}
Loading