4848#include " llvm/IR/DerivedTypes.h"
4949#include " llvm/Support/ErrorHandling.h"
5050#include < bitset>
51+ #include < cctype>
5152#include < optional>
5253
5354using namespace clang ;
@@ -8350,14 +8351,16 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
83508351// / Handle the __ptrauth qualifier.
83518352static void HandlePtrAuthQualifier (ASTContext &Ctx, QualType &T,
83528353 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 ( );
83568357 Expr *KeyArg = Attr.getArgAsExpr (0 );
83578358 Expr *IsAddressDiscriminatedArg =
83588359 Attr.getNumArgs () >= 2 ? Attr.getArgAsExpr (1 ) : nullptr ;
83598360 Expr *ExtraDiscriminatorArg =
83608361 Attr.getNumArgs () >= 3 ? Attr.getArgAsExpr (2 ) : nullptr ;
8362+ Expr *AuthenticationOptionsArg =
8363+ Attr.getNumArgs () >= 4 ? Attr.getArgAsExpr (3 ) : nullptr ;
83618364
83628365 unsigned Key;
83638366 if (S.checkConstantPointerAuthKey (KeyArg, Key)) {
@@ -8373,10 +8376,140 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
83738376 IsAddressDiscriminated);
83748377 IsInvalid |= !S.checkPointerAuthDiscriminatorArg (
83758378 ExtraDiscriminatorArg, PointerAuthDiscArgKind::Extra, 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+ IsInvalid = true ;
8408+ ReportEvaluationOfExpressionIfNeeded ();
8409+ };
8410+ if (AuthenticationOptionsArg->isValueDependent () ||
8411+ AuthenticationOptionsArg->isTypeDependent ()) {
8412+ DiagnoseInvalidOptionsParameter (" is dependent" );
8413+ return ;
8414+ }
8415+ if (OptionsStringLiteral) {
8416+ OptionsString = OptionsStringLiteral->getString ();
8417+ HasEvaluatedOptionsString = true ;
8418+ } else {
8419+ Expr::EvalResult Eval;
8420+ bool Result = AuthenticationOptionsArg->EvaluateAsRValue (Eval, Ctx);
8421+ if (Result && Eval.Val .isLValue ()) {
8422+ auto *BaseExpr = Eval.Val .getLValueBase ().dyn_cast <const Expr *>();
8423+ const StringLiteral *EvaluatedStringLiteral =
8424+ dyn_cast<StringLiteral>(const_cast <Expr *>(BaseExpr));
8425+ if (EvaluatedStringLiteral) {
8426+ CharUnits StartOffset = Eval.Val .getLValueOffset ();
8427+ EvaluatedString = EvaluatedStringLiteral->getString ().drop_front (
8428+ StartOffset.getQuantity ());
8429+ OptionsString = EvaluatedString;
8430+ HasEvaluatedOptionsString = true ;
8431+ }
8432+ }
8433+ }
8434+ if (!HasEvaluatedOptionsString) {
8435+ DiagnoseInvalidOptionsParameter (
8436+ " must be a string of comma separated flags" );
8437+ return ;
8438+ }
8439+ for (char Ch : OptionsString) {
8440+ if (Ch != ' -' && Ch != ' ,' && !isWhitespace (Ch) && !isalpha (Ch)) {
8441+ DiagnoseInvalidOptionsParameter (" contains invalid characters" );
8442+ return ;
8443+ }
8444+ }
8445+ HasEvaluatedOptionsString = true ;
8446+ OptionsString = OptionsString.trim ();
8447+ llvm::SmallVector<StringRef> Options;
8448+ if (!OptionsString.empty ())
8449+ OptionsString.split (Options, ' ,' );
8450+
8451+ auto OptionHandler = [&](auto Value, auto *Option,
8452+ std::string *LastOption = nullptr ) {
8453+ return [&, Value, Option, LastOption](StringRef OptionString) {
8454+ if (!*Option) {
8455+ *Option = Value;
8456+ if (LastOption)
8457+ *LastOption = OptionString;
8458+ return true ;
8459+ }
8460+ bool IsAuthenticationMode =
8461+ std::is_same_v<decltype (Value), PointerAuthenticationMode>;
8462+ S.Diag (AuthenticationOptionsRange.getBegin (),
8463+ diag::err_ptrauth_repeated_authentication_option)
8464+ << AttrName << !IsAuthenticationMode << OptionString
8465+ << (LastOption ? *LastOption : " " );
8466+ return false ;
8467+ };
8468+ };
83768469
8377- if (IsInvalid) {
8378- Attr.setInvalid ();
8379- return ;
8470+ for (unsigned Idx = 0 ; Idx < Options.size (); ++Idx) {
8471+ StringRef Option = Options[Idx].trim ();
8472+ if (Option.empty ()) {
8473+ bool IsLastOption = Idx == (Options.size () - 1 );
8474+ DiagnoseInvalidOptionsParameter (
8475+ IsLastOption ? " has a trailing comma" : " contains an empty option" );
8476+ continue ;
8477+ }
8478+ auto SelectedHandler =
8479+ llvm::StringSwitch<std::function<bool (StringRef)>>(Option)
8480+ .Case (PointerAuthenticationOptionStrip,
8481+ OptionHandler (PointerAuthenticationMode::Strip,
8482+ &AuthenticationMode, &LastAuthenticationMode))
8483+ .Case (PointerAuthenticationOptionSignAndStrip,
8484+ OptionHandler (PointerAuthenticationMode::SignAndStrip,
8485+ &AuthenticationMode, &LastAuthenticationMode))
8486+ .Case (PointerAuthenticationOptionSignAndAuth,
8487+ OptionHandler (PointerAuthenticationMode::SignAndAuth,
8488+ &AuthenticationMode, &LastAuthenticationMode))
8489+ .Case (PointerAuthenticationOptionIsaPointer,
8490+ OptionHandler (true ,
8491+ &IsIsaPointer))
8492+ .Case (PointerAuthenticationOptionAuthenticatesNullValues,
8493+ OptionHandler (true ,
8494+ &AuthenticatesNullValues))
8495+ .Default ([&](StringRef Option) {
8496+ if (size_t WhitespaceIndex =
8497+ Option.find_first_of (" \t\n\v\f\r " );
8498+ WhitespaceIndex != Option.npos ) {
8499+ StringRef LeadingOption = Option.slice (0 , WhitespaceIndex);
8500+ S.Diag (AuthenticationOptionsRange.getBegin (),
8501+ diag::err_ptrauth_option_missing_comma)
8502+ << AttrName << LeadingOption;
8503+ } else {
8504+ S.Diag (AuthenticationOptionsRange.getBegin (),
8505+ diag::err_ptrauth_unknown_authentication_option)
8506+ << AttrName << Option;
8507+ }
8508+ return false ;
8509+ });
8510+ if (!SelectedHandler (Option))
8511+ IsInvalid = true ;
8512+ }
83808513 }
83818514
83828515 if (!T->isSignableType (Ctx) && !T->isDependentType ()) {
@@ -8385,6 +8518,9 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
83858518 return ;
83868519 }
83878520
8521+ if (!AuthenticationMode)
8522+ AuthenticationMode = PointerAuthenticationMode::SignAndAuth;
8523+
83888524 if (T.getPointerAuth ()) {
83898525 S.Diag (Attr.getLoc (), diag::err_ptrauth_qualifier_redundant) << T;
83908526 Attr.setInvalid ();
@@ -8397,13 +8533,19 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
83978533 return ;
83988534 }
83998535
8536+ if (IsInvalid) {
8537+ Attr.setInvalid ();
8538+ return ;
8539+ }
8540+
84008541 assert ((!IsAddressDiscriminatedArg || IsAddressDiscriminated <= 1 ) &&
84018542 " address discriminator arg should be either 0 or 1" );
84028543 PointerAuthQualifier Qual = PointerAuthQualifier::Create (
8403- Key, IsAddressDiscriminated, ExtraDiscriminator,
8404- PointerAuthenticationMode::SignAndAuth, /* IsIsaPointer= */ false ,
8405- /* AuthenticatesNullValues= */ false );
8544+ Key, IsAddressDiscriminated, ExtraDiscriminator, *AuthenticationMode,
8545+ IsIsaPointer, AuthenticatesNullValues);
8546+ assert (Qual. getAuthenticationMode () == *AuthenticationMode );
84068547 T = S.Context .getPointerAuthType (T, Qual);
8548+ assert (T.getPointerAuth ().getAuthenticationMode () == *AuthenticationMode);
84078549}
84088550
84098551// / HandleArmSveVectorBitsTypeAttr - The "arm_sve_vector_bits" attribute is
0 commit comments