[llvm] f59209a - [AsmParser] Unify parsing of attributes

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 15 08:51:21 PDT 2021


Author: Nikita Popov
Date: 2021-07-15T17:51:11+02:00
New Revision: f59209a86eaf5ec2edea74b9b6e4932148efb3e0

URL: https://github.com/llvm/llvm-project/commit/f59209a86eaf5ec2edea74b9b6e4932148efb3e0
DIFF: https://github.com/llvm/llvm-project/commit/f59209a86eaf5ec2edea74b9b6e4932148efb3e0.diff

LOG: [AsmParser] Unify parsing of attributes

Continuing on from D105780, this should be the last major bit of
attribute cleanup. Currently, LLParser implements attribute parsing
for functions, parameters and returns separately, enumerating all
supported (and unsupported) attributes each time. This patch
extracts the common parsing logic, and performs a check afterwards
whether the attribute is valid in the given position. Parameters
and returns are handled together, while function attributes need
slightly different logic to support attribute groups.

Differential Revision: https://reviews.llvm.org/D105938

Added: 
    

Modified: 
    llvm/include/llvm/AsmParser/LLParser.h
    llvm/lib/AsmParser/LLParser.cpp
    llvm/test/Assembler/byref-parse-error-10.ll
    llvm/test/Assembler/byref-parse-error-5.ll
    llvm/test/Assembler/byref-parse-error-6.ll
    llvm/test/Assembler/byref-parse-error-7.ll
    llvm/test/Assembler/byref-parse-error-8.ll
    llvm/test/Assembler/byref-parse-error-9.ll
    llvm/test/Assembler/invalid-immarg2.ll
    llvm/test/Assembler/invalid-immarg3.ll
    llvm/test/Assembler/invalid-safestack-param.ll
    llvm/test/Assembler/invalid-safestack-return.ll
    llvm/test/Assembler/mustprogress-parse-error-0.ll
    llvm/test/Assembler/mustprogress-parse-error-1.ll
    llvm/test/Transforms/LoopDeletion/assume.ll
    llvm/test/Verifier/swifterror2.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index cba501f2bb6d1..fd9ffb58c0329 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -258,8 +258,15 @@ namespace llvm {
       return parseOptionalAddrSpace(
           AddrSpace, M->getDataLayout().getProgramAddressSpace());
     };
-    bool parseOptionalParamAttrs(AttrBuilder &B);
-    bool parseOptionalReturnAttrs(AttrBuilder &B);
+    bool parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B,
+                            bool InAttrGroup);
+    bool parseOptionalParamOrReturnAttrs(AttrBuilder &B, bool IsParam);
+    bool parseOptionalParamAttrs(AttrBuilder &B) {
+      return parseOptionalParamOrReturnAttrs(B, true);
+    }
+    bool parseOptionalReturnAttrs(AttrBuilder &B) {
+      return parseOptionalParamOrReturnAttrs(B, false);
+    }
     bool parseOptionalLinkage(unsigned &Res, bool &HasLinkage,
                               unsigned &Visibility, unsigned &DLLStorageClass,
                               bool &DSOLocal);

diff  --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index f9eb805326823..1b83d220109c7 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -1243,212 +1243,144 @@ bool LLParser::parseUnnamedAttrGrp() {
   return false;
 }
 
+static Attribute::AttrKind tokenToAttribute(lltok::Kind Kind) {
+  switch (Kind) {
+#define GET_ATTR_NAMES
+#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
+  case lltok::kw_##DISPLAY_NAME: \
+    return Attribute::ENUM_NAME;
+#include "llvm/IR/Attributes.inc"
+  default:
+    return Attribute::None;
+  }
+}
+
+bool LLParser::parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B,
+                                  bool InAttrGroup) {
+  if (Attribute::isTypeAttrKind(Attr))
+    return parseRequiredTypeAttr(B, Lex.getKind(), Attr);
+
+  switch (Attr) {
+  case Attribute::Alignment: {
+    MaybeAlign Alignment;
+    if (InAttrGroup) {
+      uint32_t Value = 0;
+      Lex.Lex();
+      if (parseToken(lltok::equal, "expected '=' here") || parseUInt32(Value))
+        return true;
+      Alignment = Align(Value);
+    } else {
+      if (parseOptionalAlignment(Alignment, true))
+        return true;
+    }
+    B.addAlignmentAttr(Alignment);
+    return false;
+  }
+  case Attribute::StackAlignment: {
+    unsigned Alignment;
+    if (InAttrGroup) {
+      Lex.Lex();
+      if (parseToken(lltok::equal, "expected '=' here") ||
+          parseUInt32(Alignment))
+        return true;
+    } else {
+      if (parseOptionalStackAlignment(Alignment))
+        return true;
+    }
+    B.addStackAlignmentAttr(Alignment);
+    return false;
+  }
+  case Attribute::AllocSize: {
+    unsigned ElemSizeArg;
+    Optional<unsigned> NumElemsArg;
+    if (parseAllocSizeArguments(ElemSizeArg, NumElemsArg))
+      return true;
+    B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
+    return false;
+  }
+  case Attribute::VScaleRange: {
+    unsigned MinValue, MaxValue;
+    if (parseVScaleRangeArguments(MinValue, MaxValue))
+      return true;
+    B.addVScaleRangeAttr(MinValue, MaxValue);
+    return false;
+  }
+  case Attribute::Dereferenceable: {
+    uint64_t Bytes;
+    if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes))
+      return true;
+    B.addDereferenceableAttr(Bytes);
+    return false;
+  }
+  case Attribute::DereferenceableOrNull: {
+    uint64_t Bytes;
+    if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes))
+      return true;
+    B.addDereferenceableOrNullAttr(Bytes);
+    return false;
+  }
+  default:
+    B.addAttribute(Attr);
+    Lex.Lex();
+    return false;
+  }
+}
+
 /// parseFnAttributeValuePairs
 ///   ::= <attr> | <attr> '=' <value>
 bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B,
                                           std::vector<unsigned> &FwdRefAttrGrps,
-                                          bool inAttrGrp, LocTy &BuiltinLoc) {
+                                          bool InAttrGrp, LocTy &BuiltinLoc) {
   bool HaveError = false;
 
   B.clear();
 
   while (true) {
     lltok::Kind Token = Lex.getKind();
-    if (Token == lltok::kw_builtin)
-      BuiltinLoc = Lex.getLoc();
-    switch (Token) {
-    default:
-      if (!inAttrGrp) return HaveError;
-      return error(Lex.getLoc(), "unterminated attribute group");
-    case lltok::rbrace:
-      // Finished.
-      return false;
+    if (Token == lltok::rbrace)
+      return HaveError; // Finished.
+
+    if (Token == lltok::StringConstant) {
+      if (parseStringAttribute(B))
+        return true;
+      continue;
+    }
 
-    case lltok::AttrGrpID: {
+    if (Token == lltok::AttrGrpID) {
       // Allow a function to reference an attribute group:
       //
       //   define void @foo() #1 { ... }
-      if (inAttrGrp)
+      if (InAttrGrp) {
         HaveError |= error(
             Lex.getLoc(),
             "cannot have an attribute group reference in an attribute group");
-
-      unsigned AttrGrpNum = Lex.getUIntVal();
-      if (inAttrGrp) break;
-
-      // Save the reference to the attribute group. We'll fill it in later.
-      FwdRefAttrGrps.push_back(AttrGrpNum);
-      break;
-    }
-    // Target-dependent attributes:
-    case lltok::StringConstant: {
-      if (parseStringAttribute(B))
-        return true;
-      continue;
-    }
-
-    // Target-independent attributes:
-    case lltok::kw_align: {
-      // As a hack, we allow function alignment to be initially parsed as an
-      // attribute on a function declaration/definition or added to an attribute
-      // group and later moved to the alignment field.
-      MaybeAlign Alignment;
-      if (inAttrGrp) {
-        Lex.Lex();
-        uint32_t Value = 0;
-        if (parseToken(lltok::equal, "expected '=' here") || parseUInt32(Value))
-          return true;
-        Alignment = Align(Value);
       } else {
-        if (parseOptionalAlignment(Alignment))
-          return true;
+        // Save the reference to the attribute group. We'll fill it in later.
+        FwdRefAttrGrps.push_back(Lex.getUIntVal());
       }
-      B.addAlignmentAttr(Alignment);
-      continue;
-    }
-    case lltok::kw_alignstack: {
-      unsigned Alignment;
-      if (inAttrGrp) {
-        Lex.Lex();
-        if (parseToken(lltok::equal, "expected '=' here") ||
-            parseUInt32(Alignment))
-          return true;
-      } else {
-        if (parseOptionalStackAlignment(Alignment))
-          return true;
-      }
-      B.addStackAlignmentAttr(Alignment);
-      continue;
-    }
-    case lltok::kw_allocsize: {
-      unsigned ElemSizeArg;
-      Optional<unsigned> NumElemsArg;
-      // inAttrGrp doesn't matter; we only support allocsize(a[, b])
-      if (parseAllocSizeArguments(ElemSizeArg, NumElemsArg))
-        return true;
-      B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
-      continue;
-    }
-    case lltok::kw_vscale_range: {
-      unsigned MinValue, MaxValue;
-      // inAttrGrp doesn't matter; we only support vscale_range(a[, b])
-      if (parseVScaleRangeArguments(MinValue, MaxValue))
-        return true;
-      B.addVScaleRangeAttr(MinValue, MaxValue);
+      Lex.Lex();
       continue;
     }
-    case lltok::kw_alwaysinline: B.addAttribute(Attribute::AlwaysInline); break;
-    case lltok::kw_argmemonly: B.addAttribute(Attribute::ArgMemOnly); break;
-    case lltok::kw_builtin: B.addAttribute(Attribute::Builtin); break;
-    case lltok::kw_cold: B.addAttribute(Attribute::Cold); break;
-    case lltok::kw_hot: B.addAttribute(Attribute::Hot); break;
-    case lltok::kw_convergent: B.addAttribute(Attribute::Convergent); break;
-    case lltok::kw_inaccessiblememonly:
-      B.addAttribute(Attribute::InaccessibleMemOnly); break;
-    case lltok::kw_inaccessiblemem_or_argmemonly:
-      B.addAttribute(Attribute::InaccessibleMemOrArgMemOnly); break;
-    case lltok::kw_inlinehint: B.addAttribute(Attribute::InlineHint); break;
-    case lltok::kw_jumptable: B.addAttribute(Attribute::JumpTable); break;
-    case lltok::kw_minsize: B.addAttribute(Attribute::MinSize); break;
-    case lltok::kw_mustprogress:
-      B.addAttribute(Attribute::MustProgress);
-      break;
-    case lltok::kw_naked: B.addAttribute(Attribute::Naked); break;
-    case lltok::kw_nobuiltin: B.addAttribute(Attribute::NoBuiltin); break;
-    case lltok::kw_nocallback:
-      B.addAttribute(Attribute::NoCallback);
-      break;
-    case lltok::kw_noduplicate: B.addAttribute(Attribute::NoDuplicate); break;
-    case lltok::kw_nofree: B.addAttribute(Attribute::NoFree); break;
-    case lltok::kw_noimplicitfloat:
-      B.addAttribute(Attribute::NoImplicitFloat); break;
-    case lltok::kw_noinline: B.addAttribute(Attribute::NoInline); break;
-    case lltok::kw_nonlazybind: B.addAttribute(Attribute::NonLazyBind); break;
-    case lltok::kw_nomerge: B.addAttribute(Attribute::NoMerge); break;
-    case lltok::kw_noredzone: B.addAttribute(Attribute::NoRedZone); break;
-    case lltok::kw_noreturn: B.addAttribute(Attribute::NoReturn); break;
-    case lltok::kw_nosync: B.addAttribute(Attribute::NoSync); break;
-    case lltok::kw_nocf_check: B.addAttribute(Attribute::NoCfCheck); break;
-    case lltok::kw_noprofile: B.addAttribute(Attribute::NoProfile); break;
-    case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break;
-    case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break;
-    case lltok::kw_nosanitize_coverage:
-      B.addAttribute(Attribute::NoSanitizeCoverage);
-      break;
-    case lltok::kw_null_pointer_is_valid:
-      B.addAttribute(Attribute::NullPointerIsValid); break;
-    case lltok::kw_optforfuzzing:
-      B.addAttribute(Attribute::OptForFuzzing); break;
-    case lltok::kw_optnone: B.addAttribute(Attribute::OptimizeNone); break;
-    case lltok::kw_optsize: B.addAttribute(Attribute::OptimizeForSize); break;
-    case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break;
-    case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break;
-    case lltok::kw_returns_twice:
-      B.addAttribute(Attribute::ReturnsTwice); break;
-    case lltok::kw_speculatable: B.addAttribute(Attribute::Speculatable); break;
-    case lltok::kw_ssp: B.addAttribute(Attribute::StackProtect); break;
-    case lltok::kw_sspreq: B.addAttribute(Attribute::StackProtectReq); break;
-    case lltok::kw_sspstrong:
-      B.addAttribute(Attribute::StackProtectStrong); break;
-    case lltok::kw_safestack: B.addAttribute(Attribute::SafeStack); break;
-    case lltok::kw_shadowcallstack:
-      B.addAttribute(Attribute::ShadowCallStack); break;
-    case lltok::kw_sanitize_address:
-      B.addAttribute(Attribute::SanitizeAddress); break;
-    case lltok::kw_sanitize_hwaddress:
-      B.addAttribute(Attribute::SanitizeHWAddress); break;
-    case lltok::kw_sanitize_memtag:
-      B.addAttribute(Attribute::SanitizeMemTag); break;
-    case lltok::kw_sanitize_thread:
-      B.addAttribute(Attribute::SanitizeThread); break;
-    case lltok::kw_sanitize_memory:
-      B.addAttribute(Attribute::SanitizeMemory); break;
-    case lltok::kw_speculative_load_hardening:
-      B.addAttribute(Attribute::SpeculativeLoadHardening);
-      break;
-    case lltok::kw_strictfp: B.addAttribute(Attribute::StrictFP); break;
-    case lltok::kw_uwtable: B.addAttribute(Attribute::UWTable); break;
-    case lltok::kw_willreturn: B.addAttribute(Attribute::WillReturn); break;
-    case lltok::kw_writeonly: B.addAttribute(Attribute::WriteOnly); break;
-    case lltok::kw_preallocated: {
-      if (parseRequiredTypeAttr(B, lltok::kw_preallocated,
-                                Attribute::Preallocated))
-        return true;
-      break;
-    }
 
-    // error handling.
-    case lltok::kw_inreg:
-    case lltok::kw_signext:
-    case lltok::kw_zeroext:
-      HaveError |=
-          error(Lex.getLoc(), "invalid use of attribute on a function");
-      break;
-    case lltok::kw_byval:
-    case lltok::kw_dereferenceable:
-    case lltok::kw_dereferenceable_or_null:
-    case lltok::kw_inalloca:
-    case lltok::kw_nest:
-    case lltok::kw_noalias:
-    case lltok::kw_noundef:
-    case lltok::kw_nocapture:
-    case lltok::kw_nonnull:
-    case lltok::kw_returned:
-    case lltok::kw_sret:
-    case lltok::kw_swifterror:
-    case lltok::kw_swiftself:
-    case lltok::kw_swiftasync:
-    case lltok::kw_immarg:
-    case lltok::kw_byref:
-      HaveError |=
-          error(Lex.getLoc(),
-                "invalid use of parameter-only attribute on a function");
-      break;
+    SMLoc Loc = Lex.getLoc();
+    if (Token == lltok::kw_builtin)
+      BuiltinLoc = Loc;
+
+    Attribute::AttrKind Attr = tokenToAttribute(Token);
+    if (Attr == Attribute::None) {
+      if (!InAttrGrp)
+        return HaveError;
+      return error(Lex.getLoc(), "unterminated attribute group");
     }
 
-    // parsePreallocated() consumes token
-    if (Token != lltok::kw_preallocated)
-      Lex.Lex();
+    if (parseEnumAttribute(Attr, B, InAttrGrp))
+      return true;
+
+    // As a hack, we allow function alignment to be initially parsed as an
+    // attribute on a function declaration/definition or added to an attribute
+    // group and later moved to the alignment field.
+    if (!Attribute::canUseAsFnAttr(Attr) && Attr != Attribute::Alignment)
+      HaveError |= error(Loc, "this attribute does not apply to functions");
   }
 }
 
@@ -1685,258 +1617,32 @@ bool LLParser::parseStringAttribute(AttrBuilder &B) {
   return false;
 }
 
-/// parseOptionalParamAttrs - parse a potentially empty list of parameter
-/// attributes.
-bool LLParser::parseOptionalParamAttrs(AttrBuilder &B) {
+/// Parse a potentially empty list of parameter or return attributes.
+bool LLParser::parseOptionalParamOrReturnAttrs(AttrBuilder &B, bool IsParam) {
   bool HaveError = false;
 
   B.clear();
 
   while (true) {
     lltok::Kind Token = Lex.getKind();
-    switch (Token) {
-    default:  // End of attributes.
-      return HaveError;
-    case lltok::StringConstant: {
+    if (Token == lltok::StringConstant) {
       if (parseStringAttribute(B))
         return true;
       continue;
     }
-    case lltok::kw_align: {
-      MaybeAlign Alignment;
-      if (parseOptionalAlignment(Alignment, true))
-        return true;
-      B.addAlignmentAttr(Alignment);
-      continue;
-    }
-    case lltok::kw_alignstack: {
-      unsigned Alignment;
-      if (parseOptionalStackAlignment(Alignment))
-        return true;
-      B.addStackAlignmentAttr(Alignment);
-      continue;
-    }
-    case lltok::kw_byval:
-      if (parseRequiredTypeAttr(B, lltok::kw_byval, Attribute::ByVal))
-        return true;
-      continue;
-    case lltok::kw_byref:
-      if (parseRequiredTypeAttr(B, lltok::kw_byref, Attribute::ByRef))
-        return true;
-      continue;
-    case lltok::kw_inalloca:
-      if (parseRequiredTypeAttr(B, lltok::kw_inalloca, Attribute::InAlloca))
-        return true;
-      continue;
-    case lltok::kw_preallocated:
-      if (parseRequiredTypeAttr(B, lltok::kw_preallocated,
-                                Attribute::Preallocated))
-        return true;
-      continue;
-    case lltok::kw_sret:
-      if (parseRequiredTypeAttr(B, lltok::kw_sret, Attribute::StructRet))
-        return true;
-      continue;
-    case lltok::kw_dereferenceable: {
-      uint64_t Bytes;
-      if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes))
-        return true;
-      B.addDereferenceableAttr(Bytes);
-      continue;
-    }
-    case lltok::kw_dereferenceable_or_null: {
-      uint64_t Bytes;
-      if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes))
-        return true;
-      B.addDereferenceableOrNullAttr(Bytes);
-      continue;
-    }
-    case lltok::kw_inreg:           B.addAttribute(Attribute::InReg); break;
-    case lltok::kw_nest:            B.addAttribute(Attribute::Nest); break;
-    case lltok::kw_noundef:
-      B.addAttribute(Attribute::NoUndef);
-      break;
-    case lltok::kw_noalias:         B.addAttribute(Attribute::NoAlias); break;
-    case lltok::kw_nocapture:       B.addAttribute(Attribute::NoCapture); break;
-    case lltok::kw_nofree:          B.addAttribute(Attribute::NoFree); break;
-    case lltok::kw_nonnull:         B.addAttribute(Attribute::NonNull); break;
-    case lltok::kw_readnone:        B.addAttribute(Attribute::ReadNone); break;
-    case lltok::kw_readonly:        B.addAttribute(Attribute::ReadOnly); break;
-    case lltok::kw_returned:        B.addAttribute(Attribute::Returned); break;
-    case lltok::kw_signext:         B.addAttribute(Attribute::SExt); break;
-    case lltok::kw_swifterror:      B.addAttribute(Attribute::SwiftError); break;
-    case lltok::kw_swiftself:       B.addAttribute(Attribute::SwiftSelf); break;
-    case lltok::kw_swiftasync:      B.addAttribute(Attribute::SwiftAsync); break;
-    case lltok::kw_writeonly:       B.addAttribute(Attribute::WriteOnly); break;
-    case lltok::kw_zeroext:         B.addAttribute(Attribute::ZExt); break;
-    case lltok::kw_immarg:          B.addAttribute(Attribute::ImmArg); break;
-
-    case lltok::kw_alwaysinline:
-    case lltok::kw_argmemonly:
-    case lltok::kw_builtin:
-    case lltok::kw_inlinehint:
-    case lltok::kw_jumptable:
-    case lltok::kw_minsize:
-    case lltok::kw_mustprogress:
-    case lltok::kw_naked:
-    case lltok::kw_nobuiltin:
-    case lltok::kw_noduplicate:
-    case lltok::kw_noimplicitfloat:
-    case lltok::kw_noinline:
-    case lltok::kw_nonlazybind:
-    case lltok::kw_nomerge:
-    case lltok::kw_noprofile:
-    case lltok::kw_noredzone:
-    case lltok::kw_noreturn:
-    case lltok::kw_nocf_check:
-    case lltok::kw_nounwind:
-    case lltok::kw_nosanitize_coverage:
-    case lltok::kw_optforfuzzing:
-    case lltok::kw_optnone:
-    case lltok::kw_optsize:
-    case lltok::kw_returns_twice:
-    case lltok::kw_sanitize_address:
-    case lltok::kw_sanitize_hwaddress:
-    case lltok::kw_sanitize_memtag:
-    case lltok::kw_sanitize_memory:
-    case lltok::kw_sanitize_thread:
-    case lltok::kw_speculative_load_hardening:
-    case lltok::kw_ssp:
-    case lltok::kw_sspreq:
-    case lltok::kw_sspstrong:
-    case lltok::kw_safestack:
-    case lltok::kw_shadowcallstack:
-    case lltok::kw_strictfp:
-    case lltok::kw_uwtable:
-    case lltok::kw_vscale_range:
-      HaveError |=
-          error(Lex.getLoc(), "invalid use of function-only attribute");
-      break;
-    }
-
-    Lex.Lex();
-  }
-}
-
-/// parseOptionalReturnAttrs - parse a potentially empty list of return
-/// attributes.
-bool LLParser::parseOptionalReturnAttrs(AttrBuilder &B) {
-  bool HaveError = false;
 
-  B.clear();
-
-  while (true) {
-    lltok::Kind Token = Lex.getKind();
-    switch (Token) {
-    default:  // End of attributes.
+    SMLoc Loc = Lex.getLoc();
+    Attribute::AttrKind Attr = tokenToAttribute(Token);
+    if (Attr == Attribute::None)
       return HaveError;
-    case lltok::StringConstant: {
-      if (parseStringAttribute(B))
-        return true;
-      continue;
-    }
-    case lltok::kw_dereferenceable: {
-      uint64_t Bytes;
-      if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes))
-        return true;
-      B.addDereferenceableAttr(Bytes);
-      continue;
-    }
-    case lltok::kw_dereferenceable_or_null: {
-      uint64_t Bytes;
-      if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes))
-        return true;
-      B.addDereferenceableOrNullAttr(Bytes);
-      continue;
-    }
-    case lltok::kw_align: {
-      MaybeAlign Alignment;
-      if (parseOptionalAlignment(Alignment))
-        return true;
-      B.addAlignmentAttr(Alignment);
-      continue;
-    }
-    case lltok::kw_inreg:           B.addAttribute(Attribute::InReg); break;
-    case lltok::kw_noalias:         B.addAttribute(Attribute::NoAlias); break;
-    case lltok::kw_noundef:
-      B.addAttribute(Attribute::NoUndef);
-      break;
-    case lltok::kw_nonnull:         B.addAttribute(Attribute::NonNull); break;
-    case lltok::kw_signext:         B.addAttribute(Attribute::SExt); break;
-    case lltok::kw_zeroext:         B.addAttribute(Attribute::ZExt); break;
-
-    // error handling.
-    case lltok::kw_byval:
-    case lltok::kw_inalloca:
-    case lltok::kw_nest:
-    case lltok::kw_nocapture:
-    case lltok::kw_returned:
-    case lltok::kw_sret:
-    case lltok::kw_swifterror:
-    case lltok::kw_swiftself:
-    case lltok::kw_swiftasync:
-    case lltok::kw_immarg:
-    case lltok::kw_byref:
-      HaveError |=
-          error(Lex.getLoc(), "invalid use of parameter-only attribute");
-      break;
 
-    case lltok::kw_alignstack:
-    case lltok::kw_alwaysinline:
-    case lltok::kw_argmemonly:
-    case lltok::kw_builtin:
-    case lltok::kw_cold:
-    case lltok::kw_inlinehint:
-    case lltok::kw_jumptable:
-    case lltok::kw_minsize:
-    case lltok::kw_mustprogress:
-    case lltok::kw_naked:
-    case lltok::kw_nobuiltin:
-    case lltok::kw_noduplicate:
-    case lltok::kw_noimplicitfloat:
-    case lltok::kw_noinline:
-    case lltok::kw_nonlazybind:
-    case lltok::kw_nomerge:
-    case lltok::kw_noprofile:
-    case lltok::kw_noredzone:
-    case lltok::kw_noreturn:
-    case lltok::kw_nocf_check:
-    case lltok::kw_nounwind:
-    case lltok::kw_nosanitize_coverage:
-    case lltok::kw_optforfuzzing:
-    case lltok::kw_optnone:
-    case lltok::kw_optsize:
-    case lltok::kw_returns_twice:
-    case lltok::kw_sanitize_address:
-    case lltok::kw_sanitize_hwaddress:
-    case lltok::kw_sanitize_memtag:
-    case lltok::kw_sanitize_memory:
-    case lltok::kw_sanitize_thread:
-    case lltok::kw_speculative_load_hardening:
-    case lltok::kw_ssp:
-    case lltok::kw_sspreq:
-    case lltok::kw_sspstrong:
-    case lltok::kw_safestack:
-    case lltok::kw_shadowcallstack:
-    case lltok::kw_strictfp:
-    case lltok::kw_uwtable:
-    case lltok::kw_vscale_range:
-      HaveError |=
-          error(Lex.getLoc(), "invalid use of function-only attribute");
-      break;
-    case lltok::kw_readnone:
-    case lltok::kw_readonly:
-      HaveError |=
-          error(Lex.getLoc(), "invalid use of attribute on return type");
-      break;
-    case lltok::kw_preallocated:
-      HaveError |=
-          error(Lex.getLoc(),
-                "invalid use of parameter-only/call site-only attribute");
-      break;
-    }
+    if (parseEnumAttribute(Attr, B, /* InAttrGroup */ false))
+      return true;
 
-    Lex.Lex();
+    if (IsParam && !Attribute::canUseAsParamAttr(Attr))
+      HaveError |= error(Loc, "this attribute does not apply to parameters");
+    if (!IsParam && !Attribute::canUseAsRetAttr(Attr))
+      HaveError |= error(Loc, "this attribute does not apply to return values");
   }
 }
 

diff  --git a/llvm/test/Assembler/byref-parse-error-10.ll b/llvm/test/Assembler/byref-parse-error-10.ll
index 55997e5ffe542..272c4113ec770 100644
--- a/llvm/test/Assembler/byref-parse-error-10.ll
+++ b/llvm/test/Assembler/byref-parse-error-10.ll
@@ -1,6 +1,6 @@
 ; RUN: not llvm-as < %s 2>&1 | FileCheck %s
 
-; CHECK: <stdin>:[[@LINE+1]]:27: error: invalid use of parameter-only attribute on a function{{$}}
+; CHECK: <stdin>:[[@LINE+1]]:33: error: expected type{{$}}
 define void @test_byref() byref(4) {
   ret void
 }

diff  --git a/llvm/test/Assembler/byref-parse-error-5.ll b/llvm/test/Assembler/byref-parse-error-5.ll
index c1a154805f41b..55ebd08e44ad2 100644
--- a/llvm/test/Assembler/byref-parse-error-5.ll
+++ b/llvm/test/Assembler/byref-parse-error-5.ll
@@ -1,6 +1,6 @@
 ; RUN: not llvm-as < %s 2>&1 | FileCheck %s
 
-; CHECK: <stdin>:[[@LINE+1]]:8: error: invalid use of parameter-only attribute{{$}}
+; CHECK: <stdin>:[[@LINE+1]]:14: error: expected '('{{$}}
 define byref i8* @test_byref() {
   ret void
 }

diff  --git a/llvm/test/Assembler/byref-parse-error-6.ll b/llvm/test/Assembler/byref-parse-error-6.ll
index c5ecf83596e21..f83378a0bf10d 100644
--- a/llvm/test/Assembler/byref-parse-error-6.ll
+++ b/llvm/test/Assembler/byref-parse-error-6.ll
@@ -1,6 +1,6 @@
 ; RUN: not llvm-as < %s 2>&1 | FileCheck %s
 
-; CHECK: <stdin>:[[@LINE+1]]:8: error: invalid use of parameter-only attribute{{$}}
+; CHECK: <stdin>:[[@LINE+1]]:14: error: expected '('{{$}}
 define byref 8 i8* @test_byref() {
   ret void
 }

diff  --git a/llvm/test/Assembler/byref-parse-error-7.ll b/llvm/test/Assembler/byref-parse-error-7.ll
index 9ac60af5348dc..33764e42864d2 100644
--- a/llvm/test/Assembler/byref-parse-error-7.ll
+++ b/llvm/test/Assembler/byref-parse-error-7.ll
@@ -1,6 +1,6 @@
 ; RUN: not llvm-as < %s 2>&1 | FileCheck %s
 
-; CHECK: <stdin>:[[@LINE+1]]:8: error: invalid use of parameter-only attribute{{$}}
+; CHECK: <stdin>:[[@LINE+1]]:14: error: expected type{{$}}
 define byref(8) i8* @test_byref() {
   ret void
 }

diff  --git a/llvm/test/Assembler/byref-parse-error-8.ll b/llvm/test/Assembler/byref-parse-error-8.ll
index 8f86b9f8afc42..2770eb9acac12 100644
--- a/llvm/test/Assembler/byref-parse-error-8.ll
+++ b/llvm/test/Assembler/byref-parse-error-8.ll
@@ -1,6 +1,6 @@
 ; RUN: not llvm-as < %s 2>&1 | FileCheck %s
 
-; CHECK: <stdin>:[[@LINE+1]]:27: error: invalid use of parameter-only attribute on a function{{$}}
+; CHECK: <stdin>:[[@LINE+1]]:33: error: expected '('{{$}}
 define void @test_byref() byref {
   ret void
 }

diff  --git a/llvm/test/Assembler/byref-parse-error-9.ll b/llvm/test/Assembler/byref-parse-error-9.ll
index bc707062a2e8d..c816dbf936667 100644
--- a/llvm/test/Assembler/byref-parse-error-9.ll
+++ b/llvm/test/Assembler/byref-parse-error-9.ll
@@ -1,6 +1,6 @@
 ; RUN: not llvm-as < %s 2>&1 | FileCheck %s
 
-; CHECK: <stdin>:[[@LINE+1]]:27: error: invalid use of parameter-only attribute on a function{{$}}
+; CHECK: <stdin>:[[@LINE+1]]:32: error: expected '('{{$}}
 define void @test_byref() byref=4 {
   ret void
 }

diff  --git a/llvm/test/Assembler/invalid-immarg2.ll b/llvm/test/Assembler/invalid-immarg2.ll
index f4589108a9fd6..efbf7b7509f02 100644
--- a/llvm/test/Assembler/invalid-immarg2.ll
+++ b/llvm/test/Assembler/invalid-immarg2.ll
@@ -1,4 +1,4 @@
 ; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
 
-; CHECK: error: invalid use of parameter-only attribute on a function
+; CHECK: error: this attribute does not apply to functions
 declare void @llvm.immarg.func() immarg

diff  --git a/llvm/test/Assembler/invalid-immarg3.ll b/llvm/test/Assembler/invalid-immarg3.ll
index c03d7fafdc2bf..43adff93cc95e 100644
--- a/llvm/test/Assembler/invalid-immarg3.ll
+++ b/llvm/test/Assembler/invalid-immarg3.ll
@@ -1,4 +1,4 @@
 ; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
 
-; CHECK: error: invalid use of parameter-only attribute
+; CHECK: error: this attribute does not apply to return values
 declare immarg i32 @llvm.immarg.retattr(i32)

diff  --git a/llvm/test/Assembler/invalid-safestack-param.ll b/llvm/test/Assembler/invalid-safestack-param.ll
index b9046c4c33bd7..3cbbf037742b3 100644
--- a/llvm/test/Assembler/invalid-safestack-param.ll
+++ b/llvm/test/Assembler/invalid-safestack-param.ll
@@ -1,4 +1,4 @@
 ; RUN: not llvm-as -o /dev/null %s 2>&1 | FileCheck %s
 
-; CHECK: error: invalid use of function-only attribute
+; CHECK: error: this attribute does not apply to parameters
 declare void @foo(i32 safestack %x)

diff  --git a/llvm/test/Assembler/invalid-safestack-return.ll b/llvm/test/Assembler/invalid-safestack-return.ll
index 605e72e84c8e3..81a1d25666cd6 100644
--- a/llvm/test/Assembler/invalid-safestack-return.ll
+++ b/llvm/test/Assembler/invalid-safestack-return.ll
@@ -1,4 +1,4 @@
 ; RUN: not llvm-as -o /dev/null %s 2>&1 | FileCheck %s
 
-; CHECK: error: invalid use of function-only attribute
+; CHECK: error: this attribute does not apply to return values
 declare safestack void @foo()

diff  --git a/llvm/test/Assembler/mustprogress-parse-error-0.ll b/llvm/test/Assembler/mustprogress-parse-error-0.ll
index 56d4e6eb6fa41..b5aab406c73ed 100644
--- a/llvm/test/Assembler/mustprogress-parse-error-0.ll
+++ b/llvm/test/Assembler/mustprogress-parse-error-0.ll
@@ -1,6 +1,6 @@
 ; RUN: not llvm-as < %s 2>&1 | FileCheck %s
 
-; CHECK: [[@LINE+1]]:35: error: invalid use of function-only attribute 
+; CHECK: [[@LINE+1]]:35: error: this attribute does not apply to parameters
 define void @test_mustprogress(i8 mustprogress %a) {
   ret void
 }

diff  --git a/llvm/test/Assembler/mustprogress-parse-error-1.ll b/llvm/test/Assembler/mustprogress-parse-error-1.ll
index ced1650e5a9cc..8909bfd570fc1 100644
--- a/llvm/test/Assembler/mustprogress-parse-error-1.ll
+++ b/llvm/test/Assembler/mustprogress-parse-error-1.ll
@@ -1,6 +1,6 @@
 ; RUN: not llvm-as < %s 2>&1 | FileCheck %s
 
-; CHECK: [[@LINE+1]]:8: error: invalid use of function-only attribute 
+; CHECK: [[@LINE+1]]:8: error: this attribute does not apply to return values
 define mustprogress void @test_mustprogress(i8 %a) {
   ret void
 }

diff  --git a/llvm/test/Transforms/LoopDeletion/assume.ll b/llvm/test/Transforms/LoopDeletion/assume.ll
index 124188cd5b654..6e2644ea8b235 100644
--- a/llvm/test/Transforms/LoopDeletion/assume.ll
+++ b/llvm/test/Transforms/LoopDeletion/assume.ll
@@ -37,4 +37,4 @@ _ZSt8_DestroyIP3LocILi3EEEvT_S3_.exit:            ; preds = %2
 declare void @llvm.assume(i1) #1
 
 attributes #0 = { "target-cpu"="x86-64" }
-attributes #1 = { willreturn readnone norecurse nocapture nofree }
+attributes #1 = { willreturn readnone norecurse nofree }

diff  --git a/llvm/test/Verifier/swifterror2.ll b/llvm/test/Verifier/swifterror2.ll
index 23d3b6321d6a1..75eeb2fc7e156 100644
--- a/llvm/test/Verifier/swifterror2.ll
+++ b/llvm/test/Verifier/swifterror2.ll
@@ -1,4 +1,4 @@
 ; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
 
-; CHECK: invalid use of parameter-only attribute
+; CHECK: this attribute does not apply to return values
 declare swifterror void @c(i32** swifterror %a)


        


More information about the llvm-commits mailing list