Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang] Split up SemaDeclAttr.cpp #93966

Merged
merged 9 commits into from
Jun 5, 2024
Merged

Conversation

Endilll
Copy link
Contributor

@Endilll Endilll commented May 31, 2024

This patch moves language- and target-specific functions out of SemaDeclAttr.cpp. As a consequence, SemaAVR, SemaM68k, SemaMSP430, SemaOpenCL, SemaSwift were created (but they are not the only languages and targets affected).

Notable things are that Sema.h actually grew a bit, because of templated helpers that rely on Sema that I had to make available from outside of SemaDeclAttr.cpp. I also had to left CUDA-related in SemaDeclAttr.cpp, because it looks like HIP is building up on top of CUDA attributes.

This is a follow-up to #93179 and continuation of efforts to split Sema up. Additional context can be found in #84184 and #92682.

@Endilll Endilll added the clang:frontend Language frontend issues, e.g. anything involving "Sema" label May 31, 2024
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:ARM backend:AArch64 backend:RISC-V backend:X86 HLSL HLSL Language Support clang:openmp OpenMP related changes to Clang labels May 31, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented May 31, 2024

@llvm/pr-subscribers-backend-arm
@llvm/pr-subscribers-hlsl
@llvm/pr-subscribers-backend-risc-v

@llvm/pr-subscribers-clang

Author: Vlad Serebrennikov (Endilll)

Changes

This patch moves language- and target-specific functions out of SemaDeclAttr.cpp. As a consequence, SemaAVR, SemaM68k, SemaMSP430, SemaOpenCL, SemaSwift were created (but they are not the only languages and targets affected).

Notable things are that Sema.h actually grew a bit, because of templated helpers that rely on Sema that I had to make available from outside of SemaDeclAttr.cpp. I also had to left CUDA-related in SemaDeclAttr.cpp, because it looks like HIP is building up on top of CUDA attributes.

This is a follow-up to #93179 and continuation of efforts to split Sema up. Additional context can be found in #84184 and #92682.


Patch is 257.01 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/93966.diff

37 Files Affected:

  • (modified) clang/include/clang/Sema/Attr.h (+86)
  • (modified) clang/include/clang/Sema/Sema.h (+145-18)
  • (modified) clang/include/clang/Sema/SemaARM.h (+11)
  • (added) clang/include/clang/Sema/SemaAVR.h (+31)
  • (modified) clang/include/clang/Sema/SemaBPF.h (+6)
  • (modified) clang/include/clang/Sema/SemaHLSL.h (+8)
  • (added) clang/include/clang/Sema/SemaM68k.h (+29)
  • (modified) clang/include/clang/Sema/SemaMIPS.h (+3)
  • (added) clang/include/clang/Sema/SemaMSP430.h (+29)
  • (modified) clang/include/clang/Sema/SemaObjC.h (+50)
  • (added) clang/include/clang/Sema/SemaOpenCL.h (+34)
  • (modified) clang/include/clang/Sema/SemaOpenMP.h (+3)
  • (modified) clang/include/clang/Sema/SemaRISCV.h (+4)
  • (modified) clang/include/clang/Sema/SemaSYCL.h (+4)
  • (added) clang/include/clang/Sema/SemaSwift.h (+57)
  • (modified) clang/include/clang/Sema/SemaX86.h (+5)
  • (modified) clang/lib/Sema/CMakeLists.txt (+5)
  • (modified) clang/lib/Sema/Sema.cpp (+10)
  • (modified) clang/lib/Sema/SemaAPINotes.cpp (+3-2)
  • (modified) clang/lib/Sema/SemaARM.cpp (+195)
  • (added) clang/lib/Sema/SemaAVR.cpp (+47)
  • (modified) clang/lib/Sema/SemaBPF.cpp (+19)
  • (modified) clang/lib/Sema/SemaDecl.cpp (+2-1)
  • (modified) clang/lib/Sema/SemaDeclAttr.cpp (+166-2780)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+227)
  • (added) clang/lib/Sema/SemaM68k.cpp (+53)
  • (modified) clang/lib/Sema/SemaMIPS.cpp (+59)
  • (added) clang/lib/Sema/SemaMSP430.cpp (+75)
  • (modified) clang/lib/Sema/SemaObjC.cpp (+771)
  • (added) clang/lib/Sema/SemaOpenCL.cpp (+97)
  • (modified) clang/lib/Sema/SemaOpenMP.cpp (+38)
  • (modified) clang/lib/Sema/SemaRISCV.cpp (+64)
  • (modified) clang/lib/Sema/SemaSYCL.cpp (+40)
  • (added) clang/lib/Sema/SemaSwift.cpp (+761)
  • (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+5-3)
  • (modified) clang/lib/Sema/SemaType.cpp (+3-3)
  • (modified) clang/lib/Sema/SemaX86.cpp (+93)
diff --git a/clang/include/clang/Sema/Attr.h b/clang/include/clang/Sema/Attr.h
index 1133862568a6c..25a20bb697914 100644
--- a/clang/include/clang/Sema/Attr.h
+++ b/clang/include/clang/Sema/Attr.h
@@ -14,7 +14,11 @@
 #define LLVM_CLANG_SEMA_ATTR_H
 
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/SourceLocation.h"
 #include "llvm/Support/Casting.h"
 
 namespace clang {
@@ -32,5 +36,87 @@ inline bool isFunctionOrMethodOrBlockForAttrSubject(const Decl *D) {
   return isFuncOrMethodForAttrSubject(D) || llvm::isa<BlockDecl>(D);
 }
 
+/// Return true if the given decl has a declarator that should have
+/// been processed by Sema::GetTypeForDeclarator.
+inline bool hasDeclarator(const Decl *D) {
+  // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl.
+  return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) ||
+         isa<TypedefNameDecl>(D) || isa<ObjCPropertyDecl>(D);
+}
+
+/// hasFunctionProto - Return true if the given decl has a argument
+/// information. This decl should have already passed
+/// isFuncOrMethodForAttrSubject or isFunctionOrMethodOrBlockForAttrSubject.
+inline bool hasFunctionProto(const Decl *D) {
+  if (const FunctionType *FnTy = D->getFunctionType())
+    return isa<FunctionProtoType>(FnTy);
+  return isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D);
+}
+
+/// getFunctionOrMethodNumParams - Return number of function or method
+/// parameters. It is an error to call this on a K&R function (use
+/// hasFunctionProto first).
+inline unsigned getFunctionOrMethodNumParams(const Decl *D) {
+  if (const FunctionType *FnTy = D->getFunctionType())
+    return cast<FunctionProtoType>(FnTy)->getNumParams();
+  if (const auto *BD = dyn_cast<BlockDecl>(D))
+    return BD->getNumParams();
+  return cast<ObjCMethodDecl>(D)->param_size();
+}
+
+inline const ParmVarDecl *getFunctionOrMethodParam(const Decl *D,
+                                                   unsigned Idx) {
+  if (const auto *FD = dyn_cast<FunctionDecl>(D))
+    return FD->getParamDecl(Idx);
+  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
+    return MD->getParamDecl(Idx);
+  if (const auto *BD = dyn_cast<BlockDecl>(D))
+    return BD->getParamDecl(Idx);
+  return nullptr;
+}
+
+inline QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
+  if (const FunctionType *FnTy = D->getFunctionType())
+    return cast<FunctionProtoType>(FnTy)->getParamType(Idx);
+  if (const auto *BD = dyn_cast<BlockDecl>(D))
+    return BD->getParamDecl(Idx)->getType();
+
+  return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType();
+}
+
+inline SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) {
+  if (auto *PVD = getFunctionOrMethodParam(D, Idx))
+    return PVD->getSourceRange();
+  return SourceRange();
+}
+
+inline QualType getFunctionOrMethodResultType(const Decl *D) {
+  if (const FunctionType *FnTy = D->getFunctionType())
+    return FnTy->getReturnType();
+  return cast<ObjCMethodDecl>(D)->getReturnType();
+}
+
+inline SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) {
+  if (const auto *FD = dyn_cast<FunctionDecl>(D))
+    return FD->getReturnTypeSourceRange();
+  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
+    return MD->getReturnTypeSourceRange();
+  return SourceRange();
+}
+
+inline bool isFunctionOrMethodVariadic(const Decl *D) {
+  if (const FunctionType *FnTy = D->getFunctionType())
+    return cast<FunctionProtoType>(FnTy)->isVariadic();
+  if (const auto *BD = dyn_cast<BlockDecl>(D))
+    return BD->isVariadic();
+  return cast<ObjCMethodDecl>(D)->isVariadic();
+}
+
+inline bool isInstanceMethod(const Decl *D) {
+  if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(D))
+    return MethodDecl->isInstance();
+  return false;
+}
+
 } // namespace clang
 #endif // LLVM_CLANG_SEMA_ATTR_H
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 7dea2b6826cfd..956f15773ead8 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -47,6 +47,7 @@
 #include "clang/Basic/TemplateKinds.h"
 #include "clang/Basic/TypeTraits.h"
 #include "clang/Sema/AnalysisBasedWarnings.h"
+#include "clang/Sema/Attr.h"
 #include "clang/Sema/CleanupInfo.h"
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/ExternalSemaSource.h"
@@ -171,21 +172,26 @@ class PseudoObjectExpr;
 class QualType;
 class SemaAMDGPU;
 class SemaARM;
+class SemaAVR;
 class SemaBPF;
 class SemaCodeCompletion;
 class SemaCUDA;
 class SemaHLSL;
 class SemaHexagon;
 class SemaLoongArch;
+class SemaM68k;
 class SemaMIPS;
+class SemaMSP430;
 class SemaNVPTX;
 class SemaObjC;
 class SemaOpenACC;
+class SemaOpenCL;
 class SemaOpenMP;
 class SemaPPC;
 class SemaPseudoObject;
 class SemaRISCV;
 class SemaSYCL;
+class SemaSwift;
 class SemaSystemZ;
 class SemaWasm;
 class SemaX86;
@@ -1011,6 +1017,11 @@ class Sema final : public SemaBase {
     return *ARMPtr;
   }
 
+  SemaAVR &AVR() {
+    assert(AVRPtr);
+    return *AVRPtr;
+  }
+
   SemaBPF &BPF() {
     assert(BPFPtr);
     return *BPFPtr;
@@ -1041,11 +1052,21 @@ class Sema final : public SemaBase {
     return *LoongArchPtr;
   }
 
+  SemaM68k &M68k() {
+    assert(M68kPtr);
+    return *M68kPtr;
+  }
+
   SemaMIPS &MIPS() {
     assert(MIPSPtr);
     return *MIPSPtr;
   }
 
+  SemaMSP430 &MSP430() {
+    assert(MSP430Ptr);
+    return *MSP430Ptr;
+  }
+
   SemaNVPTX &NVPTX() {
     assert(NVPTXPtr);
     return *NVPTXPtr;
@@ -1061,6 +1082,11 @@ class Sema final : public SemaBase {
     return *OpenACCPtr;
   }
 
+  SemaOpenCL &OpenCL() {
+    assert(OpenCLPtr);
+    return *OpenCLPtr;
+  }
+
   SemaOpenMP &OpenMP() {
     assert(OpenMPPtr && "SemaOpenMP is dead");
     return *OpenMPPtr;
@@ -1086,6 +1112,11 @@ class Sema final : public SemaBase {
     return *SYCLPtr;
   }
 
+  SemaSwift &Swift() {
+    assert(SwiftPtr);
+    return *SwiftPtr;
+  }
+
   SemaSystemZ &SystemZ() {
     assert(SystemZPtr);
     return *SystemZPtr;
@@ -1133,21 +1164,26 @@ class Sema final : public SemaBase {
 
   std::unique_ptr<SemaAMDGPU> AMDGPUPtr;
   std::unique_ptr<SemaARM> ARMPtr;
+  std::unique_ptr<SemaAVR> AVRPtr;
   std::unique_ptr<SemaBPF> BPFPtr;
   std::unique_ptr<SemaCodeCompletion> CodeCompletionPtr;
   std::unique_ptr<SemaCUDA> CUDAPtr;
   std::unique_ptr<SemaHLSL> HLSLPtr;
   std::unique_ptr<SemaHexagon> HexagonPtr;
   std::unique_ptr<SemaLoongArch> LoongArchPtr;
+  std::unique_ptr<SemaM68k> M68kPtr;
   std::unique_ptr<SemaMIPS> MIPSPtr;
+  std::unique_ptr<SemaMSP430> MSP430Ptr;
   std::unique_ptr<SemaNVPTX> NVPTXPtr;
   std::unique_ptr<SemaObjC> ObjCPtr;
   std::unique_ptr<SemaOpenACC> OpenACCPtr;
+  std::unique_ptr<SemaOpenCL> OpenCLPtr;
   std::unique_ptr<SemaOpenMP> OpenMPPtr;
   std::unique_ptr<SemaPPC> PPCPtr;
   std::unique_ptr<SemaPseudoObject> PseudoObjectPtr;
   std::unique_ptr<SemaRISCV> RISCVPtr;
   std::unique_ptr<SemaSYCL> SYCLPtr;
+  std::unique_ptr<SemaSwift> SwiftPtr;
   std::unique_ptr<SemaSystemZ> SystemZPtr;
   std::unique_ptr<SemaWasm> WasmPtr;
   std::unique_ptr<SemaX86> X86Ptr;
@@ -3711,8 +3747,6 @@ class Sema final : public SemaBase {
                                           const AttributeCommonInfo &CI,
                                           const IdentifierInfo *Ident);
   MinSizeAttr *mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI);
-  SwiftNameAttr *mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA,
-                                    StringRef Name);
   OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D,
                                           const AttributeCommonInfo &CI);
   InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL);
@@ -3726,8 +3760,6 @@ class Sema final : public SemaBase {
       const ParsedAttr &attr, CallingConv &CC, const FunctionDecl *FD = nullptr,
       CUDAFunctionTarget CFT = CUDAFunctionTarget::InvalidTarget);
 
-  void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
-                           ParameterABI ABI);
   bool CheckRegparmAttr(const ParsedAttr &attr, unsigned &value);
 
   /// Create an CUDALaunchBoundsAttr attribute.
@@ -3742,20 +3774,6 @@ class Sema final : public SemaBase {
                            Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks);
 
   enum class RetainOwnershipKind { NS, CF, OS };
-  void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
-                        RetainOwnershipKind K, bool IsTemplateInstantiation);
-
-  bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
-
-  /// Do a check to make sure \p Name looks like a legal argument for the
-  /// swift_name attribute applied to decl \p D.  Raise a diagnostic if the name
-  /// is invalid for the given declaration.
-  ///
-  /// \p AL is used to provide caret diagnostics in case of a malformed name.
-  ///
-  /// \returns true if the name is a valid swift name for \p D, false otherwise.
-  bool DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc,
-                         const ParsedAttr &AL, bool IsAsync);
 
   UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI,
                           StringRef UuidAsWritten, MSGuidDecl *GuidDecl);
@@ -3825,6 +3843,115 @@ class Sema final : public SemaBase {
 
   void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
 
+  /// Diagnose mutually exclusive attributes when present on a given
+  /// declaration. Returns true if diagnosed.
+  template <typename AttrTy>
+  bool checkAttrMutualExclusion(Decl *D, const ParsedAttr &AL) {
+    if (const auto *A = D->getAttr<AttrTy>()) {
+      Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
+          << AL << A
+          << (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute());
+      Diag(A->getLocation(), diag::note_conflicting_attribute);
+      return true;
+    }
+    return false;
+  }
+
+  template <typename AttrTy>
+  bool checkAttrMutualExclusion(Decl *D, const Attr &AL) {
+    if (const auto *A = D->getAttr<AttrTy>()) {
+      Diag(AL.getLocation(), diag::err_attributes_are_not_compatible)
+          << &AL << A
+          << (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute());
+      Diag(A->getLocation(), diag::note_conflicting_attribute);
+      return true;
+    }
+    return false;
+  }
+
+  template <typename... DiagnosticArgs>
+  static const Sema::SemaDiagnosticBuilder &
+  appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr) {
+    return Bldr;
+  }
+
+  template <typename T, typename... DiagnosticArgs>
+  static const Sema::SemaDiagnosticBuilder &
+  appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr, T &&ExtraArg,
+                    DiagnosticArgs &&...ExtraArgs) {
+    return appendDiagnostics(Bldr << std::forward<T>(ExtraArg),
+                             std::forward<DiagnosticArgs>(ExtraArgs)...);
+  }
+
+  /// Add an attribute @c AttrType to declaration @c D, provided that
+  /// @c PassesCheck is true.
+  /// Otherwise, emit diagnostic @c DiagID, passing in all parameters
+  /// specified in @c ExtraArgs.
+  template <typename AttrType, typename... DiagnosticArgs>
+  void handleSimpleAttributeOrDiagnose(Decl *D, const AttributeCommonInfo &CI,
+                                       bool PassesCheck, unsigned DiagID,
+                                       DiagnosticArgs &&...ExtraArgs) {
+    if (!PassesCheck) {
+      Sema::SemaDiagnosticBuilder DB = Diag(D->getBeginLoc(), DiagID);
+      appendDiagnostics(DB, std::forward<DiagnosticArgs>(ExtraArgs)...);
+      return;
+    }
+    handleSimpleAttribute<AttrType>(D, CI);
+  }
+
+  /// Applies the given attribute to the Decl without performing any
+  /// additional semantic checking.
+  template <typename AttrType>
+  void handleSimpleAttribute(Decl *D, const AttributeCommonInfo &CI) {
+    D->addAttr(::new (Context) AttrType(Context, CI));
+  }
+
+  /// Check if IdxExpr is a valid parameter index for a function or
+  /// instance method D.  May output an error.
+  ///
+  /// \returns true if IdxExpr is a valid index.
+  template <typename AttrInfo>
+  bool checkFunctionOrMethodParameterIndex(const Decl *D, const AttrInfo &AI,
+                                           unsigned AttrArgNum,
+                                           const Expr *IdxExpr, ParamIdx &Idx,
+                                           bool CanIndexImplicitThis = false) {
+    assert(isFunctionOrMethodOrBlockForAttrSubject(D));
+
+    // In C++ the implicit 'this' function parameter also counts.
+    // Parameters are counted from one.
+    bool HP = hasFunctionProto(D);
+    bool HasImplicitThisParam = isInstanceMethod(D);
+    bool IV = HP && isFunctionOrMethodVariadic(D);
+    unsigned NumParams =
+        (HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam;
+
+    std::optional<llvm::APSInt> IdxInt;
+    if (IdxExpr->isTypeDependent() ||
+        !(IdxInt = IdxExpr->getIntegerConstantExpr(Context))) {
+      Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
+          << &AI << AttrArgNum << AANT_ArgumentIntegerConstant
+          << IdxExpr->getSourceRange();
+      return false;
+    }
+
+    unsigned IdxSource = IdxInt->getLimitedValue(UINT_MAX);
+    if (IdxSource < 1 || (!IV && IdxSource > NumParams)) {
+      Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds)
+          << &AI << AttrArgNum << IdxExpr->getSourceRange();
+      return false;
+    }
+    if (HasImplicitThisParam && !CanIndexImplicitThis) {
+      if (IdxSource == 1) {
+        Diag(getAttrLoc(AI), diag::err_attribute_invalid_implicit_this_argument)
+            << &AI << IdxExpr->getSourceRange();
+        return false;
+      }
+    }
+
+    Idx = ParamIdx(IdxSource, D);
+    return true;
+  }
+
   ///@}
 
   //
diff --git a/clang/include/clang/Sema/SemaARM.h b/clang/include/clang/Sema/SemaARM.h
index 02698a33abd55..b1d6768f23fb4 100644
--- a/clang/include/clang/Sema/SemaARM.h
+++ b/clang/include/clang/Sema/SemaARM.h
@@ -13,8 +13,10 @@
 #ifndef LLVM_CLANG_SEMA_SEMAARM_H
 #define LLVM_CLANG_SEMA_SEMAARM_H
 
+#include "clang/AST/DeclBase.h"
 #include "clang/AST/Expr.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/SemaBase.h"
 #include "llvm/ADT/SmallVector.h"
 #include <tuple>
@@ -54,6 +56,15 @@ class SemaARM : public SemaBase {
   bool BuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, int ArgNum,
                             unsigned ExpectedFieldNum, bool AllowName);
   bool BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall);
+
+  bool MveAliasValid(unsigned BuiltinID, StringRef AliasName);
+  bool CdeAliasValid(unsigned BuiltinID, StringRef AliasName);
+  bool SveAliasValid(unsigned BuiltinID, StringRef AliasName);
+  bool SmeAliasValid(unsigned BuiltinID, StringRef AliasName);
+  void handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL);
+  void handleNewAttr(Decl *D, const ParsedAttr &AL);
+  void handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL);
+  void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
 };
 
 SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD);
diff --git a/clang/include/clang/Sema/SemaAVR.h b/clang/include/clang/Sema/SemaAVR.h
new file mode 100644
index 0000000000000..4b2445321d566
--- /dev/null
+++ b/clang/include/clang/Sema/SemaAVR.h
@@ -0,0 +1,31 @@
+//===----- SemaAVR.h ------- AVR target-specific routines -----*- C++ -*---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file declares semantic analysis functions specific to AVR.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMAAVR_H
+#define LLVM_CLANG_SEMA_SEMAAVR_H
+
+#include "clang/Sema/ParsedAttr.h"
+#include "clang/Sema/SemaBase.h"
+
+namespace clang {
+
+class SemaAVR : public SemaBase {
+public:
+  SemaAVR(Sema &S);
+
+  void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
+  void handleSignalAttr(Decl *D, const ParsedAttr &AL);
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_SEMAAVR_H
\ No newline at end of file
diff --git a/clang/include/clang/Sema/SemaBPF.h b/clang/include/clang/Sema/SemaBPF.h
index a3bf59128d254..24d4f073ca7d1 100644
--- a/clang/include/clang/Sema/SemaBPF.h
+++ b/clang/include/clang/Sema/SemaBPF.h
@@ -13,7 +13,10 @@
 #ifndef LLVM_CLANG_SEMA_SEMABPF_H
 #define LLVM_CLANG_SEMA_SEMABPF_H
 
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
 #include "clang/AST/Expr.h"
+#include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/SemaBase.h"
 
 namespace clang {
@@ -22,6 +25,9 @@ class SemaBPF : public SemaBase {
   SemaBPF(Sema &S);
 
   bool CheckBPFBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+
+  void handlePreserveAIRecord(RecordDecl *RD);
+  void handlePreserveAccessIndexAttr(Decl *D, const ParsedAttr &AL);
 };
 } // namespace clang
 
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index eac1f7c07c85d..6f3b03564c67c 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -20,6 +20,7 @@
 #include "clang/Basic/AttributeCommonInfo.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/SemaBase.h"
 #include <initializer_list>
@@ -50,6 +51,13 @@ class SemaHLSL : public SemaBase {
       const Attr *A, HLSLShaderAttr::ShaderType Stage,
       std::initializer_list<HLSLShaderAttr::ShaderType> AllowedStages);
   void DiagnoseAvailabilityViolations(TranslationUnitDecl *TU);
+
+  void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL);
+  void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL);
+  void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL);
+  void handleShaderAttr(Decl *D, const ParsedAttr &AL);
+  void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
+  void handleParamModifierAttr(Decl *D, const ParsedAttr &AL);
 };
 
 } // namespace clang
diff --git a/clang/include/clang/Sema/SemaM68k.h b/clang/include/clang/Sema/SemaM68k.h
new file mode 100644
index 0000000000000..66175632f710d
--- /dev/null
+++ b/clang/include/clang/Sema/SemaM68k.h
@@ -0,0 +1,29 @@
+//===----- SemaM68k.h ------ M68k target-specific routines ----*- C++ -*---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file declares semantic analysis functions specific to M68k.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMAM68K_H
+#define LLVM_CLANG_SEMA_SEMAM68K_H
+
+#include "clang/AST/DeclBase.h"
+#include "clang/Sema/ParsedAttr.h"
+#include "clang/Sema/SemaBase.h"
+
+namespace clang {
+class SemaM68k : public SemaBase {
+public:
+  SemaM68k(Sema &S);
+
+  void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_SEMAM68K_H
diff --git a/clang/include/clang/Sema/SemaMIPS.h b/clang/include/clang/Sema/SemaMIPS.h
index 3f1781b36efd9..b84c532ebad3a 100644
--- a/clang/include/clang/Sema/SemaMIPS.h
+++ b/clang/include/clang/Sema/SemaMIPS.h
@@ -13,8 +13,10 @@
 #ifndef LLVM_CLANG_SEMA_SEMAMIPS_H
 #define LLVM_CLANG_SEMA_SEMAMIPS_H
 
+#include "clang/AST/DeclBase.h"
 #include "clang/AST/Expr.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/SemaBase.h"
 
 namespace clang {
@@ -27,6 +29,7 @@ class SemaMIPS : public SemaBase {
   bool CheckMipsBuiltinCpu(const TargetInfo &TI, unsigned BuiltinID,
                            CallExpr *TheCall);
   bool CheckMipsBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall);
+  void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
 };
 } // namespace clang
 
diff --git a/clang/include/clang/Sema/SemaMSP430.h b/clang/include/clang/Sema/SemaMSP430.h
new file mode 100644
index 0000000000000..4ec6f4...
[truncated]

@llvmbot
Copy link
Collaborator

llvmbot commented May 31, 2024

@llvm/pr-subscribers-backend-x86

Author: Vlad Serebrennikov (Endilll)

Changes

This patch moves language- and target-specific functions out of SemaDeclAttr.cpp. As a consequence, SemaAVR, SemaM68k, SemaMSP430, SemaOpenCL, SemaSwift were created (but they are not the only languages and targets affected).

Notable things are that Sema.h actually grew a bit, because of templated helpers that rely on Sema that I had to make available from outside of SemaDeclAttr.cpp. I also had to left CUDA-related in SemaDeclAttr.cpp, because it looks like HIP is building up on top of CUDA attributes.

This is a follow-up to #93179 and continuation of efforts to split Sema up. Additional context can be found in #84184 and #92682.


Patch is 257.01 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/93966.diff

37 Files Affected:

  • (modified) clang/include/clang/Sema/Attr.h (+86)
  • (modified) clang/include/clang/Sema/Sema.h (+145-18)
  • (modified) clang/include/clang/Sema/SemaARM.h (+11)
  • (added) clang/include/clang/Sema/SemaAVR.h (+31)
  • (modified) clang/include/clang/Sema/SemaBPF.h (+6)
  • (modified) clang/include/clang/Sema/SemaHLSL.h (+8)
  • (added) clang/include/clang/Sema/SemaM68k.h (+29)
  • (modified) clang/include/clang/Sema/SemaMIPS.h (+3)
  • (added) clang/include/clang/Sema/SemaMSP430.h (+29)
  • (modified) clang/include/clang/Sema/SemaObjC.h (+50)
  • (added) clang/include/clang/Sema/SemaOpenCL.h (+34)
  • (modified) clang/include/clang/Sema/SemaOpenMP.h (+3)
  • (modified) clang/include/clang/Sema/SemaRISCV.h (+4)
  • (modified) clang/include/clang/Sema/SemaSYCL.h (+4)
  • (added) clang/include/clang/Sema/SemaSwift.h (+57)
  • (modified) clang/include/clang/Sema/SemaX86.h (+5)
  • (modified) clang/lib/Sema/CMakeLists.txt (+5)
  • (modified) clang/lib/Sema/Sema.cpp (+10)
  • (modified) clang/lib/Sema/SemaAPINotes.cpp (+3-2)
  • (modified) clang/lib/Sema/SemaARM.cpp (+195)
  • (added) clang/lib/Sema/SemaAVR.cpp (+47)
  • (modified) clang/lib/Sema/SemaBPF.cpp (+19)
  • (modified) clang/lib/Sema/SemaDecl.cpp (+2-1)
  • (modified) clang/lib/Sema/SemaDeclAttr.cpp (+166-2780)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+227)
  • (added) clang/lib/Sema/SemaM68k.cpp (+53)
  • (modified) clang/lib/Sema/SemaMIPS.cpp (+59)
  • (added) clang/lib/Sema/SemaMSP430.cpp (+75)
  • (modified) clang/lib/Sema/SemaObjC.cpp (+771)
  • (added) clang/lib/Sema/SemaOpenCL.cpp (+97)
  • (modified) clang/lib/Sema/SemaOpenMP.cpp (+38)
  • (modified) clang/lib/Sema/SemaRISCV.cpp (+64)
  • (modified) clang/lib/Sema/SemaSYCL.cpp (+40)
  • (added) clang/lib/Sema/SemaSwift.cpp (+761)
  • (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+5-3)
  • (modified) clang/lib/Sema/SemaType.cpp (+3-3)
  • (modified) clang/lib/Sema/SemaX86.cpp (+93)
diff --git a/clang/include/clang/Sema/Attr.h b/clang/include/clang/Sema/Attr.h
index 1133862568a6c..25a20bb697914 100644
--- a/clang/include/clang/Sema/Attr.h
+++ b/clang/include/clang/Sema/Attr.h
@@ -14,7 +14,11 @@
 #define LLVM_CLANG_SEMA_ATTR_H
 
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/SourceLocation.h"
 #include "llvm/Support/Casting.h"
 
 namespace clang {
@@ -32,5 +36,87 @@ inline bool isFunctionOrMethodOrBlockForAttrSubject(const Decl *D) {
   return isFuncOrMethodForAttrSubject(D) || llvm::isa<BlockDecl>(D);
 }
 
+/// Return true if the given decl has a declarator that should have
+/// been processed by Sema::GetTypeForDeclarator.
+inline bool hasDeclarator(const Decl *D) {
+  // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl.
+  return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) ||
+         isa<TypedefNameDecl>(D) || isa<ObjCPropertyDecl>(D);
+}
+
+/// hasFunctionProto - Return true if the given decl has a argument
+/// information. This decl should have already passed
+/// isFuncOrMethodForAttrSubject or isFunctionOrMethodOrBlockForAttrSubject.
+inline bool hasFunctionProto(const Decl *D) {
+  if (const FunctionType *FnTy = D->getFunctionType())
+    return isa<FunctionProtoType>(FnTy);
+  return isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D);
+}
+
+/// getFunctionOrMethodNumParams - Return number of function or method
+/// parameters. It is an error to call this on a K&R function (use
+/// hasFunctionProto first).
+inline unsigned getFunctionOrMethodNumParams(const Decl *D) {
+  if (const FunctionType *FnTy = D->getFunctionType())
+    return cast<FunctionProtoType>(FnTy)->getNumParams();
+  if (const auto *BD = dyn_cast<BlockDecl>(D))
+    return BD->getNumParams();
+  return cast<ObjCMethodDecl>(D)->param_size();
+}
+
+inline const ParmVarDecl *getFunctionOrMethodParam(const Decl *D,
+                                                   unsigned Idx) {
+  if (const auto *FD = dyn_cast<FunctionDecl>(D))
+    return FD->getParamDecl(Idx);
+  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
+    return MD->getParamDecl(Idx);
+  if (const auto *BD = dyn_cast<BlockDecl>(D))
+    return BD->getParamDecl(Idx);
+  return nullptr;
+}
+
+inline QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
+  if (const FunctionType *FnTy = D->getFunctionType())
+    return cast<FunctionProtoType>(FnTy)->getParamType(Idx);
+  if (const auto *BD = dyn_cast<BlockDecl>(D))
+    return BD->getParamDecl(Idx)->getType();
+
+  return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType();
+}
+
+inline SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) {
+  if (auto *PVD = getFunctionOrMethodParam(D, Idx))
+    return PVD->getSourceRange();
+  return SourceRange();
+}
+
+inline QualType getFunctionOrMethodResultType(const Decl *D) {
+  if (const FunctionType *FnTy = D->getFunctionType())
+    return FnTy->getReturnType();
+  return cast<ObjCMethodDecl>(D)->getReturnType();
+}
+
+inline SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) {
+  if (const auto *FD = dyn_cast<FunctionDecl>(D))
+    return FD->getReturnTypeSourceRange();
+  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
+    return MD->getReturnTypeSourceRange();
+  return SourceRange();
+}
+
+inline bool isFunctionOrMethodVariadic(const Decl *D) {
+  if (const FunctionType *FnTy = D->getFunctionType())
+    return cast<FunctionProtoType>(FnTy)->isVariadic();
+  if (const auto *BD = dyn_cast<BlockDecl>(D))
+    return BD->isVariadic();
+  return cast<ObjCMethodDecl>(D)->isVariadic();
+}
+
+inline bool isInstanceMethod(const Decl *D) {
+  if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(D))
+    return MethodDecl->isInstance();
+  return false;
+}
+
 } // namespace clang
 #endif // LLVM_CLANG_SEMA_ATTR_H
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 7dea2b6826cfd..956f15773ead8 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -47,6 +47,7 @@
 #include "clang/Basic/TemplateKinds.h"
 #include "clang/Basic/TypeTraits.h"
 #include "clang/Sema/AnalysisBasedWarnings.h"
+#include "clang/Sema/Attr.h"
 #include "clang/Sema/CleanupInfo.h"
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/ExternalSemaSource.h"
@@ -171,21 +172,26 @@ class PseudoObjectExpr;
 class QualType;
 class SemaAMDGPU;
 class SemaARM;
+class SemaAVR;
 class SemaBPF;
 class SemaCodeCompletion;
 class SemaCUDA;
 class SemaHLSL;
 class SemaHexagon;
 class SemaLoongArch;
+class SemaM68k;
 class SemaMIPS;
+class SemaMSP430;
 class SemaNVPTX;
 class SemaObjC;
 class SemaOpenACC;
+class SemaOpenCL;
 class SemaOpenMP;
 class SemaPPC;
 class SemaPseudoObject;
 class SemaRISCV;
 class SemaSYCL;
+class SemaSwift;
 class SemaSystemZ;
 class SemaWasm;
 class SemaX86;
@@ -1011,6 +1017,11 @@ class Sema final : public SemaBase {
     return *ARMPtr;
   }
 
+  SemaAVR &AVR() {
+    assert(AVRPtr);
+    return *AVRPtr;
+  }
+
   SemaBPF &BPF() {
     assert(BPFPtr);
     return *BPFPtr;
@@ -1041,11 +1052,21 @@ class Sema final : public SemaBase {
     return *LoongArchPtr;
   }
 
+  SemaM68k &M68k() {
+    assert(M68kPtr);
+    return *M68kPtr;
+  }
+
   SemaMIPS &MIPS() {
     assert(MIPSPtr);
     return *MIPSPtr;
   }
 
+  SemaMSP430 &MSP430() {
+    assert(MSP430Ptr);
+    return *MSP430Ptr;
+  }
+
   SemaNVPTX &NVPTX() {
     assert(NVPTXPtr);
     return *NVPTXPtr;
@@ -1061,6 +1082,11 @@ class Sema final : public SemaBase {
     return *OpenACCPtr;
   }
 
+  SemaOpenCL &OpenCL() {
+    assert(OpenCLPtr);
+    return *OpenCLPtr;
+  }
+
   SemaOpenMP &OpenMP() {
     assert(OpenMPPtr && "SemaOpenMP is dead");
     return *OpenMPPtr;
@@ -1086,6 +1112,11 @@ class Sema final : public SemaBase {
     return *SYCLPtr;
   }
 
+  SemaSwift &Swift() {
+    assert(SwiftPtr);
+    return *SwiftPtr;
+  }
+
   SemaSystemZ &SystemZ() {
     assert(SystemZPtr);
     return *SystemZPtr;
@@ -1133,21 +1164,26 @@ class Sema final : public SemaBase {
 
   std::unique_ptr<SemaAMDGPU> AMDGPUPtr;
   std::unique_ptr<SemaARM> ARMPtr;
+  std::unique_ptr<SemaAVR> AVRPtr;
   std::unique_ptr<SemaBPF> BPFPtr;
   std::unique_ptr<SemaCodeCompletion> CodeCompletionPtr;
   std::unique_ptr<SemaCUDA> CUDAPtr;
   std::unique_ptr<SemaHLSL> HLSLPtr;
   std::unique_ptr<SemaHexagon> HexagonPtr;
   std::unique_ptr<SemaLoongArch> LoongArchPtr;
+  std::unique_ptr<SemaM68k> M68kPtr;
   std::unique_ptr<SemaMIPS> MIPSPtr;
+  std::unique_ptr<SemaMSP430> MSP430Ptr;
   std::unique_ptr<SemaNVPTX> NVPTXPtr;
   std::unique_ptr<SemaObjC> ObjCPtr;
   std::unique_ptr<SemaOpenACC> OpenACCPtr;
+  std::unique_ptr<SemaOpenCL> OpenCLPtr;
   std::unique_ptr<SemaOpenMP> OpenMPPtr;
   std::unique_ptr<SemaPPC> PPCPtr;
   std::unique_ptr<SemaPseudoObject> PseudoObjectPtr;
   std::unique_ptr<SemaRISCV> RISCVPtr;
   std::unique_ptr<SemaSYCL> SYCLPtr;
+  std::unique_ptr<SemaSwift> SwiftPtr;
   std::unique_ptr<SemaSystemZ> SystemZPtr;
   std::unique_ptr<SemaWasm> WasmPtr;
   std::unique_ptr<SemaX86> X86Ptr;
@@ -3711,8 +3747,6 @@ class Sema final : public SemaBase {
                                           const AttributeCommonInfo &CI,
                                           const IdentifierInfo *Ident);
   MinSizeAttr *mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI);
-  SwiftNameAttr *mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA,
-                                    StringRef Name);
   OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D,
                                           const AttributeCommonInfo &CI);
   InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL);
@@ -3726,8 +3760,6 @@ class Sema final : public SemaBase {
       const ParsedAttr &attr, CallingConv &CC, const FunctionDecl *FD = nullptr,
       CUDAFunctionTarget CFT = CUDAFunctionTarget::InvalidTarget);
 
-  void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
-                           ParameterABI ABI);
   bool CheckRegparmAttr(const ParsedAttr &attr, unsigned &value);
 
   /// Create an CUDALaunchBoundsAttr attribute.
@@ -3742,20 +3774,6 @@ class Sema final : public SemaBase {
                            Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks);
 
   enum class RetainOwnershipKind { NS, CF, OS };
-  void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
-                        RetainOwnershipKind K, bool IsTemplateInstantiation);
-
-  bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
-
-  /// Do a check to make sure \p Name looks like a legal argument for the
-  /// swift_name attribute applied to decl \p D.  Raise a diagnostic if the name
-  /// is invalid for the given declaration.
-  ///
-  /// \p AL is used to provide caret diagnostics in case of a malformed name.
-  ///
-  /// \returns true if the name is a valid swift name for \p D, false otherwise.
-  bool DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc,
-                         const ParsedAttr &AL, bool IsAsync);
 
   UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI,
                           StringRef UuidAsWritten, MSGuidDecl *GuidDecl);
@@ -3825,6 +3843,115 @@ class Sema final : public SemaBase {
 
   void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
 
+  /// Diagnose mutually exclusive attributes when present on a given
+  /// declaration. Returns true if diagnosed.
+  template <typename AttrTy>
+  bool checkAttrMutualExclusion(Decl *D, const ParsedAttr &AL) {
+    if (const auto *A = D->getAttr<AttrTy>()) {
+      Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
+          << AL << A
+          << (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute());
+      Diag(A->getLocation(), diag::note_conflicting_attribute);
+      return true;
+    }
+    return false;
+  }
+
+  template <typename AttrTy>
+  bool checkAttrMutualExclusion(Decl *D, const Attr &AL) {
+    if (const auto *A = D->getAttr<AttrTy>()) {
+      Diag(AL.getLocation(), diag::err_attributes_are_not_compatible)
+          << &AL << A
+          << (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute());
+      Diag(A->getLocation(), diag::note_conflicting_attribute);
+      return true;
+    }
+    return false;
+  }
+
+  template <typename... DiagnosticArgs>
+  static const Sema::SemaDiagnosticBuilder &
+  appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr) {
+    return Bldr;
+  }
+
+  template <typename T, typename... DiagnosticArgs>
+  static const Sema::SemaDiagnosticBuilder &
+  appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr, T &&ExtraArg,
+                    DiagnosticArgs &&...ExtraArgs) {
+    return appendDiagnostics(Bldr << std::forward<T>(ExtraArg),
+                             std::forward<DiagnosticArgs>(ExtraArgs)...);
+  }
+
+  /// Add an attribute @c AttrType to declaration @c D, provided that
+  /// @c PassesCheck is true.
+  /// Otherwise, emit diagnostic @c DiagID, passing in all parameters
+  /// specified in @c ExtraArgs.
+  template <typename AttrType, typename... DiagnosticArgs>
+  void handleSimpleAttributeOrDiagnose(Decl *D, const AttributeCommonInfo &CI,
+                                       bool PassesCheck, unsigned DiagID,
+                                       DiagnosticArgs &&...ExtraArgs) {
+    if (!PassesCheck) {
+      Sema::SemaDiagnosticBuilder DB = Diag(D->getBeginLoc(), DiagID);
+      appendDiagnostics(DB, std::forward<DiagnosticArgs>(ExtraArgs)...);
+      return;
+    }
+    handleSimpleAttribute<AttrType>(D, CI);
+  }
+
+  /// Applies the given attribute to the Decl without performing any
+  /// additional semantic checking.
+  template <typename AttrType>
+  void handleSimpleAttribute(Decl *D, const AttributeCommonInfo &CI) {
+    D->addAttr(::new (Context) AttrType(Context, CI));
+  }
+
+  /// Check if IdxExpr is a valid parameter index for a function or
+  /// instance method D.  May output an error.
+  ///
+  /// \returns true if IdxExpr is a valid index.
+  template <typename AttrInfo>
+  bool checkFunctionOrMethodParameterIndex(const Decl *D, const AttrInfo &AI,
+                                           unsigned AttrArgNum,
+                                           const Expr *IdxExpr, ParamIdx &Idx,
+                                           bool CanIndexImplicitThis = false) {
+    assert(isFunctionOrMethodOrBlockForAttrSubject(D));
+
+    // In C++ the implicit 'this' function parameter also counts.
+    // Parameters are counted from one.
+    bool HP = hasFunctionProto(D);
+    bool HasImplicitThisParam = isInstanceMethod(D);
+    bool IV = HP && isFunctionOrMethodVariadic(D);
+    unsigned NumParams =
+        (HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam;
+
+    std::optional<llvm::APSInt> IdxInt;
+    if (IdxExpr->isTypeDependent() ||
+        !(IdxInt = IdxExpr->getIntegerConstantExpr(Context))) {
+      Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
+          << &AI << AttrArgNum << AANT_ArgumentIntegerConstant
+          << IdxExpr->getSourceRange();
+      return false;
+    }
+
+    unsigned IdxSource = IdxInt->getLimitedValue(UINT_MAX);
+    if (IdxSource < 1 || (!IV && IdxSource > NumParams)) {
+      Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds)
+          << &AI << AttrArgNum << IdxExpr->getSourceRange();
+      return false;
+    }
+    if (HasImplicitThisParam && !CanIndexImplicitThis) {
+      if (IdxSource == 1) {
+        Diag(getAttrLoc(AI), diag::err_attribute_invalid_implicit_this_argument)
+            << &AI << IdxExpr->getSourceRange();
+        return false;
+      }
+    }
+
+    Idx = ParamIdx(IdxSource, D);
+    return true;
+  }
+
   ///@}
 
   //
diff --git a/clang/include/clang/Sema/SemaARM.h b/clang/include/clang/Sema/SemaARM.h
index 02698a33abd55..b1d6768f23fb4 100644
--- a/clang/include/clang/Sema/SemaARM.h
+++ b/clang/include/clang/Sema/SemaARM.h
@@ -13,8 +13,10 @@
 #ifndef LLVM_CLANG_SEMA_SEMAARM_H
 #define LLVM_CLANG_SEMA_SEMAARM_H
 
+#include "clang/AST/DeclBase.h"
 #include "clang/AST/Expr.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/SemaBase.h"
 #include "llvm/ADT/SmallVector.h"
 #include <tuple>
@@ -54,6 +56,15 @@ class SemaARM : public SemaBase {
   bool BuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, int ArgNum,
                             unsigned ExpectedFieldNum, bool AllowName);
   bool BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall);
+
+  bool MveAliasValid(unsigned BuiltinID, StringRef AliasName);
+  bool CdeAliasValid(unsigned BuiltinID, StringRef AliasName);
+  bool SveAliasValid(unsigned BuiltinID, StringRef AliasName);
+  bool SmeAliasValid(unsigned BuiltinID, StringRef AliasName);
+  void handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL);
+  void handleNewAttr(Decl *D, const ParsedAttr &AL);
+  void handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL);
+  void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
 };
 
 SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD);
diff --git a/clang/include/clang/Sema/SemaAVR.h b/clang/include/clang/Sema/SemaAVR.h
new file mode 100644
index 0000000000000..4b2445321d566
--- /dev/null
+++ b/clang/include/clang/Sema/SemaAVR.h
@@ -0,0 +1,31 @@
+//===----- SemaAVR.h ------- AVR target-specific routines -----*- C++ -*---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file declares semantic analysis functions specific to AVR.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMAAVR_H
+#define LLVM_CLANG_SEMA_SEMAAVR_H
+
+#include "clang/Sema/ParsedAttr.h"
+#include "clang/Sema/SemaBase.h"
+
+namespace clang {
+
+class SemaAVR : public SemaBase {
+public:
+  SemaAVR(Sema &S);
+
+  void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
+  void handleSignalAttr(Decl *D, const ParsedAttr &AL);
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_SEMAAVR_H
\ No newline at end of file
diff --git a/clang/include/clang/Sema/SemaBPF.h b/clang/include/clang/Sema/SemaBPF.h
index a3bf59128d254..24d4f073ca7d1 100644
--- a/clang/include/clang/Sema/SemaBPF.h
+++ b/clang/include/clang/Sema/SemaBPF.h
@@ -13,7 +13,10 @@
 #ifndef LLVM_CLANG_SEMA_SEMABPF_H
 #define LLVM_CLANG_SEMA_SEMABPF_H
 
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
 #include "clang/AST/Expr.h"
+#include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/SemaBase.h"
 
 namespace clang {
@@ -22,6 +25,9 @@ class SemaBPF : public SemaBase {
   SemaBPF(Sema &S);
 
   bool CheckBPFBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+
+  void handlePreserveAIRecord(RecordDecl *RD);
+  void handlePreserveAccessIndexAttr(Decl *D, const ParsedAttr &AL);
 };
 } // namespace clang
 
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index eac1f7c07c85d..6f3b03564c67c 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -20,6 +20,7 @@
 #include "clang/Basic/AttributeCommonInfo.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/SemaBase.h"
 #include <initializer_list>
@@ -50,6 +51,13 @@ class SemaHLSL : public SemaBase {
       const Attr *A, HLSLShaderAttr::ShaderType Stage,
       std::initializer_list<HLSLShaderAttr::ShaderType> AllowedStages);
   void DiagnoseAvailabilityViolations(TranslationUnitDecl *TU);
+
+  void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL);
+  void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL);
+  void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL);
+  void handleShaderAttr(Decl *D, const ParsedAttr &AL);
+  void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
+  void handleParamModifierAttr(Decl *D, const ParsedAttr &AL);
 };
 
 } // namespace clang
diff --git a/clang/include/clang/Sema/SemaM68k.h b/clang/include/clang/Sema/SemaM68k.h
new file mode 100644
index 0000000000000..66175632f710d
--- /dev/null
+++ b/clang/include/clang/Sema/SemaM68k.h
@@ -0,0 +1,29 @@
+//===----- SemaM68k.h ------ M68k target-specific routines ----*- C++ -*---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file declares semantic analysis functions specific to M68k.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMAM68K_H
+#define LLVM_CLANG_SEMA_SEMAM68K_H
+
+#include "clang/AST/DeclBase.h"
+#include "clang/Sema/ParsedAttr.h"
+#include "clang/Sema/SemaBase.h"
+
+namespace clang {
+class SemaM68k : public SemaBase {
+public:
+  SemaM68k(Sema &S);
+
+  void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_SEMAM68K_H
diff --git a/clang/include/clang/Sema/SemaMIPS.h b/clang/include/clang/Sema/SemaMIPS.h
index 3f1781b36efd9..b84c532ebad3a 100644
--- a/clang/include/clang/Sema/SemaMIPS.h
+++ b/clang/include/clang/Sema/SemaMIPS.h
@@ -13,8 +13,10 @@
 #ifndef LLVM_CLANG_SEMA_SEMAMIPS_H
 #define LLVM_CLANG_SEMA_SEMAMIPS_H
 
+#include "clang/AST/DeclBase.h"
 #include "clang/AST/Expr.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/SemaBase.h"
 
 namespace clang {
@@ -27,6 +29,7 @@ class SemaMIPS : public SemaBase {
   bool CheckMipsBuiltinCpu(const TargetInfo &TI, unsigned BuiltinID,
                            CallExpr *TheCall);
   bool CheckMipsBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall);
+  void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
 };
 } // namespace clang
 
diff --git a/clang/include/clang/Sema/SemaMSP430.h b/clang/include/clang/Sema/SemaMSP430.h
new file mode 100644
index 0000000000000..4ec6f4...
[truncated]

@llvmbot
Copy link
Collaborator

llvmbot commented May 31, 2024

@llvm/pr-subscribers-backend-aarch64

Author: Vlad Serebrennikov (Endilll)

Changes

This patch moves language- and target-specific functions out of SemaDeclAttr.cpp. As a consequence, SemaAVR, SemaM68k, SemaMSP430, SemaOpenCL, SemaSwift were created (but they are not the only languages and targets affected).

Notable things are that Sema.h actually grew a bit, because of templated helpers that rely on Sema that I had to make available from outside of SemaDeclAttr.cpp. I also had to left CUDA-related in SemaDeclAttr.cpp, because it looks like HIP is building up on top of CUDA attributes.

This is a follow-up to #93179 and continuation of efforts to split Sema up. Additional context can be found in #84184 and #92682.


Patch is 257.01 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/93966.diff

37 Files Affected:

  • (modified) clang/include/clang/Sema/Attr.h (+86)
  • (modified) clang/include/clang/Sema/Sema.h (+145-18)
  • (modified) clang/include/clang/Sema/SemaARM.h (+11)
  • (added) clang/include/clang/Sema/SemaAVR.h (+31)
  • (modified) clang/include/clang/Sema/SemaBPF.h (+6)
  • (modified) clang/include/clang/Sema/SemaHLSL.h (+8)
  • (added) clang/include/clang/Sema/SemaM68k.h (+29)
  • (modified) clang/include/clang/Sema/SemaMIPS.h (+3)
  • (added) clang/include/clang/Sema/SemaMSP430.h (+29)
  • (modified) clang/include/clang/Sema/SemaObjC.h (+50)
  • (added) clang/include/clang/Sema/SemaOpenCL.h (+34)
  • (modified) clang/include/clang/Sema/SemaOpenMP.h (+3)
  • (modified) clang/include/clang/Sema/SemaRISCV.h (+4)
  • (modified) clang/include/clang/Sema/SemaSYCL.h (+4)
  • (added) clang/include/clang/Sema/SemaSwift.h (+57)
  • (modified) clang/include/clang/Sema/SemaX86.h (+5)
  • (modified) clang/lib/Sema/CMakeLists.txt (+5)
  • (modified) clang/lib/Sema/Sema.cpp (+10)
  • (modified) clang/lib/Sema/SemaAPINotes.cpp (+3-2)
  • (modified) clang/lib/Sema/SemaARM.cpp (+195)
  • (added) clang/lib/Sema/SemaAVR.cpp (+47)
  • (modified) clang/lib/Sema/SemaBPF.cpp (+19)
  • (modified) clang/lib/Sema/SemaDecl.cpp (+2-1)
  • (modified) clang/lib/Sema/SemaDeclAttr.cpp (+166-2780)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+227)
  • (added) clang/lib/Sema/SemaM68k.cpp (+53)
  • (modified) clang/lib/Sema/SemaMIPS.cpp (+59)
  • (added) clang/lib/Sema/SemaMSP430.cpp (+75)
  • (modified) clang/lib/Sema/SemaObjC.cpp (+771)
  • (added) clang/lib/Sema/SemaOpenCL.cpp (+97)
  • (modified) clang/lib/Sema/SemaOpenMP.cpp (+38)
  • (modified) clang/lib/Sema/SemaRISCV.cpp (+64)
  • (modified) clang/lib/Sema/SemaSYCL.cpp (+40)
  • (added) clang/lib/Sema/SemaSwift.cpp (+761)
  • (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+5-3)
  • (modified) clang/lib/Sema/SemaType.cpp (+3-3)
  • (modified) clang/lib/Sema/SemaX86.cpp (+93)
diff --git a/clang/include/clang/Sema/Attr.h b/clang/include/clang/Sema/Attr.h
index 1133862568a6c..25a20bb697914 100644
--- a/clang/include/clang/Sema/Attr.h
+++ b/clang/include/clang/Sema/Attr.h
@@ -14,7 +14,11 @@
 #define LLVM_CLANG_SEMA_ATTR_H
 
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/SourceLocation.h"
 #include "llvm/Support/Casting.h"
 
 namespace clang {
@@ -32,5 +36,87 @@ inline bool isFunctionOrMethodOrBlockForAttrSubject(const Decl *D) {
   return isFuncOrMethodForAttrSubject(D) || llvm::isa<BlockDecl>(D);
 }
 
+/// Return true if the given decl has a declarator that should have
+/// been processed by Sema::GetTypeForDeclarator.
+inline bool hasDeclarator(const Decl *D) {
+  // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl.
+  return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) ||
+         isa<TypedefNameDecl>(D) || isa<ObjCPropertyDecl>(D);
+}
+
+/// hasFunctionProto - Return true if the given decl has a argument
+/// information. This decl should have already passed
+/// isFuncOrMethodForAttrSubject or isFunctionOrMethodOrBlockForAttrSubject.
+inline bool hasFunctionProto(const Decl *D) {
+  if (const FunctionType *FnTy = D->getFunctionType())
+    return isa<FunctionProtoType>(FnTy);
+  return isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D);
+}
+
+/// getFunctionOrMethodNumParams - Return number of function or method
+/// parameters. It is an error to call this on a K&R function (use
+/// hasFunctionProto first).
+inline unsigned getFunctionOrMethodNumParams(const Decl *D) {
+  if (const FunctionType *FnTy = D->getFunctionType())
+    return cast<FunctionProtoType>(FnTy)->getNumParams();
+  if (const auto *BD = dyn_cast<BlockDecl>(D))
+    return BD->getNumParams();
+  return cast<ObjCMethodDecl>(D)->param_size();
+}
+
+inline const ParmVarDecl *getFunctionOrMethodParam(const Decl *D,
+                                                   unsigned Idx) {
+  if (const auto *FD = dyn_cast<FunctionDecl>(D))
+    return FD->getParamDecl(Idx);
+  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
+    return MD->getParamDecl(Idx);
+  if (const auto *BD = dyn_cast<BlockDecl>(D))
+    return BD->getParamDecl(Idx);
+  return nullptr;
+}
+
+inline QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
+  if (const FunctionType *FnTy = D->getFunctionType())
+    return cast<FunctionProtoType>(FnTy)->getParamType(Idx);
+  if (const auto *BD = dyn_cast<BlockDecl>(D))
+    return BD->getParamDecl(Idx)->getType();
+
+  return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType();
+}
+
+inline SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) {
+  if (auto *PVD = getFunctionOrMethodParam(D, Idx))
+    return PVD->getSourceRange();
+  return SourceRange();
+}
+
+inline QualType getFunctionOrMethodResultType(const Decl *D) {
+  if (const FunctionType *FnTy = D->getFunctionType())
+    return FnTy->getReturnType();
+  return cast<ObjCMethodDecl>(D)->getReturnType();
+}
+
+inline SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) {
+  if (const auto *FD = dyn_cast<FunctionDecl>(D))
+    return FD->getReturnTypeSourceRange();
+  if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
+    return MD->getReturnTypeSourceRange();
+  return SourceRange();
+}
+
+inline bool isFunctionOrMethodVariadic(const Decl *D) {
+  if (const FunctionType *FnTy = D->getFunctionType())
+    return cast<FunctionProtoType>(FnTy)->isVariadic();
+  if (const auto *BD = dyn_cast<BlockDecl>(D))
+    return BD->isVariadic();
+  return cast<ObjCMethodDecl>(D)->isVariadic();
+}
+
+inline bool isInstanceMethod(const Decl *D) {
+  if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(D))
+    return MethodDecl->isInstance();
+  return false;
+}
+
 } // namespace clang
 #endif // LLVM_CLANG_SEMA_ATTR_H
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 7dea2b6826cfd..956f15773ead8 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -47,6 +47,7 @@
 #include "clang/Basic/TemplateKinds.h"
 #include "clang/Basic/TypeTraits.h"
 #include "clang/Sema/AnalysisBasedWarnings.h"
+#include "clang/Sema/Attr.h"
 #include "clang/Sema/CleanupInfo.h"
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/ExternalSemaSource.h"
@@ -171,21 +172,26 @@ class PseudoObjectExpr;
 class QualType;
 class SemaAMDGPU;
 class SemaARM;
+class SemaAVR;
 class SemaBPF;
 class SemaCodeCompletion;
 class SemaCUDA;
 class SemaHLSL;
 class SemaHexagon;
 class SemaLoongArch;
+class SemaM68k;
 class SemaMIPS;
+class SemaMSP430;
 class SemaNVPTX;
 class SemaObjC;
 class SemaOpenACC;
+class SemaOpenCL;
 class SemaOpenMP;
 class SemaPPC;
 class SemaPseudoObject;
 class SemaRISCV;
 class SemaSYCL;
+class SemaSwift;
 class SemaSystemZ;
 class SemaWasm;
 class SemaX86;
@@ -1011,6 +1017,11 @@ class Sema final : public SemaBase {
     return *ARMPtr;
   }
 
+  SemaAVR &AVR() {
+    assert(AVRPtr);
+    return *AVRPtr;
+  }
+
   SemaBPF &BPF() {
     assert(BPFPtr);
     return *BPFPtr;
@@ -1041,11 +1052,21 @@ class Sema final : public SemaBase {
     return *LoongArchPtr;
   }
 
+  SemaM68k &M68k() {
+    assert(M68kPtr);
+    return *M68kPtr;
+  }
+
   SemaMIPS &MIPS() {
     assert(MIPSPtr);
     return *MIPSPtr;
   }
 
+  SemaMSP430 &MSP430() {
+    assert(MSP430Ptr);
+    return *MSP430Ptr;
+  }
+
   SemaNVPTX &NVPTX() {
     assert(NVPTXPtr);
     return *NVPTXPtr;
@@ -1061,6 +1082,11 @@ class Sema final : public SemaBase {
     return *OpenACCPtr;
   }
 
+  SemaOpenCL &OpenCL() {
+    assert(OpenCLPtr);
+    return *OpenCLPtr;
+  }
+
   SemaOpenMP &OpenMP() {
     assert(OpenMPPtr && "SemaOpenMP is dead");
     return *OpenMPPtr;
@@ -1086,6 +1112,11 @@ class Sema final : public SemaBase {
     return *SYCLPtr;
   }
 
+  SemaSwift &Swift() {
+    assert(SwiftPtr);
+    return *SwiftPtr;
+  }
+
   SemaSystemZ &SystemZ() {
     assert(SystemZPtr);
     return *SystemZPtr;
@@ -1133,21 +1164,26 @@ class Sema final : public SemaBase {
 
   std::unique_ptr<SemaAMDGPU> AMDGPUPtr;
   std::unique_ptr<SemaARM> ARMPtr;
+  std::unique_ptr<SemaAVR> AVRPtr;
   std::unique_ptr<SemaBPF> BPFPtr;
   std::unique_ptr<SemaCodeCompletion> CodeCompletionPtr;
   std::unique_ptr<SemaCUDA> CUDAPtr;
   std::unique_ptr<SemaHLSL> HLSLPtr;
   std::unique_ptr<SemaHexagon> HexagonPtr;
   std::unique_ptr<SemaLoongArch> LoongArchPtr;
+  std::unique_ptr<SemaM68k> M68kPtr;
   std::unique_ptr<SemaMIPS> MIPSPtr;
+  std::unique_ptr<SemaMSP430> MSP430Ptr;
   std::unique_ptr<SemaNVPTX> NVPTXPtr;
   std::unique_ptr<SemaObjC> ObjCPtr;
   std::unique_ptr<SemaOpenACC> OpenACCPtr;
+  std::unique_ptr<SemaOpenCL> OpenCLPtr;
   std::unique_ptr<SemaOpenMP> OpenMPPtr;
   std::unique_ptr<SemaPPC> PPCPtr;
   std::unique_ptr<SemaPseudoObject> PseudoObjectPtr;
   std::unique_ptr<SemaRISCV> RISCVPtr;
   std::unique_ptr<SemaSYCL> SYCLPtr;
+  std::unique_ptr<SemaSwift> SwiftPtr;
   std::unique_ptr<SemaSystemZ> SystemZPtr;
   std::unique_ptr<SemaWasm> WasmPtr;
   std::unique_ptr<SemaX86> X86Ptr;
@@ -3711,8 +3747,6 @@ class Sema final : public SemaBase {
                                           const AttributeCommonInfo &CI,
                                           const IdentifierInfo *Ident);
   MinSizeAttr *mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI);
-  SwiftNameAttr *mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA,
-                                    StringRef Name);
   OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D,
                                           const AttributeCommonInfo &CI);
   InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL);
@@ -3726,8 +3760,6 @@ class Sema final : public SemaBase {
       const ParsedAttr &attr, CallingConv &CC, const FunctionDecl *FD = nullptr,
       CUDAFunctionTarget CFT = CUDAFunctionTarget::InvalidTarget);
 
-  void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
-                           ParameterABI ABI);
   bool CheckRegparmAttr(const ParsedAttr &attr, unsigned &value);
 
   /// Create an CUDALaunchBoundsAttr attribute.
@@ -3742,20 +3774,6 @@ class Sema final : public SemaBase {
                            Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks);
 
   enum class RetainOwnershipKind { NS, CF, OS };
-  void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
-                        RetainOwnershipKind K, bool IsTemplateInstantiation);
-
-  bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
-
-  /// Do a check to make sure \p Name looks like a legal argument for the
-  /// swift_name attribute applied to decl \p D.  Raise a diagnostic if the name
-  /// is invalid for the given declaration.
-  ///
-  /// \p AL is used to provide caret diagnostics in case of a malformed name.
-  ///
-  /// \returns true if the name is a valid swift name for \p D, false otherwise.
-  bool DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc,
-                         const ParsedAttr &AL, bool IsAsync);
 
   UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI,
                           StringRef UuidAsWritten, MSGuidDecl *GuidDecl);
@@ -3825,6 +3843,115 @@ class Sema final : public SemaBase {
 
   void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
 
+  /// Diagnose mutually exclusive attributes when present on a given
+  /// declaration. Returns true if diagnosed.
+  template <typename AttrTy>
+  bool checkAttrMutualExclusion(Decl *D, const ParsedAttr &AL) {
+    if (const auto *A = D->getAttr<AttrTy>()) {
+      Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
+          << AL << A
+          << (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute());
+      Diag(A->getLocation(), diag::note_conflicting_attribute);
+      return true;
+    }
+    return false;
+  }
+
+  template <typename AttrTy>
+  bool checkAttrMutualExclusion(Decl *D, const Attr &AL) {
+    if (const auto *A = D->getAttr<AttrTy>()) {
+      Diag(AL.getLocation(), diag::err_attributes_are_not_compatible)
+          << &AL << A
+          << (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute());
+      Diag(A->getLocation(), diag::note_conflicting_attribute);
+      return true;
+    }
+    return false;
+  }
+
+  template <typename... DiagnosticArgs>
+  static const Sema::SemaDiagnosticBuilder &
+  appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr) {
+    return Bldr;
+  }
+
+  template <typename T, typename... DiagnosticArgs>
+  static const Sema::SemaDiagnosticBuilder &
+  appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr, T &&ExtraArg,
+                    DiagnosticArgs &&...ExtraArgs) {
+    return appendDiagnostics(Bldr << std::forward<T>(ExtraArg),
+                             std::forward<DiagnosticArgs>(ExtraArgs)...);
+  }
+
+  /// Add an attribute @c AttrType to declaration @c D, provided that
+  /// @c PassesCheck is true.
+  /// Otherwise, emit diagnostic @c DiagID, passing in all parameters
+  /// specified in @c ExtraArgs.
+  template <typename AttrType, typename... DiagnosticArgs>
+  void handleSimpleAttributeOrDiagnose(Decl *D, const AttributeCommonInfo &CI,
+                                       bool PassesCheck, unsigned DiagID,
+                                       DiagnosticArgs &&...ExtraArgs) {
+    if (!PassesCheck) {
+      Sema::SemaDiagnosticBuilder DB = Diag(D->getBeginLoc(), DiagID);
+      appendDiagnostics(DB, std::forward<DiagnosticArgs>(ExtraArgs)...);
+      return;
+    }
+    handleSimpleAttribute<AttrType>(D, CI);
+  }
+
+  /// Applies the given attribute to the Decl without performing any
+  /// additional semantic checking.
+  template <typename AttrType>
+  void handleSimpleAttribute(Decl *D, const AttributeCommonInfo &CI) {
+    D->addAttr(::new (Context) AttrType(Context, CI));
+  }
+
+  /// Check if IdxExpr is a valid parameter index for a function or
+  /// instance method D.  May output an error.
+  ///
+  /// \returns true if IdxExpr is a valid index.
+  template <typename AttrInfo>
+  bool checkFunctionOrMethodParameterIndex(const Decl *D, const AttrInfo &AI,
+                                           unsigned AttrArgNum,
+                                           const Expr *IdxExpr, ParamIdx &Idx,
+                                           bool CanIndexImplicitThis = false) {
+    assert(isFunctionOrMethodOrBlockForAttrSubject(D));
+
+    // In C++ the implicit 'this' function parameter also counts.
+    // Parameters are counted from one.
+    bool HP = hasFunctionProto(D);
+    bool HasImplicitThisParam = isInstanceMethod(D);
+    bool IV = HP && isFunctionOrMethodVariadic(D);
+    unsigned NumParams =
+        (HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam;
+
+    std::optional<llvm::APSInt> IdxInt;
+    if (IdxExpr->isTypeDependent() ||
+        !(IdxInt = IdxExpr->getIntegerConstantExpr(Context))) {
+      Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
+          << &AI << AttrArgNum << AANT_ArgumentIntegerConstant
+          << IdxExpr->getSourceRange();
+      return false;
+    }
+
+    unsigned IdxSource = IdxInt->getLimitedValue(UINT_MAX);
+    if (IdxSource < 1 || (!IV && IdxSource > NumParams)) {
+      Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds)
+          << &AI << AttrArgNum << IdxExpr->getSourceRange();
+      return false;
+    }
+    if (HasImplicitThisParam && !CanIndexImplicitThis) {
+      if (IdxSource == 1) {
+        Diag(getAttrLoc(AI), diag::err_attribute_invalid_implicit_this_argument)
+            << &AI << IdxExpr->getSourceRange();
+        return false;
+      }
+    }
+
+    Idx = ParamIdx(IdxSource, D);
+    return true;
+  }
+
   ///@}
 
   //
diff --git a/clang/include/clang/Sema/SemaARM.h b/clang/include/clang/Sema/SemaARM.h
index 02698a33abd55..b1d6768f23fb4 100644
--- a/clang/include/clang/Sema/SemaARM.h
+++ b/clang/include/clang/Sema/SemaARM.h
@@ -13,8 +13,10 @@
 #ifndef LLVM_CLANG_SEMA_SEMAARM_H
 #define LLVM_CLANG_SEMA_SEMAARM_H
 
+#include "clang/AST/DeclBase.h"
 #include "clang/AST/Expr.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/SemaBase.h"
 #include "llvm/ADT/SmallVector.h"
 #include <tuple>
@@ -54,6 +56,15 @@ class SemaARM : public SemaBase {
   bool BuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, int ArgNum,
                             unsigned ExpectedFieldNum, bool AllowName);
   bool BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall);
+
+  bool MveAliasValid(unsigned BuiltinID, StringRef AliasName);
+  bool CdeAliasValid(unsigned BuiltinID, StringRef AliasName);
+  bool SveAliasValid(unsigned BuiltinID, StringRef AliasName);
+  bool SmeAliasValid(unsigned BuiltinID, StringRef AliasName);
+  void handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL);
+  void handleNewAttr(Decl *D, const ParsedAttr &AL);
+  void handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL);
+  void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
 };
 
 SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD);
diff --git a/clang/include/clang/Sema/SemaAVR.h b/clang/include/clang/Sema/SemaAVR.h
new file mode 100644
index 0000000000000..4b2445321d566
--- /dev/null
+++ b/clang/include/clang/Sema/SemaAVR.h
@@ -0,0 +1,31 @@
+//===----- SemaAVR.h ------- AVR target-specific routines -----*- C++ -*---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file declares semantic analysis functions specific to AVR.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMAAVR_H
+#define LLVM_CLANG_SEMA_SEMAAVR_H
+
+#include "clang/Sema/ParsedAttr.h"
+#include "clang/Sema/SemaBase.h"
+
+namespace clang {
+
+class SemaAVR : public SemaBase {
+public:
+  SemaAVR(Sema &S);
+
+  void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
+  void handleSignalAttr(Decl *D, const ParsedAttr &AL);
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_SEMAAVR_H
\ No newline at end of file
diff --git a/clang/include/clang/Sema/SemaBPF.h b/clang/include/clang/Sema/SemaBPF.h
index a3bf59128d254..24d4f073ca7d1 100644
--- a/clang/include/clang/Sema/SemaBPF.h
+++ b/clang/include/clang/Sema/SemaBPF.h
@@ -13,7 +13,10 @@
 #ifndef LLVM_CLANG_SEMA_SEMABPF_H
 #define LLVM_CLANG_SEMA_SEMABPF_H
 
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
 #include "clang/AST/Expr.h"
+#include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/SemaBase.h"
 
 namespace clang {
@@ -22,6 +25,9 @@ class SemaBPF : public SemaBase {
   SemaBPF(Sema &S);
 
   bool CheckBPFBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+
+  void handlePreserveAIRecord(RecordDecl *RD);
+  void handlePreserveAccessIndexAttr(Decl *D, const ParsedAttr &AL);
 };
 } // namespace clang
 
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index eac1f7c07c85d..6f3b03564c67c 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -20,6 +20,7 @@
 #include "clang/Basic/AttributeCommonInfo.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/SemaBase.h"
 #include <initializer_list>
@@ -50,6 +51,13 @@ class SemaHLSL : public SemaBase {
       const Attr *A, HLSLShaderAttr::ShaderType Stage,
       std::initializer_list<HLSLShaderAttr::ShaderType> AllowedStages);
   void DiagnoseAvailabilityViolations(TranslationUnitDecl *TU);
+
+  void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL);
+  void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL);
+  void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL);
+  void handleShaderAttr(Decl *D, const ParsedAttr &AL);
+  void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
+  void handleParamModifierAttr(Decl *D, const ParsedAttr &AL);
 };
 
 } // namespace clang
diff --git a/clang/include/clang/Sema/SemaM68k.h b/clang/include/clang/Sema/SemaM68k.h
new file mode 100644
index 0000000000000..66175632f710d
--- /dev/null
+++ b/clang/include/clang/Sema/SemaM68k.h
@@ -0,0 +1,29 @@
+//===----- SemaM68k.h ------ M68k target-specific routines ----*- C++ -*---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file declares semantic analysis functions specific to M68k.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMAM68K_H
+#define LLVM_CLANG_SEMA_SEMAM68K_H
+
+#include "clang/AST/DeclBase.h"
+#include "clang/Sema/ParsedAttr.h"
+#include "clang/Sema/SemaBase.h"
+
+namespace clang {
+class SemaM68k : public SemaBase {
+public:
+  SemaM68k(Sema &S);
+
+  void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_SEMAM68K_H
diff --git a/clang/include/clang/Sema/SemaMIPS.h b/clang/include/clang/Sema/SemaMIPS.h
index 3f1781b36efd9..b84c532ebad3a 100644
--- a/clang/include/clang/Sema/SemaMIPS.h
+++ b/clang/include/clang/Sema/SemaMIPS.h
@@ -13,8 +13,10 @@
 #ifndef LLVM_CLANG_SEMA_SEMAMIPS_H
 #define LLVM_CLANG_SEMA_SEMAMIPS_H
 
+#include "clang/AST/DeclBase.h"
 #include "clang/AST/Expr.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/SemaBase.h"
 
 namespace clang {
@@ -27,6 +29,7 @@ class SemaMIPS : public SemaBase {
   bool CheckMipsBuiltinCpu(const TargetInfo &TI, unsigned BuiltinID,
                            CallExpr *TheCall);
   bool CheckMipsBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall);
+  void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
 };
 } // namespace clang
 
diff --git a/clang/include/clang/Sema/SemaMSP430.h b/clang/include/clang/Sema/SemaMSP430.h
new file mode 100644
index 0000000000000..4ec6f4...
[truncated]

Copy link
Collaborator

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't take a close look at the individual .cpp files, I assume that is mostly just Copy & paste.

I would like us to be a little more forward-decl aggressive in the headers however, and perhpas try to minimize what gets pushed up to Sema.h.

@@ -3825,6 +3843,115 @@ class Sema final : public SemaBase {

void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);

/// Diagnose mutually exclusive attributes when present on a given
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where did this section of stuff come from? At least the first 2 are attribute related and might be better in the Attr.td with a SemaRef, perhaps a few others as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making functions accept reference to SemaBase is novel, but seem to work fine without negative consequences. I moved the whole block to Sema/Attr.h.

clang/include/clang/Sema/SemaOpenMP.h Outdated Show resolved Hide resolved
clang/include/clang/Sema/SemaRISCV.h Outdated Show resolved Hide resolved
clang/include/clang/Sema/SemaSYCL.h Outdated Show resolved Hide resolved
clang/include/clang/Sema/SemaSwift.h Outdated Show resolved Hide resolved
Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Precommit CI failures seem relevant.

clang/include/clang/Sema/Attr.h Show resolved Hide resolved
clang/include/clang/Sema/Attr.h Show resolved Hide resolved
Copy link

github-actions bot commented May 31, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@RKSimon
Copy link
Collaborator

RKSimon commented May 31, 2024

Would it make sense to add a new header (SemaUtils.h? SemaTargetUtils.h?) to move most of the exposed templated helpers to instead of Sema.h?

@Endilll
Copy link
Contributor Author

Endilll commented May 31, 2024

Would it make sense to add a new header (SemaUtils.h? SemaTargetUtils.h?) to move most of the exposed templated helpers to instead of Sema.h?

That's what Sema/Attr.h does, and I put the helpers for attribute handling there after Erich's suggestion.

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@Endilll Endilll merged commit 6b755b0 into llvm:main Jun 5, 2024
7 checks passed
@Endilll Endilll deleted the splitting-semadeclattr branch June 5, 2024 05:46
@pogo59
Copy link
Collaborator

pogo59 commented Jun 5, 2024

I wonder if a lot of the new target-specific headers don't need to be in clang/include. That subtree is for headers that declare the exported interface (exported to other libs/layers); if the target-specific headers are just there for splitting up the module, they can stay in clang/lib/Sema.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AArch64 backend:ARM backend:RISC-V backend:X86 clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:openmp OpenMP related changes to Clang clang Clang issues not falling into any other category HLSL HLSL Language Support
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

7 participants