[clang] [clang][ptrauth] add support for options parameter to __ptrauth (PR #136828)

Oliver Hunt via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 23 01:59:38 PDT 2025


================
@@ -8374,20 +8376,191 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
   IsInvalid |= !S.checkPointerAuthDiscriminatorArg(
       ExtraDiscriminatorArg, Sema::PADAK_ExtraDiscPtrAuth, ExtraDiscriminator);
 
-  if (IsInvalid) {
-    Attr.setInvalid();
-    return;
+  std::optional<PointerAuthenticationMode> AuthenticationMode = std::nullopt;
+  SourceRange AuthenticationModeRange;
+
+  if (AuthenticationOptionsArg && !AuthenticationOptionsArg->containsErrors() ) {
+    std::string OptionsString;
+    bool IsInitialized = false;
+    const StringLiteral *OptionsStringLiteral = dyn_cast<StringLiteral>(AuthenticationOptionsArg);
+    auto ReportEvaluationOfExpressionIfNeeded = [&](){
+      if (OptionsStringLiteral || !IsInitialized)
+        return;
+      S.Diag(AuthenticationOptionsArg->getBeginLoc(),
+        diag::note_ptrauth_evaluating_options) << OptionsString << AuthenticationOptionsArg->getSourceRange();
+    };
+    auto DiagnoseInvalidOptionsParameter = [&](llvm::StringRef Reason, std::optional<char> InvalidCh, auto Location) {
+      S.Diag(AuthenticationOptionsArg->getExprLoc(),
+             diag::err_ptrauth_invalid_option)
+          << AttrName << Reason << Location << !!InvalidCh << (InvalidCh ? *InvalidCh : '\0');
+      Attr.setInvalid();
+      ReportEvaluationOfExpressionIfNeeded();
+    };
+    if (AuthenticationOptionsArg->isValueDependent() || AuthenticationOptionsArg->isTypeDependent()) {
+      DiagnoseInvalidOptionsParameter("is dependent", std::nullopt, AuthenticationOptionsArg->getSourceRange());
+      return;
+    }
+    if (OptionsStringLiteral) {
+      if (OptionsStringLiteral->containsNonAsciiOrNull()) {
+        DiagnoseInvalidOptionsParameter("contains invalid characters", std::nullopt, AuthenticationOptionsArg->getSourceRange());
+        return;
+      }
+      OptionsString = OptionsStringLiteral->getString();
+    } else if (S.EvaluateAsString(AuthenticationOptionsArg, OptionsString, S.Context, Sema::StringEvaluationContext::PtrauthOptions, /*ErrorOnInvalidMessage=*/false)) {
+      for (char Ch : OptionsString) {
+        if (!Ch || !isascii(Ch)) {
+          DiagnoseInvalidOptionsParameter("contains invalid characters", Ch, AuthenticationOptionsArg->getSourceRange());
+          return;
+        }
+      }
+    } else {
+      Attr.setInvalid();
+      return;
+    }
+    IsInitialized = true;
+    bool HasSeenOption = false;
+    unsigned CurrentIdx = 0;
+
+    auto OptionStringIdxLocation = [&](unsigned Idx) {
----------------
ojhunt wrote:

This code is moderately concise parser of the grammar:

option :- [a-z\-]+
options :- option (',' option)*

The reason for the complexity - vs. just a split(',').map(trim) - is just error messaging. We could simplify if people think it's warranted, but the error message tests are already reduced from what it could be.

https://github.com/llvm/llvm-project/pull/136828


More information about the cfe-commits mailing list