@@ -8350,14 +8350,15 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
83508350// / Handle the __ptrauth qualifier.
83518351static void HandlePtrAuthQualifier (ASTContext &Ctx, QualType &T,
83528352 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" );
83568355 Expr *KeyArg = Attr.getArgAsExpr (0 );
83578356 Expr *IsAddressDiscriminatedArg =
83588357 Attr.getNumArgs () >= 2 ? Attr.getArgAsExpr (1 ) : nullptr ;
83598358 Expr *ExtraDiscriminatorArg =
83608359 Attr.getNumArgs () >= 3 ? Attr.getArgAsExpr (2 ) : nullptr ;
8360+ Expr *AuthenticationOptionsArg =
8361+ Attr.getNumArgs () >= 4 ? Attr.getArgAsExpr (3 ) : nullptr ;
83618362
83628363 unsigned Key;
83638364 if (S.checkConstantPointerAuthKey (KeyArg, Key)) {
@@ -8373,10 +8374,137 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
83738374 IsAddressDiscriminated);
83748375 IsInvalid |= !S.checkPointerAuthDiscriminatorArg (
83758376 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+ };
83768466
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+ }
83808508 }
83818509
83828510 if (!T->isSignableType (Ctx) && !T->isDependentType ()) {
@@ -8385,6 +8513,9 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
83858513 return ;
83868514 }
83878515
8516+ if (!AuthenticationMode)
8517+ AuthenticationMode = PointerAuthenticationMode::SignAndAuth;
8518+
83888519 if (T.getPointerAuth ()) {
83898520 S.Diag (Attr.getLoc (), diag::err_ptrauth_qualifier_redundant) << T;
83908521 Attr.setInvalid ();
@@ -8397,13 +8528,19 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
83978528 return ;
83988529 }
83998530
8531+ if (IsInvalid) {
8532+ Attr.setInvalid ();
8533+ return ;
8534+ }
8535+
84008536 assert ((!IsAddressDiscriminatedArg || IsAddressDiscriminated <= 1 ) &&
84018537 " address discriminator arg should be either 0 or 1" );
84028538 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 );
84068542 T = S.Context .getPointerAuthType (T, Qual);
8543+ assert (T.getPointerAuth ().getAuthenticationMode () == *AuthenticationMode);
84078544}
84088545
84098546// / HandleArmSveVectorBitsTypeAttr - The "arm_sve_vector_bits" attribute is
0 commit comments