@@ -8350,14 +8350,15 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
8350
8350
/// Handle the __ptrauth qualifier.
8351
8351
static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
8352
8352
const ParsedAttr &Attr, Sema &S) {
8353
-
8354
- assert((Attr.getNumArgs() > 0 && Attr.getNumArgs() <= 3) &&
8355
- "__ptrauth qualifier takes between 1 and 3 arguments");
8353
+ assert((Attr.getNumArgs() > 0 && Attr.getNumArgs() <= 4) &&
8354
+ "__ptrauth qualifier takes between 1 and 4 arguments");
8356
8355
Expr *KeyArg = Attr.getArgAsExpr(0);
8357
8356
Expr *IsAddressDiscriminatedArg =
8358
8357
Attr.getNumArgs() >= 2 ? Attr.getArgAsExpr(1) : nullptr;
8359
8358
Expr *ExtraDiscriminatorArg =
8360
8359
Attr.getNumArgs() >= 3 ? Attr.getArgAsExpr(2) : nullptr;
8360
+ Expr *AuthenticationOptionsArg =
8361
+ Attr.getNumArgs() >= 4 ? Attr.getArgAsExpr(3) : nullptr;
8361
8362
8362
8363
unsigned Key;
8363
8364
if (S.checkConstantPointerAuthKey(KeyArg, Key)) {
@@ -8373,10 +8374,137 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
8373
8374
IsAddressDiscriminated);
8374
8375
IsInvalid |= !S.checkPointerAuthDiscriminatorArg(
8375
8376
ExtraDiscriminatorArg, PointerAuthDiscArgKind::Extra, ExtraDiscriminator);
8377
+ std::string LastAuthenticationMode;
8378
+ std::optional<PointerAuthenticationMode> AuthenticationMode = std::nullopt;
8379
+ bool IsIsaPointer = false;
8380
+ bool AuthenticatesNullValues = false;
8381
+
8382
+ if (AuthenticationOptionsArg && !AuthenticationOptionsArg->containsErrors()) {
8383
+ StringRef OptionsString;
8384
+ std::string EvaluatedString;
8385
+ bool HasEvaluatedOptionsString = false;
8386
+ const StringLiteral *OptionsStringLiteral =
8387
+ dyn_cast<StringLiteral>(AuthenticationOptionsArg);
8388
+ SourceRange AuthenticationOptionsRange =
8389
+ AuthenticationOptionsArg->getSourceRange();
8390
+ bool ReportedEvaluation = false;
8391
+ auto ReportEvaluationOfExpressionIfNeeded = [&]() {
8392
+ if (OptionsStringLiteral || !HasEvaluatedOptionsString ||
8393
+ ReportedEvaluation)
8394
+ return;
8395
+ ReportedEvaluation = true;
8396
+ S.Diag(AuthenticationOptionsRange.getBegin(),
8397
+ diag::note_ptrauth_evaluating_options)
8398
+ << OptionsString << AuthenticationOptionsRange;
8399
+ };
8400
+ auto DiagnoseInvalidOptionsParameter = [&](llvm::StringRef Reason) {
8401
+ S.Diag(AuthenticationOptionsRange.getBegin(),
8402
+ diag::err_ptrauth_invalid_option) << Reason;
8403
+ Attr.setInvalid();
8404
+ IsInvalid = true;
8405
+ ReportEvaluationOfExpressionIfNeeded();
8406
+ };
8407
+ if (AuthenticationOptionsArg->isValueDependent() ||
8408
+ AuthenticationOptionsArg->isTypeDependent()) {
8409
+ DiagnoseInvalidOptionsParameter("is dependent");
8410
+ return;
8411
+ }
8412
+ if (OptionsStringLiteral) {
8413
+ OptionsString = OptionsStringLiteral->getString();
8414
+ HasEvaluatedOptionsString = true;
8415
+ } else {
8416
+ Expr::EvalResult Eval;
8417
+ bool Result = AuthenticationOptionsArg->EvaluateAsRValue(Eval, Ctx);
8418
+ if (Result && Eval.Val.isLValue()) {
8419
+ auto *BaseExpr = Eval.Val.getLValueBase().dyn_cast<const Expr *>();
8420
+ const StringLiteral *EvaluatedStringLiteral =
8421
+ dyn_cast<StringLiteral>(const_cast<Expr *>(BaseExpr));
8422
+ if (EvaluatedStringLiteral) {
8423
+ CharUnits StartOffset = Eval.Val.getLValueOffset();
8424
+ EvaluatedString = EvaluatedStringLiteral->getString().drop_front(
8425
+ StartOffset.getQuantity());
8426
+ OptionsString = EvaluatedString;
8427
+ HasEvaluatedOptionsString = true;
8428
+ }
8429
+ }
8430
+ }
8431
+ if (!HasEvaluatedOptionsString) {
8432
+ DiagnoseInvalidOptionsParameter(
8433
+ "must be a string of comma separated flags");
8434
+ return;
8435
+ }
8436
+ for (char Ch : OptionsString) {
8437
+ if (Ch != '-' && Ch != ',' && !isWhitespace(Ch) && !isalpha(Ch)) {
8438
+ DiagnoseInvalidOptionsParameter("contains invalid characters");
8439
+ return;
8440
+ }
8441
+ }
8442
+ HasEvaluatedOptionsString = true;
8443
+ OptionsString = OptionsString.trim();
8444
+ llvm::SmallVector<StringRef> Options;
8445
+ if (!OptionsString.empty())
8446
+ OptionsString.split(Options, ',');
8447
+
8448
+ auto OptionHandler = [&](auto Value, auto *Option,
8449
+ std::string *LastOption = nullptr) {
8450
+ return [&, Value, Option, LastOption](StringRef OptionString) {
8451
+ if (!*Option) {
8452
+ *Option = Value;
8453
+ if (LastOption)
8454
+ *LastOption = OptionString;
8455
+ return true;
8456
+ }
8457
+ bool IsAuthenticationMode =
8458
+ std::is_same_v<decltype(Value), PointerAuthenticationMode>;
8459
+ S.Diag(AuthenticationOptionsRange.getBegin(),
8460
+ diag::err_ptrauth_repeated_authentication_option)
8461
+ << !IsAuthenticationMode << OptionString
8462
+ << (LastOption ? *LastOption : "");
8463
+ return false;
8464
+ };
8465
+ };
8376
8466
8377
- if (IsInvalid) {
8378
- Attr.setInvalid();
8379
- return;
8467
+ for (unsigned Idx = 0; Idx < Options.size(); ++Idx) {
8468
+ StringRef Option = Options[Idx].trim();
8469
+ if (Option.empty()) {
8470
+ bool IsLastOption = Idx == (Options.size() - 1);
8471
+ DiagnoseInvalidOptionsParameter(
8472
+ IsLastOption ? "has a trailing comma" : "contains an empty option");
8473
+ continue;
8474
+ }
8475
+ auto SelectedHandler =
8476
+ llvm::StringSwitch<std::function<bool(StringRef)>>(Option)
8477
+ .Case(PointerAuthenticationOptionStrip,
8478
+ OptionHandler(PointerAuthenticationMode::Strip,
8479
+ &AuthenticationMode, &LastAuthenticationMode))
8480
+ .Case(PointerAuthenticationOptionSignAndStrip,
8481
+ OptionHandler(PointerAuthenticationMode::SignAndStrip,
8482
+ &AuthenticationMode, &LastAuthenticationMode))
8483
+ .Case(PointerAuthenticationOptionSignAndAuth,
8484
+ OptionHandler(PointerAuthenticationMode::SignAndAuth,
8485
+ &AuthenticationMode, &LastAuthenticationMode))
8486
+ .Case(PointerAuthenticationOptionIsaPointer,
8487
+ OptionHandler(true, &IsIsaPointer))
8488
+ .Case(PointerAuthenticationOptionAuthenticatesNullValues,
8489
+ OptionHandler(true, &AuthenticatesNullValues))
8490
+ .Default([&](StringRef Option) {
8491
+ if (size_t WhitespaceIndex =
8492
+ Option.find_first_of(" \t\n\v\f\r");
8493
+ WhitespaceIndex != Option.npos) {
8494
+ StringRef LeadingOption = Option.slice(0, WhitespaceIndex);
8495
+ S.Diag(AuthenticationOptionsRange.getBegin(),
8496
+ diag::err_ptrauth_option_missing_comma)
8497
+ << LeadingOption;
8498
+ } else {
8499
+ S.Diag(AuthenticationOptionsRange.getBegin(),
8500
+ diag::err_ptrauth_unknown_authentication_option)
8501
+ << Option;
8502
+ }
8503
+ return false;
8504
+ });
8505
+ if (!SelectedHandler(Option))
8506
+ IsInvalid = true;
8507
+ }
8380
8508
}
8381
8509
8382
8510
if (!T->isSignableType(Ctx) && !T->isDependentType()) {
@@ -8385,6 +8513,9 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
8385
8513
return;
8386
8514
}
8387
8515
8516
+ if (!AuthenticationMode)
8517
+ AuthenticationMode = PointerAuthenticationMode::SignAndAuth;
8518
+
8388
8519
if (T.getPointerAuth()) {
8389
8520
S.Diag(Attr.getLoc(), diag::err_ptrauth_qualifier_redundant) << T;
8390
8521
Attr.setInvalid();
@@ -8397,13 +8528,19 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
8397
8528
return;
8398
8529
}
8399
8530
8531
+ if (IsInvalid) {
8532
+ Attr.setInvalid();
8533
+ return;
8534
+ }
8535
+
8400
8536
assert((!IsAddressDiscriminatedArg || IsAddressDiscriminated <= 1) &&
8401
8537
"address discriminator arg should be either 0 or 1");
8402
8538
PointerAuthQualifier Qual = PointerAuthQualifier::Create(
8403
- Key, IsAddressDiscriminated, ExtraDiscriminator,
8404
- PointerAuthenticationMode::SignAndAuth, /* IsIsaPointer=*/false,
8405
- /*AuthenticatesNullValues=*/false );
8539
+ Key, IsAddressDiscriminated, ExtraDiscriminator, *AuthenticationMode,
8540
+ IsIsaPointer, AuthenticatesNullValues);
8541
+ assert(Qual.getAuthenticationMode() == *AuthenticationMode );
8406
8542
T = S.Context.getPointerAuthType(T, Qual);
8543
+ assert(T.getPointerAuth().getAuthenticationMode() == *AuthenticationMode);
8407
8544
}
8408
8545
8409
8546
/// HandleArmSveVectorBitsTypeAttr - The "arm_sve_vector_bits" attribute is
0 commit comments