[clang] [clang] Define ptrauth_string_discriminator builtin. (PR #93903)

Ahmed Bougacha via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 18 13:55:29 PDT 2024


https://github.com/ahmedbougacha updated https://github.com/llvm/llvm-project/pull/93903

>From 607592e7071a604fc63252cb3686545ed1f1b0b8 Mon Sep 17 00:00:00 2001
From: Ahmed Bougacha <ahmed at bougacha.org>
Date: Thu, 30 May 2024 17:22:29 -0700
Subject: [PATCH 1/6] [clang] Define ptrauth_string_discriminator builtin.

This exposes the ABI-stable hash function that allows computing a 16-bit
discriminator from a constant string.

This allows manually matching the implicit string discriminators
computed in the ABI (e.g., from mangled names for vtable pointer/entry
signing), as well as enabling the use of interesting discriminators when
manually annotating specific pointers with the __ptrauth qualifier.

Co-Authored-By: John McCall <rjmccall at apple.com>
---
 clang/include/clang/Basic/Builtins.td         |  6 ++++++
 .../clang/Basic/DiagnosticSemaKinds.td        |  2 ++
 clang/lib/AST/ExprConstant.cpp                |  7 +++++++
 clang/lib/Headers/ptrauth.h                   | 17 ++++++++++++++++
 clang/lib/Sema/SemaChecking.cpp               | 20 +++++++++++++++++++
 clang/test/CodeGen/ptrauth-intrinsics.c       | 13 ++++++++++++
 clang/test/Sema/ptrauth-intrinsics-macro.c    |  5 +++++
 7 files changed, 70 insertions(+)

diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 7bef5fd7ad40f..e07ddf3b9b70b 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4411,6 +4411,12 @@ def PtrauthAuth : Builtin {
   let Prototype = "void*(void*,int,void*)";
 }
 
+def PtrauthStringDiscriminator : Builtin {
+  let Spellings = ["__builtin_ptrauth_string_discriminator"];
+  let Attributes = [NoThrow, Const, Constexpr];
+  let Prototype = "size_t(char const*)";
+}
+
 // OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions.
 // We need the generic prototype, since the packet type could be anything.
 def ReadPipe : OCLPipeLangBuiltin {
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 14736784cff5f..0900dad3c18cd 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -930,6 +930,8 @@ def warn_ptrauth_sign_null_pointer :
 def warn_ptrauth_auth_null_pointer :
   Warning<"authenticating a null pointer will almost certainly trap">,
   InGroup<PtrAuthNullPointers>;
+def err_ptrauth_string_not_literal : Error<
+  "argument must be a string literal%select{| of char type}0">;
 
 /// main()
 // static main() is not an error in C, just in C++.
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 9ac53438de8e4..c9467c5ea1847 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -58,6 +58,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/SipHash.h"
 #include "llvm/Support/TimeProfiler.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cstring>
@@ -12590,6 +12591,12 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
   case Builtin::BI__builtin_expect_with_probability:
     return Visit(E->getArg(0));
 
+  case Builtin::BI__builtin_ptrauth_string_discriminator: {
+    auto literal = cast<StringLiteral>(E->getArg(0)->IgnoreParenImpCasts());
+    auto result = getPointerAuthStableSipHash16(literal->getString());
+    return Success(result, E);
+  }
+
   case Builtin::BI__builtin_ffs:
   case Builtin::BI__builtin_ffsl:
   case Builtin::BI__builtin_ffsll: {
diff --git a/clang/lib/Headers/ptrauth.h b/clang/lib/Headers/ptrauth.h
index a9d182aa24470..cce639dc8170c 100644
--- a/clang/lib/Headers/ptrauth.h
+++ b/clang/lib/Headers/ptrauth.h
@@ -125,6 +125,17 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
 #define ptrauth_auth_data(__value, __old_key, __old_data)                      \
   __builtin_ptrauth_auth(__value, __old_key, __old_data)
 
+/* Compute a constant discriminator from the given string.
+
+   The result can be used as the second argument to
+   ptrauth_blend_discriminator or the third argument to the
+   __ptrauth qualifier.  It has type size_t.
+
+   The argument must be a string literal.
+   A call to this function is an integer constant expression. */
+#define ptrauth_string_discriminator(__string)                                 \
+  __builtin_ptrauth_string_discriminator(__string)
+
 /* Compute a signature for the given pair of pointer-sized values.
    The order of the arguments is significant.
 
@@ -186,6 +197,12 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
     __value;                                                                   \
   })
 
+#define ptrauth_string_discriminator(__string)                                 \
+  ({                                                                           \
+    (void)__string;                                                            \
+    ((ptrauth_extra_data_t)0);                                                 \
+  })
+
 #define ptrauth_sign_generic_data(__value, __data)                             \
   ({                                                                           \
     (void)__value;                                                             \
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 07cd0727eb3f4..b583de94b594c 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2166,6 +2166,24 @@ static ExprResult PointerAuthAuthAndResign(Sema &S, CallExpr *Call) {
   return Call;
 }
 
+static ExprResult PointerAuthStringDiscriminator(Sema &S, CallExpr *call) {
+  if (checkPointerAuthEnabled(S, call)) return ExprError();
+
+  // We've already performed normal call type-checking.
+  Expr *arg = call->getArgs()[0]->IgnoreParenImpCasts();
+
+  // Operand must be an ordinary or UTF-8 string literal.
+  auto literal = dyn_cast<StringLiteral>(arg);
+  if (!literal || literal->getCharByteWidth() != 1) {
+    S.Diag(arg->getExprLoc(), diag::err_ptrauth_string_not_literal)
+      << (literal ? 1 : 0)
+      << arg->getSourceRange();
+    return ExprError();
+  }
+
+  return call;
+}
+
 static ExprResult BuiltinLaunder(Sema &S, CallExpr *TheCall) {
   if (S.checkArgCount(TheCall, 1))
     return ExprError();
@@ -2933,6 +2951,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
     return PointerAuthSignGenericData(*this, TheCall);
   case Builtin::BI__builtin_ptrauth_auth_and_resign:
     return PointerAuthAuthAndResign(*this, TheCall);
+  case Builtin::BI__builtin_ptrauth_string_discriminator:
+    return PointerAuthStringDiscriminator(*this, TheCall);
   // OpenCL v2.0, s6.13.16 - Pipe functions
   case Builtin::BIread_pipe:
   case Builtin::BIwrite_pipe:
diff --git a/clang/test/CodeGen/ptrauth-intrinsics.c b/clang/test/CodeGen/ptrauth-intrinsics.c
index 17f28dddb3801..d602325da8b17 100644
--- a/clang/test/CodeGen/ptrauth-intrinsics.c
+++ b/clang/test/CodeGen/ptrauth-intrinsics.c
@@ -71,3 +71,16 @@ void test_sign_generic_data() {
   // CHECK-NEXT: store i64 [[RESULT]], ptr @signature,
   signature = __builtin_ptrauth_sign_generic_data(fnptr, ptr_discriminator);
 }
+
+// CHECK-LABEL: define void @test_string_discriminator()
+void test_string_discriminator() {
+  // CHECK:      [[X:%.*]] = alloca i32
+
+  // Check a couple of random discriminators used by Swift.
+
+  // CHECK:      store i32 58298, ptr [[X]],
+  int x = __builtin_ptrauth_string_discriminator("InitializeWithCopy");
+
+  // CHECK:      store i32 9112, ptr [[X]],
+  x = __builtin_ptrauth_string_discriminator("DestroyArray");
+}
diff --git a/clang/test/Sema/ptrauth-intrinsics-macro.c b/clang/test/Sema/ptrauth-intrinsics-macro.c
index 07d6374045145..540f2846b7ce1 100644
--- a/clang/test/Sema/ptrauth-intrinsics-macro.c
+++ b/clang/test/Sema/ptrauth-intrinsics-macro.c
@@ -32,3 +32,8 @@ void test(int *dp, int value) {
   int t2 = ptrauth_sign_generic_data(dp, 0);
   (void)t2;
 }
+
+void test_string_discriminator(int *dp) {
+  ptrauth_extra_data_t t0 = ptrauth_string_discriminator("string");
+  (void)t0;
+}

>From 8e948733ffcd82e43f72a76d6595ae6a6173f500 Mon Sep 17 00:00:00 2001
From: Ahmed Bougacha <ahmed at bougacha.org>
Date: Mon, 3 Jun 2024 11:00:39 -0700
Subject: [PATCH 2/6] Document ptrauth_string_discriminator in
 clang/docs/PointerAuthentication.

---
 clang/docs/PointerAuthentication.rst | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/clang/docs/PointerAuthentication.rst b/clang/docs/PointerAuthentication.rst
index 19b3384293aed..bd8bf92984225 100644
--- a/clang/docs/PointerAuthentication.rst
+++ b/clang/docs/PointerAuthentication.rst
@@ -328,6 +328,21 @@ be done in a single instruction with an immediate integer.
 ``pointer`` must have pointer type, and ``integer`` must have integer type. The
 result has type ``ptrauth_extra_data_t``.
 
+``ptrauth_string_discriminator``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: c
+
+  ptrauth_string_discriminator(string)
+
+Produce a discriminator value for the given string.  ``string`` must be
+a string literal of ``char`` character type.  The result has type
+``ptrauth_extra_data_t``.
+
+The result is always a constant expression.  The result value is never zero and
+always within range for both the ``__ptrauth`` qualifier and
+``ptrauth_blend_discriminator``.
+
 ``ptrauth_strip``
 ^^^^^^^^^^^^^^^^^
 

>From e41501874dcc45ab57dba09cb0a08c4f68d0677b Mon Sep 17 00:00:00 2001
From: Ahmed Bougacha <ahmed at bougacha.org>
Date: Mon, 3 Jun 2024 13:32:21 -0700
Subject: [PATCH 3/6] Address review feedback.

- add missing sema test
- also test ELF codegen for intrinsics
- various capitalization and type nits
---
 clang/lib/AST/ExprConstant.cpp          |  7 ++++---
 clang/lib/Sema/SemaChecking.cpp         | 18 +++++++++---------
 clang/test/CodeGen/ptrauth-intrinsics.c | 15 ++++++++-------
 clang/test/Sema/ptrauth.c               | 11 +++++++++++
 4 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index c9467c5ea1847..12c233bd35ec7 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -12592,9 +12592,10 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
     return Visit(E->getArg(0));
 
   case Builtin::BI__builtin_ptrauth_string_discriminator: {
-    auto literal = cast<StringLiteral>(E->getArg(0)->IgnoreParenImpCasts());
-    auto result = getPointerAuthStableSipHash16(literal->getString());
-    return Success(result, E);
+    const auto *Literal =
+        cast<StringLiteral>(E->getArg(0)->IgnoreParenImpCasts());
+    uint64_t Result = getPointerAuthStableSipHash16(Literal->getString());
+    return Success(Result, E);
   }
 
   case Builtin::BI__builtin_ffs:
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index b583de94b594c..324c02075f19b 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2166,22 +2166,22 @@ static ExprResult PointerAuthAuthAndResign(Sema &S, CallExpr *Call) {
   return Call;
 }
 
-static ExprResult PointerAuthStringDiscriminator(Sema &S, CallExpr *call) {
-  if (checkPointerAuthEnabled(S, call)) return ExprError();
+static ExprResult PointerAuthStringDiscriminator(Sema &S, CallExpr *Call) {
+  if (checkPointerAuthEnabled(S, Call)) return ExprError();
 
   // We've already performed normal call type-checking.
-  Expr *arg = call->getArgs()[0]->IgnoreParenImpCasts();
+  const Expr *Arg = Call->getArg(0)->IgnoreParenImpCasts();
 
   // Operand must be an ordinary or UTF-8 string literal.
-  auto literal = dyn_cast<StringLiteral>(arg);
-  if (!literal || literal->getCharByteWidth() != 1) {
-    S.Diag(arg->getExprLoc(), diag::err_ptrauth_string_not_literal)
-      << (literal ? 1 : 0)
-      << arg->getSourceRange();
+  const auto *Literal = dyn_cast<StringLiteral>(Arg);
+  if (!Literal || Literal->getCharByteWidth() != 1) {
+    S.Diag(Arg->getExprLoc(), diag::err_ptrauth_string_not_literal)
+      << (Literal ? 1 : 0)
+      << Arg->getSourceRange();
     return ExprError();
   }
 
-  return call;
+  return Call;
 }
 
 static ExprResult BuiltinLaunder(Sema &S, CallExpr *TheCall) {
diff --git a/clang/test/CodeGen/ptrauth-intrinsics.c b/clang/test/CodeGen/ptrauth-intrinsics.c
index d602325da8b17..db37d78553769 100644
--- a/clang/test/CodeGen/ptrauth-intrinsics.c
+++ b/clang/test/CodeGen/ptrauth-intrinsics.c
@@ -1,11 +1,12 @@
 // RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-intrinsics -emit-llvm %s  -o - | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-elf     -fptrauth-intrinsics -emit-llvm %s  -o - | FileCheck %s
 
 void (*fnptr)(void);
 long int_discriminator;
 void *ptr_discriminator;
 long signature;
 
-// CHECK-LABEL: define void @test_auth()
+// CHECK-LABEL: define {{.*}}void @test_auth()
 void test_auth() {
   // CHECK:      [[PTR:%.*]] = load ptr, ptr @fnptr,
   // CHECK-NEXT: [[DISC0:%.*]] = load ptr, ptr @ptr_discriminator,
@@ -17,7 +18,7 @@ void test_auth() {
   fnptr = __builtin_ptrauth_auth(fnptr, 0, ptr_discriminator);
 }
 
-// CHECK-LABEL: define void @test_strip()
+// CHECK-LABEL: define {{.*}}void @test_strip()
 void test_strip() {
   // CHECK:      [[PTR:%.*]] = load ptr, ptr @fnptr,
   // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[PTR]] to i64
@@ -27,7 +28,7 @@ void test_strip() {
   fnptr = __builtin_ptrauth_strip(fnptr, 0);
 }
 
-// CHECK-LABEL: define void @test_sign_unauthenticated()
+// CHECK-LABEL: define {{.*}}void @test_sign_unauthenticated()
 void test_sign_unauthenticated() {
   // CHECK:      [[PTR:%.*]] = load ptr, ptr @fnptr,
   // CHECK-NEXT: [[DISC0:%.*]] = load ptr, ptr @ptr_discriminator,
@@ -39,7 +40,7 @@ void test_sign_unauthenticated() {
   fnptr = __builtin_ptrauth_sign_unauthenticated(fnptr, 0, ptr_discriminator);
 }
 
-// CHECK-LABEL: define void @test_auth_and_resign()
+// CHECK-LABEL: define {{.*}}void @test_auth_and_resign()
 void test_auth_and_resign() {
   // CHECK:      [[PTR:%.*]] = load ptr, ptr @fnptr,
   // CHECK-NEXT: [[DISC0:%.*]] = load ptr, ptr @ptr_discriminator,
@@ -51,7 +52,7 @@ void test_auth_and_resign() {
   fnptr = __builtin_ptrauth_auth_and_resign(fnptr, 0, ptr_discriminator, 3, 15);
 }
 
-// CHECK-LABEL: define void @test_blend_discriminator()
+// CHECK-LABEL: define {{.*}}void @test_blend_discriminator()
 void test_blend_discriminator() {
   // CHECK:      [[PTR:%.*]] = load ptr, ptr @fnptr,
   // CHECK-NEXT: [[DISC:%.*]] = load i64, ptr @int_discriminator,
@@ -61,7 +62,7 @@ void test_blend_discriminator() {
   int_discriminator = __builtin_ptrauth_blend_discriminator(fnptr, int_discriminator);
 }
 
-// CHECK-LABEL: define void @test_sign_generic_data()
+// CHECK-LABEL: define {{.*}}void @test_sign_generic_data()
 void test_sign_generic_data() {
   // CHECK:      [[PTR:%.*]] = load ptr, ptr @fnptr,
   // CHECK-NEXT: [[DISC0:%.*]] = load ptr, ptr @ptr_discriminator,
@@ -72,7 +73,7 @@ void test_sign_generic_data() {
   signature = __builtin_ptrauth_sign_generic_data(fnptr, ptr_discriminator);
 }
 
-// CHECK-LABEL: define void @test_string_discriminator()
+// CHECK-LABEL: define {{.*}}void @test_string_discriminator()
 void test_string_discriminator() {
   // CHECK:      [[X:%.*]] = alloca i32
 
diff --git a/clang/test/Sema/ptrauth.c b/clang/test/Sema/ptrauth.c
index 3ad3d70c24e41..467ce5e02038c 100644
--- a/clang/test/Sema/ptrauth.c
+++ b/clang/test/Sema/ptrauth.c
@@ -47,6 +47,17 @@ void test_blend_discriminator(int *dp, int (*fp)(int), int value) {
   float *mismatch = __builtin_ptrauth_blend_discriminator(dp, value); // expected-error {{incompatible integer to pointer conversion initializing 'float *' with an expression of type}}
 }
 
+void test_string_discriminator(const char *str) {
+  __builtin_ptrauth_string_discriminator(); // expected-error {{too few arguments}}
+  __builtin_ptrauth_string_discriminator(str, str); // expected-error {{too many arguments}}
+  (void) __builtin_ptrauth_string_discriminator("test string"); // no warning
+
+  __builtin_ptrauth_string_discriminator(str); // expected-error {{argument must be a string literal}}
+
+  void *mismatch = __builtin_ptrauth_string_discriminator("test string"); // expected-error {{incompatible integer to pointer conversion initializing 'void *' with an expression of type 'unsigned long'}}
+}
+
+
 void test_sign_unauthenticated(int *dp, int (*fp)(int)) {
   __builtin_ptrauth_sign_unauthenticated(dp, VALID_DATA_KEY); // expected-error {{too few arguments}}
   __builtin_ptrauth_sign_unauthenticated(dp, VALID_DATA_KEY, dp, dp); // expected-error {{too many arguments}}

>From a70e589bb5de3b6658b25a74db0f339c1e35157d Mon Sep 17 00:00:00 2001
From: Ahmed Bougacha <ahmed at bougacha.org>
Date: Mon, 3 Jun 2024 13:38:23 -0700
Subject: [PATCH 4/6] Format.

---
 clang/lib/Sema/SemaChecking.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 324c02075f19b..60a7a383858a2 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2167,7 +2167,8 @@ static ExprResult PointerAuthAuthAndResign(Sema &S, CallExpr *Call) {
 }
 
 static ExprResult PointerAuthStringDiscriminator(Sema &S, CallExpr *Call) {
-  if (checkPointerAuthEnabled(S, Call)) return ExprError();
+  if (checkPointerAuthEnabled(S, Call))
+    return ExprError();
 
   // We've already performed normal call type-checking.
   const Expr *Arg = Call->getArg(0)->IgnoreParenImpCasts();
@@ -2176,8 +2177,7 @@ static ExprResult PointerAuthStringDiscriminator(Sema &S, CallExpr *Call) {
   const auto *Literal = dyn_cast<StringLiteral>(Arg);
   if (!Literal || Literal->getCharByteWidth() != 1) {
     S.Diag(Arg->getExprLoc(), diag::err_ptrauth_string_not_literal)
-      << (Literal ? 1 : 0)
-      << Arg->getSourceRange();
+        << (Literal ? 1 : 0) << Arg->getSourceRange();
     return ExprError();
   }
 

>From 30be782dc331f8a8f02aed1641042e99bad680a6 Mon Sep 17 00:00:00 2001
From: Ahmed Bougacha <ahmed at bougacha.org>
Date: Mon, 17 Jun 2024 09:34:02 -0700
Subject: [PATCH 5/6] Adopt renamed getPointerAuthStableSipHash.

---
 clang/lib/AST/ExprConstant.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 12c233bd35ec7..97b4c2080e14f 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -12594,7 +12594,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
   case Builtin::BI__builtin_ptrauth_string_discriminator: {
     const auto *Literal =
         cast<StringLiteral>(E->getArg(0)->IgnoreParenImpCasts());
-    uint64_t Result = getPointerAuthStableSipHash16(Literal->getString());
+    uint64_t Result = getPointerAuthStableSipHash(Literal->getString());
     return Success(Result, E);
   }
 

>From 11e7dcc489e2159c5747b57e3d1379764128c3dc Mon Sep 17 00:00:00 2001
From: Ahmed Bougacha <ahmed at bougacha.org>
Date: Mon, 17 Jun 2024 13:56:58 -0700
Subject: [PATCH 6/6] Address review feedback.

- tweaks to header/doc comments
- add test for wide string literal
---
 clang/docs/PointerAuthentication.rst | 14 ++++++++------
 clang/lib/Headers/ptrauth.h          | 12 +++++++-----
 clang/test/Sema/ptrauth.c            |  1 +
 3 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/clang/docs/PointerAuthentication.rst b/clang/docs/PointerAuthentication.rst
index bd8bf92984225..130e6571a7bdb 100644
--- a/clang/docs/PointerAuthentication.rst
+++ b/clang/docs/PointerAuthentication.rst
@@ -335,13 +335,15 @@ result has type ``ptrauth_extra_data_t``.
 
   ptrauth_string_discriminator(string)
 
-Produce a discriminator value for the given string.  ``string`` must be
-a string literal of ``char`` character type.  The result has type
-``ptrauth_extra_data_t``.
+Compute a constant discriminator from the given string.
 
-The result is always a constant expression.  The result value is never zero and
-always within range for both the ``__ptrauth`` qualifier and
-``ptrauth_blend_discriminator``.
+``string`` must be a string literal of ``char`` character type.  The result has
+type ``ptrauth_extra_data_t``.
+
+The result value is never zero and always within range for both the
+``__ptrauth`` qualifier and ``ptrauth_blend_discriminator``.
+
+This can be used in constant expressions.
 
 ``ptrauth_strip``
 ^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Headers/ptrauth.h b/clang/lib/Headers/ptrauth.h
index cce639dc8170c..fd9df16bcc614 100644
--- a/clang/lib/Headers/ptrauth.h
+++ b/clang/lib/Headers/ptrauth.h
@@ -127,12 +127,14 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
 
 /* Compute a constant discriminator from the given string.
 
-   The result can be used as the second argument to
-   ptrauth_blend_discriminator or the third argument to the
-   __ptrauth qualifier.  It has type size_t.
+   The argument must be a string literal of char character type.  The result
+   has type ptrauth_extra_data_t.
 
-   The argument must be a string literal.
-   A call to this function is an integer constant expression. */
+   The result value is never zero and always within range for both the
+   __ptrauth qualifier and ptrauth_blend_discriminator.
+
+   This can be used in constant expressions.
+*/
 #define ptrauth_string_discriminator(__string)                                 \
   __builtin_ptrauth_string_discriminator(__string)
 
diff --git a/clang/test/Sema/ptrauth.c b/clang/test/Sema/ptrauth.c
index 467ce5e02038c..20786093ecd4c 100644
--- a/clang/test/Sema/ptrauth.c
+++ b/clang/test/Sema/ptrauth.c
@@ -53,6 +53,7 @@ void test_string_discriminator(const char *str) {
   (void) __builtin_ptrauth_string_discriminator("test string"); // no warning
 
   __builtin_ptrauth_string_discriminator(str); // expected-error {{argument must be a string literal}}
+  __builtin_ptrauth_string_discriminator(L"wide test"); // expected-error {{argument must be a string literal}} expected-warning {{incompatible pointer types passing 'int[10]' to parameter of type 'const char *'}}
 
   void *mismatch = __builtin_ptrauth_string_discriminator("test string"); // expected-error {{incompatible integer to pointer conversion initializing 'void *' with an expression of type 'unsigned long'}}
 }



More information about the cfe-commits mailing list