13
13
#ifndef LLVM_CLANG_SEMA_ATTR_H
14
14
#define LLVM_CLANG_SEMA_ATTR_H
15
15
16
+ #include " clang/AST/Attr.h"
16
17
#include " clang/AST/Decl.h"
18
+ #include " clang/AST/DeclBase.h"
19
+ #include " clang/AST/DeclCXX.h"
17
20
#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"
18
27
#include " llvm/Support/Casting.h"
19
28
20
29
namespace clang {
@@ -32,5 +41,152 @@ inline bool isFunctionOrMethodOrBlockForAttrSubject(const Decl *D) {
32
41
return isFuncOrMethodForAttrSubject (D) || llvm::isa<BlockDecl>(D);
33
42
}
34
43
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
+
35
191
} // namespace clang
36
192
#endif // LLVM_CLANG_SEMA_ATTR_H
0 commit comments