@@ -8350,14 +8350,16 @@ 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 " );
8355+ StringRef AttrName = Attr. getAttrName ()-> getName ( );
83568356 Expr *KeyArg = Attr.getArgAsExpr (0 );
83578357 Expr *IsAddressDiscriminatedArg =
83588358 Attr.getNumArgs () >= 2 ? Attr.getArgAsExpr (1 ) : nullptr ;
83598359 Expr *ExtraDiscriminatorArg =
83608360 Attr.getNumArgs () >= 3 ? Attr.getArgAsExpr (2 ) : nullptr ;
8361+ Expr *AuthenticationOptionsArg =
8362+ Attr.getNumArgs () >= 4 ? Attr.getArgAsExpr (3 ) : nullptr ;
83618363
83628364 unsigned Key;
83638365 if (S.checkConstantPointerAuthKey (KeyArg, Key)) {
@@ -8373,10 +8375,138 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
83738375 IsAddressDiscriminated);
83748376 IsInvalid |= !S.checkPointerAuthDiscriminatorArg (
83758377 ExtraDiscriminatorArg, PointerAuthDiscArgKind::Extra, ExtraDiscriminator);
8378+ std::string LastAuthenticationMode;
8379+ std::optional<PointerAuthenticationMode> AuthenticationMode = std::nullopt ;
8380+ bool IsIsaPointer = false ;
8381+ bool AuthenticatesNullValues = false ;
8382+
8383+ if (AuthenticationOptionsArg && !AuthenticationOptionsArg->containsErrors ()) {
8384+ StringRef OptionsString;
8385+ std::string EvaluatedString;
8386+ bool HasEvaluatedOptionsString = false ;
8387+ const StringLiteral *OptionsStringLiteral =
8388+ dyn_cast<StringLiteral>(AuthenticationOptionsArg);
8389+ SourceRange AuthenticationOptionsRange =
8390+ AuthenticationOptionsArg->getSourceRange ();
8391+ bool ReportedEvaluation = false ;
8392+ auto ReportEvaluationOfExpressionIfNeeded = [&]() {
8393+ if (OptionsStringLiteral || !HasEvaluatedOptionsString ||
8394+ ReportedEvaluation)
8395+ return ;
8396+ ReportedEvaluation = true ;
8397+ S.Diag (AuthenticationOptionsRange.getBegin (),
8398+ diag::note_ptrauth_evaluating_options)
8399+ << OptionsString << AuthenticationOptionsRange;
8400+ };
8401+ auto DiagnoseInvalidOptionsParameter = [&](llvm::StringRef Reason) {
8402+ S.Diag (AuthenticationOptionsRange.getBegin (),
8403+ diag::err_ptrauth_invalid_option)
8404+ << AttrName << Reason;
8405+ Attr.setInvalid ();
8406+ IsInvalid = true ;
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+ };
83768468
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+ .Case (PointerAuthenticationOptionIsaPointer,
8489+ OptionHandler (true , &IsIsaPointer))
8490+ .Case (PointerAuthenticationOptionAuthenticatesNullValues,
8491+ OptionHandler (true , &AuthenticatesNullValues))
8492+ .Default ([&](StringRef Option) {
8493+ if (size_t WhitespaceIndex =
8494+ Option.find_first_of (" \t\n\v\f\r " );
8495+ WhitespaceIndex != Option.npos ) {
8496+ StringRef LeadingOption = Option.slice (0 , WhitespaceIndex);
8497+ S.Diag (AuthenticationOptionsRange.getBegin (),
8498+ diag::err_ptrauth_option_missing_comma)
8499+ << AttrName << LeadingOption;
8500+ } else {
8501+ S.Diag (AuthenticationOptionsRange.getBegin (),
8502+ diag::err_ptrauth_unknown_authentication_option)
8503+ << AttrName << Option;
8504+ }
8505+ return false ;
8506+ });
8507+ if (!SelectedHandler (Option))
8508+ IsInvalid = true ;
8509+ }
83808510 }
83818511
83828512 if (!T->isSignableType (Ctx) && !T->isDependentType ()) {
@@ -8385,6 +8515,9 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
83858515 return ;
83868516 }
83878517
8518+ if (!AuthenticationMode)
8519+ AuthenticationMode = PointerAuthenticationMode::SignAndAuth;
8520+
83888521 if (T.getPointerAuth ()) {
83898522 S.Diag (Attr.getLoc (), diag::err_ptrauth_qualifier_redundant) << T;
83908523 Attr.setInvalid ();
@@ -8397,13 +8530,19 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
83978530 return ;
83988531 }
83998532
8533+ if (IsInvalid) {
8534+ Attr.setInvalid ();
8535+ return ;
8536+ }
8537+
84008538 assert ((!IsAddressDiscriminatedArg || IsAddressDiscriminated <= 1 ) &&
84018539 " address discriminator arg should be either 0 or 1" );
84028540 PointerAuthQualifier Qual = PointerAuthQualifier::Create (
8403- Key, IsAddressDiscriminated, ExtraDiscriminator,
8404- PointerAuthenticationMode::SignAndAuth, /* IsIsaPointer= */ false ,
8405- /* AuthenticatesNullValues= */ false );
8541+ Key, IsAddressDiscriminated, ExtraDiscriminator, *AuthenticationMode,
8542+ IsIsaPointer, AuthenticatesNullValues);
8543+ assert (Qual. getAuthenticationMode () == *AuthenticationMode );
84068544 T = S.Context .getPointerAuthType (T, Qual);
8545+ assert (T.getPointerAuth ().getAuthenticationMode () == *AuthenticationMode);
84078546}
84088547
84098548// / HandleArmSveVectorBitsTypeAttr - The "arm_sve_vector_bits" attribute is
0 commit comments