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