[clang] [clang][PAC] ptrauth_qualifier and ptrauth_intrinsic should only be available on Darwin (PR #153912)
Oliver Hunt via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 18 06:22:07 PDT 2025
https://github.com/ojhunt updated https://github.com/llvm/llvm-project/pull/153912
>From ea731927d6bdf85a3cdb333b756447658f2c2ea6 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oliver at apple.com>
Date: Fri, 15 Aug 2025 18:40:12 -0700
Subject: [PATCH 1/4] [clang][PAC] Make ptrauth_qualifier and ptrauth_intrinsic
Darwin only features
For backwards compatibility reasons the ptrauth_qualifier and ptrauth_intrinsic
features need to be testable with __has_feature() on Apple platforms, but for
other platforms this backwards compatibility issue does not exist.
This PR resolves these issues by making the ptrauth_qualifier and
ptrauth_intrinsic tests conditional upon a darwin target. This also
allows us to revert the ptrauth_qualifier check from an extension to a
feature test again, as is required on these platforms.
At the same time we introduce a new predefined macro __PTRAUTH__
that answers the same question as __has_feature(ptrauth_qualifier)
and __has_feature(ptrauth_intrinsic) as those tests are synonymous
and only exist separately for compatibility reasons.
The requirement to test for the __PTRAUTH__ macro also resolves the
hazard presented by mixing the ptrauth_qualifier flag (that impacts
ABI and security policies) with -pedantics-errors, which makes
__has_extension return false for all extensions.
---
clang/include/clang/Basic/Features.def | 4 +--
clang/lib/Frontend/FrontendActions.cpp | 1 +
clang/lib/Frontend/InitPreprocessor.cpp | 3 +++
clang/lib/Headers/ptrauth.h | 4 +--
clang/lib/Lex/PPMacroExpansion.cpp | 1 +
clang/test/Preprocessor/ptrauth_extension.c | 30 ++++++++++++++++++---
clang/test/Preprocessor/ptrauth_feature.c | 2 +-
clang/test/Sema/ptrauth-qualifier.c | 16 +++++++++--
clang/test/SemaObjC/ptrauth-qualifier.m | 16 +++++++++--
9 files changed, 64 insertions(+), 13 deletions(-)
diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def
index b9efc6a6a2e9d..6f414105d7c36 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -147,8 +147,8 @@ FEATURE(type_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Type))
FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread))
FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow))
FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
-FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics)
-EXTENSION(ptrauth_qualifier, LangOpts.PointerAuthIntrinsics)
+FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics && Target.getTriple().isOSDarwin())
+FEATURE(ptrauth_qualifier, LangOpts.PointerAuthIntrinsics && Target.getTriple().isOSDarwin())
FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls)
FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns)
FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtrAddressDiscrimination)
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index 685a9bbf2cde9..d29a08c43fc12 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -1159,6 +1159,7 @@ void DumpCompilerOptionsAction::ExecuteAction() {
raw_ostream &OS = *OSP;
const Preprocessor &PP = CI.getPreprocessor();
const LangOptions &LangOpts = PP.getLangOpts();
+ const TargetInfo &Target = CI.getTarget();
// FIXME: Rather than manually format the JSON (which is awkward due to
// needing to remove trailing commas), this should make use of a JSON library.
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 008a35d5265e1..accddfebc0f6f 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -1528,6 +1528,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
#undef TARGET_OS
}
+ if (LangOpts.PointerAuthIntrinsics)
+ Builder.defineMacro("__PTRAUTH__");
+
// Get other target #defines.
TI.getTargetDefines(LangOpts, Builder);
}
diff --git a/clang/lib/Headers/ptrauth.h b/clang/lib/Headers/ptrauth.h
index 7f7d387cbdfda..f902ca1e3bbd3 100644
--- a/clang/lib/Headers/ptrauth.h
+++ b/clang/lib/Headers/ptrauth.h
@@ -95,7 +95,7 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
__ptrauth qualifier; the compiler will perform this check
automatically. */
-#if __has_feature(ptrauth_intrinsics)
+#if __has_feature(ptrauth_intrinsics) || defined(__PTRAUTH__)
/* Strip the signature from a value without authenticating it.
@@ -388,6 +388,6 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
#define __ptrauth_objc_isa_uintptr
#define __ptrauth_objc_super_pointer
-#endif /* __has_feature(ptrauth_intrinsics) */
+#endif /* __has_feature(ptrauth_intrinsics) || defined(__PTRAUTH__) */
#endif /* __PTRAUTH_H */
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index 6f12ac80d677e..f9dfd0eb14bc0 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1089,6 +1089,7 @@ static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc,
/// specified by the identifier as a standard language feature.
static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
const LangOptions &LangOpts = PP.getLangOpts();
+ const TargetInfo &Target = PP.getTargetInfo();
// Normalize the feature name, __foo__ becomes foo.
if (Feature.starts_with("__") && Feature.ends_with("__") &&
diff --git a/clang/test/Preprocessor/ptrauth_extension.c b/clang/test/Preprocessor/ptrauth_extension.c
index d6b79187ba62d..3267b0786c28f 100644
--- a/clang/test/Preprocessor/ptrauth_extension.c
+++ b/clang/test/Preprocessor/ptrauth_extension.c
@@ -4,10 +4,32 @@
// RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-calls | \
// RUN: FileCheck %s --check-prefixes=NOINTRIN
-#if __has_extension(ptrauth_qualifier)
-// INTRIN: has_ptrauth_qualifier
-void has_ptrauth_qualifier() {}
-#else
+// RUN: %clang_cc1 -E %s -DIS_DARWIN -triple=arm64e-apple-darwin -fptrauth-intrinsics | \
+// RUN: FileCheck %s --check-prefixes=INTRIN,INTRIN_MAC
+
+// RUN: %clang_cc1 -E %s -DIS_DARWIN -triple=arm64e-apple-darwin -fptrauth-calls | \
+// RUN: FileCheck %s --check-prefixes=NOINTRIN
+
+#if defined(IS_DARWIN) && __has_extension(ptrauth_qualifier)
+// INTRIN_MAC: has_ptrauth_qualifier1
+void has_ptrauth_qualifier1() {}
+#ifndef __PTRAUTH__
+#error ptrauth_qualifier extension present without predefined test macro
+#endif
+#endif
+#if defined(IS_DARWIN) && __has_feature(ptrauth_qualifier)
+// INTRIN_MAC: has_ptrauth_qualifier2
+void has_ptrauth_qualifier2() {}
+#ifndef __PTRAUTH__
+#error ptrauth_qualifier extension present without predefined test macro
+#endif
+#endif
+#if defined(__PTRAUTH__)
+// INTRIN: has_ptrauth_qualifier3
+void has_ptrauth_qualifier3() {}
+#endif
+
+#if !defined(__PTRAUTH__) && !__has_feature(ptrauth_qualifier) && !__has_extension(ptrauth_qualifier)
// NOINTRIN: no_ptrauth_qualifier
void no_ptrauth_qualifier() {}
#endif
diff --git a/clang/test/Preprocessor/ptrauth_feature.c b/clang/test/Preprocessor/ptrauth_feature.c
index a440791d6cc69..45d9cd4245dba 100644
--- a/clang/test/Preprocessor/ptrauth_feature.c
+++ b/clang/test/Preprocessor/ptrauth_feature.c
@@ -34,7 +34,7 @@
// RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-elf-got | \
// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,ELFGOT
-#if __has_feature(ptrauth_intrinsics)
+#if defined(__PTRAUTH__)
// INTRIN: has_ptrauth_intrinsics
void has_ptrauth_intrinsics() {}
#else
diff --git a/clang/test/Sema/ptrauth-qualifier.c b/clang/test/Sema/ptrauth-qualifier.c
index 5d932b724f07a..3e568ce9f37e3 100644
--- a/clang/test/Sema/ptrauth-qualifier.c
+++ b/clang/test/Sema/ptrauth-qualifier.c
@@ -1,13 +1,25 @@
-// RUN: %clang_cc1 -triple arm64-apple-ios -std=c23 -fsyntax-only -verify -fptrauth-intrinsics %s
+// RUN: %clang_cc1 -triple arm64-apple-ios -DIS_DARWIN -std=c23 -fsyntax-only -verify -fptrauth-intrinsics %s
// RUN: %clang_cc1 -triple aarch64-linux-gnu -std=c23 -fsyntax-only -verify -fptrauth-intrinsics %s
-#if !__has_extension(ptrauth_qualifier)
+#if defined(IS_DARWIN) && !__has_extension(ptrauth_qualifier)
// This error means that the __ptrauth qualifier availability test says that it
// is not available. This error is not expected in the output, if it is seen
// there is a feature detection regression.
#error __ptrauth qualifier not enabled
#endif
+#if defined(IS_DARWIN) && !__has_feature(ptrauth_qualifier)
+// This error means that the __has_feature test for ptrauth_qualifier has
+// failed, despite it being expected on darwin.
+#error __ptrauth qualifier not enabled
+#elif !defined(IS_DARWIN) && (__has_feature(ptrauth_qualifier) || __has_extension(ptrauth_qualifier))
+#error ptrauth_qualifier labeled a feature on a non-darwin platform
+#endif
+
+#if !defined (__PTRAUTH__)
+#error __PTRAUTH__ test macro not defined when ptrauth is enabled
+#endif
+
#if __aarch64__
#define VALID_CODE_KEY 0
#define VALID_DATA_KEY 2
diff --git a/clang/test/SemaObjC/ptrauth-qualifier.m b/clang/test/SemaObjC/ptrauth-qualifier.m
index 74bbe6f09899b..67a73bbe45777 100644
--- a/clang/test/SemaObjC/ptrauth-qualifier.m
+++ b/clang/test/SemaObjC/ptrauth-qualifier.m
@@ -1,13 +1,25 @@
-// RUN: %clang_cc1 -triple arm64-apple-ios -fsyntax-only -verify -fptrauth-intrinsics %s
+// RUN: %clang_cc1 -triple arm64-apple-ios -DIS_DARWIN -fsyntax-only -verify -fptrauth-intrinsics %s
// RUN: %clang_cc1 -triple aarch64-linux-gnu -fsyntax-only -verify -fptrauth-intrinsics %s
-#if !__has_extension(ptrauth_qualifier)
+#if defined(IS_DARWIN) && !__has_extension(ptrauth_qualifier)
// This error means that the __ptrauth qualifier availability test says that it
// is not available. This error is not expected in the output, if it is seen
// there is a feature detection regression.
#error __ptrauth qualifier not enabled
#endif
+#if defined(IS_DARWIN) && !__has_feature(ptrauth_qualifier)
+// This error means that the __has_feature test for ptrauth_qualifier has
+// failed, despite it being expected on darwin.
+#error __ptrauth qualifier not enabled
+#elif !defined(IS_DARWIN) && (__has_feature(ptrauth_qualifier) || __has_extension(ptrauth_qualifier))
+#error ptrauth_qualifier labeled a feature on a non-darwin platform
+#endif
+
+#if !defined (__PTRAUTH__)
+#error __PTRAUTH__ test macro not defined when ptrauth is enabled
+#endif
+
@interface Foo
// expected-warning at -1 {{class 'Foo' defined without specifying a base class}}
// expected-note at -2 {{add a super class to fix this problem}}
>From ee8c1ae5072d014fc60656a073f30f61d402d7d3 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oliver at apple.com>
Date: Sun, 17 Aug 2025 22:32:32 -0700
Subject: [PATCH 2/4] Add release note
---
clang/docs/ReleaseNotes.rst | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 604b4c3f714b7..3106fe7b7797c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -144,6 +144,11 @@ New Compiler Flags
Deprecated Compiler Flags
-------------------------
+- Use of `__has_feature` to detect the `ptrauth_qualifier` and `ptrauth_intrinsics`
+ features has been deprecated, and is restricted to the arm64e target only. The
+ correct method to check for these features is to test for the `__PTRAUTH__`
+ macro.
+
Modified Compiler Flags
-----------------------
>From b1b2de3f797b6dc81ec671cc462bc863a8895a35 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oliver at apple.com>
Date: Mon, 18 Aug 2025 06:14:03 -0700
Subject: [PATCH 3/4] Update clang/docs/ReleaseNotes.rst
Co-authored-by: Aaron Ballman <aaron at aaronballman.com>
---
clang/docs/ReleaseNotes.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3106fe7b7797c..e474c14816d9d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -144,9 +144,9 @@ New Compiler Flags
Deprecated Compiler Flags
-------------------------
-- Use of `__has_feature` to detect the `ptrauth_qualifier` and `ptrauth_intrinsics`
+- Use of ``__has_feature`` to detect the ``ptrauth_qualifier`` and ``ptrauth_intrinsics``
features has been deprecated, and is restricted to the arm64e target only. The
- correct method to check for these features is to test for the `__PTRAUTH__`
+ correct method to check for these features is to test for the ``__PTRAUTH__``
macro.
Modified Compiler Flags
>From bade8f37d3c4ba78baadc5391be2f5530231e761 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oliver at apple.com>
Date: Mon, 18 Aug 2025 06:21:46 -0700
Subject: [PATCH 4/4] Revert addition of a new declaration requirement
---
clang/include/clang/Basic/Features.def | 6 ++++--
clang/lib/Frontend/FrontendActions.cpp | 2 +-
clang/lib/Lex/PPMacroExpansion.cpp | 1 -
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def
index 6f414105d7c36..7039844aaf270 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -147,8 +147,10 @@ FEATURE(type_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Type))
FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread))
FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow))
FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
-FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics && Target.getTriple().isOSDarwin())
-FEATURE(ptrauth_qualifier, LangOpts.PointerAuthIntrinsics && Target.getTriple().isOSDarwin())
+FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics &&
+ PP.getTargetInfo().getTriple().isOSDarwin())
+FEATURE(ptrauth_qualifier, LangOpts.PointerAuthIntrinsics &&
+ PP.getTargetInfo().getTriple().isOSDarwin())
FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls)
FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns)
FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtrAddressDiscrimination)
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index d29a08c43fc12..815bdc0bb54c3 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -1159,7 +1159,7 @@ void DumpCompilerOptionsAction::ExecuteAction() {
raw_ostream &OS = *OSP;
const Preprocessor &PP = CI.getPreprocessor();
const LangOptions &LangOpts = PP.getLangOpts();
- const TargetInfo &Target = CI.getTarget();
+
// FIXME: Rather than manually format the JSON (which is awkward due to
// needing to remove trailing commas), this should make use of a JSON library.
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index f9dfd0eb14bc0..6f12ac80d677e 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1089,7 +1089,6 @@ static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc,
/// specified by the identifier as a standard language feature.
static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
const LangOptions &LangOpts = PP.getLangOpts();
- const TargetInfo &Target = PP.getTargetInfo();
// Normalize the feature name, __foo__ becomes foo.
if (Feature.starts_with("__") && Feature.ends_with("__") &&
More information about the cfe-commits
mailing list