[clang] [Clang][AArch64] Fix crash with large arguments to MTE built-ins (PR #197620)
Igor Kudrin via cfe-commits
cfe-commits at lists.llvm.org
Fri May 22 20:52:44 PDT 2026
https://github.com/igorkudrin updated https://github.com/llvm/llvm-project/pull/197620
>From 8ba8c4ed4b8cd7d8d83815a52604d92c71b84dd7 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Thu, 7 May 2026 23:36:38 -0700
Subject: [PATCH 1/4] [AArch64] Fix possible miscompilation with
`__builtin_arm_gmi`
The `@llvm.aarch64.gmi` intrinsic returns a 64-bit value, but
`SemaARM::BuiltinARMMemoryTaggingCall()` incorrectly sets the type of
the call instruction to `Context.IntTy`. This results in miscompilations
when a truncate instruction is required but missing from the generated
code. Note that in the `-O0` case below a 64-bit value is stored in
a 32-bit stack slot:
```
> cat test.c
int test(void* a, unsigned m) {
return __builtin_arm_gmi(a, m);
}
> clang -target aarch64 -march=armv9+memtag -O0 -S -emit-llvm test.c -o -
define dso_local i32 @test(ptr noundef %0, i32 noundef %1) #0 {
%3 = alloca i32, align 4
...
%9 = call i64 @llvm.aarch64.gmi(ptr %6, i64 %8)
store i64 %9, ptr %3, align 4
%10 = load i32, ptr %3, align 4
ret i32 %10
}
> clang -target aarch64 -march=armv9+memtag -O3 -S -emit-llvm test.c -o -
define dso_local i32 @test(ptr nocapture noundef readnone %0, i32 noundef %1) local_unnamed_addr #0 {
ret i32 undef
}
```
The patch fixes this by setting the return type to `Context.LongLongTy`.
---
clang/lib/Sema/SemaARM.cpp | 2 +-
clang/test/CodeGen/arm64-mte.c | 13 +++++++++++--
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index 7871fd624a467..68728f25f5231 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -94,7 +94,7 @@ bool SemaARM::BuiltinARMMemoryTaggingCall(unsigned BuiltinID,
if (!SecArgType->isIntegerType())
return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_integer)
<< "second" << SecArgType << Arg1->getSourceRange();
- TheCall->setType(Context.IntTy);
+ TheCall->setType(Context.LongLongTy);
return false;
}
diff --git a/clang/test/CodeGen/arm64-mte.c b/clang/test/CodeGen/arm64-mte.c
index ff6f8de5d4bb4..9e2b3736ac4c0 100644
--- a/clang/test/CodeGen/arm64-mte.c
+++ b/clang/test/CodeGen/arm64-mte.c
@@ -49,9 +49,18 @@ short *increment_tag2(short *a) {
return __arm_mte_increment_tag(a,3);
}
-// CHECK-LABEL: define{{.*}} i32 @exclude_tag
+// CHECK-LABEL: define{{.*}} i32 @exclude_tag1
attribute
-unsigned exclude_tag(int *a, unsigned m) {
+unsigned exclude_tag1(int *a, unsigned m) {
+// CHECK: [[T0:%[0-9]+]] = zext i32 %m to i64
+// CHECK: [[T2:%[0-9]+]] = tail call i64 @llvm.aarch64.gmi(ptr %a, i64 [[T0]])
+// CHECK: trunc i64 [[T2]] to i32
+ return __arm_mte_exclude_tag(a, m);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @exclude_tag2
+attribute
+int exclude_tag2(int *a, unsigned m) {
// CHECK: [[T0:%[0-9]+]] = zext i32 %m to i64
// CHECK: [[T2:%[0-9]+]] = tail call i64 @llvm.aarch64.gmi(ptr %a, i64 [[T0]])
// CHECK: trunc i64 [[T2]] to i32
>From 6a5c7b208b2ffa69ad7fe158079de8e6439202aa Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Wed, 13 May 2026 19:41:39 -0700
Subject: [PATCH 2/4] fixup! Update prototypes, remove explicit 'setType()'
---
clang/include/clang/Basic/BuiltinsAArch64.td | 6 +++---
clang/lib/Sema/SemaARM.cpp | 2 --
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/clang/include/clang/Basic/BuiltinsAArch64.td b/clang/include/clang/Basic/BuiltinsAArch64.td
index 8e5dbb5f4172d..ba30e344911aa 100644
--- a/clang/include/clang/Basic/BuiltinsAArch64.td
+++ b/clang/include/clang/Basic/BuiltinsAArch64.td
@@ -75,12 +75,12 @@ let Attributes = [NoThrow, Const], Features = "crc" in {
// Memory Tagging Extensions (MTE)
let Attributes = [CustomTypeChecking], Features = "mte" in {
- def irg : AArch64TargetBuiltin<"void * (void *, unsigned int)">;
+ def irg : AArch64TargetBuiltin<"void * (void *, uint64_t)">;
def addg : AArch64TargetBuiltin<"void * (void *, unsigned int)">;
- def gmi : AArch64TargetBuiltin<"unsigned int (void *, unsigned int)">;
+ def gmi : AArch64TargetBuiltin<"uint64_t (void *, uint64_t)">;
def ldg : AArch64TargetBuiltin<"void * (void *)">;
def stg : AArch64TargetBuiltin<"void (void *)">;
- def subp : AArch64TargetBuiltin<"unsigned int (void *, void *)">;
+ def subp : AArch64TargetBuiltin<"int64_t (void *, void *)">;
}
// SME state function
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index 68728f25f5231..2599eb04f3c12 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -94,7 +94,6 @@ bool SemaARM::BuiltinARMMemoryTaggingCall(unsigned BuiltinID,
if (!SecArgType->isIntegerType())
return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_integer)
<< "second" << SecArgType << Arg1->getSourceRange();
- TheCall->setType(Context.LongLongTy);
return false;
}
@@ -176,7 +175,6 @@ bool SemaARM::BuiltinARMMemoryTaggingCall(unsigned BuiltinID,
TheCall->setArg(0, ArgExprA.get());
TheCall->setArg(1, ArgExprB.get());
- TheCall->setType(Context.LongLongTy);
return false;
}
assert(false && "Unhandled ARM MTE intrinsic");
>From 048850a92f695cb3a11741533085d2355094f41e Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Wed, 13 May 2026 19:43:37 -0700
Subject: [PATCH 3/4] [Clang][AArch64] Fix crash with large arguments to MTE
built-ins
The second argument to `__builtin_arm_irg()` and `__builtin_arm_gmi()`
is expected to be 64-bit. When a wider type is passed, the compiler
still generates a `zext` instruction, leading to a backend error:
```
> cat test.c
unsigned test(void* a, unsigned __int128 m) {
return __builtin_arm_gmi(a, m);
}
> clang -target aarch64 -march=armv9+memtag -S test.c
fatal error: error in backend: Cannot select: ... i64,ch = load<... zext from i128>
```
This is fixed by replacing `CreateZExt()` with `CreateZExtOrTrunc()`.
---
clang/lib/CodeGen/TargetBuiltins/ARM.cpp | 4 ++--
clang/test/CodeGen/arm64-mte.c | 18 ++++++++++++++++++
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
index 647c3ff44928a..bccddf36d3cfa 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -4915,7 +4915,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Value *Pointer = EmitScalarExpr(E->getArg(0));
Value *Mask = EmitScalarExpr(E->getArg(1));
- Mask = Builder.CreateZExt(Mask, Int64Ty);
+ Mask = Builder.CreateZExtOrTrunc(Mask, Int64Ty);
return Builder.CreateCall(CGM.getIntrinsic(MTEIntrinsicID),
{Pointer, Mask});
}
@@ -4931,7 +4931,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
Value *Pointer = EmitScalarExpr(E->getArg(0));
Value *ExcludedMask = EmitScalarExpr(E->getArg(1));
- ExcludedMask = Builder.CreateZExt(ExcludedMask, Int64Ty);
+ ExcludedMask = Builder.CreateZExtOrTrunc(ExcludedMask, Int64Ty);
return Builder.CreateCall(
CGM.getIntrinsic(MTEIntrinsicID), {Pointer, ExcludedMask});
}
diff --git a/clang/test/CodeGen/arm64-mte.c b/clang/test/CodeGen/arm64-mte.c
index 9e2b3736ac4c0..c943ed7c4a0eb 100644
--- a/clang/test/CodeGen/arm64-mte.c
+++ b/clang/test/CodeGen/arm64-mte.c
@@ -35,6 +35,15 @@ char *create_tag3(char *a, unsigned b) {
return __arm_mte_create_random_tag(a,b);
}
+// CHECK-LABEL: define{{.*}} ptr @create_tag4
+attribute
+char *create_tag4(char *a, unsigned __int128 b) {
+// CHECK: [[T1:%[0-9]+]] = trunc i128 %b to i64
+// CHECK: [[T2:%[0-9]+]] = tail call ptr @llvm.aarch64.irg(ptr %a, i64 [[T1]])
+// CHECK: ret ptr [[T2:%[0-9]+]]
+ return __arm_mte_create_random_tag(a,b);
+}
+
// CHECK-LABEL: define{{.*}} ptr @increment_tag1
attribute
char *increment_tag1(char *a) {
@@ -67,6 +76,15 @@ int exclude_tag2(int *a, unsigned m) {
return __arm_mte_exclude_tag(a, m);
}
+// CHECK-LABEL: define{{.*}} i128 @exclude_tag3
+attribute
+unsigned __int128 exclude_tag3(int *a, unsigned __int128 m) {
+// CHECK: [[T0:%[0-9]+]] = trunc i128 %m to i64
+// CHECK: [[T2:%[0-9]+]] = tail call i64 @llvm.aarch64.gmi(ptr %a, i64 [[T0]])
+// CHECK: zext i64 [[T2]] to i128
+ return __arm_mte_exclude_tag(a, m);
+}
+
// CHECK-LABEL: define{{.*}} ptr @get_tag1
attribute
int *get_tag1(int *a) {
>From 75256ac94b95276511f214942c60b09cf4cb9dc8 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Thu, 21 May 2026 20:54:04 -0700
Subject: [PATCH 4/4] fixup! Convert arguments to uint64 in Sema
---
.../clang/Basic/DiagnosticSemaKinds.td | 2 --
clang/lib/CodeGen/TargetBuiltins/ARM.cpp | 12 +++++-----
clang/lib/Sema/SemaARM.cpp | 22 ++++++++++---------
clang/test/AST/ast-dump-aarch64-mte.c | 10 +++++----
clang/test/CodeGen/arm64-mte.c | 14 ++++++------
clang/test/Sema/builtins-arm64-mte.c | 16 +++++++++++---
6 files changed, 44 insertions(+), 32 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index dbe6cb2c3a41c..7a09d85f52ef4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13284,8 +13284,6 @@ def err_memtag_any2arg_pointer : Error<
"at least one argument of MTE builtin function must be a pointer (%0, %1 invalid)">;
def err_memtag_arg_must_be_pointer : Error<
"%0 argument of MTE builtin function must be a pointer (%1 invalid)">;
-def err_memtag_arg_must_be_integer : Error<
- "%0 argument of MTE builtin function must be an integer type (%1 invalid)">;
def warn_dereference_of_noderef_type : Warning<
"dereferencing %0; was declared with a 'noderef' type">, InGroup<NoDeref>;
diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
index 9e9b1895bea11..b7c7bc8ebf9a0 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -4914,8 +4914,8 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
if (MTEIntrinsicID == Intrinsic::aarch64_irg) {
Value *Pointer = EmitScalarExpr(E->getArg(0));
Value *Mask = EmitScalarExpr(E->getArg(1));
-
- Mask = Builder.CreateZExtOrTrunc(Mask, Int64Ty);
+ assert(Mask->getType()->getScalarSizeInBits() == 64 &&
+ "SemaARM::BuiltinARMMemoryTaggingCall() enforces this");
return Builder.CreateCall(CGM.getIntrinsic(MTEIntrinsicID),
{Pointer, Mask});
}
@@ -4930,10 +4930,10 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
if (MTEIntrinsicID == Intrinsic::aarch64_gmi) {
Value *Pointer = EmitScalarExpr(E->getArg(0));
Value *ExcludedMask = EmitScalarExpr(E->getArg(1));
-
- ExcludedMask = Builder.CreateZExtOrTrunc(ExcludedMask, Int64Ty);
- return Builder.CreateCall(
- CGM.getIntrinsic(MTEIntrinsicID), {Pointer, ExcludedMask});
+ assert(ExcludedMask->getType()->getScalarSizeInBits() == 64 &&
+ "SemaARM::BuiltinARMMemoryTaggingCall() enforces this");
+ return Builder.CreateCall(CGM.getIntrinsic(MTEIntrinsicID),
+ {Pointer, ExcludedMask});
}
// Although it is possible to supply a different return
// address (first arg) to this intrinsic, for now we set
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index f57c9c8b87cd5..47e4b4f90485a 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -42,13 +42,14 @@ bool SemaARM::BuiltinARMMemoryTaggingCall(unsigned BuiltinID,
<< "first" << FirstArgType << Arg0->getSourceRange();
TheCall->setArg(0, FirstArg.get());
- ExprResult SecArg = SemaRef.DefaultLvalueConversion(Arg1);
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ Context, Context.getIntTypeForBitwidth(64, /*Signed=*/false),
+ /*Consumed=*/false);
+ ExprResult SecArg =
+ SemaRef.PerformCopyInitialization(Entity,
+ /*EqualLoc=*/SourceLocation(), Arg1);
if (SecArg.isInvalid())
return true;
- QualType SecArgType = SecArg.get()->getType();
- if (!SecArgType->isIntegerType())
- return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_integer)
- << "second" << SecArgType << Arg1->getSourceRange();
TheCall->setArg(1, SecArg.get());
// Derive the return type from the pointer argument.
@@ -92,13 +93,14 @@ bool SemaARM::BuiltinARMMemoryTaggingCall(unsigned BuiltinID,
<< "first" << FirstArgType << Arg0->getSourceRange();
TheCall->setArg(0, FirstArg.get());
- ExprResult SecArg = SemaRef.DefaultLvalueConversion(Arg1);
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ Context, Context.getIntTypeForBitwidth(64, /*Signed=*/false),
+ /*Consumed=*/false);
+ ExprResult SecArg =
+ SemaRef.PerformCopyInitialization(Entity,
+ /*EqualLoc=*/SourceLocation(), Arg1);
if (SecArg.isInvalid())
return true;
- QualType SecArgType = SecArg.get()->getType();
- if (!SecArgType->isIntegerType())
- return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_integer)
- << "second" << SecArgType << Arg1->getSourceRange();
TheCall->setArg(1, SecArg.get());
return false;
diff --git a/clang/test/AST/ast-dump-aarch64-mte.c b/clang/test/AST/ast-dump-aarch64-mte.c
index c5def39676e9a..8e06371cafd77 100644
--- a/clang/test/AST/ast-dump-aarch64-mte.c
+++ b/clang/test/AST/ast-dump-aarch64-mte.c
@@ -21,8 +21,9 @@ void test() {
// CHECK-NEXT: | | | `-DeclRefExpr {{.+}} '<builtin fn type>' Function {{.+}} '__builtin_arm_irg' 'void *(void *, unsigned long)'
// CHECK-NEXT: | | |-ImplicitCastExpr {{.+}} 'struct A *' <LValueToRValue>
// CHECK-NEXT: | | | `-DeclRefExpr {{.+}} 'struct A *' lvalue Var {{.+}} 'ptr_a' 'struct A *'
- // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'unsigned int' <LValueToRValue>
- // CHECK-NEXT: | | `-DeclRefExpr {{.+}} 'unsigned int' lvalue Var {{.+}} 'uval' 'unsigned int'
+ // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'unsigned long' <IntegralCast>
+ // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'unsigned int' <LValueToRValue>
+ // CHECK-NEXT: | | `-DeclRefExpr {{.+}} 'unsigned int' lvalue Var {{.+}} 'uval' 'unsigned int'
ptr_a = __arm_mte_increment_tag(ptr_a, 5);
// CHECK-NEXT: | |-BinaryOperator {{.+}} 'struct A *' '='
@@ -43,8 +44,9 @@ void test() {
// CHECK-NEXT: | | | `-DeclRefExpr {{.+}} '<builtin fn type>' Function {{.+}} '__builtin_arm_gmi' 'unsigned long (void *, unsigned long)'
// CHECK-NEXT: | | |-ImplicitCastExpr {{.+}} 'struct A *' <LValueToRValue>
// CHECK-NEXT: | | | `-DeclRefExpr {{.+}} 'struct A *' lvalue Var {{.+}} 'ptr_a' 'struct A *'
- // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'unsigned int' <LValueToRValue>
- // CHECK-NEXT: | | `-DeclRefExpr {{.+}} 'unsigned int' lvalue Var {{.+}} 'uval' 'unsigned int'
+ // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'unsigned long' <IntegralCast>
+ // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} 'unsigned int' <LValueToRValue>
+ // CHECK-NEXT: | | `-DeclRefExpr {{.+}} 'unsigned int' lvalue Var {{.+}} 'uval' 'unsigned int'
ptr_a = __arm_mte_get_tag(ptr_a);
// CHECK-NEXT: | |-BinaryOperator {{.+}} 'struct A *' '='
diff --git a/clang/test/CodeGen/arm64-mte.c b/clang/test/CodeGen/arm64-mte.c
index c943ed7c4a0eb..6a00f12ce3671 100644
--- a/clang/test/CodeGen/arm64-mte.c
+++ b/clang/test/CodeGen/arm64-mte.c
@@ -13,7 +13,7 @@
// CHECK-LABEL: define{{.*}} ptr @create_tag1
attribute
int *create_tag1(int *a, unsigned b) {
-// CHECK: [[T1:%[0-9]+]] = zext i32 %b to i64
+// CHECK: [[T1:%[a-z0-9]+]] = zext i32 %b to i64
// CHECK: [[T2:%[0-9]+]] = tail call ptr @llvm.aarch64.irg(ptr %a, i64 [[T1]])
return __arm_mte_create_random_tag(a,b);
}
@@ -21,7 +21,7 @@ int *create_tag1(int *a, unsigned b) {
// CHECK-LABEL: define{{.*}} ptr @create_tag2
attribute
short *create_tag2(short *a, unsigned b) {
-// CHECK: [[T1:%[0-9]+]] = zext i32 %b to i64
+// CHECK: [[T1:%[a-z0-9]+]] = zext i32 %b to i64
// CHECK: [[T2:%[0-9]+]] = tail call ptr @llvm.aarch64.irg(ptr %a, i64 [[T1]])
return __arm_mte_create_random_tag(a,b);
}
@@ -29,7 +29,7 @@ short *create_tag2(short *a, unsigned b) {
// CHECK-LABEL: define{{.*}} ptr @create_tag3
attribute
char *create_tag3(char *a, unsigned b) {
-// CHECK: [[T1:%[0-9]+]] = zext i32 %b to i64
+// CHECK: [[T1:%[a-z0-9]+]] = zext i32 %b to i64
// CHECK: [[T2:%[0-9]+]] = tail call ptr @llvm.aarch64.irg(ptr %a, i64 [[T1]])
// CHECK: ret ptr [[T2:%[0-9]+]]
return __arm_mte_create_random_tag(a,b);
@@ -38,7 +38,7 @@ char *create_tag3(char *a, unsigned b) {
// CHECK-LABEL: define{{.*}} ptr @create_tag4
attribute
char *create_tag4(char *a, unsigned __int128 b) {
-// CHECK: [[T1:%[0-9]+]] = trunc i128 %b to i64
+// CHECK: [[T1:%[a-z0-9]+]] = trunc i128 %b to i64
// CHECK: [[T2:%[0-9]+]] = tail call ptr @llvm.aarch64.irg(ptr %a, i64 [[T1]])
// CHECK: ret ptr [[T2:%[0-9]+]]
return __arm_mte_create_random_tag(a,b);
@@ -61,7 +61,7 @@ short *increment_tag2(short *a) {
// CHECK-LABEL: define{{.*}} i32 @exclude_tag1
attribute
unsigned exclude_tag1(int *a, unsigned m) {
-// CHECK: [[T0:%[0-9]+]] = zext i32 %m to i64
+// CHECK: [[T0:%[a-z0-9]+]] = zext i32 %m to i64
// CHECK: [[T2:%[0-9]+]] = tail call i64 @llvm.aarch64.gmi(ptr %a, i64 [[T0]])
// CHECK: trunc i64 [[T2]] to i32
return __arm_mte_exclude_tag(a, m);
@@ -70,7 +70,7 @@ unsigned exclude_tag1(int *a, unsigned m) {
// CHECK-LABEL: define{{.*}} i32 @exclude_tag2
attribute
int exclude_tag2(int *a, unsigned m) {
-// CHECK: [[T0:%[0-9]+]] = zext i32 %m to i64
+// CHECK: [[T0:%[a-z0-9]+]] = zext i32 %m to i64
// CHECK: [[T2:%[0-9]+]] = tail call i64 @llvm.aarch64.gmi(ptr %a, i64 [[T0]])
// CHECK: trunc i64 [[T2]] to i32
return __arm_mte_exclude_tag(a, m);
@@ -79,7 +79,7 @@ int exclude_tag2(int *a, unsigned m) {
// CHECK-LABEL: define{{.*}} i128 @exclude_tag3
attribute
unsigned __int128 exclude_tag3(int *a, unsigned __int128 m) {
-// CHECK: [[T0:%[0-9]+]] = trunc i128 %m to i64
+// CHECK: [[T0:%[a-z0-9]+]] = trunc i128 %m to i64
// CHECK: [[T2:%[0-9]+]] = tail call i64 @llvm.aarch64.gmi(ptr %a, i64 [[T0]])
// CHECK: zext i64 [[T2]] to i128
return __arm_mte_exclude_tag(a, m);
diff --git a/clang/test/Sema/builtins-arm64-mte.c b/clang/test/Sema/builtins-arm64-mte.c
index 1b0621f3c5e31..252ff88c4fd56 100644
--- a/clang/test/Sema/builtins-arm64-mte.c
+++ b/clang/test/Sema/builtins-arm64-mte.c
@@ -11,8 +11,13 @@ int *create_tag1(int a, unsigned b) {
}
int *create_tag2(int *a, unsigned *b) {
- // expected-error at +1 {{second argument of MTE builtin function must be an integer type ('unsigned int *' invalid)}}
+#ifdef __cplusplus
+ // expected-error at +1 {{cannot initialize a parameter of type 'unsigned long' with an lvalue of type 'unsigned int *'}}
+ return __arm_mte_create_random_tag(a,b);
+#else
+ // expected-error at +1 {{incompatible pointer to integer conversion passing 'unsigned int *' to parameter of type 'unsigned long'}}
return __arm_mte_create_random_tag(a,b);
+#endif
}
int *create_tag3(const int *a, unsigned b) {
@@ -76,8 +81,13 @@ unsigned exclude_tag1(int *ptr, unsigned m) {
}
unsigned exclude_tag2(int *ptr, int *m) {
- // expected-error at +1 {{second argument of MTE builtin function must be an integer type ('int *' invalid)}}
+#ifdef __cplusplus
+ // expected-error at +1 {{cannot initialize a parameter of type 'unsigned long' with an lvalue of type 'int *'}}
return __arm_mte_exclude_tag(ptr, m);
+#else
+ // expected-error at +1 {{incompatible pointer to integer conversion passing 'int *' to parameter of type 'unsigned long'}}
+ return __arm_mte_exclude_tag(ptr, m);
+#endif
}
void get_tag1(void) {
@@ -142,4 +152,4 @@ int *create_tag1(int *a, unsigned b) {
// expected-error at +1 {{'__builtin_arm_irg' needs target feature mte}}
return __arm_mte_create_random_tag(a,b);
}
-#endif
\ No newline at end of file
+#endif
More information about the cfe-commits
mailing list