Skip to content

Commit 666e332

Browse files
authored
[PAC] Define __builtin_ptrauth_type_discriminator (llvm#100204)
The builtin computes the discriminator for a type, which can be used to sign/authenticate function pointers and member function pointers. If the type passed to the builtin is a C++ member function pointer type, the result is the discriminator used to signed member function pointers of that type. If the type is a function, function pointer, or function reference type, the result is the discriminator used to sign functions of that type. It is ill-formed to use this builtin with any other type. A call to this function is an integer constant expression. Co-Authored-By: John McCall [email protected]
1 parent eff6250 commit 666e332

File tree

14 files changed

+183
-3
lines changed

14 files changed

+183
-3
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,9 @@ def warn_ptrauth_auth_null_pointer :
942942
InGroup<PtrAuthNullPointers>;
943943
def err_ptrauth_string_not_literal : Error<
944944
"argument must be a string literal%select{| of char type}0">;
945+
def err_ptrauth_type_disc_undiscriminated : Error<
946+
"cannot pass undiscriminated type %0 to "
947+
"'__builtin_ptrauth_type_discriminator'">;
945948

946949
def note_ptrauth_virtual_function_pointer_incomplete_arg_ret :
947950
Note<"cannot take an address of a virtual member function if its return or "

clang/include/clang/Basic/TokenKinds.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,8 @@ ALIAS("__is_same_as", __is_same, KEYCXX)
596596
KEYWORD(__private_extern__ , KEYALL)
597597
KEYWORD(__module_private__ , KEYALL)
598598

599+
UNARY_EXPR_OR_TYPE_TRAIT(__builtin_ptrauth_type_discriminator, PtrAuthTypeDiscriminator, KEYALL)
600+
599601
// Extension that will be enabled for Microsoft, Borland and PS4, but can be
600602
// disabled via '-fno-declspec'.
601603
KEYWORD(__declspec , 0)

clang/include/clang/Parse/Parser.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3890,6 +3890,8 @@ class Parser : public CodeCompletionHandler {
38903890
ExprResult ParseArrayTypeTrait();
38913891
ExprResult ParseExpressionTrait();
38923892

3893+
ExprResult ParseBuiltinPtrauthTypeDiscriminator();
3894+
38933895
//===--------------------------------------------------------------------===//
38943896
// Preprocessor code-completion pass-through
38953897
void CodeCompleteDirective(bool InConditional) override;

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3456,6 +3456,8 @@ class Sema final : public SemaBase {
34563456
TemplateIdAnnotation *TemplateId,
34573457
bool IsMemberSpecialization);
34583458

3459+
bool checkPointerAuthEnabled(SourceLocation Loc, SourceRange Range);
3460+
34593461
bool checkConstantPointerAuthKey(Expr *keyExpr, unsigned &key);
34603462

34613463
/// Diagnose function specifiers on a declaration of an identifier that

clang/lib/AST/ExprConstant.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14058,6 +14058,12 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
1405814058
E);
1405914059
}
1406014060

14061+
case UETT_PtrAuthTypeDiscriminator: {
14062+
if (E->getArgumentType()->isDependentType())
14063+
return false;
14064+
return Success(
14065+
Info.Ctx.getPointerAuthTypeDiscriminator(E->getArgumentType()), E);
14066+
}
1406114067
case UETT_VecStep: {
1406214068
QualType Ty = E->getTypeOfArgument();
1406314069

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5179,6 +5179,14 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
51795179
Diags.Report(DiagID);
51805180
return;
51815181
}
5182+
case UETT_PtrAuthTypeDiscriminator: {
5183+
DiagnosticsEngine &Diags = Context.getDiags();
5184+
unsigned DiagID = Diags.getCustomDiagID(
5185+
DiagnosticsEngine::Error,
5186+
"cannot yet mangle __builtin_ptrauth_type_discriminator expression");
5187+
Diags.Report(E->getExprLoc(), DiagID);
5188+
return;
5189+
}
51825190
case UETT_VecStep: {
51835191
DiagnosticsEngine &Diags = Context.getDiags();
51845192
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,

clang/lib/Headers/ptrauth.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,23 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
202202
#define ptrauth_string_discriminator(__string) \
203203
__builtin_ptrauth_string_discriminator(__string)
204204

205+
/* Compute a constant discriminator from the given type.
206+
207+
The result can be used as the second argument to
208+
ptrauth_blend_discriminator or the third argument to the
209+
__ptrauth qualifier. It has type size_t.
210+
211+
If the type is a C++ member function pointer type, the result is
212+
the discriminator used to signed member function pointers of that
213+
type. If the type is a function, function pointer, or function
214+
reference type, the result is the discriminator used to sign
215+
functions of that type. It is ill-formed to use this macro with any
216+
other type.
217+
218+
A call to this function is an integer constant expression. */
219+
#define ptrauth_type_discriminator(__type) \
220+
__builtin_ptrauth_type_discriminator(__type)
221+
205222
/* Compute a signature for the given pair of pointer-sized values.
206223
The order of the arguments is significant.
207224
@@ -289,6 +306,8 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
289306
((ptrauth_extra_data_t)0); \
290307
})
291308

309+
#define ptrauth_type_discriminator(__type) ((ptrauth_extra_data_t)0)
310+
292311
#define ptrauth_sign_generic_data(__value, __data) \
293312
({ \
294313
(void)__value; \

clang/lib/Parse/ParseExpr.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,26 @@ bool Parser::isRevertibleTypeTrait(const IdentifierInfo *II,
841841
return false;
842842
}
843843

844+
ExprResult Parser::ParseBuiltinPtrauthTypeDiscriminator() {
845+
SourceLocation Loc = ConsumeToken();
846+
847+
BalancedDelimiterTracker T(*this, tok::l_paren);
848+
if (T.expectAndConsume())
849+
return ExprError();
850+
851+
TypeResult Ty = ParseTypeName();
852+
if (Ty.isInvalid()) {
853+
SkipUntil(tok::r_paren, StopAtSemi);
854+
return ExprError();
855+
}
856+
857+
SourceLocation EndLoc = Tok.getLocation();
858+
T.consumeClose();
859+
return Actions.ActOnUnaryExprOrTypeTraitExpr(
860+
Loc, UETT_PtrAuthTypeDiscriminator,
861+
/*isType=*/true, Ty.get().getAsOpaquePtr(), SourceRange(Loc, EndLoc));
862+
}
863+
844864
/// Parse a cast-expression, or, if \pisUnaryExpression is true, parse
845865
/// a unary-expression.
846866
///
@@ -1806,6 +1826,9 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
18061826
Res = ParseArrayTypeTrait();
18071827
break;
18081828

1829+
case tok::kw___builtin_ptrauth_type_discriminator:
1830+
return ParseBuiltinPtrauthTypeDiscriminator();
1831+
18091832
case tok::kw___is_lvalue_expr:
18101833
case tok::kw___is_rvalue_expr:
18111834
if (NotPrimaryExpression)

clang/lib/Sema/SemaChecking.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,14 +1489,18 @@ enum PointerAuthOpKind {
14891489
};
14901490
}
14911491

1492-
static bool checkPointerAuthEnabled(Sema &S, Expr *E) {
1493-
if (S.getLangOpts().PointerAuthIntrinsics)
1492+
bool Sema::checkPointerAuthEnabled(SourceLocation Loc, SourceRange Range) {
1493+
if (getLangOpts().PointerAuthIntrinsics)
14941494
return false;
14951495

1496-
S.Diag(E->getExprLoc(), diag::err_ptrauth_disabled) << E->getSourceRange();
1496+
Diag(Loc, diag::err_ptrauth_disabled) << Range;
14971497
return true;
14981498
}
14991499

1500+
static bool checkPointerAuthEnabled(Sema &S, Expr *E) {
1501+
return S.checkPointerAuthEnabled(E->getExprLoc(), E->getSourceRange());
1502+
}
1503+
15001504
static bool checkPointerAuthKey(Sema &S, Expr *&Arg) {
15011505
// Convert it to type 'int'.
15021506
if (convertArgumentToType(S, Arg, S.Context.IntTy))

clang/lib/Sema/SemaExpr.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4117,6 +4117,21 @@ static bool CheckVectorElementsTraitOperandType(Sema &S, QualType T,
41174117
return false;
41184118
}
41194119

4120+
static bool checkPtrAuthTypeDiscriminatorOperandType(Sema &S, QualType T,
4121+
SourceLocation Loc,
4122+
SourceRange ArgRange) {
4123+
if (S.checkPointerAuthEnabled(Loc, ArgRange))
4124+
return true;
4125+
4126+
if (!T->isFunctionType() && !T->isFunctionPointerType() &&
4127+
!T->isFunctionReferenceType() && !T->isMemberFunctionPointerType()) {
4128+
S.Diag(Loc, diag::err_ptrauth_type_disc_undiscriminated) << T << ArgRange;
4129+
return true;
4130+
}
4131+
4132+
return false;
4133+
}
4134+
41204135
static bool CheckExtensionTraitOperandType(Sema &S, QualType T,
41214136
SourceLocation Loc,
41224137
SourceRange ArgRange,
@@ -4511,6 +4526,10 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
45114526
return CheckVectorElementsTraitOperandType(*this, ExprType, OpLoc,
45124527
ExprRange);
45134528

4529+
if (ExprKind == UETT_PtrAuthTypeDiscriminator)
4530+
return checkPtrAuthTypeDiscriminatorOperandType(*this, ExprType, OpLoc,
4531+
ExprRange);
4532+
45144533
// Explicitly list some types as extensions.
45154534
if (!CheckExtensionTraitOperandType(*this, ExprType, OpLoc, ExprRange,
45164535
ExprKind))

0 commit comments

Comments
 (0)