Skip to content

Commit 6b755b0

Browse files
authored
[clang] Split up SemaDeclAttr.cpp (#93966)
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.
1 parent e282118 commit 6b755b0

37 files changed

+3254
-2784
lines changed

clang/include/clang/Sema/Attr.h

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,17 @@
1313
#ifndef LLVM_CLANG_SEMA_ATTR_H
1414
#define LLVM_CLANG_SEMA_ATTR_H
1515

16+
#include "clang/AST/Attr.h"
1617
#include "clang/AST/Decl.h"
18+
#include "clang/AST/DeclBase.h"
19+
#include "clang/AST/DeclCXX.h"
1720
#include "clang/AST/DeclObjC.h"
21+
#include "clang/AST/Type.h"
22+
#include "clang/Basic/AttributeCommonInfo.h"
23+
#include "clang/Basic/DiagnosticSema.h"
24+
#include "clang/Basic/SourceLocation.h"
25+
#include "clang/Sema/ParsedAttr.h"
26+
#include "clang/Sema/SemaBase.h"
1827
#include "llvm/Support/Casting.h"
1928

2029
namespace clang {
@@ -32,5 +41,152 @@ inline bool isFunctionOrMethodOrBlockForAttrSubject(const Decl *D) {
3241
return isFuncOrMethodForAttrSubject(D) || llvm::isa<BlockDecl>(D);
3342
}
3443

44+
/// Return true if the given decl has a declarator that should have
45+
/// been processed by Sema::GetTypeForDeclarator.
46+
inline bool hasDeclarator(const Decl *D) {
47+
// In some sense, TypedefDecl really *ought* to be a DeclaratorDecl.
48+
return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) ||
49+
isa<TypedefNameDecl>(D) || isa<ObjCPropertyDecl>(D);
50+
}
51+
52+
/// hasFunctionProto - Return true if the given decl has a argument
53+
/// information. This decl should have already passed
54+
/// isFuncOrMethodForAttrSubject or isFunctionOrMethodOrBlockForAttrSubject.
55+
inline bool hasFunctionProto(const Decl *D) {
56+
if (const FunctionType *FnTy = D->getFunctionType())
57+
return isa<FunctionProtoType>(FnTy);
58+
return isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D);
59+
}
60+
61+
/// getFunctionOrMethodNumParams - Return number of function or method
62+
/// parameters. It is an error to call this on a K&R function (use
63+
/// hasFunctionProto first).
64+
inline unsigned getFunctionOrMethodNumParams(const Decl *D) {
65+
if (const FunctionType *FnTy = D->getFunctionType())
66+
return cast<FunctionProtoType>(FnTy)->getNumParams();
67+
if (const auto *BD = dyn_cast<BlockDecl>(D))
68+
return BD->getNumParams();
69+
return cast<ObjCMethodDecl>(D)->param_size();
70+
}
71+
72+
inline const ParmVarDecl *getFunctionOrMethodParam(const Decl *D,
73+
unsigned Idx) {
74+
if (const auto *FD = dyn_cast<FunctionDecl>(D))
75+
return FD->getParamDecl(Idx);
76+
if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
77+
return MD->getParamDecl(Idx);
78+
if (const auto *BD = dyn_cast<BlockDecl>(D))
79+
return BD->getParamDecl(Idx);
80+
return nullptr;
81+
}
82+
83+
inline QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
84+
if (const FunctionType *FnTy = D->getFunctionType())
85+
return cast<FunctionProtoType>(FnTy)->getParamType(Idx);
86+
if (const auto *BD = dyn_cast<BlockDecl>(D))
87+
return BD->getParamDecl(Idx)->getType();
88+
89+
return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType();
90+
}
91+
92+
inline SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) {
93+
if (auto *PVD = getFunctionOrMethodParam(D, Idx))
94+
return PVD->getSourceRange();
95+
return SourceRange();
96+
}
97+
98+
inline QualType getFunctionOrMethodResultType(const Decl *D) {
99+
if (const FunctionType *FnTy = D->getFunctionType())
100+
return FnTy->getReturnType();
101+
return cast<ObjCMethodDecl>(D)->getReturnType();
102+
}
103+
104+
inline SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) {
105+
if (const auto *FD = dyn_cast<FunctionDecl>(D))
106+
return FD->getReturnTypeSourceRange();
107+
if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
108+
return MD->getReturnTypeSourceRange();
109+
return SourceRange();
110+
}
111+
112+
inline bool isFunctionOrMethodVariadic(const Decl *D) {
113+
if (const FunctionType *FnTy = D->getFunctionType())
114+
return cast<FunctionProtoType>(FnTy)->isVariadic();
115+
if (const auto *BD = dyn_cast<BlockDecl>(D))
116+
return BD->isVariadic();
117+
return cast<ObjCMethodDecl>(D)->isVariadic();
118+
}
119+
120+
inline bool isInstanceMethod(const Decl *D) {
121+
if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(D))
122+
return MethodDecl->isInstance();
123+
return false;
124+
}
125+
126+
/// Diagnose mutually exclusive attributes when present on a given
127+
/// declaration. Returns true if diagnosed.
128+
template <typename AttrTy>
129+
bool checkAttrMutualExclusion(SemaBase &S, Decl *D, const ParsedAttr &AL) {
130+
if (const auto *A = D->getAttr<AttrTy>()) {
131+
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
132+
<< AL << A
133+
<< (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute());
134+
S.Diag(A->getLocation(), diag::note_conflicting_attribute);
135+
return true;
136+
}
137+
return false;
138+
}
139+
140+
template <typename AttrTy>
141+
bool checkAttrMutualExclusion(SemaBase &S, Decl *D, const Attr &AL) {
142+
if (const auto *A = D->getAttr<AttrTy>()) {
143+
S.Diag(AL.getLocation(), diag::err_attributes_are_not_compatible)
144+
<< &AL << A
145+
<< (AL.isRegularKeywordAttribute() || A->isRegularKeywordAttribute());
146+
Diag(A->getLocation(), diag::note_conflicting_attribute);
147+
return true;
148+
}
149+
return false;
150+
}
151+
152+
template <typename... DiagnosticArgs>
153+
const SemaBase::SemaDiagnosticBuilder &
154+
appendDiagnostics(const SemaBase::SemaDiagnosticBuilder &Bldr) {
155+
return Bldr;
156+
}
157+
158+
template <typename T, typename... DiagnosticArgs>
159+
const SemaBase::SemaDiagnosticBuilder &
160+
appendDiagnostics(const SemaBase::SemaDiagnosticBuilder &Bldr, T &&ExtraArg,
161+
DiagnosticArgs &&...ExtraArgs) {
162+
return appendDiagnostics(Bldr << std::forward<T>(ExtraArg),
163+
std::forward<DiagnosticArgs>(ExtraArgs)...);
164+
}
165+
166+
/// Applies the given attribute to the Decl without performing any
167+
/// additional semantic checking.
168+
template <typename AttrType>
169+
void handleSimpleAttribute(SemaBase &S, Decl *D,
170+
const AttributeCommonInfo &CI) {
171+
D->addAttr(::new (S.getASTContext()) AttrType(S.getASTContext(), CI));
172+
}
173+
174+
/// Add an attribute @c AttrType to declaration @c D, provided that
175+
/// @c PassesCheck is true.
176+
/// Otherwise, emit diagnostic @c DiagID, passing in all parameters
177+
/// specified in @c ExtraArgs.
178+
template <typename AttrType, typename... DiagnosticArgs>
179+
void handleSimpleAttributeOrDiagnose(SemaBase &S, Decl *D,
180+
const AttributeCommonInfo &CI,
181+
bool PassesCheck, unsigned DiagID,
182+
DiagnosticArgs &&...ExtraArgs) {
183+
if (!PassesCheck) {
184+
SemaBase::SemaDiagnosticBuilder DB = S.Diag(D->getBeginLoc(), DiagID);
185+
appendDiagnostics(DB, std::forward<DiagnosticArgs>(ExtraArgs)...);
186+
return;
187+
}
188+
handleSimpleAttribute<AttrType>(S, D, CI);
189+
}
190+
35191
} // namespace clang
36192
#endif // LLVM_CLANG_SEMA_ATTR_H

clang/include/clang/Sema/Sema.h

Lines changed: 82 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "clang/Basic/TemplateKinds.h"
4848
#include "clang/Basic/TypeTraits.h"
4949
#include "clang/Sema/AnalysisBasedWarnings.h"
50+
#include "clang/Sema/Attr.h"
5051
#include "clang/Sema/CleanupInfo.h"
5152
#include "clang/Sema/DeclSpec.h"
5253
#include "clang/Sema/ExternalSemaSource.h"
@@ -171,21 +172,26 @@ class PseudoObjectExpr;
171172
class QualType;
172173
class SemaAMDGPU;
173174
class SemaARM;
175+
class SemaAVR;
174176
class SemaBPF;
175177
class SemaCodeCompletion;
176178
class SemaCUDA;
177179
class SemaHLSL;
178180
class SemaHexagon;
179181
class SemaLoongArch;
182+
class SemaM68k;
180183
class SemaMIPS;
184+
class SemaMSP430;
181185
class SemaNVPTX;
182186
class SemaObjC;
183187
class SemaOpenACC;
188+
class SemaOpenCL;
184189
class SemaOpenMP;
185190
class SemaPPC;
186191
class SemaPseudoObject;
187192
class SemaRISCV;
188193
class SemaSYCL;
194+
class SemaSwift;
189195
class SemaSystemZ;
190196
class SemaWasm;
191197
class SemaX86;
@@ -1011,6 +1017,11 @@ class Sema final : public SemaBase {
10111017
return *ARMPtr;
10121018
}
10131019

1020+
SemaAVR &AVR() {
1021+
assert(AVRPtr);
1022+
return *AVRPtr;
1023+
}
1024+
10141025
SemaBPF &BPF() {
10151026
assert(BPFPtr);
10161027
return *BPFPtr;
@@ -1041,11 +1052,21 @@ class Sema final : public SemaBase {
10411052
return *LoongArchPtr;
10421053
}
10431054

1055+
SemaM68k &M68k() {
1056+
assert(M68kPtr);
1057+
return *M68kPtr;
1058+
}
1059+
10441060
SemaMIPS &MIPS() {
10451061
assert(MIPSPtr);
10461062
return *MIPSPtr;
10471063
}
10481064

1065+
SemaMSP430 &MSP430() {
1066+
assert(MSP430Ptr);
1067+
return *MSP430Ptr;
1068+
}
1069+
10491070
SemaNVPTX &NVPTX() {
10501071
assert(NVPTXPtr);
10511072
return *NVPTXPtr;
@@ -1061,6 +1082,11 @@ class Sema final : public SemaBase {
10611082
return *OpenACCPtr;
10621083
}
10631084

1085+
SemaOpenCL &OpenCL() {
1086+
assert(OpenCLPtr);
1087+
return *OpenCLPtr;
1088+
}
1089+
10641090
SemaOpenMP &OpenMP() {
10651091
assert(OpenMPPtr && "SemaOpenMP is dead");
10661092
return *OpenMPPtr;
@@ -1086,6 +1112,11 @@ class Sema final : public SemaBase {
10861112
return *SYCLPtr;
10871113
}
10881114

1115+
SemaSwift &Swift() {
1116+
assert(SwiftPtr);
1117+
return *SwiftPtr;
1118+
}
1119+
10891120
SemaSystemZ &SystemZ() {
10901121
assert(SystemZPtr);
10911122
return *SystemZPtr;
@@ -1133,21 +1164,26 @@ class Sema final : public SemaBase {
11331164

11341165
std::unique_ptr<SemaAMDGPU> AMDGPUPtr;
11351166
std::unique_ptr<SemaARM> ARMPtr;
1167+
std::unique_ptr<SemaAVR> AVRPtr;
11361168
std::unique_ptr<SemaBPF> BPFPtr;
11371169
std::unique_ptr<SemaCodeCompletion> CodeCompletionPtr;
11381170
std::unique_ptr<SemaCUDA> CUDAPtr;
11391171
std::unique_ptr<SemaHLSL> HLSLPtr;
11401172
std::unique_ptr<SemaHexagon> HexagonPtr;
11411173
std::unique_ptr<SemaLoongArch> LoongArchPtr;
1174+
std::unique_ptr<SemaM68k> M68kPtr;
11421175
std::unique_ptr<SemaMIPS> MIPSPtr;
1176+
std::unique_ptr<SemaMSP430> MSP430Ptr;
11431177
std::unique_ptr<SemaNVPTX> NVPTXPtr;
11441178
std::unique_ptr<SemaObjC> ObjCPtr;
11451179
std::unique_ptr<SemaOpenACC> OpenACCPtr;
1180+
std::unique_ptr<SemaOpenCL> OpenCLPtr;
11461181
std::unique_ptr<SemaOpenMP> OpenMPPtr;
11471182
std::unique_ptr<SemaPPC> PPCPtr;
11481183
std::unique_ptr<SemaPseudoObject> PseudoObjectPtr;
11491184
std::unique_ptr<SemaRISCV> RISCVPtr;
11501185
std::unique_ptr<SemaSYCL> SYCLPtr;
1186+
std::unique_ptr<SemaSwift> SwiftPtr;
11511187
std::unique_ptr<SemaSystemZ> SystemZPtr;
11521188
std::unique_ptr<SemaWasm> WasmPtr;
11531189
std::unique_ptr<SemaX86> X86Ptr;
@@ -3711,8 +3747,6 @@ class Sema final : public SemaBase {
37113747
const AttributeCommonInfo &CI,
37123748
const IdentifierInfo *Ident);
37133749
MinSizeAttr *mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI);
3714-
SwiftNameAttr *mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA,
3715-
StringRef Name);
37163750
OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D,
37173751
const AttributeCommonInfo &CI);
37183752
InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL);
@@ -3726,8 +3760,6 @@ class Sema final : public SemaBase {
37263760
const ParsedAttr &attr, CallingConv &CC, const FunctionDecl *FD = nullptr,
37273761
CUDAFunctionTarget CFT = CUDAFunctionTarget::InvalidTarget);
37283762

3729-
void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
3730-
ParameterABI ABI);
37313763
bool CheckRegparmAttr(const ParsedAttr &attr, unsigned &value);
37323764

37333765
/// Create an CUDALaunchBoundsAttr attribute.
@@ -3742,20 +3774,6 @@ class Sema final : public SemaBase {
37423774
Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks);
37433775

37443776
enum class RetainOwnershipKind { NS, CF, OS };
3745-
void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
3746-
RetainOwnershipKind K, bool IsTemplateInstantiation);
3747-
3748-
bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
3749-
3750-
/// Do a check to make sure \p Name looks like a legal argument for the
3751-
/// swift_name attribute applied to decl \p D. Raise a diagnostic if the name
3752-
/// is invalid for the given declaration.
3753-
///
3754-
/// \p AL is used to provide caret diagnostics in case of a malformed name.
3755-
///
3756-
/// \returns true if the name is a valid swift name for \p D, false otherwise.
3757-
bool DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc,
3758-
const ParsedAttr &AL, bool IsAsync);
37593777

37603778
UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI,
37613779
StringRef UuidAsWritten, MSGuidDecl *GuidDecl);
@@ -3825,6 +3843,52 @@ class Sema final : public SemaBase {
38253843

38263844
void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
38273845

3846+
/// Check if IdxExpr is a valid parameter index for a function or
3847+
/// instance method D. May output an error.
3848+
///
3849+
/// \returns true if IdxExpr is a valid index.
3850+
template <typename AttrInfo>
3851+
bool checkFunctionOrMethodParameterIndex(const Decl *D, const AttrInfo &AI,
3852+
unsigned AttrArgNum,
3853+
const Expr *IdxExpr, ParamIdx &Idx,
3854+
bool CanIndexImplicitThis = false) {
3855+
assert(isFunctionOrMethodOrBlockForAttrSubject(D));
3856+
3857+
// In C++ the implicit 'this' function parameter also counts.
3858+
// Parameters are counted from one.
3859+
bool HP = hasFunctionProto(D);
3860+
bool HasImplicitThisParam = isInstanceMethod(D);
3861+
bool IV = HP && isFunctionOrMethodVariadic(D);
3862+
unsigned NumParams =
3863+
(HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam;
3864+
3865+
std::optional<llvm::APSInt> IdxInt;
3866+
if (IdxExpr->isTypeDependent() ||
3867+
!(IdxInt = IdxExpr->getIntegerConstantExpr(Context))) {
3868+
Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
3869+
<< &AI << AttrArgNum << AANT_ArgumentIntegerConstant
3870+
<< IdxExpr->getSourceRange();
3871+
return false;
3872+
}
3873+
3874+
unsigned IdxSource = IdxInt->getLimitedValue(UINT_MAX);
3875+
if (IdxSource < 1 || (!IV && IdxSource > NumParams)) {
3876+
Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds)
3877+
<< &AI << AttrArgNum << IdxExpr->getSourceRange();
3878+
return false;
3879+
}
3880+
if (HasImplicitThisParam && !CanIndexImplicitThis) {
3881+
if (IdxSource == 1) {
3882+
Diag(getAttrLoc(AI), diag::err_attribute_invalid_implicit_this_argument)
3883+
<< &AI << IdxExpr->getSourceRange();
3884+
return false;
3885+
}
3886+
}
3887+
3888+
Idx = ParamIdx(IdxSource, D);
3889+
return true;
3890+
}
3891+
38283892
///@}
38293893

38303894
//

0 commit comments

Comments
 (0)