File: | clang/lib/Sema/SemaDeclAttr.cpp |
Warning: | line 5876, column 24 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===// | |||
2 | // | |||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |||
4 | // See https://llvm.org/LICENSE.txt for license information. | |||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |||
6 | // | |||
7 | //===----------------------------------------------------------------------===// | |||
8 | // | |||
9 | // This file implements decl-related attribute processing. | |||
10 | // | |||
11 | //===----------------------------------------------------------------------===// | |||
12 | ||||
13 | #include "clang/AST/ASTConsumer.h" | |||
14 | #include "clang/AST/ASTContext.h" | |||
15 | #include "clang/AST/ASTMutationListener.h" | |||
16 | #include "clang/AST/CXXInheritance.h" | |||
17 | #include "clang/AST/DeclCXX.h" | |||
18 | #include "clang/AST/DeclObjC.h" | |||
19 | #include "clang/AST/DeclTemplate.h" | |||
20 | #include "clang/AST/Expr.h" | |||
21 | #include "clang/AST/ExprCXX.h" | |||
22 | #include "clang/AST/Mangle.h" | |||
23 | #include "clang/AST/RecursiveASTVisitor.h" | |||
24 | #include "clang/AST/Type.h" | |||
25 | #include "clang/Basic/CharInfo.h" | |||
26 | #include "clang/Basic/SourceLocation.h" | |||
27 | #include "clang/Basic/SourceManager.h" | |||
28 | #include "clang/Basic/TargetBuiltins.h" | |||
29 | #include "clang/Basic/TargetInfo.h" | |||
30 | #include "clang/Lex/Preprocessor.h" | |||
31 | #include "clang/Sema/DeclSpec.h" | |||
32 | #include "clang/Sema/DelayedDiagnostic.h" | |||
33 | #include "clang/Sema/Initialization.h" | |||
34 | #include "clang/Sema/Lookup.h" | |||
35 | #include "clang/Sema/ParsedAttr.h" | |||
36 | #include "clang/Sema/Scope.h" | |||
37 | #include "clang/Sema/ScopeInfo.h" | |||
38 | #include "clang/Sema/SemaInternal.h" | |||
39 | #include "llvm/ADT/Optional.h" | |||
40 | #include "llvm/ADT/STLExtras.h" | |||
41 | #include "llvm/ADT/StringExtras.h" | |||
42 | #include "llvm/IR/Assumptions.h" | |||
43 | #include "llvm/Support/Error.h" | |||
44 | #include "llvm/Support/MathExtras.h" | |||
45 | #include "llvm/Support/raw_ostream.h" | |||
46 | ||||
47 | using namespace clang; | |||
48 | using namespace sema; | |||
49 | ||||
50 | namespace AttributeLangSupport { | |||
51 | enum LANG { | |||
52 | C, | |||
53 | Cpp, | |||
54 | ObjC | |||
55 | }; | |||
56 | } // end namespace AttributeLangSupport | |||
57 | ||||
58 | //===----------------------------------------------------------------------===// | |||
59 | // Helper functions | |||
60 | //===----------------------------------------------------------------------===// | |||
61 | ||||
62 | /// isFunctionOrMethod - Return true if the given decl has function | |||
63 | /// type (function or function-typed variable) or an Objective-C | |||
64 | /// method. | |||
65 | static bool isFunctionOrMethod(const Decl *D) { | |||
66 | return (D->getFunctionType() != nullptr) || isa<ObjCMethodDecl>(D); | |||
67 | } | |||
68 | ||||
69 | /// Return true if the given decl has function type (function or | |||
70 | /// function-typed variable) or an Objective-C method or a block. | |||
71 | static bool isFunctionOrMethodOrBlock(const Decl *D) { | |||
72 | return isFunctionOrMethod(D) || isa<BlockDecl>(D); | |||
73 | } | |||
74 | ||||
75 | /// Return true if the given decl has a declarator that should have | |||
76 | /// been processed by Sema::GetTypeForDeclarator. | |||
77 | static bool hasDeclarator(const Decl *D) { | |||
78 | // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl. | |||
79 | return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) || isa<TypedefNameDecl>(D) || | |||
80 | isa<ObjCPropertyDecl>(D); | |||
81 | } | |||
82 | ||||
83 | /// hasFunctionProto - Return true if the given decl has a argument | |||
84 | /// information. This decl should have already passed | |||
85 | /// isFunctionOrMethod or isFunctionOrMethodOrBlock. | |||
86 | static bool hasFunctionProto(const Decl *D) { | |||
87 | if (const FunctionType *FnTy = D->getFunctionType()) | |||
88 | return isa<FunctionProtoType>(FnTy); | |||
89 | return isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D); | |||
90 | } | |||
91 | ||||
92 | /// getFunctionOrMethodNumParams - Return number of function or method | |||
93 | /// parameters. It is an error to call this on a K&R function (use | |||
94 | /// hasFunctionProto first). | |||
95 | static unsigned getFunctionOrMethodNumParams(const Decl *D) { | |||
96 | if (const FunctionType *FnTy = D->getFunctionType()) | |||
97 | return cast<FunctionProtoType>(FnTy)->getNumParams(); | |||
98 | if (const auto *BD = dyn_cast<BlockDecl>(D)) | |||
99 | return BD->getNumParams(); | |||
100 | return cast<ObjCMethodDecl>(D)->param_size(); | |||
101 | } | |||
102 | ||||
103 | static const ParmVarDecl *getFunctionOrMethodParam(const Decl *D, | |||
104 | unsigned Idx) { | |||
105 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) | |||
106 | return FD->getParamDecl(Idx); | |||
107 | if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) | |||
108 | return MD->getParamDecl(Idx); | |||
109 | if (const auto *BD = dyn_cast<BlockDecl>(D)) | |||
110 | return BD->getParamDecl(Idx); | |||
111 | return nullptr; | |||
112 | } | |||
113 | ||||
114 | static QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) { | |||
115 | if (const FunctionType *FnTy = D->getFunctionType()) | |||
116 | return cast<FunctionProtoType>(FnTy)->getParamType(Idx); | |||
117 | if (const auto *BD = dyn_cast<BlockDecl>(D)) | |||
118 | return BD->getParamDecl(Idx)->getType(); | |||
119 | ||||
120 | return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType(); | |||
121 | } | |||
122 | ||||
123 | static SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) { | |||
124 | if (auto *PVD = getFunctionOrMethodParam(D, Idx)) | |||
125 | return PVD->getSourceRange(); | |||
126 | return SourceRange(); | |||
127 | } | |||
128 | ||||
129 | static QualType getFunctionOrMethodResultType(const Decl *D) { | |||
130 | if (const FunctionType *FnTy = D->getFunctionType()) | |||
131 | return FnTy->getReturnType(); | |||
132 | return cast<ObjCMethodDecl>(D)->getReturnType(); | |||
133 | } | |||
134 | ||||
135 | static SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) { | |||
136 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) | |||
137 | return FD->getReturnTypeSourceRange(); | |||
138 | if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) | |||
139 | return MD->getReturnTypeSourceRange(); | |||
140 | return SourceRange(); | |||
141 | } | |||
142 | ||||
143 | static bool isFunctionOrMethodVariadic(const Decl *D) { | |||
144 | if (const FunctionType *FnTy = D->getFunctionType()) | |||
145 | return cast<FunctionProtoType>(FnTy)->isVariadic(); | |||
146 | if (const auto *BD = dyn_cast<BlockDecl>(D)) | |||
147 | return BD->isVariadic(); | |||
148 | return cast<ObjCMethodDecl>(D)->isVariadic(); | |||
149 | } | |||
150 | ||||
151 | static bool isInstanceMethod(const Decl *D) { | |||
152 | if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(D)) | |||
153 | return MethodDecl->isInstance(); | |||
154 | return false; | |||
155 | } | |||
156 | ||||
157 | static inline bool isNSStringType(QualType T, ASTContext &Ctx) { | |||
158 | const auto *PT = T->getAs<ObjCObjectPointerType>(); | |||
159 | if (!PT) | |||
160 | return false; | |||
161 | ||||
162 | ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface(); | |||
163 | if (!Cls) | |||
164 | return false; | |||
165 | ||||
166 | IdentifierInfo* ClsName = Cls->getIdentifier(); | |||
167 | ||||
168 | // FIXME: Should we walk the chain of classes? | |||
169 | return ClsName == &Ctx.Idents.get("NSString") || | |||
170 | ClsName == &Ctx.Idents.get("NSMutableString"); | |||
171 | } | |||
172 | ||||
173 | static inline bool isCFStringType(QualType T, ASTContext &Ctx) { | |||
174 | const auto *PT = T->getAs<PointerType>(); | |||
175 | if (!PT) | |||
176 | return false; | |||
177 | ||||
178 | const auto *RT = PT->getPointeeType()->getAs<RecordType>(); | |||
179 | if (!RT) | |||
180 | return false; | |||
181 | ||||
182 | const RecordDecl *RD = RT->getDecl(); | |||
183 | if (RD->getTagKind() != TTK_Struct) | |||
184 | return false; | |||
185 | ||||
186 | return RD->getIdentifier() == &Ctx.Idents.get("__CFString"); | |||
187 | } | |||
188 | ||||
189 | static unsigned getNumAttributeArgs(const ParsedAttr &AL) { | |||
190 | // FIXME: Include the type in the argument list. | |||
191 | return AL.getNumArgs() + AL.hasParsedType(); | |||
192 | } | |||
193 | ||||
194 | template <typename Compare> | |||
195 | static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL, | |||
196 | unsigned Num, unsigned Diag, | |||
197 | Compare Comp) { | |||
198 | if (Comp(getNumAttributeArgs(AL), Num)) { | |||
199 | S.Diag(AL.getLoc(), Diag) << AL << Num; | |||
200 | return false; | |||
201 | } | |||
202 | ||||
203 | return true; | |||
204 | } | |||
205 | ||||
206 | /// Check if the attribute has exactly as many args as Num. May | |||
207 | /// output an error. | |||
208 | static bool checkAttributeNumArgs(Sema &S, const ParsedAttr &AL, unsigned Num) { | |||
209 | return checkAttributeNumArgsImpl(S, AL, Num, | |||
210 | diag::err_attribute_wrong_number_arguments, | |||
211 | std::not_equal_to<unsigned>()); | |||
212 | } | |||
213 | ||||
214 | /// Check if the attribute has at least as many args as Num. May | |||
215 | /// output an error. | |||
216 | static bool checkAttributeAtLeastNumArgs(Sema &S, const ParsedAttr &AL, | |||
217 | unsigned Num) { | |||
218 | return checkAttributeNumArgsImpl(S, AL, Num, | |||
219 | diag::err_attribute_too_few_arguments, | |||
220 | std::less<unsigned>()); | |||
221 | } | |||
222 | ||||
223 | /// Check if the attribute has at most as many args as Num. May | |||
224 | /// output an error. | |||
225 | static bool checkAttributeAtMostNumArgs(Sema &S, const ParsedAttr &AL, | |||
226 | unsigned Num) { | |||
227 | return checkAttributeNumArgsImpl(S, AL, Num, | |||
228 | diag::err_attribute_too_many_arguments, | |||
229 | std::greater<unsigned>()); | |||
230 | } | |||
231 | ||||
232 | /// A helper function to provide Attribute Location for the Attr types | |||
233 | /// AND the ParsedAttr. | |||
234 | template <typename AttrInfo> | |||
235 | static std::enable_if_t<std::is_base_of<Attr, AttrInfo>::value, SourceLocation> | |||
236 | getAttrLoc(const AttrInfo &AL) { | |||
237 | return AL.getLocation(); | |||
238 | } | |||
239 | static SourceLocation getAttrLoc(const ParsedAttr &AL) { return AL.getLoc(); } | |||
240 | ||||
241 | /// If Expr is a valid integer constant, get the value of the integer | |||
242 | /// expression and return success or failure. May output an error. | |||
243 | /// | |||
244 | /// Negative argument is implicitly converted to unsigned, unless | |||
245 | /// \p StrictlyUnsigned is true. | |||
246 | template <typename AttrInfo> | |||
247 | static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr, | |||
248 | uint32_t &Val, unsigned Idx = UINT_MAX(2147483647 *2U +1U), | |||
249 | bool StrictlyUnsigned = false) { | |||
250 | Optional<llvm::APSInt> I = llvm::APSInt(32); | |||
251 | if (Expr->isTypeDependent() || Expr->isValueDependent() || | |||
252 | !(I = Expr->getIntegerConstantExpr(S.Context))) { | |||
253 | if (Idx != UINT_MAX(2147483647 *2U +1U)) | |||
254 | S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type) | |||
255 | << &AI << Idx << AANT_ArgumentIntegerConstant | |||
256 | << Expr->getSourceRange(); | |||
257 | else | |||
258 | S.Diag(getAttrLoc(AI), diag::err_attribute_argument_type) | |||
259 | << &AI << AANT_ArgumentIntegerConstant << Expr->getSourceRange(); | |||
260 | return false; | |||
261 | } | |||
262 | ||||
263 | if (!I->isIntN(32)) { | |||
264 | S.Diag(Expr->getExprLoc(), diag::err_ice_too_large) | |||
265 | << I->toString(10, false) << 32 << /* Unsigned */ 1; | |||
266 | return false; | |||
267 | } | |||
268 | ||||
269 | if (StrictlyUnsigned && I->isSigned() && I->isNegative()) { | |||
270 | S.Diag(getAttrLoc(AI), diag::err_attribute_requires_positive_integer) | |||
271 | << &AI << /*non-negative*/ 1; | |||
272 | return false; | |||
273 | } | |||
274 | ||||
275 | Val = (uint32_t)I->getZExtValue(); | |||
276 | return true; | |||
277 | } | |||
278 | ||||
279 | /// Wrapper around checkUInt32Argument, with an extra check to be sure | |||
280 | /// that the result will fit into a regular (signed) int. All args have the same | |||
281 | /// purpose as they do in checkUInt32Argument. | |||
282 | template <typename AttrInfo> | |||
283 | static bool checkPositiveIntArgument(Sema &S, const AttrInfo &AI, const Expr *Expr, | |||
284 | int &Val, unsigned Idx = UINT_MAX(2147483647 *2U +1U)) { | |||
285 | uint32_t UVal; | |||
286 | if (!checkUInt32Argument(S, AI, Expr, UVal, Idx)) | |||
287 | return false; | |||
288 | ||||
289 | if (UVal > (uint32_t)std::numeric_limits<int>::max()) { | |||
290 | llvm::APSInt I(32); // for toString | |||
291 | I = UVal; | |||
292 | S.Diag(Expr->getExprLoc(), diag::err_ice_too_large) | |||
293 | << I.toString(10, false) << 32 << /* Unsigned */ 0; | |||
294 | return false; | |||
295 | } | |||
296 | ||||
297 | Val = UVal; | |||
298 | return true; | |||
299 | } | |||
300 | ||||
301 | /// Diagnose mutually exclusive attributes when present on a given | |||
302 | /// declaration. Returns true if diagnosed. | |||
303 | template <typename AttrTy> | |||
304 | static bool checkAttrMutualExclusion(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
305 | if (const auto *A = D->getAttr<AttrTy>()) { | |||
306 | S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << A; | |||
307 | S.Diag(A->getLocation(), diag::note_conflicting_attribute); | |||
308 | return true; | |||
309 | } | |||
310 | return false; | |||
311 | } | |||
312 | ||||
313 | template <typename AttrTy> | |||
314 | static bool checkAttrMutualExclusion(Sema &S, Decl *D, const Attr &AL) { | |||
315 | if (const auto *A = D->getAttr<AttrTy>()) { | |||
316 | S.Diag(AL.getLocation(), diag::err_attributes_are_not_compatible) << &AL | |||
317 | << A; | |||
318 | S.Diag(A->getLocation(), diag::note_conflicting_attribute); | |||
319 | return true; | |||
320 | } | |||
321 | return false; | |||
322 | } | |||
323 | ||||
324 | /// Check if IdxExpr is a valid parameter index for a function or | |||
325 | /// instance method D. May output an error. | |||
326 | /// | |||
327 | /// \returns true if IdxExpr is a valid index. | |||
328 | template <typename AttrInfo> | |||
329 | static bool checkFunctionOrMethodParameterIndex( | |||
330 | Sema &S, const Decl *D, const AttrInfo &AI, unsigned AttrArgNum, | |||
331 | const Expr *IdxExpr, ParamIdx &Idx, bool CanIndexImplicitThis = false) { | |||
332 | assert(isFunctionOrMethodOrBlock(D))((isFunctionOrMethodOrBlock(D)) ? static_cast<void> (0) : __assert_fail ("isFunctionOrMethodOrBlock(D)", "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 332, __PRETTY_FUNCTION__)); | |||
333 | ||||
334 | // In C++ the implicit 'this' function parameter also counts. | |||
335 | // Parameters are counted from one. | |||
336 | bool HP = hasFunctionProto(D); | |||
337 | bool HasImplicitThisParam = isInstanceMethod(D); | |||
338 | bool IV = HP && isFunctionOrMethodVariadic(D); | |||
339 | unsigned NumParams = | |||
340 | (HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam; | |||
341 | ||||
342 | Optional<llvm::APSInt> IdxInt; | |||
343 | if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || | |||
344 | !(IdxInt = IdxExpr->getIntegerConstantExpr(S.Context))) { | |||
345 | S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type) | |||
346 | << &AI << AttrArgNum << AANT_ArgumentIntegerConstant | |||
347 | << IdxExpr->getSourceRange(); | |||
348 | return false; | |||
349 | } | |||
350 | ||||
351 | unsigned IdxSource = IdxInt->getLimitedValue(UINT_MAX(2147483647 *2U +1U)); | |||
352 | if (IdxSource < 1 || (!IV && IdxSource > NumParams)) { | |||
353 | S.Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds) | |||
354 | << &AI << AttrArgNum << IdxExpr->getSourceRange(); | |||
355 | return false; | |||
356 | } | |||
357 | if (HasImplicitThisParam && !CanIndexImplicitThis) { | |||
358 | if (IdxSource == 1) { | |||
359 | S.Diag(getAttrLoc(AI), diag::err_attribute_invalid_implicit_this_argument) | |||
360 | << &AI << IdxExpr->getSourceRange(); | |||
361 | return false; | |||
362 | } | |||
363 | } | |||
364 | ||||
365 | Idx = ParamIdx(IdxSource, D); | |||
366 | return true; | |||
367 | } | |||
368 | ||||
369 | /// Check if the argument \p ArgNum of \p Attr is a ASCII string literal. | |||
370 | /// If not emit an error and return false. If the argument is an identifier it | |||
371 | /// will emit an error with a fixit hint and treat it as if it was a string | |||
372 | /// literal. | |||
373 | bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum, | |||
374 | StringRef &Str, | |||
375 | SourceLocation *ArgLocation) { | |||
376 | // Look for identifiers. If we have one emit a hint to fix it to a literal. | |||
377 | if (AL.isArgIdent(ArgNum)) { | |||
378 | IdentifierLoc *Loc = AL.getArgAsIdent(ArgNum); | |||
379 | Diag(Loc->Loc, diag::err_attribute_argument_type) | |||
380 | << AL << AANT_ArgumentString | |||
381 | << FixItHint::CreateInsertion(Loc->Loc, "\"") | |||
382 | << FixItHint::CreateInsertion(getLocForEndOfToken(Loc->Loc), "\""); | |||
383 | Str = Loc->Ident->getName(); | |||
384 | if (ArgLocation) | |||
385 | *ArgLocation = Loc->Loc; | |||
386 | return true; | |||
387 | } | |||
388 | ||||
389 | // Now check for an actual string literal. | |||
390 | Expr *ArgExpr = AL.getArgAsExpr(ArgNum); | |||
391 | const auto *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts()); | |||
392 | if (ArgLocation) | |||
393 | *ArgLocation = ArgExpr->getBeginLoc(); | |||
394 | ||||
395 | if (!Literal || !Literal->isAscii()) { | |||
396 | Diag(ArgExpr->getBeginLoc(), diag::err_attribute_argument_type) | |||
397 | << AL << AANT_ArgumentString; | |||
398 | return false; | |||
399 | } | |||
400 | ||||
401 | Str = Literal->getString(); | |||
402 | return true; | |||
403 | } | |||
404 | ||||
405 | /// Applies the given attribute to the Decl without performing any | |||
406 | /// additional semantic checking. | |||
407 | template <typename AttrType> | |||
408 | static void handleSimpleAttribute(Sema &S, Decl *D, | |||
409 | const AttributeCommonInfo &CI) { | |||
410 | D->addAttr(::new (S.Context) AttrType(S.Context, CI)); | |||
411 | } | |||
412 | ||||
413 | template <typename... DiagnosticArgs> | |||
414 | static const Sema::SemaDiagnosticBuilder& | |||
415 | appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr) { | |||
416 | return Bldr; | |||
417 | } | |||
418 | ||||
419 | template <typename T, typename... DiagnosticArgs> | |||
420 | static const Sema::SemaDiagnosticBuilder& | |||
421 | appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr, T &&ExtraArg, | |||
422 | DiagnosticArgs &&... ExtraArgs) { | |||
423 | return appendDiagnostics(Bldr << std::forward<T>(ExtraArg), | |||
424 | std::forward<DiagnosticArgs>(ExtraArgs)...); | |||
425 | } | |||
426 | ||||
427 | /// Add an attribute {@code AttrType} to declaration {@code D}, provided that | |||
428 | /// {@code PassesCheck} is true. | |||
429 | /// Otherwise, emit diagnostic {@code DiagID}, passing in all parameters | |||
430 | /// specified in {@code ExtraArgs}. | |||
431 | template <typename AttrType, typename... DiagnosticArgs> | |||
432 | static void handleSimpleAttributeOrDiagnose(Sema &S, Decl *D, | |||
433 | const AttributeCommonInfo &CI, | |||
434 | bool PassesCheck, unsigned DiagID, | |||
435 | DiagnosticArgs &&... ExtraArgs) { | |||
436 | if (!PassesCheck) { | |||
437 | Sema::SemaDiagnosticBuilder DB = S.Diag(D->getBeginLoc(), DiagID); | |||
438 | appendDiagnostics(DB, std::forward<DiagnosticArgs>(ExtraArgs)...); | |||
439 | return; | |||
440 | } | |||
441 | handleSimpleAttribute<AttrType>(S, D, CI); | |||
442 | } | |||
443 | ||||
444 | template <typename AttrType> | |||
445 | static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D, | |||
446 | const ParsedAttr &AL) { | |||
447 | handleSimpleAttribute<AttrType>(S, D, AL); | |||
448 | } | |||
449 | ||||
450 | /// Applies the given attribute to the Decl so long as the Decl doesn't | |||
451 | /// already have one of the given incompatible attributes. | |||
452 | template <typename AttrType, typename IncompatibleAttrType, | |||
453 | typename... IncompatibleAttrTypes> | |||
454 | static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D, | |||
455 | const ParsedAttr &AL) { | |||
456 | if (checkAttrMutualExclusion<IncompatibleAttrType>(S, D, AL)) | |||
457 | return; | |||
458 | handleSimpleAttributeWithExclusions<AttrType, IncompatibleAttrTypes...>(S, D, | |||
459 | AL); | |||
460 | } | |||
461 | ||||
462 | /// Check if the passed-in expression is of type int or bool. | |||
463 | static bool isIntOrBool(Expr *Exp) { | |||
464 | QualType QT = Exp->getType(); | |||
465 | return QT->isBooleanType() || QT->isIntegerType(); | |||
466 | } | |||
467 | ||||
468 | ||||
469 | // Check to see if the type is a smart pointer of some kind. We assume | |||
470 | // it's a smart pointer if it defines both operator-> and operator*. | |||
471 | static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) { | |||
472 | auto IsOverloadedOperatorPresent = [&S](const RecordDecl *Record, | |||
473 | OverloadedOperatorKind Op) { | |||
474 | DeclContextLookupResult Result = | |||
475 | Record->lookup(S.Context.DeclarationNames.getCXXOperatorName(Op)); | |||
476 | return !Result.empty(); | |||
477 | }; | |||
478 | ||||
479 | const RecordDecl *Record = RT->getDecl(); | |||
480 | bool foundStarOperator = IsOverloadedOperatorPresent(Record, OO_Star); | |||
481 | bool foundArrowOperator = IsOverloadedOperatorPresent(Record, OO_Arrow); | |||
482 | if (foundStarOperator && foundArrowOperator) | |||
483 | return true; | |||
484 | ||||
485 | const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record); | |||
486 | if (!CXXRecord) | |||
487 | return false; | |||
488 | ||||
489 | for (auto BaseSpecifier : CXXRecord->bases()) { | |||
490 | if (!foundStarOperator) | |||
491 | foundStarOperator = IsOverloadedOperatorPresent( | |||
492 | BaseSpecifier.getType()->getAsRecordDecl(), OO_Star); | |||
493 | if (!foundArrowOperator) | |||
494 | foundArrowOperator = IsOverloadedOperatorPresent( | |||
495 | BaseSpecifier.getType()->getAsRecordDecl(), OO_Arrow); | |||
496 | } | |||
497 | ||||
498 | if (foundStarOperator && foundArrowOperator) | |||
499 | return true; | |||
500 | ||||
501 | return false; | |||
502 | } | |||
503 | ||||
504 | /// Check if passed in Decl is a pointer type. | |||
505 | /// Note that this function may produce an error message. | |||
506 | /// \return true if the Decl is a pointer type; false otherwise | |||
507 | static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D, | |||
508 | const ParsedAttr &AL) { | |||
509 | const auto *VD = cast<ValueDecl>(D); | |||
510 | QualType QT = VD->getType(); | |||
511 | if (QT->isAnyPointerType()) | |||
512 | return true; | |||
513 | ||||
514 | if (const auto *RT = QT->getAs<RecordType>()) { | |||
515 | // If it's an incomplete type, it could be a smart pointer; skip it. | |||
516 | // (We don't want to force template instantiation if we can avoid it, | |||
517 | // since that would alter the order in which templates are instantiated.) | |||
518 | if (RT->isIncompleteType()) | |||
519 | return true; | |||
520 | ||||
521 | if (threadSafetyCheckIsSmartPointer(S, RT)) | |||
522 | return true; | |||
523 | } | |||
524 | ||||
525 | S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_pointer) << AL << QT; | |||
526 | return false; | |||
527 | } | |||
528 | ||||
529 | /// Checks that the passed in QualType either is of RecordType or points | |||
530 | /// to RecordType. Returns the relevant RecordType, null if it does not exit. | |||
531 | static const RecordType *getRecordType(QualType QT) { | |||
532 | if (const auto *RT = QT->getAs<RecordType>()) | |||
533 | return RT; | |||
534 | ||||
535 | // Now check if we point to record type. | |||
536 | if (const auto *PT = QT->getAs<PointerType>()) | |||
537 | return PT->getPointeeType()->getAs<RecordType>(); | |||
538 | ||||
539 | return nullptr; | |||
540 | } | |||
541 | ||||
542 | template <typename AttrType> | |||
543 | static bool checkRecordDeclForAttr(const RecordDecl *RD) { | |||
544 | // Check if the record itself has the attribute. | |||
545 | if (RD->hasAttr<AttrType>()) | |||
546 | return true; | |||
547 | ||||
548 | // Else check if any base classes have the attribute. | |||
549 | if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) { | |||
550 | CXXBasePaths BPaths(false, false); | |||
551 | if (CRD->lookupInBases( | |||
552 | [](const CXXBaseSpecifier *BS, CXXBasePath &) { | |||
553 | const auto &Ty = *BS->getType(); | |||
554 | // If it's type-dependent, we assume it could have the attribute. | |||
555 | if (Ty.isDependentType()) | |||
556 | return true; | |||
557 | return Ty.castAs<RecordType>()->getDecl()->hasAttr<AttrType>(); | |||
558 | }, | |||
559 | BPaths, true)) | |||
560 | return true; | |||
561 | } | |||
562 | return false; | |||
563 | } | |||
564 | ||||
565 | static bool checkRecordTypeForCapability(Sema &S, QualType Ty) { | |||
566 | const RecordType *RT = getRecordType(Ty); | |||
567 | ||||
568 | if (!RT) | |||
569 | return false; | |||
570 | ||||
571 | // Don't check for the capability if the class hasn't been defined yet. | |||
572 | if (RT->isIncompleteType()) | |||
573 | return true; | |||
574 | ||||
575 | // Allow smart pointers to be used as capability objects. | |||
576 | // FIXME -- Check the type that the smart pointer points to. | |||
577 | if (threadSafetyCheckIsSmartPointer(S, RT)) | |||
578 | return true; | |||
579 | ||||
580 | return checkRecordDeclForAttr<CapabilityAttr>(RT->getDecl()); | |||
581 | } | |||
582 | ||||
583 | static bool checkTypedefTypeForCapability(QualType Ty) { | |||
584 | const auto *TD = Ty->getAs<TypedefType>(); | |||
585 | if (!TD) | |||
586 | return false; | |||
587 | ||||
588 | TypedefNameDecl *TN = TD->getDecl(); | |||
589 | if (!TN) | |||
590 | return false; | |||
591 | ||||
592 | return TN->hasAttr<CapabilityAttr>(); | |||
593 | } | |||
594 | ||||
595 | static bool typeHasCapability(Sema &S, QualType Ty) { | |||
596 | if (checkTypedefTypeForCapability(Ty)) | |||
597 | return true; | |||
598 | ||||
599 | if (checkRecordTypeForCapability(S, Ty)) | |||
600 | return true; | |||
601 | ||||
602 | return false; | |||
603 | } | |||
604 | ||||
605 | static bool isCapabilityExpr(Sema &S, const Expr *Ex) { | |||
606 | // Capability expressions are simple expressions involving the boolean logic | |||
607 | // operators &&, || or !, a simple DeclRefExpr, CastExpr or a ParenExpr. Once | |||
608 | // a DeclRefExpr is found, its type should be checked to determine whether it | |||
609 | // is a capability or not. | |||
610 | ||||
611 | if (const auto *E = dyn_cast<CastExpr>(Ex)) | |||
612 | return isCapabilityExpr(S, E->getSubExpr()); | |||
613 | else if (const auto *E = dyn_cast<ParenExpr>(Ex)) | |||
614 | return isCapabilityExpr(S, E->getSubExpr()); | |||
615 | else if (const auto *E = dyn_cast<UnaryOperator>(Ex)) { | |||
616 | if (E->getOpcode() == UO_LNot || E->getOpcode() == UO_AddrOf || | |||
617 | E->getOpcode() == UO_Deref) | |||
618 | return isCapabilityExpr(S, E->getSubExpr()); | |||
619 | return false; | |||
620 | } else if (const auto *E = dyn_cast<BinaryOperator>(Ex)) { | |||
621 | if (E->getOpcode() == BO_LAnd || E->getOpcode() == BO_LOr) | |||
622 | return isCapabilityExpr(S, E->getLHS()) && | |||
623 | isCapabilityExpr(S, E->getRHS()); | |||
624 | return false; | |||
625 | } | |||
626 | ||||
627 | return typeHasCapability(S, Ex->getType()); | |||
628 | } | |||
629 | ||||
630 | /// Checks that all attribute arguments, starting from Sidx, resolve to | |||
631 | /// a capability object. | |||
632 | /// \param Sidx The attribute argument index to start checking with. | |||
633 | /// \param ParamIdxOk Whether an argument can be indexing into a function | |||
634 | /// parameter list. | |||
635 | static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D, | |||
636 | const ParsedAttr &AL, | |||
637 | SmallVectorImpl<Expr *> &Args, | |||
638 | unsigned Sidx = 0, | |||
639 | bool ParamIdxOk = false) { | |||
640 | if (Sidx == AL.getNumArgs()) { | |||
641 | // If we don't have any capability arguments, the attribute implicitly | |||
642 | // refers to 'this'. So we need to make sure that 'this' exists, i.e. we're | |||
643 | // a non-static method, and that the class is a (scoped) capability. | |||
644 | const auto *MD = dyn_cast<const CXXMethodDecl>(D); | |||
645 | if (MD && !MD->isStatic()) { | |||
646 | const CXXRecordDecl *RD = MD->getParent(); | |||
647 | // FIXME -- need to check this again on template instantiation | |||
648 | if (!checkRecordDeclForAttr<CapabilityAttr>(RD) && | |||
649 | !checkRecordDeclForAttr<ScopedLockableAttr>(RD)) | |||
650 | S.Diag(AL.getLoc(), | |||
651 | diag::warn_thread_attribute_not_on_capability_member) | |||
652 | << AL << MD->getParent(); | |||
653 | } else { | |||
654 | S.Diag(AL.getLoc(), diag::warn_thread_attribute_not_on_non_static_member) | |||
655 | << AL; | |||
656 | } | |||
657 | } | |||
658 | ||||
659 | for (unsigned Idx = Sidx; Idx < AL.getNumArgs(); ++Idx) { | |||
660 | Expr *ArgExp = AL.getArgAsExpr(Idx); | |||
661 | ||||
662 | if (ArgExp->isTypeDependent()) { | |||
663 | // FIXME -- need to check this again on template instantiation | |||
664 | Args.push_back(ArgExp); | |||
665 | continue; | |||
666 | } | |||
667 | ||||
668 | if (const auto *StrLit = dyn_cast<StringLiteral>(ArgExp)) { | |||
669 | if (StrLit->getLength() == 0 || | |||
670 | (StrLit->isAscii() && StrLit->getString() == StringRef("*"))) { | |||
671 | // Pass empty strings to the analyzer without warnings. | |||
672 | // Treat "*" as the universal lock. | |||
673 | Args.push_back(ArgExp); | |||
674 | continue; | |||
675 | } | |||
676 | ||||
677 | // We allow constant strings to be used as a placeholder for expressions | |||
678 | // that are not valid C++ syntax, but warn that they are ignored. | |||
679 | S.Diag(AL.getLoc(), diag::warn_thread_attribute_ignored) << AL; | |||
680 | Args.push_back(ArgExp); | |||
681 | continue; | |||
682 | } | |||
683 | ||||
684 | QualType ArgTy = ArgExp->getType(); | |||
685 | ||||
686 | // A pointer to member expression of the form &MyClass::mu is treated | |||
687 | // specially -- we need to look at the type of the member. | |||
688 | if (const auto *UOp = dyn_cast<UnaryOperator>(ArgExp)) | |||
689 | if (UOp->getOpcode() == UO_AddrOf) | |||
690 | if (const auto *DRE = dyn_cast<DeclRefExpr>(UOp->getSubExpr())) | |||
691 | if (DRE->getDecl()->isCXXInstanceMember()) | |||
692 | ArgTy = DRE->getDecl()->getType(); | |||
693 | ||||
694 | // First see if we can just cast to record type, or pointer to record type. | |||
695 | const RecordType *RT = getRecordType(ArgTy); | |||
696 | ||||
697 | // Now check if we index into a record type function param. | |||
698 | if(!RT && ParamIdxOk) { | |||
699 | const auto *FD = dyn_cast<FunctionDecl>(D); | |||
700 | const auto *IL = dyn_cast<IntegerLiteral>(ArgExp); | |||
701 | if(FD && IL) { | |||
702 | unsigned int NumParams = FD->getNumParams(); | |||
703 | llvm::APInt ArgValue = IL->getValue(); | |||
704 | uint64_t ParamIdxFromOne = ArgValue.getZExtValue(); | |||
705 | uint64_t ParamIdxFromZero = ParamIdxFromOne - 1; | |||
706 | if (!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) { | |||
707 | S.Diag(AL.getLoc(), | |||
708 | diag::err_attribute_argument_out_of_bounds_extra_info) | |||
709 | << AL << Idx + 1 << NumParams; | |||
710 | continue; | |||
711 | } | |||
712 | ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType(); | |||
713 | } | |||
714 | } | |||
715 | ||||
716 | // If the type does not have a capability, see if the components of the | |||
717 | // expression have capabilities. This allows for writing C code where the | |||
718 | // capability may be on the type, and the expression is a capability | |||
719 | // boolean logic expression. Eg) requires_capability(A || B && !C) | |||
720 | if (!typeHasCapability(S, ArgTy) && !isCapabilityExpr(S, ArgExp)) | |||
721 | S.Diag(AL.getLoc(), diag::warn_thread_attribute_argument_not_lockable) | |||
722 | << AL << ArgTy; | |||
723 | ||||
724 | Args.push_back(ArgExp); | |||
725 | } | |||
726 | } | |||
727 | ||||
728 | //===----------------------------------------------------------------------===// | |||
729 | // Attribute Implementations | |||
730 | //===----------------------------------------------------------------------===// | |||
731 | ||||
732 | static void handlePtGuardedVarAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
733 | if (!threadSafetyCheckIsPointer(S, D, AL)) | |||
734 | return; | |||
735 | ||||
736 | D->addAttr(::new (S.Context) PtGuardedVarAttr(S.Context, AL)); | |||
737 | } | |||
738 | ||||
739 | static bool checkGuardedByAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, | |||
740 | Expr *&Arg) { | |||
741 | SmallVector<Expr *, 1> Args; | |||
742 | // check that all arguments are lockable objects | |||
743 | checkAttrArgsAreCapabilityObjs(S, D, AL, Args); | |||
744 | unsigned Size = Args.size(); | |||
745 | if (Size != 1) | |||
746 | return false; | |||
747 | ||||
748 | Arg = Args[0]; | |||
749 | ||||
750 | return true; | |||
751 | } | |||
752 | ||||
753 | static void handleGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
754 | Expr *Arg = nullptr; | |||
755 | if (!checkGuardedByAttrCommon(S, D, AL, Arg)) | |||
756 | return; | |||
757 | ||||
758 | D->addAttr(::new (S.Context) GuardedByAttr(S.Context, AL, Arg)); | |||
759 | } | |||
760 | ||||
761 | static void handlePtGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
762 | Expr *Arg = nullptr; | |||
763 | if (!checkGuardedByAttrCommon(S, D, AL, Arg)) | |||
764 | return; | |||
765 | ||||
766 | if (!threadSafetyCheckIsPointer(S, D, AL)) | |||
767 | return; | |||
768 | ||||
769 | D->addAttr(::new (S.Context) PtGuardedByAttr(S.Context, AL, Arg)); | |||
770 | } | |||
771 | ||||
772 | static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, | |||
773 | SmallVectorImpl<Expr *> &Args) { | |||
774 | if (!checkAttributeAtLeastNumArgs(S, AL, 1)) | |||
775 | return false; | |||
776 | ||||
777 | // Check that this attribute only applies to lockable types. | |||
778 | QualType QT = cast<ValueDecl>(D)->getType(); | |||
779 | if (!QT->isDependentType() && !typeHasCapability(S, QT)) { | |||
780 | S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_lockable) << AL; | |||
781 | return false; | |||
782 | } | |||
783 | ||||
784 | // Check that all arguments are lockable objects. | |||
785 | checkAttrArgsAreCapabilityObjs(S, D, AL, Args); | |||
786 | if (Args.empty()) | |||
787 | return false; | |||
788 | ||||
789 | return true; | |||
790 | } | |||
791 | ||||
792 | static void handleAcquiredAfterAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
793 | SmallVector<Expr *, 1> Args; | |||
794 | if (!checkAcquireOrderAttrCommon(S, D, AL, Args)) | |||
795 | return; | |||
796 | ||||
797 | Expr **StartArg = &Args[0]; | |||
798 | D->addAttr(::new (S.Context) | |||
799 | AcquiredAfterAttr(S.Context, AL, StartArg, Args.size())); | |||
800 | } | |||
801 | ||||
802 | static void handleAcquiredBeforeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
803 | SmallVector<Expr *, 1> Args; | |||
804 | if (!checkAcquireOrderAttrCommon(S, D, AL, Args)) | |||
805 | return; | |||
806 | ||||
807 | Expr **StartArg = &Args[0]; | |||
808 | D->addAttr(::new (S.Context) | |||
809 | AcquiredBeforeAttr(S.Context, AL, StartArg, Args.size())); | |||
810 | } | |||
811 | ||||
812 | static bool checkLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, | |||
813 | SmallVectorImpl<Expr *> &Args) { | |||
814 | // zero or more arguments ok | |||
815 | // check that all arguments are lockable objects | |||
816 | checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, /*ParamIdxOk=*/true); | |||
817 | ||||
818 | return true; | |||
819 | } | |||
820 | ||||
821 | static void handleAssertSharedLockAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
822 | SmallVector<Expr *, 1> Args; | |||
823 | if (!checkLockFunAttrCommon(S, D, AL, Args)) | |||
824 | return; | |||
825 | ||||
826 | unsigned Size = Args.size(); | |||
827 | Expr **StartArg = Size == 0 ? nullptr : &Args[0]; | |||
828 | D->addAttr(::new (S.Context) | |||
829 | AssertSharedLockAttr(S.Context, AL, StartArg, Size)); | |||
830 | } | |||
831 | ||||
832 | static void handleAssertExclusiveLockAttr(Sema &S, Decl *D, | |||
833 | const ParsedAttr &AL) { | |||
834 | SmallVector<Expr *, 1> Args; | |||
835 | if (!checkLockFunAttrCommon(S, D, AL, Args)) | |||
836 | return; | |||
837 | ||||
838 | unsigned Size = Args.size(); | |||
839 | Expr **StartArg = Size == 0 ? nullptr : &Args[0]; | |||
840 | D->addAttr(::new (S.Context) | |||
841 | AssertExclusiveLockAttr(S.Context, AL, StartArg, Size)); | |||
842 | } | |||
843 | ||||
844 | /// Checks to be sure that the given parameter number is in bounds, and | |||
845 | /// is an integral type. Will emit appropriate diagnostics if this returns | |||
846 | /// false. | |||
847 | /// | |||
848 | /// AttrArgNo is used to actually retrieve the argument, so it's base-0. | |||
849 | template <typename AttrInfo> | |||
850 | static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD, | |||
851 | const AttrInfo &AI, unsigned AttrArgNo) { | |||
852 | assert(AI.isArgExpr(AttrArgNo) && "Expected expression argument")((AI.isArgExpr(AttrArgNo) && "Expected expression argument" ) ? static_cast<void> (0) : __assert_fail ("AI.isArgExpr(AttrArgNo) && \"Expected expression argument\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 852, __PRETTY_FUNCTION__)); | |||
853 | Expr *AttrArg = AI.getArgAsExpr(AttrArgNo); | |||
854 | ParamIdx Idx; | |||
855 | if (!checkFunctionOrMethodParameterIndex(S, FD, AI, AttrArgNo + 1, AttrArg, | |||
856 | Idx)) | |||
857 | return false; | |||
858 | ||||
859 | const ParmVarDecl *Param = FD->getParamDecl(Idx.getASTIndex()); | |||
860 | if (!Param->getType()->isIntegerType() && !Param->getType()->isCharType()) { | |||
861 | SourceLocation SrcLoc = AttrArg->getBeginLoc(); | |||
862 | S.Diag(SrcLoc, diag::err_attribute_integers_only) | |||
863 | << AI << Param->getSourceRange(); | |||
864 | return false; | |||
865 | } | |||
866 | return true; | |||
867 | } | |||
868 | ||||
869 | static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
870 | if (!checkAttributeAtLeastNumArgs(S, AL, 1) || | |||
871 | !checkAttributeAtMostNumArgs(S, AL, 2)) | |||
872 | return; | |||
873 | ||||
874 | const auto *FD = cast<FunctionDecl>(D); | |||
875 | if (!FD->getReturnType()->isPointerType()) { | |||
876 | S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) << AL; | |||
877 | return; | |||
878 | } | |||
879 | ||||
880 | const Expr *SizeExpr = AL.getArgAsExpr(0); | |||
881 | int SizeArgNoVal; | |||
882 | // Parameter indices are 1-indexed, hence Index=1 | |||
883 | if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNoVal, /*Idx=*/1)) | |||
884 | return; | |||
885 | if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/0)) | |||
886 | return; | |||
887 | ParamIdx SizeArgNo(SizeArgNoVal, D); | |||
888 | ||||
889 | ParamIdx NumberArgNo; | |||
890 | if (AL.getNumArgs() == 2) { | |||
891 | const Expr *NumberExpr = AL.getArgAsExpr(1); | |||
892 | int Val; | |||
893 | // Parameter indices are 1-based, hence Index=2 | |||
894 | if (!checkPositiveIntArgument(S, AL, NumberExpr, Val, /*Idx=*/2)) | |||
895 | return; | |||
896 | if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/1)) | |||
897 | return; | |||
898 | NumberArgNo = ParamIdx(Val, D); | |||
899 | } | |||
900 | ||||
901 | D->addAttr(::new (S.Context) | |||
902 | AllocSizeAttr(S.Context, AL, SizeArgNo, NumberArgNo)); | |||
903 | } | |||
904 | ||||
905 | static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, | |||
906 | SmallVectorImpl<Expr *> &Args) { | |||
907 | if (!checkAttributeAtLeastNumArgs(S, AL, 1)) | |||
908 | return false; | |||
909 | ||||
910 | if (!isIntOrBool(AL.getArgAsExpr(0))) { | |||
911 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
912 | << AL << 1 << AANT_ArgumentIntOrBool; | |||
913 | return false; | |||
914 | } | |||
915 | ||||
916 | // check that all arguments are lockable objects | |||
917 | checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 1); | |||
918 | ||||
919 | return true; | |||
920 | } | |||
921 | ||||
922 | static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D, | |||
923 | const ParsedAttr &AL) { | |||
924 | SmallVector<Expr*, 2> Args; | |||
925 | if (!checkTryLockFunAttrCommon(S, D, AL, Args)) | |||
926 | return; | |||
927 | ||||
928 | D->addAttr(::new (S.Context) SharedTrylockFunctionAttr( | |||
929 | S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size())); | |||
930 | } | |||
931 | ||||
932 | static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, | |||
933 | const ParsedAttr &AL) { | |||
934 | SmallVector<Expr*, 2> Args; | |||
935 | if (!checkTryLockFunAttrCommon(S, D, AL, Args)) | |||
936 | return; | |||
937 | ||||
938 | D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr( | |||
939 | S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size())); | |||
940 | } | |||
941 | ||||
942 | static void handleLockReturnedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
943 | // check that the argument is lockable object | |||
944 | SmallVector<Expr*, 1> Args; | |||
945 | checkAttrArgsAreCapabilityObjs(S, D, AL, Args); | |||
946 | unsigned Size = Args.size(); | |||
947 | if (Size == 0) | |||
948 | return; | |||
949 | ||||
950 | D->addAttr(::new (S.Context) LockReturnedAttr(S.Context, AL, Args[0])); | |||
951 | } | |||
952 | ||||
953 | static void handleLocksExcludedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
954 | if (!checkAttributeAtLeastNumArgs(S, AL, 1)) | |||
955 | return; | |||
956 | ||||
957 | // check that all arguments are lockable objects | |||
958 | SmallVector<Expr*, 1> Args; | |||
959 | checkAttrArgsAreCapabilityObjs(S, D, AL, Args); | |||
960 | unsigned Size = Args.size(); | |||
961 | if (Size == 0) | |||
962 | return; | |||
963 | Expr **StartArg = &Args[0]; | |||
964 | ||||
965 | D->addAttr(::new (S.Context) | |||
966 | LocksExcludedAttr(S.Context, AL, StartArg, Size)); | |||
967 | } | |||
968 | ||||
969 | static bool checkFunctionConditionAttr(Sema &S, Decl *D, const ParsedAttr &AL, | |||
970 | Expr *&Cond, StringRef &Msg) { | |||
971 | Cond = AL.getArgAsExpr(0); | |||
972 | if (!Cond->isTypeDependent()) { | |||
973 | ExprResult Converted = S.PerformContextuallyConvertToBool(Cond); | |||
974 | if (Converted.isInvalid()) | |||
975 | return false; | |||
976 | Cond = Converted.get(); | |||
977 | } | |||
978 | ||||
979 | if (!S.checkStringLiteralArgumentAttr(AL, 1, Msg)) | |||
980 | return false; | |||
981 | ||||
982 | if (Msg.empty()) | |||
983 | Msg = "<no message provided>"; | |||
984 | ||||
985 | SmallVector<PartialDiagnosticAt, 8> Diags; | |||
986 | if (isa<FunctionDecl>(D) && !Cond->isValueDependent() && | |||
987 | !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D), | |||
988 | Diags)) { | |||
989 | S.Diag(AL.getLoc(), diag::err_attr_cond_never_constant_expr) << AL; | |||
990 | for (const PartialDiagnosticAt &PDiag : Diags) | |||
991 | S.Diag(PDiag.first, PDiag.second); | |||
992 | return false; | |||
993 | } | |||
994 | return true; | |||
995 | } | |||
996 | ||||
997 | static void handleEnableIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
998 | S.Diag(AL.getLoc(), diag::ext_clang_enable_if); | |||
999 | ||||
1000 | Expr *Cond; | |||
1001 | StringRef Msg; | |||
1002 | if (checkFunctionConditionAttr(S, D, AL, Cond, Msg)) | |||
1003 | D->addAttr(::new (S.Context) EnableIfAttr(S.Context, AL, Cond, Msg)); | |||
1004 | } | |||
1005 | ||||
1006 | namespace { | |||
1007 | /// Determines if a given Expr references any of the given function's | |||
1008 | /// ParmVarDecls, or the function's implicit `this` parameter (if applicable). | |||
1009 | class ArgumentDependenceChecker | |||
1010 | : public RecursiveASTVisitor<ArgumentDependenceChecker> { | |||
1011 | #ifndef NDEBUG | |||
1012 | const CXXRecordDecl *ClassType; | |||
1013 | #endif | |||
1014 | llvm::SmallPtrSet<const ParmVarDecl *, 16> Parms; | |||
1015 | bool Result; | |||
1016 | ||||
1017 | public: | |||
1018 | ArgumentDependenceChecker(const FunctionDecl *FD) { | |||
1019 | #ifndef NDEBUG | |||
1020 | if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) | |||
1021 | ClassType = MD->getParent(); | |||
1022 | else | |||
1023 | ClassType = nullptr; | |||
1024 | #endif | |||
1025 | Parms.insert(FD->param_begin(), FD->param_end()); | |||
1026 | } | |||
1027 | ||||
1028 | bool referencesArgs(Expr *E) { | |||
1029 | Result = false; | |||
1030 | TraverseStmt(E); | |||
1031 | return Result; | |||
1032 | } | |||
1033 | ||||
1034 | bool VisitCXXThisExpr(CXXThisExpr *E) { | |||
1035 | assert(E->getType()->getPointeeCXXRecordDecl() == ClassType &&((E->getType()->getPointeeCXXRecordDecl() == ClassType && "`this` doesn't refer to the enclosing class?") ? static_cast <void> (0) : __assert_fail ("E->getType()->getPointeeCXXRecordDecl() == ClassType && \"`this` doesn't refer to the enclosing class?\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 1036, __PRETTY_FUNCTION__)) | |||
1036 | "`this` doesn't refer to the enclosing class?")((E->getType()->getPointeeCXXRecordDecl() == ClassType && "`this` doesn't refer to the enclosing class?") ? static_cast <void> (0) : __assert_fail ("E->getType()->getPointeeCXXRecordDecl() == ClassType && \"`this` doesn't refer to the enclosing class?\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 1036, __PRETTY_FUNCTION__)); | |||
1037 | Result = true; | |||
1038 | return false; | |||
1039 | } | |||
1040 | ||||
1041 | bool VisitDeclRefExpr(DeclRefExpr *DRE) { | |||
1042 | if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) | |||
1043 | if (Parms.count(PVD)) { | |||
1044 | Result = true; | |||
1045 | return false; | |||
1046 | } | |||
1047 | return true; | |||
1048 | } | |||
1049 | }; | |||
1050 | } | |||
1051 | ||||
1052 | static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1053 | S.Diag(AL.getLoc(), diag::ext_clang_diagnose_if); | |||
1054 | ||||
1055 | Expr *Cond; | |||
1056 | StringRef Msg; | |||
1057 | if (!checkFunctionConditionAttr(S, D, AL, Cond, Msg)) | |||
1058 | return; | |||
1059 | ||||
1060 | StringRef DiagTypeStr; | |||
1061 | if (!S.checkStringLiteralArgumentAttr(AL, 2, DiagTypeStr)) | |||
1062 | return; | |||
1063 | ||||
1064 | DiagnoseIfAttr::DiagnosticType DiagType; | |||
1065 | if (!DiagnoseIfAttr::ConvertStrToDiagnosticType(DiagTypeStr, DiagType)) { | |||
1066 | S.Diag(AL.getArgAsExpr(2)->getBeginLoc(), | |||
1067 | diag::err_diagnose_if_invalid_diagnostic_type); | |||
1068 | return; | |||
1069 | } | |||
1070 | ||||
1071 | bool ArgDependent = false; | |||
1072 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) | |||
1073 | ArgDependent = ArgumentDependenceChecker(FD).referencesArgs(Cond); | |||
1074 | D->addAttr(::new (S.Context) DiagnoseIfAttr( | |||
1075 | S.Context, AL, Cond, Msg, DiagType, ArgDependent, cast<NamedDecl>(D))); | |||
1076 | } | |||
1077 | ||||
1078 | static void handleNoBuiltinAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1079 | static constexpr const StringRef kWildcard = "*"; | |||
1080 | ||||
1081 | llvm::SmallVector<StringRef, 16> Names; | |||
1082 | bool HasWildcard = false; | |||
1083 | ||||
1084 | const auto AddBuiltinName = [&Names, &HasWildcard](StringRef Name) { | |||
1085 | if (Name == kWildcard) | |||
1086 | HasWildcard = true; | |||
1087 | Names.push_back(Name); | |||
1088 | }; | |||
1089 | ||||
1090 | // Add previously defined attributes. | |||
1091 | if (const auto *NBA = D->getAttr<NoBuiltinAttr>()) | |||
1092 | for (StringRef BuiltinName : NBA->builtinNames()) | |||
1093 | AddBuiltinName(BuiltinName); | |||
1094 | ||||
1095 | // Add current attributes. | |||
1096 | if (AL.getNumArgs() == 0) | |||
1097 | AddBuiltinName(kWildcard); | |||
1098 | else | |||
1099 | for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { | |||
1100 | StringRef BuiltinName; | |||
1101 | SourceLocation LiteralLoc; | |||
1102 | if (!S.checkStringLiteralArgumentAttr(AL, I, BuiltinName, &LiteralLoc)) | |||
1103 | return; | |||
1104 | ||||
1105 | if (Builtin::Context::isBuiltinFunc(BuiltinName)) | |||
1106 | AddBuiltinName(BuiltinName); | |||
1107 | else | |||
1108 | S.Diag(LiteralLoc, diag::warn_attribute_no_builtin_invalid_builtin_name) | |||
1109 | << BuiltinName << AL; | |||
1110 | } | |||
1111 | ||||
1112 | // Repeating the same attribute is fine. | |||
1113 | llvm::sort(Names); | |||
1114 | Names.erase(std::unique(Names.begin(), Names.end()), Names.end()); | |||
1115 | ||||
1116 | // Empty no_builtin must be on its own. | |||
1117 | if (HasWildcard && Names.size() > 1) | |||
1118 | S.Diag(D->getLocation(), | |||
1119 | diag::err_attribute_no_builtin_wildcard_or_builtin_name) | |||
1120 | << AL; | |||
1121 | ||||
1122 | if (D->hasAttr<NoBuiltinAttr>()) | |||
1123 | D->dropAttr<NoBuiltinAttr>(); | |||
1124 | D->addAttr(::new (S.Context) | |||
1125 | NoBuiltinAttr(S.Context, AL, Names.data(), Names.size())); | |||
1126 | } | |||
1127 | ||||
1128 | static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1129 | if (D->hasAttr<PassObjectSizeAttr>()) { | |||
1130 | S.Diag(D->getBeginLoc(), diag::err_attribute_only_once_per_parameter) << AL; | |||
1131 | return; | |||
1132 | } | |||
1133 | ||||
1134 | Expr *E = AL.getArgAsExpr(0); | |||
1135 | uint32_t Type; | |||
1136 | if (!checkUInt32Argument(S, AL, E, Type, /*Idx=*/1)) | |||
1137 | return; | |||
1138 | ||||
1139 | // pass_object_size's argument is passed in as the second argument of | |||
1140 | // __builtin_object_size. So, it has the same constraints as that second | |||
1141 | // argument; namely, it must be in the range [0, 3]. | |||
1142 | if (Type > 3) { | |||
1143 | S.Diag(E->getBeginLoc(), diag::err_attribute_argument_out_of_range) | |||
1144 | << AL << 0 << 3 << E->getSourceRange(); | |||
1145 | return; | |||
1146 | } | |||
1147 | ||||
1148 | // pass_object_size is only supported on constant pointer parameters; as a | |||
1149 | // kindness to users, we allow the parameter to be non-const for declarations. | |||
1150 | // At this point, we have no clue if `D` belongs to a function declaration or | |||
1151 | // definition, so we defer the constness check until later. | |||
1152 | if (!cast<ParmVarDecl>(D)->getType()->isPointerType()) { | |||
1153 | S.Diag(D->getBeginLoc(), diag::err_attribute_pointers_only) << AL << 1; | |||
1154 | return; | |||
1155 | } | |||
1156 | ||||
1157 | D->addAttr(::new (S.Context) PassObjectSizeAttr(S.Context, AL, (int)Type)); | |||
1158 | } | |||
1159 | ||||
1160 | static void handleConsumableAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1161 | ConsumableAttr::ConsumedState DefaultState; | |||
1162 | ||||
1163 | if (AL.isArgIdent(0)) { | |||
1164 | IdentifierLoc *IL = AL.getArgAsIdent(0); | |||
1165 | if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(), | |||
1166 | DefaultState)) { | |||
1167 | S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL | |||
1168 | << IL->Ident; | |||
1169 | return; | |||
1170 | } | |||
1171 | } else { | |||
1172 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
1173 | << AL << AANT_ArgumentIdentifier; | |||
1174 | return; | |||
1175 | } | |||
1176 | ||||
1177 | D->addAttr(::new (S.Context) ConsumableAttr(S.Context, AL, DefaultState)); | |||
1178 | } | |||
1179 | ||||
1180 | static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, | |||
1181 | const ParsedAttr &AL) { | |||
1182 | QualType ThisType = MD->getThisType()->getPointeeType(); | |||
1183 | ||||
1184 | if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) { | |||
1185 | if (!RD->hasAttr<ConsumableAttr>()) { | |||
1186 | S.Diag(AL.getLoc(), diag::warn_attr_on_unconsumable_class) << RD; | |||
1187 | ||||
1188 | return false; | |||
1189 | } | |||
1190 | } | |||
1191 | ||||
1192 | return true; | |||
1193 | } | |||
1194 | ||||
1195 | static void handleCallableWhenAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1196 | if (!checkAttributeAtLeastNumArgs(S, AL, 1)) | |||
1197 | return; | |||
1198 | ||||
1199 | if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL)) | |||
1200 | return; | |||
1201 | ||||
1202 | SmallVector<CallableWhenAttr::ConsumedState, 3> States; | |||
1203 | for (unsigned ArgIndex = 0; ArgIndex < AL.getNumArgs(); ++ArgIndex) { | |||
1204 | CallableWhenAttr::ConsumedState CallableState; | |||
1205 | ||||
1206 | StringRef StateString; | |||
1207 | SourceLocation Loc; | |||
1208 | if (AL.isArgIdent(ArgIndex)) { | |||
1209 | IdentifierLoc *Ident = AL.getArgAsIdent(ArgIndex); | |||
1210 | StateString = Ident->Ident->getName(); | |||
1211 | Loc = Ident->Loc; | |||
1212 | } else { | |||
1213 | if (!S.checkStringLiteralArgumentAttr(AL, ArgIndex, StateString, &Loc)) | |||
1214 | return; | |||
1215 | } | |||
1216 | ||||
1217 | if (!CallableWhenAttr::ConvertStrToConsumedState(StateString, | |||
1218 | CallableState)) { | |||
1219 | S.Diag(Loc, diag::warn_attribute_type_not_supported) << AL << StateString; | |||
1220 | return; | |||
1221 | } | |||
1222 | ||||
1223 | States.push_back(CallableState); | |||
1224 | } | |||
1225 | ||||
1226 | D->addAttr(::new (S.Context) | |||
1227 | CallableWhenAttr(S.Context, AL, States.data(), States.size())); | |||
1228 | } | |||
1229 | ||||
1230 | static void handleParamTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1231 | ParamTypestateAttr::ConsumedState ParamState; | |||
1232 | ||||
1233 | if (AL.isArgIdent(0)) { | |||
1234 | IdentifierLoc *Ident = AL.getArgAsIdent(0); | |||
1235 | StringRef StateString = Ident->Ident->getName(); | |||
1236 | ||||
1237 | if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString, | |||
1238 | ParamState)) { | |||
1239 | S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) | |||
1240 | << AL << StateString; | |||
1241 | return; | |||
1242 | } | |||
1243 | } else { | |||
1244 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
1245 | << AL << AANT_ArgumentIdentifier; | |||
1246 | return; | |||
1247 | } | |||
1248 | ||||
1249 | // FIXME: This check is currently being done in the analysis. It can be | |||
1250 | // enabled here only after the parser propagates attributes at | |||
1251 | // template specialization definition, not declaration. | |||
1252 | //QualType ReturnType = cast<ParmVarDecl>(D)->getType(); | |||
1253 | //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); | |||
1254 | // | |||
1255 | //if (!RD || !RD->hasAttr<ConsumableAttr>()) { | |||
1256 | // S.Diag(AL.getLoc(), diag::warn_return_state_for_unconsumable_type) << | |||
1257 | // ReturnType.getAsString(); | |||
1258 | // return; | |||
1259 | //} | |||
1260 | ||||
1261 | D->addAttr(::new (S.Context) ParamTypestateAttr(S.Context, AL, ParamState)); | |||
1262 | } | |||
1263 | ||||
1264 | static void handleReturnTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1265 | ReturnTypestateAttr::ConsumedState ReturnState; | |||
1266 | ||||
1267 | if (AL.isArgIdent(0)) { | |||
1268 | IdentifierLoc *IL = AL.getArgAsIdent(0); | |||
1269 | if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(), | |||
1270 | ReturnState)) { | |||
1271 | S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL | |||
1272 | << IL->Ident; | |||
1273 | return; | |||
1274 | } | |||
1275 | } else { | |||
1276 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
1277 | << AL << AANT_ArgumentIdentifier; | |||
1278 | return; | |||
1279 | } | |||
1280 | ||||
1281 | // FIXME: This check is currently being done in the analysis. It can be | |||
1282 | // enabled here only after the parser propagates attributes at | |||
1283 | // template specialization definition, not declaration. | |||
1284 | //QualType ReturnType; | |||
1285 | // | |||
1286 | //if (const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D)) { | |||
1287 | // ReturnType = Param->getType(); | |||
1288 | // | |||
1289 | //} else if (const CXXConstructorDecl *Constructor = | |||
1290 | // dyn_cast<CXXConstructorDecl>(D)) { | |||
1291 | // ReturnType = Constructor->getThisType()->getPointeeType(); | |||
1292 | // | |||
1293 | //} else { | |||
1294 | // | |||
1295 | // ReturnType = cast<FunctionDecl>(D)->getCallResultType(); | |||
1296 | //} | |||
1297 | // | |||
1298 | //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); | |||
1299 | // | |||
1300 | //if (!RD || !RD->hasAttr<ConsumableAttr>()) { | |||
1301 | // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) << | |||
1302 | // ReturnType.getAsString(); | |||
1303 | // return; | |||
1304 | //} | |||
1305 | ||||
1306 | D->addAttr(::new (S.Context) ReturnTypestateAttr(S.Context, AL, ReturnState)); | |||
1307 | } | |||
1308 | ||||
1309 | static void handleSetTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1310 | if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL)) | |||
1311 | return; | |||
1312 | ||||
1313 | SetTypestateAttr::ConsumedState NewState; | |||
1314 | if (AL.isArgIdent(0)) { | |||
1315 | IdentifierLoc *Ident = AL.getArgAsIdent(0); | |||
1316 | StringRef Param = Ident->Ident->getName(); | |||
1317 | if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) { | |||
1318 | S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL | |||
1319 | << Param; | |||
1320 | return; | |||
1321 | } | |||
1322 | } else { | |||
1323 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
1324 | << AL << AANT_ArgumentIdentifier; | |||
1325 | return; | |||
1326 | } | |||
1327 | ||||
1328 | D->addAttr(::new (S.Context) SetTypestateAttr(S.Context, AL, NewState)); | |||
1329 | } | |||
1330 | ||||
1331 | static void handleTestTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1332 | if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL)) | |||
1333 | return; | |||
1334 | ||||
1335 | TestTypestateAttr::ConsumedState TestState; | |||
1336 | if (AL.isArgIdent(0)) { | |||
1337 | IdentifierLoc *Ident = AL.getArgAsIdent(0); | |||
1338 | StringRef Param = Ident->Ident->getName(); | |||
1339 | if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) { | |||
1340 | S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL | |||
1341 | << Param; | |||
1342 | return; | |||
1343 | } | |||
1344 | } else { | |||
1345 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
1346 | << AL << AANT_ArgumentIdentifier; | |||
1347 | return; | |||
1348 | } | |||
1349 | ||||
1350 | D->addAttr(::new (S.Context) TestTypestateAttr(S.Context, AL, TestState)); | |||
1351 | } | |||
1352 | ||||
1353 | static void handleExtVectorTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1354 | // Remember this typedef decl, we will need it later for diagnostics. | |||
1355 | S.ExtVectorDecls.push_back(cast<TypedefNameDecl>(D)); | |||
1356 | } | |||
1357 | ||||
1358 | static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1359 | if (auto *TD = dyn_cast<TagDecl>(D)) | |||
1360 | TD->addAttr(::new (S.Context) PackedAttr(S.Context, AL)); | |||
1361 | else if (auto *FD = dyn_cast<FieldDecl>(D)) { | |||
1362 | bool BitfieldByteAligned = (!FD->getType()->isDependentType() && | |||
1363 | !FD->getType()->isIncompleteType() && | |||
1364 | FD->isBitField() && | |||
1365 | S.Context.getTypeAlign(FD->getType()) <= 8); | |||
1366 | ||||
1367 | if (S.getASTContext().getTargetInfo().getTriple().isPS4()) { | |||
1368 | if (BitfieldByteAligned) | |||
1369 | // The PS4 target needs to maintain ABI backwards compatibility. | |||
1370 | S.Diag(AL.getLoc(), diag::warn_attribute_ignored_for_field_of_type) | |||
1371 | << AL << FD->getType(); | |||
1372 | else | |||
1373 | FD->addAttr(::new (S.Context) PackedAttr(S.Context, AL)); | |||
1374 | } else { | |||
1375 | // Report warning about changed offset in the newer compiler versions. | |||
1376 | if (BitfieldByteAligned) | |||
1377 | S.Diag(AL.getLoc(), diag::warn_attribute_packed_for_bitfield); | |||
1378 | ||||
1379 | FD->addAttr(::new (S.Context) PackedAttr(S.Context, AL)); | |||
1380 | } | |||
1381 | ||||
1382 | } else | |||
1383 | S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL; | |||
1384 | } | |||
1385 | ||||
1386 | static void handlePreferredName(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1387 | auto *RD = cast<CXXRecordDecl>(D); | |||
1388 | ClassTemplateDecl *CTD = RD->getDescribedClassTemplate(); | |||
1389 | assert(CTD && "attribute does not appertain to this declaration")((CTD && "attribute does not appertain to this declaration" ) ? static_cast<void> (0) : __assert_fail ("CTD && \"attribute does not appertain to this declaration\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 1389, __PRETTY_FUNCTION__)); | |||
1390 | ||||
1391 | ParsedType PT = AL.getTypeArg(); | |||
1392 | TypeSourceInfo *TSI = nullptr; | |||
1393 | QualType T = S.GetTypeFromParser(PT, &TSI); | |||
1394 | if (!TSI) | |||
1395 | TSI = S.Context.getTrivialTypeSourceInfo(T, AL.getLoc()); | |||
1396 | ||||
1397 | if (!T.hasQualifiers() && T->isTypedefNameType()) { | |||
1398 | // Find the template name, if this type names a template specialization. | |||
1399 | const TemplateDecl *Template = nullptr; | |||
1400 | if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>( | |||
1401 | T->getAsCXXRecordDecl())) { | |||
1402 | Template = CTSD->getSpecializedTemplate(); | |||
1403 | } else if (const auto *TST = T->getAs<TemplateSpecializationType>()) { | |||
1404 | while (TST && TST->isTypeAlias()) | |||
1405 | TST = TST->getAliasedType()->getAs<TemplateSpecializationType>(); | |||
1406 | if (TST) | |||
1407 | Template = TST->getTemplateName().getAsTemplateDecl(); | |||
1408 | } | |||
1409 | ||||
1410 | if (Template && declaresSameEntity(Template, CTD)) { | |||
1411 | D->addAttr(::new (S.Context) PreferredNameAttr(S.Context, AL, TSI)); | |||
1412 | return; | |||
1413 | } | |||
1414 | } | |||
1415 | ||||
1416 | S.Diag(AL.getLoc(), diag::err_attribute_preferred_name_arg_invalid) | |||
1417 | << T << CTD; | |||
1418 | if (const auto *TT = T->getAs<TypedefType>()) | |||
1419 | S.Diag(TT->getDecl()->getLocation(), diag::note_entity_declared_at) | |||
1420 | << TT->getDecl(); | |||
1421 | } | |||
1422 | ||||
1423 | static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1424 | // The IBOutlet/IBOutletCollection attributes only apply to instance | |||
1425 | // variables or properties of Objective-C classes. The outlet must also | |||
1426 | // have an object reference type. | |||
1427 | if (const auto *VD = dyn_cast<ObjCIvarDecl>(D)) { | |||
1428 | if (!VD->getType()->getAs<ObjCObjectPointerType>()) { | |||
1429 | S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type) | |||
1430 | << AL << VD->getType() << 0; | |||
1431 | return false; | |||
1432 | } | |||
1433 | } | |||
1434 | else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) { | |||
1435 | if (!PD->getType()->getAs<ObjCObjectPointerType>()) { | |||
1436 | S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type) | |||
1437 | << AL << PD->getType() << 1; | |||
1438 | return false; | |||
1439 | } | |||
1440 | } | |||
1441 | else { | |||
1442 | S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL; | |||
1443 | return false; | |||
1444 | } | |||
1445 | ||||
1446 | return true; | |||
1447 | } | |||
1448 | ||||
1449 | static void handleIBOutlet(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1450 | if (!checkIBOutletCommon(S, D, AL)) | |||
1451 | return; | |||
1452 | ||||
1453 | D->addAttr(::new (S.Context) IBOutletAttr(S.Context, AL)); | |||
1454 | } | |||
1455 | ||||
1456 | static void handleIBOutletCollection(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1457 | ||||
1458 | // The iboutletcollection attribute can have zero or one arguments. | |||
1459 | if (AL.getNumArgs() > 1) { | |||
1460 | S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; | |||
1461 | return; | |||
1462 | } | |||
1463 | ||||
1464 | if (!checkIBOutletCommon(S, D, AL)) | |||
1465 | return; | |||
1466 | ||||
1467 | ParsedType PT; | |||
1468 | ||||
1469 | if (AL.hasParsedType()) | |||
1470 | PT = AL.getTypeArg(); | |||
1471 | else { | |||
1472 | PT = S.getTypeName(S.Context.Idents.get("NSObject"), AL.getLoc(), | |||
1473 | S.getScopeForContext(D->getDeclContext()->getParent())); | |||
1474 | if (!PT) { | |||
1475 | S.Diag(AL.getLoc(), diag::err_iboutletcollection_type) << "NSObject"; | |||
1476 | return; | |||
1477 | } | |||
1478 | } | |||
1479 | ||||
1480 | TypeSourceInfo *QTLoc = nullptr; | |||
1481 | QualType QT = S.GetTypeFromParser(PT, &QTLoc); | |||
1482 | if (!QTLoc) | |||
1483 | QTLoc = S.Context.getTrivialTypeSourceInfo(QT, AL.getLoc()); | |||
1484 | ||||
1485 | // Diagnose use of non-object type in iboutletcollection attribute. | |||
1486 | // FIXME. Gnu attribute extension ignores use of builtin types in | |||
1487 | // attributes. So, __attribute__((iboutletcollection(char))) will be | |||
1488 | // treated as __attribute__((iboutletcollection())). | |||
1489 | if (!QT->isObjCIdType() && !QT->isObjCObjectType()) { | |||
1490 | S.Diag(AL.getLoc(), | |||
1491 | QT->isBuiltinType() ? diag::err_iboutletcollection_builtintype | |||
1492 | : diag::err_iboutletcollection_type) << QT; | |||
1493 | return; | |||
1494 | } | |||
1495 | ||||
1496 | D->addAttr(::new (S.Context) IBOutletCollectionAttr(S.Context, AL, QTLoc)); | |||
1497 | } | |||
1498 | ||||
1499 | bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) { | |||
1500 | if (RefOkay) { | |||
1501 | if (T->isReferenceType()) | |||
1502 | return true; | |||
1503 | } else { | |||
1504 | T = T.getNonReferenceType(); | |||
1505 | } | |||
1506 | ||||
1507 | // The nonnull attribute, and other similar attributes, can be applied to a | |||
1508 | // transparent union that contains a pointer type. | |||
1509 | if (const RecordType *UT = T->getAsUnionType()) { | |||
1510 | if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) { | |||
1511 | RecordDecl *UD = UT->getDecl(); | |||
1512 | for (const auto *I : UD->fields()) { | |||
1513 | QualType QT = I->getType(); | |||
1514 | if (QT->isAnyPointerType() || QT->isBlockPointerType()) | |||
1515 | return true; | |||
1516 | } | |||
1517 | } | |||
1518 | } | |||
1519 | ||||
1520 | return T->isAnyPointerType() || T->isBlockPointerType(); | |||
1521 | } | |||
1522 | ||||
1523 | static bool attrNonNullArgCheck(Sema &S, QualType T, const ParsedAttr &AL, | |||
1524 | SourceRange AttrParmRange, | |||
1525 | SourceRange TypeRange, | |||
1526 | bool isReturnValue = false) { | |||
1527 | if (!S.isValidPointerAttrType(T)) { | |||
1528 | if (isReturnValue) | |||
1529 | S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) | |||
1530 | << AL << AttrParmRange << TypeRange; | |||
1531 | else | |||
1532 | S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only) | |||
1533 | << AL << AttrParmRange << TypeRange << 0; | |||
1534 | return false; | |||
1535 | } | |||
1536 | return true; | |||
1537 | } | |||
1538 | ||||
1539 | static void handleNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1540 | SmallVector<ParamIdx, 8> NonNullArgs; | |||
1541 | for (unsigned I = 0; I < AL.getNumArgs(); ++I) { | |||
1542 | Expr *Ex = AL.getArgAsExpr(I); | |||
1543 | ParamIdx Idx; | |||
1544 | if (!checkFunctionOrMethodParameterIndex(S, D, AL, I + 1, Ex, Idx)) | |||
1545 | return; | |||
1546 | ||||
1547 | // Is the function argument a pointer type? | |||
1548 | if (Idx.getASTIndex() < getFunctionOrMethodNumParams(D) && | |||
1549 | !attrNonNullArgCheck( | |||
1550 | S, getFunctionOrMethodParamType(D, Idx.getASTIndex()), AL, | |||
1551 | Ex->getSourceRange(), | |||
1552 | getFunctionOrMethodParamRange(D, Idx.getASTIndex()))) | |||
1553 | continue; | |||
1554 | ||||
1555 | NonNullArgs.push_back(Idx); | |||
1556 | } | |||
1557 | ||||
1558 | // If no arguments were specified to __attribute__((nonnull)) then all pointer | |||
1559 | // arguments have a nonnull attribute; warn if there aren't any. Skip this | |||
1560 | // check if the attribute came from a macro expansion or a template | |||
1561 | // instantiation. | |||
1562 | if (NonNullArgs.empty() && AL.getLoc().isFileID() && | |||
1563 | !S.inTemplateInstantiation()) { | |||
1564 | bool AnyPointers = isFunctionOrMethodVariadic(D); | |||
1565 | for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); | |||
1566 | I != E && !AnyPointers; ++I) { | |||
1567 | QualType T = getFunctionOrMethodParamType(D, I); | |||
1568 | if (T->isDependentType() || S.isValidPointerAttrType(T)) | |||
1569 | AnyPointers = true; | |||
1570 | } | |||
1571 | ||||
1572 | if (!AnyPointers) | |||
1573 | S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_no_pointers); | |||
1574 | } | |||
1575 | ||||
1576 | ParamIdx *Start = NonNullArgs.data(); | |||
1577 | unsigned Size = NonNullArgs.size(); | |||
1578 | llvm::array_pod_sort(Start, Start + Size); | |||
1579 | D->addAttr(::new (S.Context) NonNullAttr(S.Context, AL, Start, Size)); | |||
1580 | } | |||
1581 | ||||
1582 | static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D, | |||
1583 | const ParsedAttr &AL) { | |||
1584 | if (AL.getNumArgs() > 0) { | |||
1585 | if (D->getFunctionType()) { | |||
1586 | handleNonNullAttr(S, D, AL); | |||
1587 | } else { | |||
1588 | S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_parm_no_args) | |||
1589 | << D->getSourceRange(); | |||
1590 | } | |||
1591 | return; | |||
1592 | } | |||
1593 | ||||
1594 | // Is the argument a pointer type? | |||
1595 | if (!attrNonNullArgCheck(S, D->getType(), AL, SourceRange(), | |||
1596 | D->getSourceRange())) | |||
1597 | return; | |||
1598 | ||||
1599 | D->addAttr(::new (S.Context) NonNullAttr(S.Context, AL, nullptr, 0)); | |||
1600 | } | |||
1601 | ||||
1602 | static void handleReturnsNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1603 | QualType ResultType = getFunctionOrMethodResultType(D); | |||
1604 | SourceRange SR = getFunctionOrMethodResultSourceRange(D); | |||
1605 | if (!attrNonNullArgCheck(S, ResultType, AL, SourceRange(), SR, | |||
1606 | /* isReturnValue */ true)) | |||
1607 | return; | |||
1608 | ||||
1609 | D->addAttr(::new (S.Context) ReturnsNonNullAttr(S.Context, AL)); | |||
1610 | } | |||
1611 | ||||
1612 | static void handleNoEscapeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1613 | if (D->isInvalidDecl()) | |||
1614 | return; | |||
1615 | ||||
1616 | // noescape only applies to pointer types. | |||
1617 | QualType T = cast<ParmVarDecl>(D)->getType(); | |||
1618 | if (!S.isValidPointerAttrType(T, /* RefOkay */ true)) { | |||
1619 | S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only) | |||
1620 | << AL << AL.getRange() << 0; | |||
1621 | return; | |||
1622 | } | |||
1623 | ||||
1624 | D->addAttr(::new (S.Context) NoEscapeAttr(S.Context, AL)); | |||
1625 | } | |||
1626 | ||||
1627 | static void handleAssumeAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1628 | Expr *E = AL.getArgAsExpr(0), | |||
1629 | *OE = AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr; | |||
1630 | S.AddAssumeAlignedAttr(D, AL, E, OE); | |||
1631 | } | |||
1632 | ||||
1633 | static void handleAllocAlignAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1634 | S.AddAllocAlignAttr(D, AL, AL.getArgAsExpr(0)); | |||
1635 | } | |||
1636 | ||||
1637 | void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, | |||
1638 | Expr *OE) { | |||
1639 | QualType ResultType = getFunctionOrMethodResultType(D); | |||
1640 | SourceRange SR = getFunctionOrMethodResultSourceRange(D); | |||
1641 | ||||
1642 | AssumeAlignedAttr TmpAttr(Context, CI, E, OE); | |||
1643 | SourceLocation AttrLoc = TmpAttr.getLocation(); | |||
1644 | ||||
1645 | if (!isValidPointerAttrType(ResultType, /* RefOkay */ true)) { | |||
1646 | Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only) | |||
1647 | << &TmpAttr << TmpAttr.getRange() << SR; | |||
1648 | return; | |||
1649 | } | |||
1650 | ||||
1651 | if (!E->isValueDependent()) { | |||
1652 | Optional<llvm::APSInt> I = llvm::APSInt(64); | |||
1653 | if (!(I = E->getIntegerConstantExpr(Context))) { | |||
1654 | if (OE) | |||
1655 | Diag(AttrLoc, diag::err_attribute_argument_n_type) | |||
1656 | << &TmpAttr << 1 << AANT_ArgumentIntegerConstant | |||
1657 | << E->getSourceRange(); | |||
1658 | else | |||
1659 | Diag(AttrLoc, diag::err_attribute_argument_type) | |||
1660 | << &TmpAttr << AANT_ArgumentIntegerConstant | |||
1661 | << E->getSourceRange(); | |||
1662 | return; | |||
1663 | } | |||
1664 | ||||
1665 | if (!I->isPowerOf2()) { | |||
1666 | Diag(AttrLoc, diag::err_alignment_not_power_of_two) | |||
1667 | << E->getSourceRange(); | |||
1668 | return; | |||
1669 | } | |||
1670 | ||||
1671 | if (*I > Sema::MaximumAlignment) | |||
1672 | Diag(CI.getLoc(), diag::warn_assume_aligned_too_great) | |||
1673 | << CI.getRange() << Sema::MaximumAlignment; | |||
1674 | } | |||
1675 | ||||
1676 | if (OE && !OE->isValueDependent() && !OE->isIntegerConstantExpr(Context)) { | |||
1677 | Diag(AttrLoc, diag::err_attribute_argument_n_type) | |||
1678 | << &TmpAttr << 2 << AANT_ArgumentIntegerConstant | |||
1679 | << OE->getSourceRange(); | |||
1680 | return; | |||
1681 | } | |||
1682 | ||||
1683 | D->addAttr(::new (Context) AssumeAlignedAttr(Context, CI, E, OE)); | |||
1684 | } | |||
1685 | ||||
1686 | void Sema::AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI, | |||
1687 | Expr *ParamExpr) { | |||
1688 | QualType ResultType = getFunctionOrMethodResultType(D); | |||
1689 | ||||
1690 | AllocAlignAttr TmpAttr(Context, CI, ParamIdx()); | |||
1691 | SourceLocation AttrLoc = CI.getLoc(); | |||
1692 | ||||
1693 | if (!ResultType->isDependentType() && | |||
1694 | !isValidPointerAttrType(ResultType, /* RefOkay */ true)) { | |||
1695 | Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only) | |||
1696 | << &TmpAttr << CI.getRange() << getFunctionOrMethodResultSourceRange(D); | |||
1697 | return; | |||
1698 | } | |||
1699 | ||||
1700 | ParamIdx Idx; | |||
1701 | const auto *FuncDecl = cast<FunctionDecl>(D); | |||
1702 | if (!checkFunctionOrMethodParameterIndex(*this, FuncDecl, TmpAttr, | |||
1703 | /*AttrArgNum=*/1, ParamExpr, Idx)) | |||
1704 | return; | |||
1705 | ||||
1706 | QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex()); | |||
1707 | if (!Ty->isDependentType() && !Ty->isIntegralType(Context) && | |||
1708 | !Ty->isAlignValT()) { | |||
1709 | Diag(ParamExpr->getBeginLoc(), diag::err_attribute_integers_only) | |||
1710 | << &TmpAttr | |||
1711 | << FuncDecl->getParamDecl(Idx.getASTIndex())->getSourceRange(); | |||
1712 | return; | |||
1713 | } | |||
1714 | ||||
1715 | D->addAttr(::new (Context) AllocAlignAttr(Context, CI, Idx)); | |||
1716 | } | |||
1717 | ||||
1718 | /// Check if \p AssumptionStr is a known assumption and warn if not. | |||
1719 | static void checkAssumptionAttr(Sema &S, SourceLocation Loc, | |||
1720 | StringRef AssumptionStr) { | |||
1721 | if (llvm::KnownAssumptionStrings.count(AssumptionStr)) | |||
1722 | return; | |||
1723 | ||||
1724 | unsigned BestEditDistance = 3; | |||
1725 | StringRef Suggestion; | |||
1726 | for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) { | |||
1727 | unsigned EditDistance = | |||
1728 | AssumptionStr.edit_distance(KnownAssumptionIt.getKey()); | |||
1729 | if (EditDistance < BestEditDistance) { | |||
1730 | Suggestion = KnownAssumptionIt.getKey(); | |||
1731 | BestEditDistance = EditDistance; | |||
1732 | } | |||
1733 | } | |||
1734 | ||||
1735 | if (!Suggestion.empty()) | |||
1736 | S.Diag(Loc, diag::warn_assume_attribute_string_unknown_suggested) | |||
1737 | << AssumptionStr << Suggestion; | |||
1738 | else | |||
1739 | S.Diag(Loc, diag::warn_assume_attribute_string_unknown) << AssumptionStr; | |||
1740 | } | |||
1741 | ||||
1742 | static void handleAssumumptionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1743 | // Handle the case where the attribute has a text message. | |||
1744 | StringRef Str; | |||
1745 | SourceLocation AttrStrLoc; | |||
1746 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc)) | |||
1747 | return; | |||
1748 | ||||
1749 | checkAssumptionAttr(S, AttrStrLoc, Str); | |||
1750 | ||||
1751 | D->addAttr(::new (S.Context) AssumptionAttr(S.Context, AL, Str)); | |||
1752 | } | |||
1753 | ||||
1754 | /// Normalize the attribute, __foo__ becomes foo. | |||
1755 | /// Returns true if normalization was applied. | |||
1756 | static bool normalizeName(StringRef &AttrName) { | |||
1757 | if (AttrName.size() > 4 && AttrName.startswith("__") && | |||
1758 | AttrName.endswith("__")) { | |||
1759 | AttrName = AttrName.drop_front(2).drop_back(2); | |||
1760 | return true; | |||
1761 | } | |||
1762 | return false; | |||
1763 | } | |||
1764 | ||||
1765 | static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1766 | // This attribute must be applied to a function declaration. The first | |||
1767 | // argument to the attribute must be an identifier, the name of the resource, | |||
1768 | // for example: malloc. The following arguments must be argument indexes, the | |||
1769 | // arguments must be of integer type for Returns, otherwise of pointer type. | |||
1770 | // The difference between Holds and Takes is that a pointer may still be used | |||
1771 | // after being held. free() should be __attribute((ownership_takes)), whereas | |||
1772 | // a list append function may well be __attribute((ownership_holds)). | |||
1773 | ||||
1774 | if (!AL.isArgIdent(0)) { | |||
1775 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
1776 | << AL << 1 << AANT_ArgumentIdentifier; | |||
1777 | return; | |||
1778 | } | |||
1779 | ||||
1780 | // Figure out our Kind. | |||
1781 | OwnershipAttr::OwnershipKind K = | |||
1782 | OwnershipAttr(S.Context, AL, nullptr, nullptr, 0).getOwnKind(); | |||
1783 | ||||
1784 | // Check arguments. | |||
1785 | switch (K) { | |||
1786 | case OwnershipAttr::Takes: | |||
1787 | case OwnershipAttr::Holds: | |||
1788 | if (AL.getNumArgs() < 2) { | |||
1789 | S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << AL << 2; | |||
1790 | return; | |||
1791 | } | |||
1792 | break; | |||
1793 | case OwnershipAttr::Returns: | |||
1794 | if (AL.getNumArgs() > 2) { | |||
1795 | S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1; | |||
1796 | return; | |||
1797 | } | |||
1798 | break; | |||
1799 | } | |||
1800 | ||||
1801 | IdentifierInfo *Module = AL.getArgAsIdent(0)->Ident; | |||
1802 | ||||
1803 | StringRef ModuleName = Module->getName(); | |||
1804 | if (normalizeName(ModuleName)) { | |||
1805 | Module = &S.PP.getIdentifierTable().get(ModuleName); | |||
1806 | } | |||
1807 | ||||
1808 | SmallVector<ParamIdx, 8> OwnershipArgs; | |||
1809 | for (unsigned i = 1; i < AL.getNumArgs(); ++i) { | |||
1810 | Expr *Ex = AL.getArgAsExpr(i); | |||
1811 | ParamIdx Idx; | |||
1812 | if (!checkFunctionOrMethodParameterIndex(S, D, AL, i, Ex, Idx)) | |||
1813 | return; | |||
1814 | ||||
1815 | // Is the function argument a pointer type? | |||
1816 | QualType T = getFunctionOrMethodParamType(D, Idx.getASTIndex()); | |||
1817 | int Err = -1; // No error | |||
1818 | switch (K) { | |||
1819 | case OwnershipAttr::Takes: | |||
1820 | case OwnershipAttr::Holds: | |||
1821 | if (!T->isAnyPointerType() && !T->isBlockPointerType()) | |||
1822 | Err = 0; | |||
1823 | break; | |||
1824 | case OwnershipAttr::Returns: | |||
1825 | if (!T->isIntegerType()) | |||
1826 | Err = 1; | |||
1827 | break; | |||
1828 | } | |||
1829 | if (-1 != Err) { | |||
1830 | S.Diag(AL.getLoc(), diag::err_ownership_type) << AL << Err | |||
1831 | << Ex->getSourceRange(); | |||
1832 | return; | |||
1833 | } | |||
1834 | ||||
1835 | // Check we don't have a conflict with another ownership attribute. | |||
1836 | for (const auto *I : D->specific_attrs<OwnershipAttr>()) { | |||
1837 | // Cannot have two ownership attributes of different kinds for the same | |||
1838 | // index. | |||
1839 | if (I->getOwnKind() != K && I->args_end() != | |||
1840 | std::find(I->args_begin(), I->args_end(), Idx)) { | |||
1841 | S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << I; | |||
1842 | return; | |||
1843 | } else if (K == OwnershipAttr::Returns && | |||
1844 | I->getOwnKind() == OwnershipAttr::Returns) { | |||
1845 | // A returns attribute conflicts with any other returns attribute using | |||
1846 | // a different index. | |||
1847 | if (std::find(I->args_begin(), I->args_end(), Idx) == I->args_end()) { | |||
1848 | S.Diag(I->getLocation(), diag::err_ownership_returns_index_mismatch) | |||
1849 | << I->args_begin()->getSourceIndex(); | |||
1850 | if (I->args_size()) | |||
1851 | S.Diag(AL.getLoc(), diag::note_ownership_returns_index_mismatch) | |||
1852 | << Idx.getSourceIndex() << Ex->getSourceRange(); | |||
1853 | return; | |||
1854 | } | |||
1855 | } | |||
1856 | } | |||
1857 | OwnershipArgs.push_back(Idx); | |||
1858 | } | |||
1859 | ||||
1860 | ParamIdx *Start = OwnershipArgs.data(); | |||
1861 | unsigned Size = OwnershipArgs.size(); | |||
1862 | llvm::array_pod_sort(Start, Start + Size); | |||
1863 | D->addAttr(::new (S.Context) | |||
1864 | OwnershipAttr(S.Context, AL, Module, Start, Size)); | |||
1865 | } | |||
1866 | ||||
1867 | static void handleWeakRefAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1868 | // Check the attribute arguments. | |||
1869 | if (AL.getNumArgs() > 1) { | |||
1870 | S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; | |||
1871 | return; | |||
1872 | } | |||
1873 | ||||
1874 | // gcc rejects | |||
1875 | // class c { | |||
1876 | // static int a __attribute__((weakref ("v2"))); | |||
1877 | // static int b() __attribute__((weakref ("f3"))); | |||
1878 | // }; | |||
1879 | // and ignores the attributes of | |||
1880 | // void f(void) { | |||
1881 | // static int a __attribute__((weakref ("v2"))); | |||
1882 | // } | |||
1883 | // we reject them | |||
1884 | const DeclContext *Ctx = D->getDeclContext()->getRedeclContext(); | |||
1885 | if (!Ctx->isFileContext()) { | |||
1886 | S.Diag(AL.getLoc(), diag::err_attribute_weakref_not_global_context) | |||
1887 | << cast<NamedDecl>(D); | |||
1888 | return; | |||
1889 | } | |||
1890 | ||||
1891 | // The GCC manual says | |||
1892 | // | |||
1893 | // At present, a declaration to which `weakref' is attached can only | |||
1894 | // be `static'. | |||
1895 | // | |||
1896 | // It also says | |||
1897 | // | |||
1898 | // Without a TARGET, | |||
1899 | // given as an argument to `weakref' or to `alias', `weakref' is | |||
1900 | // equivalent to `weak'. | |||
1901 | // | |||
1902 | // gcc 4.4.1 will accept | |||
1903 | // int a7 __attribute__((weakref)); | |||
1904 | // as | |||
1905 | // int a7 __attribute__((weak)); | |||
1906 | // This looks like a bug in gcc. We reject that for now. We should revisit | |||
1907 | // it if this behaviour is actually used. | |||
1908 | ||||
1909 | // GCC rejects | |||
1910 | // static ((alias ("y"), weakref)). | |||
1911 | // Should we? How to check that weakref is before or after alias? | |||
1912 | ||||
1913 | // FIXME: it would be good for us to keep the WeakRefAttr as-written instead | |||
1914 | // of transforming it into an AliasAttr. The WeakRefAttr never uses the | |||
1915 | // StringRef parameter it was given anyway. | |||
1916 | StringRef Str; | |||
1917 | if (AL.getNumArgs() && S.checkStringLiteralArgumentAttr(AL, 0, Str)) | |||
1918 | // GCC will accept anything as the argument of weakref. Should we | |||
1919 | // check for an existing decl? | |||
1920 | D->addAttr(::new (S.Context) AliasAttr(S.Context, AL, Str)); | |||
1921 | ||||
1922 | D->addAttr(::new (S.Context) WeakRefAttr(S.Context, AL)); | |||
1923 | } | |||
1924 | ||||
1925 | static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1926 | StringRef Str; | |||
1927 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) | |||
1928 | return; | |||
1929 | ||||
1930 | // Aliases should be on declarations, not definitions. | |||
1931 | const auto *FD = cast<FunctionDecl>(D); | |||
1932 | if (FD->isThisDeclarationADefinition()) { | |||
1933 | S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 1; | |||
1934 | return; | |||
1935 | } | |||
1936 | ||||
1937 | D->addAttr(::new (S.Context) IFuncAttr(S.Context, AL, Str)); | |||
1938 | } | |||
1939 | ||||
1940 | static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1941 | StringRef Str; | |||
1942 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) | |||
1943 | return; | |||
1944 | ||||
1945 | if (S.Context.getTargetInfo().getTriple().isOSDarwin()) { | |||
1946 | S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_darwin); | |||
1947 | return; | |||
1948 | } | |||
1949 | if (S.Context.getTargetInfo().getTriple().isNVPTX()) { | |||
1950 | S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_nvptx); | |||
1951 | } | |||
1952 | ||||
1953 | // Aliases should be on declarations, not definitions. | |||
1954 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
1955 | if (FD->isThisDeclarationADefinition()) { | |||
1956 | S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 0; | |||
1957 | return; | |||
1958 | } | |||
1959 | } else { | |||
1960 | const auto *VD = cast<VarDecl>(D); | |||
1961 | if (VD->isThisDeclarationADefinition() && VD->isExternallyVisible()) { | |||
1962 | S.Diag(AL.getLoc(), diag::err_alias_is_definition) << VD << 0; | |||
1963 | return; | |||
1964 | } | |||
1965 | } | |||
1966 | ||||
1967 | // Mark target used to prevent unneeded-internal-declaration warnings. | |||
1968 | if (!S.LangOpts.CPlusPlus) { | |||
1969 | // FIXME: demangle Str for C++, as the attribute refers to the mangled | |||
1970 | // linkage name, not the pre-mangled identifier. | |||
1971 | const DeclarationNameInfo target(&S.Context.Idents.get(Str), AL.getLoc()); | |||
1972 | LookupResult LR(S, target, Sema::LookupOrdinaryName); | |||
1973 | if (S.LookupQualifiedName(LR, S.getCurLexicalContext())) | |||
1974 | for (NamedDecl *ND : LR) | |||
1975 | ND->markUsed(S.Context); | |||
1976 | } | |||
1977 | ||||
1978 | D->addAttr(::new (S.Context) AliasAttr(S.Context, AL, Str)); | |||
1979 | } | |||
1980 | ||||
1981 | static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1982 | StringRef Model; | |||
1983 | SourceLocation LiteralLoc; | |||
1984 | // Check that it is a string. | |||
1985 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Model, &LiteralLoc)) | |||
1986 | return; | |||
1987 | ||||
1988 | // Check that the value. | |||
1989 | if (Model != "global-dynamic" && Model != "local-dynamic" | |||
1990 | && Model != "initial-exec" && Model != "local-exec") { | |||
1991 | S.Diag(LiteralLoc, diag::err_attr_tlsmodel_arg); | |||
1992 | return; | |||
1993 | } | |||
1994 | ||||
1995 | D->addAttr(::new (S.Context) TLSModelAttr(S.Context, AL, Model)); | |||
1996 | } | |||
1997 | ||||
1998 | static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1999 | QualType ResultType = getFunctionOrMethodResultType(D); | |||
2000 | if (ResultType->isAnyPointerType() || ResultType->isBlockPointerType()) { | |||
2001 | D->addAttr(::new (S.Context) RestrictAttr(S.Context, AL)); | |||
2002 | return; | |||
2003 | } | |||
2004 | ||||
2005 | S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) | |||
2006 | << AL << getFunctionOrMethodResultSourceRange(D); | |||
2007 | } | |||
2008 | ||||
2009 | static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2010 | FunctionDecl *FD = cast<FunctionDecl>(D); | |||
2011 | ||||
2012 | if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { | |||
2013 | if (MD->getParent()->isLambda()) { | |||
2014 | S.Diag(AL.getLoc(), diag::err_attribute_dll_lambda) << AL; | |||
2015 | return; | |||
2016 | } | |||
2017 | } | |||
2018 | ||||
2019 | if (!checkAttributeAtLeastNumArgs(S, AL, 1)) | |||
2020 | return; | |||
2021 | ||||
2022 | SmallVector<IdentifierInfo *, 8> CPUs; | |||
2023 | for (unsigned ArgNo = 0; ArgNo < getNumAttributeArgs(AL); ++ArgNo) { | |||
2024 | if (!AL.isArgIdent(ArgNo)) { | |||
2025 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
2026 | << AL << AANT_ArgumentIdentifier; | |||
2027 | return; | |||
2028 | } | |||
2029 | ||||
2030 | IdentifierLoc *CPUArg = AL.getArgAsIdent(ArgNo); | |||
2031 | StringRef CPUName = CPUArg->Ident->getName().trim(); | |||
2032 | ||||
2033 | if (!S.Context.getTargetInfo().validateCPUSpecificCPUDispatch(CPUName)) { | |||
2034 | S.Diag(CPUArg->Loc, diag::err_invalid_cpu_specific_dispatch_value) | |||
2035 | << CPUName << (AL.getKind() == ParsedAttr::AT_CPUDispatch); | |||
2036 | return; | |||
2037 | } | |||
2038 | ||||
2039 | const TargetInfo &Target = S.Context.getTargetInfo(); | |||
2040 | if (llvm::any_of(CPUs, [CPUName, &Target](const IdentifierInfo *Cur) { | |||
2041 | return Target.CPUSpecificManglingCharacter(CPUName) == | |||
2042 | Target.CPUSpecificManglingCharacter(Cur->getName()); | |||
2043 | })) { | |||
2044 | S.Diag(AL.getLoc(), diag::warn_multiversion_duplicate_entries); | |||
2045 | return; | |||
2046 | } | |||
2047 | CPUs.push_back(CPUArg->Ident); | |||
2048 | } | |||
2049 | ||||
2050 | FD->setIsMultiVersion(true); | |||
2051 | if (AL.getKind() == ParsedAttr::AT_CPUSpecific) | |||
2052 | D->addAttr(::new (S.Context) | |||
2053 | CPUSpecificAttr(S.Context, AL, CPUs.data(), CPUs.size())); | |||
2054 | else | |||
2055 | D->addAttr(::new (S.Context) | |||
2056 | CPUDispatchAttr(S.Context, AL, CPUs.data(), CPUs.size())); | |||
2057 | } | |||
2058 | ||||
2059 | static void handleCommonAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2060 | if (S.LangOpts.CPlusPlus) { | |||
2061 | S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) | |||
2062 | << AL << AttributeLangSupport::Cpp; | |||
2063 | return; | |||
2064 | } | |||
2065 | ||||
2066 | if (CommonAttr *CA = S.mergeCommonAttr(D, AL)) | |||
2067 | D->addAttr(CA); | |||
2068 | } | |||
2069 | ||||
2070 | static void handleCmseNSEntryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2071 | if (S.LangOpts.CPlusPlus && !D->getDeclContext()->isExternCContext()) { | |||
2072 | S.Diag(AL.getLoc(), diag::err_attribute_not_clinkage) << AL; | |||
2073 | return; | |||
2074 | } | |||
2075 | ||||
2076 | const auto *FD = cast<FunctionDecl>(D); | |||
2077 | if (!FD->isExternallyVisible()) { | |||
2078 | S.Diag(AL.getLoc(), diag::warn_attribute_cmse_entry_static); | |||
2079 | return; | |||
2080 | } | |||
2081 | ||||
2082 | D->addAttr(::new (S.Context) CmseNSEntryAttr(S.Context, AL)); | |||
2083 | } | |||
2084 | ||||
2085 | static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2086 | if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, AL)) | |||
2087 | return; | |||
2088 | ||||
2089 | if (AL.isDeclspecAttribute()) { | |||
2090 | const auto &Triple = S.getASTContext().getTargetInfo().getTriple(); | |||
2091 | const auto &Arch = Triple.getArch(); | |||
2092 | if (Arch != llvm::Triple::x86 && | |||
2093 | (Arch != llvm::Triple::arm && Arch != llvm::Triple::thumb)) { | |||
2094 | S.Diag(AL.getLoc(), diag::err_attribute_not_supported_on_arch) | |||
2095 | << AL << Triple.getArchName(); | |||
2096 | return; | |||
2097 | } | |||
2098 | } | |||
2099 | ||||
2100 | D->addAttr(::new (S.Context) NakedAttr(S.Context, AL)); | |||
2101 | } | |||
2102 | ||||
2103 | static void handleNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) { | |||
2104 | if (hasDeclarator(D)) return; | |||
2105 | ||||
2106 | if (!isa<ObjCMethodDecl>(D)) { | |||
2107 | S.Diag(Attrs.getLoc(), diag::warn_attribute_wrong_decl_type) | |||
2108 | << Attrs << ExpectedFunctionOrMethod; | |||
2109 | return; | |||
2110 | } | |||
2111 | ||||
2112 | D->addAttr(::new (S.Context) NoReturnAttr(S.Context, Attrs)); | |||
2113 | } | |||
2114 | ||||
2115 | static void handleNoCfCheckAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) { | |||
2116 | if (!S.getLangOpts().CFProtectionBranch) | |||
2117 | S.Diag(Attrs.getLoc(), diag::warn_nocf_check_attribute_ignored); | |||
2118 | else | |||
2119 | handleSimpleAttribute<AnyX86NoCfCheckAttr>(S, D, Attrs); | |||
2120 | } | |||
2121 | ||||
2122 | bool Sema::CheckAttrNoArgs(const ParsedAttr &Attrs) { | |||
2123 | if (!checkAttributeNumArgs(*this, Attrs, 0)) { | |||
2124 | Attrs.setInvalid(); | |||
2125 | return true; | |||
2126 | } | |||
2127 | ||||
2128 | return false; | |||
2129 | } | |||
2130 | ||||
2131 | bool Sema::CheckAttrTarget(const ParsedAttr &AL) { | |||
2132 | // Check whether the attribute is valid on the current target. | |||
2133 | if (!AL.existsInTarget(Context.getTargetInfo())) { | |||
2134 | Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) | |||
2135 | << AL << AL.getRange(); | |||
2136 | AL.setInvalid(); | |||
2137 | return true; | |||
2138 | } | |||
2139 | ||||
2140 | return false; | |||
2141 | } | |||
2142 | ||||
2143 | static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2144 | ||||
2145 | // The checking path for 'noreturn' and 'analyzer_noreturn' are different | |||
2146 | // because 'analyzer_noreturn' does not impact the type. | |||
2147 | if (!isFunctionOrMethodOrBlock(D)) { | |||
2148 | ValueDecl *VD = dyn_cast<ValueDecl>(D); | |||
2149 | if (!VD || (!VD->getType()->isBlockPointerType() && | |||
2150 | !VD->getType()->isFunctionPointerType())) { | |||
2151 | S.Diag(AL.getLoc(), AL.isCXX11Attribute() | |||
2152 | ? diag::err_attribute_wrong_decl_type | |||
2153 | : diag::warn_attribute_wrong_decl_type) | |||
2154 | << AL << ExpectedFunctionMethodOrBlock; | |||
2155 | return; | |||
2156 | } | |||
2157 | } | |||
2158 | ||||
2159 | D->addAttr(::new (S.Context) AnalyzerNoReturnAttr(S.Context, AL)); | |||
2160 | } | |||
2161 | ||||
2162 | // PS3 PPU-specific. | |||
2163 | static void handleVecReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2164 | /* | |||
2165 | Returning a Vector Class in Registers | |||
2166 | ||||
2167 | According to the PPU ABI specifications, a class with a single member of | |||
2168 | vector type is returned in memory when used as the return value of a | |||
2169 | function. | |||
2170 | This results in inefficient code when implementing vector classes. To return | |||
2171 | the value in a single vector register, add the vecreturn attribute to the | |||
2172 | class definition. This attribute is also applicable to struct types. | |||
2173 | ||||
2174 | Example: | |||
2175 | ||||
2176 | struct Vector | |||
2177 | { | |||
2178 | __vector float xyzw; | |||
2179 | } __attribute__((vecreturn)); | |||
2180 | ||||
2181 | Vector Add(Vector lhs, Vector rhs) | |||
2182 | { | |||
2183 | Vector result; | |||
2184 | result.xyzw = vec_add(lhs.xyzw, rhs.xyzw); | |||
2185 | return result; // This will be returned in a register | |||
2186 | } | |||
2187 | */ | |||
2188 | if (VecReturnAttr *A = D->getAttr<VecReturnAttr>()) { | |||
2189 | S.Diag(AL.getLoc(), diag::err_repeat_attribute) << A; | |||
2190 | return; | |||
2191 | } | |||
2192 | ||||
2193 | const auto *R = cast<RecordDecl>(D); | |||
2194 | int count = 0; | |||
2195 | ||||
2196 | if (!isa<CXXRecordDecl>(R)) { | |||
2197 | S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member); | |||
2198 | return; | |||
2199 | } | |||
2200 | ||||
2201 | if (!cast<CXXRecordDecl>(R)->isPOD()) { | |||
2202 | S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_pod_record); | |||
2203 | return; | |||
2204 | } | |||
2205 | ||||
2206 | for (const auto *I : R->fields()) { | |||
2207 | if ((count == 1) || !I->getType()->isVectorType()) { | |||
2208 | S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member); | |||
2209 | return; | |||
2210 | } | |||
2211 | count++; | |||
2212 | } | |||
2213 | ||||
2214 | D->addAttr(::new (S.Context) VecReturnAttr(S.Context, AL)); | |||
2215 | } | |||
2216 | ||||
2217 | static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, | |||
2218 | const ParsedAttr &AL) { | |||
2219 | if (isa<ParmVarDecl>(D)) { | |||
2220 | // [[carries_dependency]] can only be applied to a parameter if it is a | |||
2221 | // parameter of a function declaration or lambda. | |||
2222 | if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) { | |||
2223 | S.Diag(AL.getLoc(), | |||
2224 | diag::err_carries_dependency_param_not_function_decl); | |||
2225 | return; | |||
2226 | } | |||
2227 | } | |||
2228 | ||||
2229 | D->addAttr(::new (S.Context) CarriesDependencyAttr(S.Context, AL)); | |||
2230 | } | |||
2231 | ||||
2232 | static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2233 | bool IsCXX17Attr = AL.isCXX11Attribute() && !AL.getScopeName(); | |||
2234 | ||||
2235 | // If this is spelled as the standard C++17 attribute, but not in C++17, warn | |||
2236 | // about using it as an extension. | |||
2237 | if (!S.getLangOpts().CPlusPlus17 && IsCXX17Attr) | |||
2238 | S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL; | |||
2239 | ||||
2240 | D->addAttr(::new (S.Context) UnusedAttr(S.Context, AL)); | |||
2241 | } | |||
2242 | ||||
2243 | static void handleConstructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2244 | uint32_t priority = ConstructorAttr::DefaultPriority; | |||
2245 | if (AL.getNumArgs() && | |||
2246 | !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority)) | |||
2247 | return; | |||
2248 | ||||
2249 | D->addAttr(::new (S.Context) ConstructorAttr(S.Context, AL, priority)); | |||
2250 | } | |||
2251 | ||||
2252 | static void handleDestructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2253 | uint32_t priority = DestructorAttr::DefaultPriority; | |||
2254 | if (AL.getNumArgs() && | |||
2255 | !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority)) | |||
2256 | return; | |||
2257 | ||||
2258 | D->addAttr(::new (S.Context) DestructorAttr(S.Context, AL, priority)); | |||
2259 | } | |||
2260 | ||||
2261 | template <typename AttrTy> | |||
2262 | static void handleAttrWithMessage(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2263 | // Handle the case where the attribute has a text message. | |||
2264 | StringRef Str; | |||
2265 | if (AL.getNumArgs() == 1 && !S.checkStringLiteralArgumentAttr(AL, 0, Str)) | |||
2266 | return; | |||
2267 | ||||
2268 | D->addAttr(::new (S.Context) AttrTy(S.Context, AL, Str)); | |||
2269 | } | |||
2270 | ||||
2271 | static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D, | |||
2272 | const ParsedAttr &AL) { | |||
2273 | if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) { | |||
2274 | S.Diag(AL.getLoc(), diag::err_objc_attr_protocol_requires_definition) | |||
2275 | << AL << AL.getRange(); | |||
2276 | return; | |||
2277 | } | |||
2278 | ||||
2279 | D->addAttr(::new (S.Context) ObjCExplicitProtocolImplAttr(S.Context, AL)); | |||
2280 | } | |||
2281 | ||||
2282 | static bool checkAvailabilityAttr(Sema &S, SourceRange Range, | |||
2283 | IdentifierInfo *Platform, | |||
2284 | VersionTuple Introduced, | |||
2285 | VersionTuple Deprecated, | |||
2286 | VersionTuple Obsoleted) { | |||
2287 | StringRef PlatformName | |||
2288 | = AvailabilityAttr::getPrettyPlatformName(Platform->getName()); | |||
2289 | if (PlatformName.empty()) | |||
2290 | PlatformName = Platform->getName(); | |||
2291 | ||||
2292 | // Ensure that Introduced <= Deprecated <= Obsoleted (although not all | |||
2293 | // of these steps are needed). | |||
2294 | if (!Introduced.empty() && !Deprecated.empty() && | |||
2295 | !(Introduced <= Deprecated)) { | |||
2296 | S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) | |||
2297 | << 1 << PlatformName << Deprecated.getAsString() | |||
2298 | << 0 << Introduced.getAsString(); | |||
2299 | return true; | |||
2300 | } | |||
2301 | ||||
2302 | if (!Introduced.empty() && !Obsoleted.empty() && | |||
2303 | !(Introduced <= Obsoleted)) { | |||
2304 | S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) | |||
2305 | << 2 << PlatformName << Obsoleted.getAsString() | |||
2306 | << 0 << Introduced.getAsString(); | |||
2307 | return true; | |||
2308 | } | |||
2309 | ||||
2310 | if (!Deprecated.empty() && !Obsoleted.empty() && | |||
2311 | !(Deprecated <= Obsoleted)) { | |||
2312 | S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) | |||
2313 | << 2 << PlatformName << Obsoleted.getAsString() | |||
2314 | << 1 << Deprecated.getAsString(); | |||
2315 | return true; | |||
2316 | } | |||
2317 | ||||
2318 | return false; | |||
2319 | } | |||
2320 | ||||
2321 | /// Check whether the two versions match. | |||
2322 | /// | |||
2323 | /// If either version tuple is empty, then they are assumed to match. If | |||
2324 | /// \p BeforeIsOkay is true, then \p X can be less than or equal to \p Y. | |||
2325 | static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y, | |||
2326 | bool BeforeIsOkay) { | |||
2327 | if (X.empty() || Y.empty()) | |||
2328 | return true; | |||
2329 | ||||
2330 | if (X == Y) | |||
2331 | return true; | |||
2332 | ||||
2333 | if (BeforeIsOkay && X < Y) | |||
2334 | return true; | |||
2335 | ||||
2336 | return false; | |||
2337 | } | |||
2338 | ||||
2339 | AvailabilityAttr *Sema::mergeAvailabilityAttr( | |||
2340 | NamedDecl *D, const AttributeCommonInfo &CI, IdentifierInfo *Platform, | |||
2341 | bool Implicit, VersionTuple Introduced, VersionTuple Deprecated, | |||
2342 | VersionTuple Obsoleted, bool IsUnavailable, StringRef Message, | |||
2343 | bool IsStrict, StringRef Replacement, AvailabilityMergeKind AMK, | |||
2344 | int Priority) { | |||
2345 | VersionTuple MergedIntroduced = Introduced; | |||
2346 | VersionTuple MergedDeprecated = Deprecated; | |||
2347 | VersionTuple MergedObsoleted = Obsoleted; | |||
2348 | bool FoundAny = false; | |||
2349 | bool OverrideOrImpl = false; | |||
2350 | switch (AMK) { | |||
2351 | case AMK_None: | |||
2352 | case AMK_Redeclaration: | |||
2353 | OverrideOrImpl = false; | |||
2354 | break; | |||
2355 | ||||
2356 | case AMK_Override: | |||
2357 | case AMK_ProtocolImplementation: | |||
2358 | OverrideOrImpl = true; | |||
2359 | break; | |||
2360 | } | |||
2361 | ||||
2362 | if (D->hasAttrs()) { | |||
2363 | AttrVec &Attrs = D->getAttrs(); | |||
2364 | for (unsigned i = 0, e = Attrs.size(); i != e;) { | |||
2365 | const auto *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]); | |||
2366 | if (!OldAA) { | |||
2367 | ++i; | |||
2368 | continue; | |||
2369 | } | |||
2370 | ||||
2371 | IdentifierInfo *OldPlatform = OldAA->getPlatform(); | |||
2372 | if (OldPlatform != Platform) { | |||
2373 | ++i; | |||
2374 | continue; | |||
2375 | } | |||
2376 | ||||
2377 | // If there is an existing availability attribute for this platform that | |||
2378 | // has a lower priority use the existing one and discard the new | |||
2379 | // attribute. | |||
2380 | if (OldAA->getPriority() < Priority) | |||
2381 | return nullptr; | |||
2382 | ||||
2383 | // If there is an existing attribute for this platform that has a higher | |||
2384 | // priority than the new attribute then erase the old one and continue | |||
2385 | // processing the attributes. | |||
2386 | if (OldAA->getPriority() > Priority) { | |||
2387 | Attrs.erase(Attrs.begin() + i); | |||
2388 | --e; | |||
2389 | continue; | |||
2390 | } | |||
2391 | ||||
2392 | FoundAny = true; | |||
2393 | VersionTuple OldIntroduced = OldAA->getIntroduced(); | |||
2394 | VersionTuple OldDeprecated = OldAA->getDeprecated(); | |||
2395 | VersionTuple OldObsoleted = OldAA->getObsoleted(); | |||
2396 | bool OldIsUnavailable = OldAA->getUnavailable(); | |||
2397 | ||||
2398 | if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl) || | |||
2399 | !versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl) || | |||
2400 | !versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl) || | |||
2401 | !(OldIsUnavailable == IsUnavailable || | |||
2402 | (OverrideOrImpl && !OldIsUnavailable && IsUnavailable))) { | |||
2403 | if (OverrideOrImpl) { | |||
2404 | int Which = -1; | |||
2405 | VersionTuple FirstVersion; | |||
2406 | VersionTuple SecondVersion; | |||
2407 | if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl)) { | |||
2408 | Which = 0; | |||
2409 | FirstVersion = OldIntroduced; | |||
2410 | SecondVersion = Introduced; | |||
2411 | } else if (!versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl)) { | |||
2412 | Which = 1; | |||
2413 | FirstVersion = Deprecated; | |||
2414 | SecondVersion = OldDeprecated; | |||
2415 | } else if (!versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl)) { | |||
2416 | Which = 2; | |||
2417 | FirstVersion = Obsoleted; | |||
2418 | SecondVersion = OldObsoleted; | |||
2419 | } | |||
2420 | ||||
2421 | if (Which == -1) { | |||
2422 | Diag(OldAA->getLocation(), | |||
2423 | diag::warn_mismatched_availability_override_unavail) | |||
2424 | << AvailabilityAttr::getPrettyPlatformName(Platform->getName()) | |||
2425 | << (AMK == AMK_Override); | |||
2426 | } else { | |||
2427 | Diag(OldAA->getLocation(), | |||
2428 | diag::warn_mismatched_availability_override) | |||
2429 | << Which | |||
2430 | << AvailabilityAttr::getPrettyPlatformName(Platform->getName()) | |||
2431 | << FirstVersion.getAsString() << SecondVersion.getAsString() | |||
2432 | << (AMK == AMK_Override); | |||
2433 | } | |||
2434 | if (AMK == AMK_Override) | |||
2435 | Diag(CI.getLoc(), diag::note_overridden_method); | |||
2436 | else | |||
2437 | Diag(CI.getLoc(), diag::note_protocol_method); | |||
2438 | } else { | |||
2439 | Diag(OldAA->getLocation(), diag::warn_mismatched_availability); | |||
2440 | Diag(CI.getLoc(), diag::note_previous_attribute); | |||
2441 | } | |||
2442 | ||||
2443 | Attrs.erase(Attrs.begin() + i); | |||
2444 | --e; | |||
2445 | continue; | |||
2446 | } | |||
2447 | ||||
2448 | VersionTuple MergedIntroduced2 = MergedIntroduced; | |||
2449 | VersionTuple MergedDeprecated2 = MergedDeprecated; | |||
2450 | VersionTuple MergedObsoleted2 = MergedObsoleted; | |||
2451 | ||||
2452 | if (MergedIntroduced2.empty()) | |||
2453 | MergedIntroduced2 = OldIntroduced; | |||
2454 | if (MergedDeprecated2.empty()) | |||
2455 | MergedDeprecated2 = OldDeprecated; | |||
2456 | if (MergedObsoleted2.empty()) | |||
2457 | MergedObsoleted2 = OldObsoleted; | |||
2458 | ||||
2459 | if (checkAvailabilityAttr(*this, OldAA->getRange(), Platform, | |||
2460 | MergedIntroduced2, MergedDeprecated2, | |||
2461 | MergedObsoleted2)) { | |||
2462 | Attrs.erase(Attrs.begin() + i); | |||
2463 | --e; | |||
2464 | continue; | |||
2465 | } | |||
2466 | ||||
2467 | MergedIntroduced = MergedIntroduced2; | |||
2468 | MergedDeprecated = MergedDeprecated2; | |||
2469 | MergedObsoleted = MergedObsoleted2; | |||
2470 | ++i; | |||
2471 | } | |||
2472 | } | |||
2473 | ||||
2474 | if (FoundAny && | |||
2475 | MergedIntroduced == Introduced && | |||
2476 | MergedDeprecated == Deprecated && | |||
2477 | MergedObsoleted == Obsoleted) | |||
2478 | return nullptr; | |||
2479 | ||||
2480 | // Only create a new attribute if !OverrideOrImpl, but we want to do | |||
2481 | // the checking. | |||
2482 | if (!checkAvailabilityAttr(*this, CI.getRange(), Platform, MergedIntroduced, | |||
2483 | MergedDeprecated, MergedObsoleted) && | |||
2484 | !OverrideOrImpl) { | |||
2485 | auto *Avail = ::new (Context) AvailabilityAttr( | |||
2486 | Context, CI, Platform, Introduced, Deprecated, Obsoleted, IsUnavailable, | |||
2487 | Message, IsStrict, Replacement, Priority); | |||
2488 | Avail->setImplicit(Implicit); | |||
2489 | return Avail; | |||
2490 | } | |||
2491 | return nullptr; | |||
2492 | } | |||
2493 | ||||
2494 | static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2495 | if (!checkAttributeNumArgs(S, AL, 1)) | |||
2496 | return; | |||
2497 | IdentifierLoc *Platform = AL.getArgAsIdent(0); | |||
2498 | ||||
2499 | IdentifierInfo *II = Platform->Ident; | |||
2500 | if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty()) | |||
2501 | S.Diag(Platform->Loc, diag::warn_availability_unknown_platform) | |||
2502 | << Platform->Ident; | |||
2503 | ||||
2504 | auto *ND = dyn_cast<NamedDecl>(D); | |||
2505 | if (!ND) // We warned about this already, so just return. | |||
2506 | return; | |||
2507 | ||||
2508 | AvailabilityChange Introduced = AL.getAvailabilityIntroduced(); | |||
2509 | AvailabilityChange Deprecated = AL.getAvailabilityDeprecated(); | |||
2510 | AvailabilityChange Obsoleted = AL.getAvailabilityObsoleted(); | |||
2511 | bool IsUnavailable = AL.getUnavailableLoc().isValid(); | |||
2512 | bool IsStrict = AL.getStrictLoc().isValid(); | |||
2513 | StringRef Str; | |||
2514 | if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getMessageExpr())) | |||
2515 | Str = SE->getString(); | |||
2516 | StringRef Replacement; | |||
2517 | if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getReplacementExpr())) | |||
2518 | Replacement = SE->getString(); | |||
2519 | ||||
2520 | if (II->isStr("swift")) { | |||
2521 | if (Introduced.isValid() || Obsoleted.isValid() || | |||
2522 | (!IsUnavailable && !Deprecated.isValid())) { | |||
2523 | S.Diag(AL.getLoc(), | |||
2524 | diag::warn_availability_swift_unavailable_deprecated_only); | |||
2525 | return; | |||
2526 | } | |||
2527 | } | |||
2528 | ||||
2529 | int PriorityModifier = AL.isPragmaClangAttribute() | |||
2530 | ? Sema::AP_PragmaClangAttribute | |||
2531 | : Sema::AP_Explicit; | |||
2532 | AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( | |||
2533 | ND, AL, II, false /*Implicit*/, Introduced.Version, Deprecated.Version, | |||
2534 | Obsoleted.Version, IsUnavailable, Str, IsStrict, Replacement, | |||
2535 | Sema::AMK_None, PriorityModifier); | |||
2536 | if (NewAttr) | |||
2537 | D->addAttr(NewAttr); | |||
2538 | ||||
2539 | // Transcribe "ios" to "watchos" (and add a new attribute) if the versioning | |||
2540 | // matches before the start of the watchOS platform. | |||
2541 | if (S.Context.getTargetInfo().getTriple().isWatchOS()) { | |||
2542 | IdentifierInfo *NewII = nullptr; | |||
2543 | if (II->getName() == "ios") | |||
2544 | NewII = &S.Context.Idents.get("watchos"); | |||
2545 | else if (II->getName() == "ios_app_extension") | |||
2546 | NewII = &S.Context.Idents.get("watchos_app_extension"); | |||
2547 | ||||
2548 | if (NewII) { | |||
2549 | auto adjustWatchOSVersion = [](VersionTuple Version) -> VersionTuple { | |||
2550 | if (Version.empty()) | |||
2551 | return Version; | |||
2552 | auto Major = Version.getMajor(); | |||
2553 | auto NewMajor = Major >= 9 ? Major - 7 : 0; | |||
2554 | if (NewMajor >= 2) { | |||
2555 | if (Version.getMinor().hasValue()) { | |||
2556 | if (Version.getSubminor().hasValue()) | |||
2557 | return VersionTuple(NewMajor, Version.getMinor().getValue(), | |||
2558 | Version.getSubminor().getValue()); | |||
2559 | else | |||
2560 | return VersionTuple(NewMajor, Version.getMinor().getValue()); | |||
2561 | } | |||
2562 | return VersionTuple(NewMajor); | |||
2563 | } | |||
2564 | ||||
2565 | return VersionTuple(2, 0); | |||
2566 | }; | |||
2567 | ||||
2568 | auto NewIntroduced = adjustWatchOSVersion(Introduced.Version); | |||
2569 | auto NewDeprecated = adjustWatchOSVersion(Deprecated.Version); | |||
2570 | auto NewObsoleted = adjustWatchOSVersion(Obsoleted.Version); | |||
2571 | ||||
2572 | AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( | |||
2573 | ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated, | |||
2574 | NewObsoleted, IsUnavailable, Str, IsStrict, Replacement, | |||
2575 | Sema::AMK_None, | |||
2576 | PriorityModifier + Sema::AP_InferredFromOtherPlatform); | |||
2577 | if (NewAttr) | |||
2578 | D->addAttr(NewAttr); | |||
2579 | } | |||
2580 | } else if (S.Context.getTargetInfo().getTriple().isTvOS()) { | |||
2581 | // Transcribe "ios" to "tvos" (and add a new attribute) if the versioning | |||
2582 | // matches before the start of the tvOS platform. | |||
2583 | IdentifierInfo *NewII = nullptr; | |||
2584 | if (II->getName() == "ios") | |||
2585 | NewII = &S.Context.Idents.get("tvos"); | |||
2586 | else if (II->getName() == "ios_app_extension") | |||
2587 | NewII = &S.Context.Idents.get("tvos_app_extension"); | |||
2588 | ||||
2589 | if (NewII) { | |||
2590 | AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( | |||
2591 | ND, AL, NewII, true /*Implicit*/, Introduced.Version, | |||
2592 | Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, IsStrict, | |||
2593 | Replacement, Sema::AMK_None, | |||
2594 | PriorityModifier + Sema::AP_InferredFromOtherPlatform); | |||
2595 | if (NewAttr) | |||
2596 | D->addAttr(NewAttr); | |||
2597 | } | |||
2598 | } | |||
2599 | } | |||
2600 | ||||
2601 | static void handleExternalSourceSymbolAttr(Sema &S, Decl *D, | |||
2602 | const ParsedAttr &AL) { | |||
2603 | if (!checkAttributeAtLeastNumArgs(S, AL, 1)) | |||
2604 | return; | |||
2605 | assert(checkAttributeAtMostNumArgs(S, AL, 3) &&((checkAttributeAtMostNumArgs(S, AL, 3) && "Invalid number of arguments in an external_source_symbol attribute" ) ? static_cast<void> (0) : __assert_fail ("checkAttributeAtMostNumArgs(S, AL, 3) && \"Invalid number of arguments in an external_source_symbol attribute\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 2606, __PRETTY_FUNCTION__)) | |||
2606 | "Invalid number of arguments in an external_source_symbol attribute")((checkAttributeAtMostNumArgs(S, AL, 3) && "Invalid number of arguments in an external_source_symbol attribute" ) ? static_cast<void> (0) : __assert_fail ("checkAttributeAtMostNumArgs(S, AL, 3) && \"Invalid number of arguments in an external_source_symbol attribute\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 2606, __PRETTY_FUNCTION__)); | |||
2607 | ||||
2608 | StringRef Language; | |||
2609 | if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(0))) | |||
2610 | Language = SE->getString(); | |||
2611 | StringRef DefinedIn; | |||
2612 | if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(1))) | |||
2613 | DefinedIn = SE->getString(); | |||
2614 | bool IsGeneratedDeclaration = AL.getArgAsIdent(2) != nullptr; | |||
2615 | ||||
2616 | D->addAttr(::new (S.Context) ExternalSourceSymbolAttr( | |||
2617 | S.Context, AL, Language, DefinedIn, IsGeneratedDeclaration)); | |||
2618 | } | |||
2619 | ||||
2620 | template <class T> | |||
2621 | static T *mergeVisibilityAttr(Sema &S, Decl *D, const AttributeCommonInfo &CI, | |||
2622 | typename T::VisibilityType value) { | |||
2623 | T *existingAttr = D->getAttr<T>(); | |||
2624 | if (existingAttr) { | |||
2625 | typename T::VisibilityType existingValue = existingAttr->getVisibility(); | |||
2626 | if (existingValue == value) | |||
2627 | return nullptr; | |||
2628 | S.Diag(existingAttr->getLocation(), diag::err_mismatched_visibility); | |||
2629 | S.Diag(CI.getLoc(), diag::note_previous_attribute); | |||
2630 | D->dropAttr<T>(); | |||
2631 | } | |||
2632 | return ::new (S.Context) T(S.Context, CI, value); | |||
2633 | } | |||
2634 | ||||
2635 | VisibilityAttr *Sema::mergeVisibilityAttr(Decl *D, | |||
2636 | const AttributeCommonInfo &CI, | |||
2637 | VisibilityAttr::VisibilityType Vis) { | |||
2638 | return ::mergeVisibilityAttr<VisibilityAttr>(*this, D, CI, Vis); | |||
2639 | } | |||
2640 | ||||
2641 | TypeVisibilityAttr * | |||
2642 | Sema::mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI, | |||
2643 | TypeVisibilityAttr::VisibilityType Vis) { | |||
2644 | return ::mergeVisibilityAttr<TypeVisibilityAttr>(*this, D, CI, Vis); | |||
2645 | } | |||
2646 | ||||
2647 | static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL, | |||
2648 | bool isTypeVisibility) { | |||
2649 | // Visibility attributes don't mean anything on a typedef. | |||
2650 | if (isa<TypedefNameDecl>(D)) { | |||
2651 | S.Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored) << AL; | |||
2652 | return; | |||
2653 | } | |||
2654 | ||||
2655 | // 'type_visibility' can only go on a type or namespace. | |||
2656 | if (isTypeVisibility && | |||
2657 | !(isa<TagDecl>(D) || | |||
2658 | isa<ObjCInterfaceDecl>(D) || | |||
2659 | isa<NamespaceDecl>(D))) { | |||
2660 | S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type) | |||
2661 | << AL << ExpectedTypeOrNamespace; | |||
2662 | return; | |||
2663 | } | |||
2664 | ||||
2665 | // Check that the argument is a string literal. | |||
2666 | StringRef TypeStr; | |||
2667 | SourceLocation LiteralLoc; | |||
2668 | if (!S.checkStringLiteralArgumentAttr(AL, 0, TypeStr, &LiteralLoc)) | |||
2669 | return; | |||
2670 | ||||
2671 | VisibilityAttr::VisibilityType type; | |||
2672 | if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) { | |||
2673 | S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) << AL | |||
2674 | << TypeStr; | |||
2675 | return; | |||
2676 | } | |||
2677 | ||||
2678 | // Complain about attempts to use protected visibility on targets | |||
2679 | // (like Darwin) that don't support it. | |||
2680 | if (type == VisibilityAttr::Protected && | |||
2681 | !S.Context.getTargetInfo().hasProtectedVisibility()) { | |||
2682 | S.Diag(AL.getLoc(), diag::warn_attribute_protected_visibility); | |||
2683 | type = VisibilityAttr::Default; | |||
2684 | } | |||
2685 | ||||
2686 | Attr *newAttr; | |||
2687 | if (isTypeVisibility) { | |||
2688 | newAttr = S.mergeTypeVisibilityAttr( | |||
2689 | D, AL, (TypeVisibilityAttr::VisibilityType)type); | |||
2690 | } else { | |||
2691 | newAttr = S.mergeVisibilityAttr(D, AL, type); | |||
2692 | } | |||
2693 | if (newAttr) | |||
2694 | D->addAttr(newAttr); | |||
2695 | } | |||
2696 | ||||
2697 | static void handleObjCNonRuntimeProtocolAttr(Sema &S, Decl *D, | |||
2698 | const ParsedAttr &AL) { | |||
2699 | handleSimpleAttribute<ObjCNonRuntimeProtocolAttr>(S, D, AL); | |||
2700 | } | |||
2701 | ||||
2702 | static void handleObjCDirectAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2703 | // objc_direct cannot be set on methods declared in the context of a protocol | |||
2704 | if (isa<ObjCProtocolDecl>(D->getDeclContext())) { | |||
2705 | S.Diag(AL.getLoc(), diag::err_objc_direct_on_protocol) << false; | |||
2706 | return; | |||
2707 | } | |||
2708 | ||||
2709 | if (S.getLangOpts().ObjCRuntime.allowsDirectDispatch()) { | |||
2710 | handleSimpleAttribute<ObjCDirectAttr>(S, D, AL); | |||
2711 | } else { | |||
2712 | S.Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL; | |||
2713 | } | |||
2714 | } | |||
2715 | ||||
2716 | static void handleObjCDirectMembersAttr(Sema &S, Decl *D, | |||
2717 | const ParsedAttr &AL) { | |||
2718 | if (S.getLangOpts().ObjCRuntime.allowsDirectDispatch()) { | |||
2719 | handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL); | |||
2720 | } else { | |||
2721 | S.Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL; | |||
2722 | } | |||
2723 | } | |||
2724 | ||||
2725 | static void handleObjCMethodFamilyAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2726 | const auto *M = cast<ObjCMethodDecl>(D); | |||
2727 | if (!AL.isArgIdent(0)) { | |||
2728 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
2729 | << AL << 1 << AANT_ArgumentIdentifier; | |||
2730 | return; | |||
2731 | } | |||
2732 | ||||
2733 | IdentifierLoc *IL = AL.getArgAsIdent(0); | |||
2734 | ObjCMethodFamilyAttr::FamilyKind F; | |||
2735 | if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) { | |||
2736 | S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL << IL->Ident; | |||
2737 | return; | |||
2738 | } | |||
2739 | ||||
2740 | if (F == ObjCMethodFamilyAttr::OMF_init && | |||
2741 | !M->getReturnType()->isObjCObjectPointerType()) { | |||
2742 | S.Diag(M->getLocation(), diag::err_init_method_bad_return_type) | |||
2743 | << M->getReturnType(); | |||
2744 | // Ignore the attribute. | |||
2745 | return; | |||
2746 | } | |||
2747 | ||||
2748 | D->addAttr(new (S.Context) ObjCMethodFamilyAttr(S.Context, AL, F)); | |||
2749 | } | |||
2750 | ||||
2751 | static void handleObjCNSObject(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2752 | if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) { | |||
2753 | QualType T = TD->getUnderlyingType(); | |||
2754 | if (!T->isCARCBridgableType()) { | |||
2755 | S.Diag(TD->getLocation(), diag::err_nsobject_attribute); | |||
2756 | return; | |||
2757 | } | |||
2758 | } | |||
2759 | else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) { | |||
2760 | QualType T = PD->getType(); | |||
2761 | if (!T->isCARCBridgableType()) { | |||
2762 | S.Diag(PD->getLocation(), diag::err_nsobject_attribute); | |||
2763 | return; | |||
2764 | } | |||
2765 | } | |||
2766 | else { | |||
2767 | // It is okay to include this attribute on properties, e.g.: | |||
2768 | // | |||
2769 | // @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject)); | |||
2770 | // | |||
2771 | // In this case it follows tradition and suppresses an error in the above | |||
2772 | // case. | |||
2773 | S.Diag(D->getLocation(), diag::warn_nsobject_attribute); | |||
2774 | } | |||
2775 | D->addAttr(::new (S.Context) ObjCNSObjectAttr(S.Context, AL)); | |||
2776 | } | |||
2777 | ||||
2778 | static void handleObjCIndependentClass(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2779 | if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) { | |||
2780 | QualType T = TD->getUnderlyingType(); | |||
2781 | if (!T->isObjCObjectPointerType()) { | |||
2782 | S.Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute); | |||
2783 | return; | |||
2784 | } | |||
2785 | } else { | |||
2786 | S.Diag(D->getLocation(), diag::warn_independentclass_attribute); | |||
2787 | return; | |||
2788 | } | |||
2789 | D->addAttr(::new (S.Context) ObjCIndependentClassAttr(S.Context, AL)); | |||
2790 | } | |||
2791 | ||||
2792 | static void handleBlocksAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2793 | if (!AL.isArgIdent(0)) { | |||
2794 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
2795 | << AL << 1 << AANT_ArgumentIdentifier; | |||
2796 | return; | |||
2797 | } | |||
2798 | ||||
2799 | IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; | |||
2800 | BlocksAttr::BlockType type; | |||
2801 | if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) { | |||
2802 | S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; | |||
2803 | return; | |||
2804 | } | |||
2805 | ||||
2806 | D->addAttr(::new (S.Context) BlocksAttr(S.Context, AL, type)); | |||
2807 | } | |||
2808 | ||||
2809 | static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2810 | unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel; | |||
2811 | if (AL.getNumArgs() > 0) { | |||
2812 | Expr *E = AL.getArgAsExpr(0); | |||
2813 | Optional<llvm::APSInt> Idx = llvm::APSInt(32); | |||
2814 | if (E->isTypeDependent() || E->isValueDependent() || | |||
2815 | !(Idx = E->getIntegerConstantExpr(S.Context))) { | |||
2816 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
2817 | << AL << 1 << AANT_ArgumentIntegerConstant << E->getSourceRange(); | |||
2818 | return; | |||
2819 | } | |||
2820 | ||||
2821 | if (Idx->isSigned() && Idx->isNegative()) { | |||
2822 | S.Diag(AL.getLoc(), diag::err_attribute_sentinel_less_than_zero) | |||
2823 | << E->getSourceRange(); | |||
2824 | return; | |||
2825 | } | |||
2826 | ||||
2827 | sentinel = Idx->getZExtValue(); | |||
2828 | } | |||
2829 | ||||
2830 | unsigned nullPos = (unsigned)SentinelAttr::DefaultNullPos; | |||
2831 | if (AL.getNumArgs() > 1) { | |||
2832 | Expr *E = AL.getArgAsExpr(1); | |||
2833 | Optional<llvm::APSInt> Idx = llvm::APSInt(32); | |||
2834 | if (E->isTypeDependent() || E->isValueDependent() || | |||
2835 | !(Idx = E->getIntegerConstantExpr(S.Context))) { | |||
2836 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
2837 | << AL << 2 << AANT_ArgumentIntegerConstant << E->getSourceRange(); | |||
2838 | return; | |||
2839 | } | |||
2840 | nullPos = Idx->getZExtValue(); | |||
2841 | ||||
2842 | if ((Idx->isSigned() && Idx->isNegative()) || nullPos > 1) { | |||
2843 | // FIXME: This error message could be improved, it would be nice | |||
2844 | // to say what the bounds actually are. | |||
2845 | S.Diag(AL.getLoc(), diag::err_attribute_sentinel_not_zero_or_one) | |||
2846 | << E->getSourceRange(); | |||
2847 | return; | |||
2848 | } | |||
2849 | } | |||
2850 | ||||
2851 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
2852 | const FunctionType *FT = FD->getType()->castAs<FunctionType>(); | |||
2853 | if (isa<FunctionNoProtoType>(FT)) { | |||
2854 | S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_named_arguments); | |||
2855 | return; | |||
2856 | } | |||
2857 | ||||
2858 | if (!cast<FunctionProtoType>(FT)->isVariadic()) { | |||
2859 | S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; | |||
2860 | return; | |||
2861 | } | |||
2862 | } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { | |||
2863 | if (!MD->isVariadic()) { | |||
2864 | S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; | |||
2865 | return; | |||
2866 | } | |||
2867 | } else if (const auto *BD = dyn_cast<BlockDecl>(D)) { | |||
2868 | if (!BD->isVariadic()) { | |||
2869 | S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; | |||
2870 | return; | |||
2871 | } | |||
2872 | } else if (const auto *V = dyn_cast<VarDecl>(D)) { | |||
2873 | QualType Ty = V->getType(); | |||
2874 | if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) { | |||
2875 | const FunctionType *FT = Ty->isFunctionPointerType() | |||
2876 | ? D->getFunctionType() | |||
2877 | : Ty->castAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>(); | |||
2878 | if (!cast<FunctionProtoType>(FT)->isVariadic()) { | |||
2879 | int m = Ty->isFunctionPointerType() ? 0 : 1; | |||
2880 | S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m; | |||
2881 | return; | |||
2882 | } | |||
2883 | } else { | |||
2884 | S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) | |||
2885 | << AL << ExpectedFunctionMethodOrBlock; | |||
2886 | return; | |||
2887 | } | |||
2888 | } else { | |||
2889 | S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) | |||
2890 | << AL << ExpectedFunctionMethodOrBlock; | |||
2891 | return; | |||
2892 | } | |||
2893 | D->addAttr(::new (S.Context) SentinelAttr(S.Context, AL, sentinel, nullPos)); | |||
2894 | } | |||
2895 | ||||
2896 | static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2897 | if (D->getFunctionType() && | |||
2898 | D->getFunctionType()->getReturnType()->isVoidType() && | |||
2899 | !isa<CXXConstructorDecl>(D)) { | |||
2900 | S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 0; | |||
2901 | return; | |||
2902 | } | |||
2903 | if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) | |||
2904 | if (MD->getReturnType()->isVoidType()) { | |||
2905 | S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 1; | |||
2906 | return; | |||
2907 | } | |||
2908 | ||||
2909 | StringRef Str; | |||
2910 | if ((AL.isCXX11Attribute() || AL.isC2xAttribute()) && !AL.getScopeName()) { | |||
2911 | // The standard attribute cannot be applied to variable declarations such | |||
2912 | // as a function pointer. | |||
2913 | if (isa<VarDecl>(D)) | |||
2914 | S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str) | |||
2915 | << AL << "functions, classes, or enumerations"; | |||
2916 | ||||
2917 | // If this is spelled as the standard C++17 attribute, but not in C++17, | |||
2918 | // warn about using it as an extension. If there are attribute arguments, | |||
2919 | // then claim it's a C++2a extension instead. | |||
2920 | // FIXME: If WG14 does not seem likely to adopt the same feature, add an | |||
2921 | // extension warning for C2x mode. | |||
2922 | const LangOptions &LO = S.getLangOpts(); | |||
2923 | if (AL.getNumArgs() == 1) { | |||
2924 | if (LO.CPlusPlus && !LO.CPlusPlus20) | |||
2925 | S.Diag(AL.getLoc(), diag::ext_cxx20_attr) << AL; | |||
2926 | ||||
2927 | // Since this this is spelled [[nodiscard]], get the optional string | |||
2928 | // literal. If in C++ mode, but not in C++2a mode, diagnose as an | |||
2929 | // extension. | |||
2930 | // FIXME: C2x should support this feature as well, even as an extension. | |||
2931 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, nullptr)) | |||
2932 | return; | |||
2933 | } else if (LO.CPlusPlus && !LO.CPlusPlus17) | |||
2934 | S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL; | |||
2935 | } | |||
2936 | ||||
2937 | D->addAttr(::new (S.Context) WarnUnusedResultAttr(S.Context, AL, Str)); | |||
2938 | } | |||
2939 | ||||
2940 | static void handleWeakImportAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2941 | // weak_import only applies to variable & function declarations. | |||
2942 | bool isDef = false; | |||
2943 | if (!D->canBeWeakImported(isDef)) { | |||
2944 | if (isDef) | |||
2945 | S.Diag(AL.getLoc(), diag::warn_attribute_invalid_on_definition) | |||
2946 | << "weak_import"; | |||
2947 | else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) || | |||
2948 | (S.Context.getTargetInfo().getTriple().isOSDarwin() && | |||
2949 | (isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) { | |||
2950 | // Nothing to warn about here. | |||
2951 | } else | |||
2952 | S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) | |||
2953 | << AL << ExpectedVariableOrFunction; | |||
2954 | ||||
2955 | return; | |||
2956 | } | |||
2957 | ||||
2958 | D->addAttr(::new (S.Context) WeakImportAttr(S.Context, AL)); | |||
2959 | } | |||
2960 | ||||
2961 | // Handles reqd_work_group_size and work_group_size_hint. | |||
2962 | template <typename WorkGroupAttr> | |||
2963 | static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2964 | uint32_t WGSize[3]; | |||
2965 | for (unsigned i = 0; i < 3; ++i) { | |||
2966 | const Expr *E = AL.getArgAsExpr(i); | |||
2967 | if (!checkUInt32Argument(S, AL, E, WGSize[i], i, | |||
2968 | /*StrictlyUnsigned=*/true)) | |||
2969 | return; | |||
2970 | if (WGSize[i] == 0) { | |||
2971 | S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero) | |||
2972 | << AL << E->getSourceRange(); | |||
2973 | return; | |||
2974 | } | |||
2975 | } | |||
2976 | ||||
2977 | WorkGroupAttr *Existing = D->getAttr<WorkGroupAttr>(); | |||
2978 | if (Existing && !(Existing->getXDim() == WGSize[0] && | |||
2979 | Existing->getYDim() == WGSize[1] && | |||
2980 | Existing->getZDim() == WGSize[2])) | |||
2981 | S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; | |||
2982 | ||||
2983 | D->addAttr(::new (S.Context) | |||
2984 | WorkGroupAttr(S.Context, AL, WGSize[0], WGSize[1], WGSize[2])); | |||
2985 | } | |||
2986 | ||||
2987 | // Handles intel_reqd_sub_group_size. | |||
2988 | static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2989 | uint32_t SGSize; | |||
2990 | const Expr *E = AL.getArgAsExpr(0); | |||
2991 | if (!checkUInt32Argument(S, AL, E, SGSize)) | |||
2992 | return; | |||
2993 | if (SGSize == 0) { | |||
2994 | S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero) | |||
2995 | << AL << E->getSourceRange(); | |||
2996 | return; | |||
2997 | } | |||
2998 | ||||
2999 | OpenCLIntelReqdSubGroupSizeAttr *Existing = | |||
3000 | D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>(); | |||
3001 | if (Existing && Existing->getSubGroupSize() != SGSize) | |||
3002 | S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; | |||
3003 | ||||
3004 | D->addAttr(::new (S.Context) | |||
3005 | OpenCLIntelReqdSubGroupSizeAttr(S.Context, AL, SGSize)); | |||
3006 | } | |||
3007 | ||||
3008 | static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3009 | if (!AL.hasParsedType()) { | |||
3010 | S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; | |||
3011 | return; | |||
3012 | } | |||
3013 | ||||
3014 | TypeSourceInfo *ParmTSI = nullptr; | |||
3015 | QualType ParmType = S.GetTypeFromParser(AL.getTypeArg(), &ParmTSI); | |||
3016 | assert(ParmTSI && "no type source info for attribute argument")((ParmTSI && "no type source info for attribute argument" ) ? static_cast<void> (0) : __assert_fail ("ParmTSI && \"no type source info for attribute argument\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 3016, __PRETTY_FUNCTION__)); | |||
3017 | ||||
3018 | if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() && | |||
3019 | (ParmType->isBooleanType() || | |||
3020 | !ParmType->isIntegralType(S.getASTContext()))) { | |||
3021 | S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument) << 2 << AL; | |||
3022 | return; | |||
3023 | } | |||
3024 | ||||
3025 | if (VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>()) { | |||
3026 | if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) { | |||
3027 | S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; | |||
3028 | return; | |||
3029 | } | |||
3030 | } | |||
3031 | ||||
3032 | D->addAttr(::new (S.Context) VecTypeHintAttr(S.Context, AL, ParmTSI)); | |||
3033 | } | |||
3034 | ||||
3035 | SectionAttr *Sema::mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI, | |||
3036 | StringRef Name) { | |||
3037 | // Explicit or partial specializations do not inherit | |||
3038 | // the section attribute from the primary template. | |||
3039 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
3040 | if (CI.getAttributeSpellingListIndex() == SectionAttr::Declspec_allocate && | |||
3041 | FD->isFunctionTemplateSpecialization()) | |||
3042 | return nullptr; | |||
3043 | } | |||
3044 | if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) { | |||
3045 | if (ExistingAttr->getName() == Name) | |||
3046 | return nullptr; | |||
3047 | Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section) | |||
3048 | << 1 /*section*/; | |||
3049 | Diag(CI.getLoc(), diag::note_previous_attribute); | |||
3050 | return nullptr; | |||
3051 | } | |||
3052 | return ::new (Context) SectionAttr(Context, CI, Name); | |||
3053 | } | |||
3054 | ||||
3055 | bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) { | |||
3056 | if (llvm::Error E = | |||
3057 | Context.getTargetInfo().isValidSectionSpecifier(SecName)) { | |||
3058 | Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) | |||
3059 | << toString(std::move(E)) << 1 /*'section'*/; | |||
3060 | return false; | |||
3061 | } | |||
3062 | return true; | |||
3063 | } | |||
3064 | ||||
3065 | static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3066 | // Make sure that there is a string literal as the sections's single | |||
3067 | // argument. | |||
3068 | StringRef Str; | |||
3069 | SourceLocation LiteralLoc; | |||
3070 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc)) | |||
3071 | return; | |||
3072 | ||||
3073 | if (!S.checkSectionName(LiteralLoc, Str)) | |||
3074 | return; | |||
3075 | ||||
3076 | // If the target wants to validate the section specifier, make it happen. | |||
3077 | if (llvm::Error E = S.Context.getTargetInfo().isValidSectionSpecifier(Str)) { | |||
3078 | S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) | |||
3079 | << toString(std::move(E)); | |||
3080 | return; | |||
3081 | } | |||
3082 | ||||
3083 | SectionAttr *NewAttr = S.mergeSectionAttr(D, AL, Str); | |||
3084 | if (NewAttr) { | |||
3085 | D->addAttr(NewAttr); | |||
3086 | if (isa<FunctionDecl, FunctionTemplateDecl, ObjCMethodDecl, | |||
3087 | ObjCPropertyDecl>(D)) | |||
3088 | S.UnifySection(NewAttr->getName(), | |||
3089 | ASTContext::PSF_Execute | ASTContext::PSF_Read, | |||
3090 | cast<NamedDecl>(D)); | |||
3091 | } | |||
3092 | } | |||
3093 | ||||
3094 | // This is used for `__declspec(code_seg("segname"))` on a decl. | |||
3095 | // `#pragma code_seg("segname")` uses checkSectionName() instead. | |||
3096 | static bool checkCodeSegName(Sema &S, SourceLocation LiteralLoc, | |||
3097 | StringRef CodeSegName) { | |||
3098 | if (llvm::Error E = | |||
3099 | S.Context.getTargetInfo().isValidSectionSpecifier(CodeSegName)) { | |||
3100 | S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) | |||
3101 | << toString(std::move(E)) << 0 /*'code-seg'*/; | |||
3102 | return false; | |||
3103 | } | |||
3104 | ||||
3105 | return true; | |||
3106 | } | |||
3107 | ||||
3108 | CodeSegAttr *Sema::mergeCodeSegAttr(Decl *D, const AttributeCommonInfo &CI, | |||
3109 | StringRef Name) { | |||
3110 | // Explicit or partial specializations do not inherit | |||
3111 | // the code_seg attribute from the primary template. | |||
3112 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
3113 | if (FD->isFunctionTemplateSpecialization()) | |||
3114 | return nullptr; | |||
3115 | } | |||
3116 | if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) { | |||
3117 | if (ExistingAttr->getName() == Name) | |||
3118 | return nullptr; | |||
3119 | Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section) | |||
3120 | << 0 /*codeseg*/; | |||
3121 | Diag(CI.getLoc(), diag::note_previous_attribute); | |||
3122 | return nullptr; | |||
3123 | } | |||
3124 | return ::new (Context) CodeSegAttr(Context, CI, Name); | |||
3125 | } | |||
3126 | ||||
3127 | static void handleCodeSegAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3128 | StringRef Str; | |||
3129 | SourceLocation LiteralLoc; | |||
3130 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc)) | |||
3131 | return; | |||
3132 | if (!checkCodeSegName(S, LiteralLoc, Str)) | |||
3133 | return; | |||
3134 | if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) { | |||
3135 | if (!ExistingAttr->isImplicit()) { | |||
3136 | S.Diag(AL.getLoc(), | |||
3137 | ExistingAttr->getName() == Str | |||
3138 | ? diag::warn_duplicate_codeseg_attribute | |||
3139 | : diag::err_conflicting_codeseg_attribute); | |||
3140 | return; | |||
3141 | } | |||
3142 | D->dropAttr<CodeSegAttr>(); | |||
3143 | } | |||
3144 | if (CodeSegAttr *CSA = S.mergeCodeSegAttr(D, AL, Str)) | |||
3145 | D->addAttr(CSA); | |||
3146 | } | |||
3147 | ||||
3148 | // Check for things we'd like to warn about. Multiversioning issues are | |||
3149 | // handled later in the process, once we know how many exist. | |||
3150 | bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { | |||
3151 | enum FirstParam { Unsupported, Duplicate, Unknown }; | |||
3152 | enum SecondParam { None, Architecture, Tune }; | |||
3153 | if (AttrStr.find("fpmath=") != StringRef::npos) | |||
3154 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3155 | << Unsupported << None << "fpmath="; | |||
3156 | ||||
3157 | // Diagnose use of tune if target doesn't support it. | |||
3158 | if (!Context.getTargetInfo().supportsTargetAttributeTune() && | |||
3159 | AttrStr.find("tune=") != StringRef::npos) | |||
3160 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3161 | << Unsupported << None << "tune="; | |||
3162 | ||||
3163 | ParsedTargetAttr ParsedAttrs = TargetAttr::parse(AttrStr); | |||
3164 | ||||
3165 | if (!ParsedAttrs.Architecture.empty() && | |||
3166 | !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Architecture)) | |||
3167 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3168 | << Unknown << Architecture << ParsedAttrs.Architecture; | |||
3169 | ||||
3170 | if (!ParsedAttrs.Tune.empty() && | |||
3171 | !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Tune)) | |||
3172 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3173 | << Unknown << Tune << ParsedAttrs.Tune; | |||
3174 | ||||
3175 | if (ParsedAttrs.DuplicateArchitecture) | |||
3176 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3177 | << Duplicate << None << "arch="; | |||
3178 | if (ParsedAttrs.DuplicateTune) | |||
3179 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3180 | << Duplicate << None << "tune="; | |||
3181 | ||||
3182 | for (const auto &Feature : ParsedAttrs.Features) { | |||
3183 | auto CurFeature = StringRef(Feature).drop_front(); // remove + or -. | |||
3184 | if (!Context.getTargetInfo().isValidFeatureName(CurFeature)) | |||
3185 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3186 | << Unsupported << None << CurFeature; | |||
3187 | } | |||
3188 | ||||
3189 | TargetInfo::BranchProtectionInfo BPI; | |||
3190 | StringRef Error; | |||
3191 | if (!ParsedAttrs.BranchProtection.empty() && | |||
3192 | !Context.getTargetInfo().validateBranchProtection( | |||
3193 | ParsedAttrs.BranchProtection, BPI, Error)) { | |||
3194 | if (Error.empty()) | |||
3195 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3196 | << Unsupported << None << "branch-protection"; | |||
3197 | else | |||
3198 | return Diag(LiteralLoc, diag::err_invalid_branch_protection_spec) | |||
3199 | << Error; | |||
3200 | } | |||
3201 | ||||
3202 | return false; | |||
3203 | } | |||
3204 | ||||
3205 | static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3206 | StringRef Str; | |||
3207 | SourceLocation LiteralLoc; | |||
3208 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) || | |||
3209 | S.checkTargetAttr(LiteralLoc, Str)) | |||
3210 | return; | |||
3211 | ||||
3212 | TargetAttr *NewAttr = ::new (S.Context) TargetAttr(S.Context, AL, Str); | |||
3213 | D->addAttr(NewAttr); | |||
3214 | } | |||
3215 | ||||
3216 | static void handleMinVectorWidthAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3217 | Expr *E = AL.getArgAsExpr(0); | |||
3218 | uint32_t VecWidth; | |||
3219 | if (!checkUInt32Argument(S, AL, E, VecWidth)) { | |||
3220 | AL.setInvalid(); | |||
3221 | return; | |||
3222 | } | |||
3223 | ||||
3224 | MinVectorWidthAttr *Existing = D->getAttr<MinVectorWidthAttr>(); | |||
3225 | if (Existing && Existing->getVectorWidth() != VecWidth) { | |||
3226 | S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; | |||
3227 | return; | |||
3228 | } | |||
3229 | ||||
3230 | D->addAttr(::new (S.Context) MinVectorWidthAttr(S.Context, AL, VecWidth)); | |||
3231 | } | |||
3232 | ||||
3233 | static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3234 | Expr *E = AL.getArgAsExpr(0); | |||
3235 | SourceLocation Loc = E->getExprLoc(); | |||
3236 | FunctionDecl *FD = nullptr; | |||
3237 | DeclarationNameInfo NI; | |||
3238 | ||||
3239 | // gcc only allows for simple identifiers. Since we support more than gcc, we | |||
3240 | // will warn the user. | |||
3241 | if (auto *DRE = dyn_cast<DeclRefExpr>(E)) { | |||
3242 | if (DRE->hasQualifier()) | |||
3243 | S.Diag(Loc, diag::warn_cleanup_ext); | |||
3244 | FD = dyn_cast<FunctionDecl>(DRE->getDecl()); | |||
3245 | NI = DRE->getNameInfo(); | |||
3246 | if (!FD) { | |||
3247 | S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 1 | |||
3248 | << NI.getName(); | |||
3249 | return; | |||
3250 | } | |||
3251 | } else if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(E)) { | |||
3252 | if (ULE->hasExplicitTemplateArgs()) | |||
3253 | S.Diag(Loc, diag::warn_cleanup_ext); | |||
3254 | FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true); | |||
3255 | NI = ULE->getNameInfo(); | |||
3256 | if (!FD) { | |||
3257 | S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2 | |||
3258 | << NI.getName(); | |||
3259 | if (ULE->getType() == S.Context.OverloadTy) | |||
3260 | S.NoteAllOverloadCandidates(ULE); | |||
3261 | return; | |||
3262 | } | |||
3263 | } else { | |||
3264 | S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 0; | |||
3265 | return; | |||
3266 | } | |||
3267 | ||||
3268 | if (FD->getNumParams() != 1) { | |||
3269 | S.Diag(Loc, diag::err_attribute_cleanup_func_must_take_one_arg) | |||
3270 | << NI.getName(); | |||
3271 | return; | |||
3272 | } | |||
3273 | ||||
3274 | // We're currently more strict than GCC about what function types we accept. | |||
3275 | // If this ever proves to be a problem it should be easy to fix. | |||
3276 | QualType Ty = S.Context.getPointerType(cast<VarDecl>(D)->getType()); | |||
3277 | QualType ParamTy = FD->getParamDecl(0)->getType(); | |||
3278 | if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(), | |||
3279 | ParamTy, Ty) != Sema::Compatible) { | |||
3280 | S.Diag(Loc, diag::err_attribute_cleanup_func_arg_incompatible_type) | |||
3281 | << NI.getName() << ParamTy << Ty; | |||
3282 | return; | |||
3283 | } | |||
3284 | ||||
3285 | D->addAttr(::new (S.Context) CleanupAttr(S.Context, AL, FD)); | |||
3286 | } | |||
3287 | ||||
3288 | static void handleEnumExtensibilityAttr(Sema &S, Decl *D, | |||
3289 | const ParsedAttr &AL) { | |||
3290 | if (!AL.isArgIdent(0)) { | |||
3291 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
3292 | << AL << 0 << AANT_ArgumentIdentifier; | |||
3293 | return; | |||
3294 | } | |||
3295 | ||||
3296 | EnumExtensibilityAttr::Kind ExtensibilityKind; | |||
3297 | IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; | |||
3298 | if (!EnumExtensibilityAttr::ConvertStrToKind(II->getName(), | |||
3299 | ExtensibilityKind)) { | |||
3300 | S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; | |||
3301 | return; | |||
3302 | } | |||
3303 | ||||
3304 | D->addAttr(::new (S.Context) | |||
3305 | EnumExtensibilityAttr(S.Context, AL, ExtensibilityKind)); | |||
3306 | } | |||
3307 | ||||
3308 | /// Handle __attribute__((format_arg((idx)))) attribute based on | |||
3309 | /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html | |||
3310 | static void handleFormatArgAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3311 | Expr *IdxExpr = AL.getArgAsExpr(0); | |||
3312 | ParamIdx Idx; | |||
3313 | if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, IdxExpr, Idx)) | |||
3314 | return; | |||
3315 | ||||
3316 | // Make sure the format string is really a string. | |||
3317 | QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex()); | |||
3318 | ||||
3319 | bool NotNSStringTy = !isNSStringType(Ty, S.Context); | |||
3320 | if (NotNSStringTy && | |||
3321 | !isCFStringType(Ty, S.Context) && | |||
3322 | (!Ty->isPointerType() || | |||
3323 | !Ty->castAs<PointerType>()->getPointeeType()->isCharType())) { | |||
3324 | S.Diag(AL.getLoc(), diag::err_format_attribute_not) | |||
3325 | << "a string type" << IdxExpr->getSourceRange() | |||
3326 | << getFunctionOrMethodParamRange(D, 0); | |||
3327 | return; | |||
3328 | } | |||
3329 | Ty = getFunctionOrMethodResultType(D); | |||
3330 | if (!isNSStringType(Ty, S.Context) && | |||
3331 | !isCFStringType(Ty, S.Context) && | |||
3332 | (!Ty->isPointerType() || | |||
3333 | !Ty->castAs<PointerType>()->getPointeeType()->isCharType())) { | |||
3334 | S.Diag(AL.getLoc(), diag::err_format_attribute_result_not) | |||
3335 | << (NotNSStringTy ? "string type" : "NSString") | |||
3336 | << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0); | |||
3337 | return; | |||
3338 | } | |||
3339 | ||||
3340 | D->addAttr(::new (S.Context) FormatArgAttr(S.Context, AL, Idx)); | |||
3341 | } | |||
3342 | ||||
3343 | enum FormatAttrKind { | |||
3344 | CFStringFormat, | |||
3345 | NSStringFormat, | |||
3346 | StrftimeFormat, | |||
3347 | SupportedFormat, | |||
3348 | IgnoredFormat, | |||
3349 | InvalidFormat | |||
3350 | }; | |||
3351 | ||||
3352 | /// getFormatAttrKind - Map from format attribute names to supported format | |||
3353 | /// types. | |||
3354 | static FormatAttrKind getFormatAttrKind(StringRef Format) { | |||
3355 | return llvm::StringSwitch<FormatAttrKind>(Format) | |||
3356 | // Check for formats that get handled specially. | |||
3357 | .Case("NSString", NSStringFormat) | |||
3358 | .Case("CFString", CFStringFormat) | |||
3359 | .Case("strftime", StrftimeFormat) | |||
3360 | ||||
3361 | // Otherwise, check for supported formats. | |||
3362 | .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat) | |||
3363 | .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat) | |||
3364 | .Case("kprintf", SupportedFormat) // OpenBSD. | |||
3365 | .Case("freebsd_kprintf", SupportedFormat) // FreeBSD. | |||
3366 | .Case("os_trace", SupportedFormat) | |||
3367 | .Case("os_log", SupportedFormat) | |||
3368 | ||||
3369 | .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat) | |||
3370 | .Default(InvalidFormat); | |||
3371 | } | |||
3372 | ||||
3373 | /// Handle __attribute__((init_priority(priority))) attributes based on | |||
3374 | /// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html | |||
3375 | static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3376 | if (!S.getLangOpts().CPlusPlus) { | |||
3377 | S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL; | |||
3378 | return; | |||
3379 | } | |||
3380 | ||||
3381 | if (S.getCurFunctionOrMethodDecl()) { | |||
3382 | S.Diag(AL.getLoc(), diag::err_init_priority_object_attr); | |||
3383 | AL.setInvalid(); | |||
3384 | return; | |||
3385 | } | |||
3386 | QualType T = cast<VarDecl>(D)->getType(); | |||
3387 | if (S.Context.getAsArrayType(T)) | |||
3388 | T = S.Context.getBaseElementType(T); | |||
3389 | if (!T->getAs<RecordType>()) { | |||
3390 | S.Diag(AL.getLoc(), diag::err_init_priority_object_attr); | |||
3391 | AL.setInvalid(); | |||
3392 | return; | |||
3393 | } | |||
3394 | ||||
3395 | Expr *E = AL.getArgAsExpr(0); | |||
3396 | uint32_t prioritynum; | |||
3397 | if (!checkUInt32Argument(S, AL, E, prioritynum)) { | |||
3398 | AL.setInvalid(); | |||
3399 | return; | |||
3400 | } | |||
3401 | ||||
3402 | // Only perform the priority check if the attribute is outside of a system | |||
3403 | // header. Values <= 100 are reserved for the implementation, and libc++ | |||
3404 | // benefits from being able to specify values in that range. | |||
3405 | if ((prioritynum < 101 || prioritynum > 65535) && | |||
3406 | !S.getSourceManager().isInSystemHeader(AL.getLoc())) { | |||
3407 | S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_range) | |||
3408 | << E->getSourceRange() << AL << 101 << 65535; | |||
3409 | AL.setInvalid(); | |||
3410 | return; | |||
3411 | } | |||
3412 | D->addAttr(::new (S.Context) InitPriorityAttr(S.Context, AL, prioritynum)); | |||
3413 | } | |||
3414 | ||||
3415 | FormatAttr *Sema::mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI, | |||
3416 | IdentifierInfo *Format, int FormatIdx, | |||
3417 | int FirstArg) { | |||
3418 | // Check whether we already have an equivalent format attribute. | |||
3419 | for (auto *F : D->specific_attrs<FormatAttr>()) { | |||
3420 | if (F->getType() == Format && | |||
3421 | F->getFormatIdx() == FormatIdx && | |||
3422 | F->getFirstArg() == FirstArg) { | |||
3423 | // If we don't have a valid location for this attribute, adopt the | |||
3424 | // location. | |||
3425 | if (F->getLocation().isInvalid()) | |||
3426 | F->setRange(CI.getRange()); | |||
3427 | return nullptr; | |||
3428 | } | |||
3429 | } | |||
3430 | ||||
3431 | return ::new (Context) FormatAttr(Context, CI, Format, FormatIdx, FirstArg); | |||
3432 | } | |||
3433 | ||||
3434 | /// Handle __attribute__((format(type,idx,firstarg))) attributes based on | |||
3435 | /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html | |||
3436 | static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3437 | if (!AL.isArgIdent(0)) { | |||
3438 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
3439 | << AL << 1 << AANT_ArgumentIdentifier; | |||
3440 | return; | |||
3441 | } | |||
3442 | ||||
3443 | // In C++ the implicit 'this' function parameter also counts, and they are | |||
3444 | // counted from one. | |||
3445 | bool HasImplicitThisParam = isInstanceMethod(D); | |||
3446 | unsigned NumArgs = getFunctionOrMethodNumParams(D) + HasImplicitThisParam; | |||
3447 | ||||
3448 | IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; | |||
3449 | StringRef Format = II->getName(); | |||
3450 | ||||
3451 | if (normalizeName(Format)) { | |||
3452 | // If we've modified the string name, we need a new identifier for it. | |||
3453 | II = &S.Context.Idents.get(Format); | |||
3454 | } | |||
3455 | ||||
3456 | // Check for supported formats. | |||
3457 | FormatAttrKind Kind = getFormatAttrKind(Format); | |||
3458 | ||||
3459 | if (Kind == IgnoredFormat) | |||
3460 | return; | |||
3461 | ||||
3462 | if (Kind == InvalidFormat) { | |||
3463 | S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) | |||
3464 | << AL << II->getName(); | |||
3465 | return; | |||
3466 | } | |||
3467 | ||||
3468 | // checks for the 2nd argument | |||
3469 | Expr *IdxExpr = AL.getArgAsExpr(1); | |||
3470 | uint32_t Idx; | |||
3471 | if (!checkUInt32Argument(S, AL, IdxExpr, Idx, 2)) | |||
3472 | return; | |||
3473 | ||||
3474 | if (Idx < 1 || Idx > NumArgs) { | |||
3475 | S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) | |||
3476 | << AL << 2 << IdxExpr->getSourceRange(); | |||
3477 | return; | |||
3478 | } | |||
3479 | ||||
3480 | // FIXME: Do we need to bounds check? | |||
3481 | unsigned ArgIdx = Idx - 1; | |||
3482 | ||||
3483 | if (HasImplicitThisParam) { | |||
3484 | if (ArgIdx == 0) { | |||
3485 | S.Diag(AL.getLoc(), | |||
3486 | diag::err_format_attribute_implicit_this_format_string) | |||
3487 | << IdxExpr->getSourceRange(); | |||
3488 | return; | |||
3489 | } | |||
3490 | ArgIdx--; | |||
3491 | } | |||
3492 | ||||
3493 | // make sure the format string is really a string | |||
3494 | QualType Ty = getFunctionOrMethodParamType(D, ArgIdx); | |||
3495 | ||||
3496 | if (Kind == CFStringFormat) { | |||
3497 | if (!isCFStringType(Ty, S.Context)) { | |||
3498 | S.Diag(AL.getLoc(), diag::err_format_attribute_not) | |||
3499 | << "a CFString" << IdxExpr->getSourceRange() | |||
3500 | << getFunctionOrMethodParamRange(D, ArgIdx); | |||
3501 | return; | |||
3502 | } | |||
3503 | } else if (Kind == NSStringFormat) { | |||
3504 | // FIXME: do we need to check if the type is NSString*? What are the | |||
3505 | // semantics? | |||
3506 | if (!isNSStringType(Ty, S.Context)) { | |||
3507 | S.Diag(AL.getLoc(), diag::err_format_attribute_not) | |||
3508 | << "an NSString" << IdxExpr->getSourceRange() | |||
3509 | << getFunctionOrMethodParamRange(D, ArgIdx); | |||
3510 | return; | |||
3511 | } | |||
3512 | } else if (!Ty->isPointerType() || | |||
3513 | !Ty->castAs<PointerType>()->getPointeeType()->isCharType()) { | |||
3514 | S.Diag(AL.getLoc(), diag::err_format_attribute_not) | |||
3515 | << "a string type" << IdxExpr->getSourceRange() | |||
3516 | << getFunctionOrMethodParamRange(D, ArgIdx); | |||
3517 | return; | |||
3518 | } | |||
3519 | ||||
3520 | // check the 3rd argument | |||
3521 | Expr *FirstArgExpr = AL.getArgAsExpr(2); | |||
3522 | uint32_t FirstArg; | |||
3523 | if (!checkUInt32Argument(S, AL, FirstArgExpr, FirstArg, 3)) | |||
3524 | return; | |||
3525 | ||||
3526 | // check if the function is variadic if the 3rd argument non-zero | |||
3527 | if (FirstArg != 0) { | |||
3528 | if (isFunctionOrMethodVariadic(D)) { | |||
3529 | ++NumArgs; // +1 for ... | |||
3530 | } else { | |||
3531 | S.Diag(D->getLocation(), diag::err_format_attribute_requires_variadic); | |||
3532 | return; | |||
3533 | } | |||
3534 | } | |||
3535 | ||||
3536 | // strftime requires FirstArg to be 0 because it doesn't read from any | |||
3537 | // variable the input is just the current time + the format string. | |||
3538 | if (Kind == StrftimeFormat) { | |||
3539 | if (FirstArg != 0) { | |||
3540 | S.Diag(AL.getLoc(), diag::err_format_strftime_third_parameter) | |||
3541 | << FirstArgExpr->getSourceRange(); | |||
3542 | return; | |||
3543 | } | |||
3544 | // if 0 it disables parameter checking (to use with e.g. va_list) | |||
3545 | } else if (FirstArg != 0 && FirstArg != NumArgs) { | |||
3546 | S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) | |||
3547 | << AL << 3 << FirstArgExpr->getSourceRange(); | |||
3548 | return; | |||
3549 | } | |||
3550 | ||||
3551 | FormatAttr *NewAttr = S.mergeFormatAttr(D, AL, II, Idx, FirstArg); | |||
3552 | if (NewAttr) | |||
3553 | D->addAttr(NewAttr); | |||
3554 | } | |||
3555 | ||||
3556 | /// Handle __attribute__((callback(CalleeIdx, PayloadIdx0, ...))) attributes. | |||
3557 | static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3558 | // The index that identifies the callback callee is mandatory. | |||
3559 | if (AL.getNumArgs() == 0) { | |||
3560 | S.Diag(AL.getLoc(), diag::err_callback_attribute_no_callee) | |||
3561 | << AL.getRange(); | |||
3562 | return; | |||
3563 | } | |||
3564 | ||||
3565 | bool HasImplicitThisParam = isInstanceMethod(D); | |||
3566 | int32_t NumArgs = getFunctionOrMethodNumParams(D); | |||
3567 | ||||
3568 | FunctionDecl *FD = D->getAsFunction(); | |||
3569 | assert(FD && "Expected a function declaration!")((FD && "Expected a function declaration!") ? static_cast <void> (0) : __assert_fail ("FD && \"Expected a function declaration!\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 3569, __PRETTY_FUNCTION__)); | |||
3570 | ||||
3571 | llvm::StringMap<int> NameIdxMapping; | |||
3572 | NameIdxMapping["__"] = -1; | |||
3573 | ||||
3574 | NameIdxMapping["this"] = 0; | |||
3575 | ||||
3576 | int Idx = 1; | |||
3577 | for (const ParmVarDecl *PVD : FD->parameters()) | |||
3578 | NameIdxMapping[PVD->getName()] = Idx++; | |||
3579 | ||||
3580 | auto UnknownName = NameIdxMapping.end(); | |||
3581 | ||||
3582 | SmallVector<int, 8> EncodingIndices; | |||
3583 | for (unsigned I = 0, E = AL.getNumArgs(); I < E; ++I) { | |||
3584 | SourceRange SR; | |||
3585 | int32_t ArgIdx; | |||
3586 | ||||
3587 | if (AL.isArgIdent(I)) { | |||
3588 | IdentifierLoc *IdLoc = AL.getArgAsIdent(I); | |||
3589 | auto It = NameIdxMapping.find(IdLoc->Ident->getName()); | |||
3590 | if (It == UnknownName) { | |||
3591 | S.Diag(AL.getLoc(), diag::err_callback_attribute_argument_unknown) | |||
3592 | << IdLoc->Ident << IdLoc->Loc; | |||
3593 | return; | |||
3594 | } | |||
3595 | ||||
3596 | SR = SourceRange(IdLoc->Loc); | |||
3597 | ArgIdx = It->second; | |||
3598 | } else if (AL.isArgExpr(I)) { | |||
3599 | Expr *IdxExpr = AL.getArgAsExpr(I); | |||
3600 | ||||
3601 | // If the expression is not parseable as an int32_t we have a problem. | |||
3602 | if (!checkUInt32Argument(S, AL, IdxExpr, (uint32_t &)ArgIdx, I + 1, | |||
3603 | false)) { | |||
3604 | S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) | |||
3605 | << AL << (I + 1) << IdxExpr->getSourceRange(); | |||
3606 | return; | |||
3607 | } | |||
3608 | ||||
3609 | // Check oob, excluding the special values, 0 and -1. | |||
3610 | if (ArgIdx < -1 || ArgIdx > NumArgs) { | |||
3611 | S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) | |||
3612 | << AL << (I + 1) << IdxExpr->getSourceRange(); | |||
3613 | return; | |||
3614 | } | |||
3615 | ||||
3616 | SR = IdxExpr->getSourceRange(); | |||
3617 | } else { | |||
3618 | llvm_unreachable("Unexpected ParsedAttr argument type!")::llvm::llvm_unreachable_internal("Unexpected ParsedAttr argument type!" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 3618); | |||
3619 | } | |||
3620 | ||||
3621 | if (ArgIdx == 0 && !HasImplicitThisParam) { | |||
3622 | S.Diag(AL.getLoc(), diag::err_callback_implicit_this_not_available) | |||
3623 | << (I + 1) << SR; | |||
3624 | return; | |||
3625 | } | |||
3626 | ||||
3627 | // Adjust for the case we do not have an implicit "this" parameter. In this | |||
3628 | // case we decrease all positive values by 1 to get LLVM argument indices. | |||
3629 | if (!HasImplicitThisParam && ArgIdx > 0) | |||
3630 | ArgIdx -= 1; | |||
3631 | ||||
3632 | EncodingIndices.push_back(ArgIdx); | |||
3633 | } | |||
3634 | ||||
3635 | int CalleeIdx = EncodingIndices.front(); | |||
3636 | // Check if the callee index is proper, thus not "this" and not "unknown". | |||
3637 | // This means the "CalleeIdx" has to be non-negative if "HasImplicitThisParam" | |||
3638 | // is false and positive if "HasImplicitThisParam" is true. | |||
3639 | if (CalleeIdx < (int)HasImplicitThisParam) { | |||
3640 | S.Diag(AL.getLoc(), diag::err_callback_attribute_invalid_callee) | |||
3641 | << AL.getRange(); | |||
3642 | return; | |||
3643 | } | |||
3644 | ||||
3645 | // Get the callee type, note the index adjustment as the AST doesn't contain | |||
3646 | // the this type (which the callee cannot reference anyway!). | |||
3647 | const Type *CalleeType = | |||
3648 | getFunctionOrMethodParamType(D, CalleeIdx - HasImplicitThisParam) | |||
3649 | .getTypePtr(); | |||
3650 | if (!CalleeType || !CalleeType->isFunctionPointerType()) { | |||
3651 | S.Diag(AL.getLoc(), diag::err_callback_callee_no_function_type) | |||
3652 | << AL.getRange(); | |||
3653 | return; | |||
3654 | } | |||
3655 | ||||
3656 | const Type *CalleeFnType = | |||
3657 | CalleeType->getPointeeType()->getUnqualifiedDesugaredType(); | |||
3658 | ||||
3659 | // TODO: Check the type of the callee arguments. | |||
3660 | ||||
3661 | const auto *CalleeFnProtoType = dyn_cast<FunctionProtoType>(CalleeFnType); | |||
3662 | if (!CalleeFnProtoType) { | |||
3663 | S.Diag(AL.getLoc(), diag::err_callback_callee_no_function_type) | |||
3664 | << AL.getRange(); | |||
3665 | return; | |||
3666 | } | |||
3667 | ||||
3668 | if (CalleeFnProtoType->getNumParams() > EncodingIndices.size() - 1) { | |||
3669 | S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) | |||
3670 | << AL << (unsigned)(EncodingIndices.size() - 1); | |||
3671 | return; | |||
3672 | } | |||
3673 | ||||
3674 | if (CalleeFnProtoType->getNumParams() < EncodingIndices.size() - 1) { | |||
3675 | S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) | |||
3676 | << AL << (unsigned)(EncodingIndices.size() - 1); | |||
3677 | return; | |||
3678 | } | |||
3679 | ||||
3680 | if (CalleeFnProtoType->isVariadic()) { | |||
3681 | S.Diag(AL.getLoc(), diag::err_callback_callee_is_variadic) << AL.getRange(); | |||
3682 | return; | |||
3683 | } | |||
3684 | ||||
3685 | // Do not allow multiple callback attributes. | |||
3686 | if (D->hasAttr<CallbackAttr>()) { | |||
3687 | S.Diag(AL.getLoc(), diag::err_callback_attribute_multiple) << AL.getRange(); | |||
3688 | return; | |||
3689 | } | |||
3690 | ||||
3691 | D->addAttr(::new (S.Context) CallbackAttr( | |||
3692 | S.Context, AL, EncodingIndices.data(), EncodingIndices.size())); | |||
3693 | } | |||
3694 | ||||
3695 | static bool isFunctionLike(const Type &T) { | |||
3696 | // Check for explicit function types. | |||
3697 | // 'called_once' is only supported in Objective-C and it has | |||
3698 | // function pointers and block pointers. | |||
3699 | return T.isFunctionPointerType() || T.isBlockPointerType(); | |||
3700 | } | |||
3701 | ||||
3702 | /// Handle 'called_once' attribute. | |||
3703 | static void handleCalledOnceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3704 | // 'called_once' only applies to parameters representing functions. | |||
3705 | QualType T = cast<ParmVarDecl>(D)->getType(); | |||
3706 | ||||
3707 | if (!isFunctionLike(*T)) { | |||
3708 | S.Diag(AL.getLoc(), diag::err_called_once_attribute_wrong_type); | |||
3709 | return; | |||
3710 | } | |||
3711 | ||||
3712 | D->addAttr(::new (S.Context) CalledOnceAttr(S.Context, AL)); | |||
3713 | } | |||
3714 | ||||
3715 | static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3716 | // Try to find the underlying union declaration. | |||
3717 | RecordDecl *RD = nullptr; | |||
3718 | const auto *TD = dyn_cast<TypedefNameDecl>(D); | |||
3719 | if (TD && TD->getUnderlyingType()->isUnionType()) | |||
3720 | RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); | |||
3721 | else | |||
3722 | RD = dyn_cast<RecordDecl>(D); | |||
3723 | ||||
3724 | if (!RD || !RD->isUnion()) { | |||
3725 | S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL | |||
3726 | << ExpectedUnion; | |||
3727 | return; | |||
3728 | } | |||
3729 | ||||
3730 | if (!RD->isCompleteDefinition()) { | |||
3731 | if (!RD->isBeingDefined()) | |||
3732 | S.Diag(AL.getLoc(), | |||
3733 | diag::warn_transparent_union_attribute_not_definition); | |||
3734 | return; | |||
3735 | } | |||
3736 | ||||
3737 | RecordDecl::field_iterator Field = RD->field_begin(), | |||
3738 | FieldEnd = RD->field_end(); | |||
3739 | if (Field == FieldEnd) { | |||
3740 | S.Diag(AL.getLoc(), diag::warn_transparent_union_attribute_zero_fields); | |||
3741 | return; | |||
3742 | } | |||
3743 | ||||
3744 | FieldDecl *FirstField = *Field; | |||
3745 | QualType FirstType = FirstField->getType(); | |||
3746 | if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) { | |||
3747 | S.Diag(FirstField->getLocation(), | |||
3748 | diag::warn_transparent_union_attribute_floating) | |||
3749 | << FirstType->isVectorType() << FirstType; | |||
3750 | return; | |||
3751 | } | |||
3752 | ||||
3753 | if (FirstType->isIncompleteType()) | |||
3754 | return; | |||
3755 | uint64_t FirstSize = S.Context.getTypeSize(FirstType); | |||
3756 | uint64_t FirstAlign = S.Context.getTypeAlign(FirstType); | |||
3757 | for (; Field != FieldEnd; ++Field) { | |||
3758 | QualType FieldType = Field->getType(); | |||
3759 | if (FieldType->isIncompleteType()) | |||
3760 | return; | |||
3761 | // FIXME: this isn't fully correct; we also need to test whether the | |||
3762 | // members of the union would all have the same calling convention as the | |||
3763 | // first member of the union. Checking just the size and alignment isn't | |||
3764 | // sufficient (consider structs passed on the stack instead of in registers | |||
3765 | // as an example). | |||
3766 | if (S.Context.getTypeSize(FieldType) != FirstSize || | |||
3767 | S.Context.getTypeAlign(FieldType) > FirstAlign) { | |||
3768 | // Warn if we drop the attribute. | |||
3769 | bool isSize = S.Context.getTypeSize(FieldType) != FirstSize; | |||
3770 | unsigned FieldBits = isSize ? S.Context.getTypeSize(FieldType) | |||
3771 | : S.Context.getTypeAlign(FieldType); | |||
3772 | S.Diag(Field->getLocation(), | |||
3773 | diag::warn_transparent_union_attribute_field_size_align) | |||
3774 | << isSize << *Field << FieldBits; | |||
3775 | unsigned FirstBits = isSize ? FirstSize : FirstAlign; | |||
3776 | S.Diag(FirstField->getLocation(), | |||
3777 | diag::note_transparent_union_first_field_size_align) | |||
3778 | << isSize << FirstBits; | |||
3779 | return; | |||
3780 | } | |||
3781 | } | |||
3782 | ||||
3783 | RD->addAttr(::new (S.Context) TransparentUnionAttr(S.Context, AL)); | |||
3784 | } | |||
3785 | ||||
3786 | void Sema::AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI, | |||
3787 | StringRef Str, MutableArrayRef<Expr *> Args) { | |||
3788 | auto *Attr = AnnotateAttr::Create(Context, Str, Args.data(), Args.size(), CI); | |||
3789 | llvm::SmallVector<PartialDiagnosticAt, 8> Notes; | |||
3790 | for (unsigned Idx = 0; Idx < Attr->args_size(); Idx++) { | |||
3791 | Expr *&E = Attr->args_begin()[Idx]; | |||
3792 | assert(E && "error are handled before")((E && "error are handled before") ? static_cast<void > (0) : __assert_fail ("E && \"error are handled before\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 3792, __PRETTY_FUNCTION__)); | |||
3793 | if (E->isValueDependent() || E->isTypeDependent()) | |||
3794 | continue; | |||
3795 | ||||
3796 | if (E->getType()->isArrayType()) | |||
3797 | E = ImpCastExprToType(E, Context.getPointerType(E->getType()), | |||
3798 | clang::CK_ArrayToPointerDecay) | |||
3799 | .get(); | |||
3800 | if (E->getType()->isFunctionType()) | |||
3801 | E = ImplicitCastExpr::Create(Context, | |||
3802 | Context.getPointerType(E->getType()), | |||
3803 | clang::CK_FunctionToPointerDecay, E, nullptr, | |||
3804 | VK_RValue, FPOptionsOverride()); | |||
3805 | if (E->isLValue()) | |||
3806 | E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(), | |||
3807 | clang::CK_LValueToRValue, E, nullptr, | |||
3808 | VK_RValue, FPOptionsOverride()); | |||
3809 | ||||
3810 | Expr::EvalResult Eval; | |||
3811 | Notes.clear(); | |||
3812 | Eval.Diag = &Notes; | |||
3813 | ||||
3814 | bool Result = | |||
3815 | E->EvaluateAsConstantExpr(Eval, Context); | |||
3816 | ||||
3817 | /// Result means the expression can be folded to a constant. | |||
3818 | /// Note.empty() means the expression is a valid constant expression in the | |||
3819 | /// current language mode. | |||
3820 | if (!Result || !Notes.empty()) { | |||
3821 | Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type) | |||
3822 | << CI << (Idx + 1) << AANT_ArgumentConstantExpr; | |||
3823 | for (auto &Note : Notes) | |||
3824 | Diag(Note.first, Note.second); | |||
3825 | return; | |||
3826 | } | |||
3827 | assert(Eval.Val.hasValue())((Eval.Val.hasValue()) ? static_cast<void> (0) : __assert_fail ("Eval.Val.hasValue()", "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 3827, __PRETTY_FUNCTION__)); | |||
3828 | E = ConstantExpr::Create(Context, E, Eval.Val); | |||
3829 | } | |||
3830 | D->addAttr(Attr); | |||
3831 | } | |||
3832 | ||||
3833 | static void handleAnnotateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3834 | // Make sure that there is a string literal as the annotation's first | |||
3835 | // argument. | |||
3836 | StringRef Str; | |||
3837 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) | |||
3838 | return; | |||
3839 | ||||
3840 | llvm::SmallVector<Expr *, 4> Args; | |||
3841 | Args.reserve(AL.getNumArgs() - 1); | |||
3842 | for (unsigned Idx = 1; Idx < AL.getNumArgs(); Idx++) { | |||
3843 | assert(!AL.isArgIdent(Idx))((!AL.isArgIdent(Idx)) ? static_cast<void> (0) : __assert_fail ("!AL.isArgIdent(Idx)", "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 3843, __PRETTY_FUNCTION__)); | |||
3844 | Args.push_back(AL.getArgAsExpr(Idx)); | |||
3845 | } | |||
3846 | ||||
3847 | S.AddAnnotationAttr(D, AL, Str, Args); | |||
3848 | } | |||
3849 | ||||
3850 | static void handleAlignValueAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3851 | S.AddAlignValueAttr(D, AL, AL.getArgAsExpr(0)); | |||
3852 | } | |||
3853 | ||||
3854 | void Sema::AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E) { | |||
3855 | AlignValueAttr TmpAttr(Context, CI, E); | |||
3856 | SourceLocation AttrLoc = CI.getLoc(); | |||
3857 | ||||
3858 | QualType T; | |||
3859 | if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) | |||
3860 | T = TD->getUnderlyingType(); | |||
3861 | else if (const auto *VD = dyn_cast<ValueDecl>(D)) | |||
3862 | T = VD->getType(); | |||
3863 | else | |||
3864 | llvm_unreachable("Unknown decl type for align_value")::llvm::llvm_unreachable_internal("Unknown decl type for align_value" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 3864); | |||
3865 | ||||
3866 | if (!T->isDependentType() && !T->isAnyPointerType() && | |||
3867 | !T->isReferenceType() && !T->isMemberPointerType()) { | |||
3868 | Diag(AttrLoc, diag::warn_attribute_pointer_or_reference_only) | |||
3869 | << &TmpAttr << T << D->getSourceRange(); | |||
3870 | return; | |||
3871 | } | |||
3872 | ||||
3873 | if (!E->isValueDependent()) { | |||
3874 | llvm::APSInt Alignment; | |||
3875 | ExprResult ICE = VerifyIntegerConstantExpression( | |||
3876 | E, &Alignment, diag::err_align_value_attribute_argument_not_int); | |||
3877 | if (ICE.isInvalid()) | |||
3878 | return; | |||
3879 | ||||
3880 | if (!Alignment.isPowerOf2()) { | |||
3881 | Diag(AttrLoc, diag::err_alignment_not_power_of_two) | |||
3882 | << E->getSourceRange(); | |||
3883 | return; | |||
3884 | } | |||
3885 | ||||
3886 | D->addAttr(::new (Context) AlignValueAttr(Context, CI, ICE.get())); | |||
3887 | return; | |||
3888 | } | |||
3889 | ||||
3890 | // Save dependent expressions in the AST to be instantiated. | |||
3891 | D->addAttr(::new (Context) AlignValueAttr(Context, CI, E)); | |||
3892 | } | |||
3893 | ||||
3894 | static void handleAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3895 | // check the attribute arguments. | |||
3896 | if (AL.getNumArgs() > 1) { | |||
3897 | S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; | |||
3898 | return; | |||
3899 | } | |||
3900 | ||||
3901 | if (AL.getNumArgs() == 0) { | |||
3902 | D->addAttr(::new (S.Context) AlignedAttr(S.Context, AL, true, nullptr)); | |||
3903 | return; | |||
3904 | } | |||
3905 | ||||
3906 | Expr *E = AL.getArgAsExpr(0); | |||
3907 | if (AL.isPackExpansion() && !E->containsUnexpandedParameterPack()) { | |||
3908 | S.Diag(AL.getEllipsisLoc(), | |||
3909 | diag::err_pack_expansion_without_parameter_packs); | |||
3910 | return; | |||
3911 | } | |||
3912 | ||||
3913 | if (!AL.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E)) | |||
3914 | return; | |||
3915 | ||||
3916 | S.AddAlignedAttr(D, AL, E, AL.isPackExpansion()); | |||
3917 | } | |||
3918 | ||||
3919 | void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, | |||
3920 | bool IsPackExpansion) { | |||
3921 | AlignedAttr TmpAttr(Context, CI, true, E); | |||
3922 | SourceLocation AttrLoc = CI.getLoc(); | |||
3923 | ||||
3924 | // C++11 alignas(...) and C11 _Alignas(...) have additional requirements. | |||
3925 | if (TmpAttr.isAlignas()) { | |||
3926 | // C++11 [dcl.align]p1: | |||
3927 | // An alignment-specifier may be applied to a variable or to a class | |||
3928 | // data member, but it shall not be applied to a bit-field, a function | |||
3929 | // parameter, the formal parameter of a catch clause, or a variable | |||
3930 | // declared with the register storage class specifier. An | |||
3931 | // alignment-specifier may also be applied to the declaration of a class | |||
3932 | // or enumeration type. | |||
3933 | // C11 6.7.5/2: | |||
3934 | // An alignment attribute shall not be specified in a declaration of | |||
3935 | // a typedef, or a bit-field, or a function, or a parameter, or an | |||
3936 | // object declared with the register storage-class specifier. | |||
3937 | int DiagKind = -1; | |||
3938 | if (isa<ParmVarDecl>(D)) { | |||
3939 | DiagKind = 0; | |||
3940 | } else if (const auto *VD = dyn_cast<VarDecl>(D)) { | |||
3941 | if (VD->getStorageClass() == SC_Register) | |||
3942 | DiagKind = 1; | |||
3943 | if (VD->isExceptionVariable()) | |||
3944 | DiagKind = 2; | |||
3945 | } else if (const auto *FD = dyn_cast<FieldDecl>(D)) { | |||
3946 | if (FD->isBitField()) | |||
3947 | DiagKind = 3; | |||
3948 | } else if (!isa<TagDecl>(D)) { | |||
3949 | Diag(AttrLoc, diag::err_attribute_wrong_decl_type) << &TmpAttr | |||
3950 | << (TmpAttr.isC11() ? ExpectedVariableOrField | |||
3951 | : ExpectedVariableFieldOrTag); | |||
3952 | return; | |||
3953 | } | |||
3954 | if (DiagKind != -1) { | |||
3955 | Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type) | |||
3956 | << &TmpAttr << DiagKind; | |||
3957 | return; | |||
3958 | } | |||
3959 | } | |||
3960 | ||||
3961 | if (E->isValueDependent()) { | |||
3962 | // We can't support a dependent alignment on a non-dependent type, | |||
3963 | // because we have no way to model that a type is "alignment-dependent" | |||
3964 | // but not dependent in any other way. | |||
3965 | if (const auto *TND = dyn_cast<TypedefNameDecl>(D)) { | |||
3966 | if (!TND->getUnderlyingType()->isDependentType()) { | |||
3967 | Diag(AttrLoc, diag::err_alignment_dependent_typedef_name) | |||
3968 | << E->getSourceRange(); | |||
3969 | return; | |||
3970 | } | |||
3971 | } | |||
3972 | ||||
3973 | // Save dependent expressions in the AST to be instantiated. | |||
3974 | AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, true, E); | |||
3975 | AA->setPackExpansion(IsPackExpansion); | |||
3976 | D->addAttr(AA); | |||
3977 | return; | |||
3978 | } | |||
3979 | ||||
3980 | // FIXME: Cache the number on the AL object? | |||
3981 | llvm::APSInt Alignment; | |||
3982 | ExprResult ICE = VerifyIntegerConstantExpression( | |||
3983 | E, &Alignment, diag::err_aligned_attribute_argument_not_int); | |||
3984 | if (ICE.isInvalid()) | |||
3985 | return; | |||
3986 | ||||
3987 | uint64_t AlignVal = Alignment.getZExtValue(); | |||
3988 | ||||
3989 | // C++11 [dcl.align]p2: | |||
3990 | // -- if the constant expression evaluates to zero, the alignment | |||
3991 | // specifier shall have no effect | |||
3992 | // C11 6.7.5p6: | |||
3993 | // An alignment specification of zero has no effect. | |||
3994 | if (!(TmpAttr.isAlignas() && !Alignment)) { | |||
3995 | if (!llvm::isPowerOf2_64(AlignVal)) { | |||
3996 | Diag(AttrLoc, diag::err_alignment_not_power_of_two) | |||
3997 | << E->getSourceRange(); | |||
3998 | return; | |||
3999 | } | |||
4000 | } | |||
4001 | ||||
4002 | unsigned MaximumAlignment = Sema::MaximumAlignment; | |||
4003 | if (Context.getTargetInfo().getTriple().isOSBinFormatCOFF()) | |||
4004 | MaximumAlignment = std::min(MaximumAlignment, 8192u); | |||
4005 | if (AlignVal > MaximumAlignment) { | |||
4006 | Diag(AttrLoc, diag::err_attribute_aligned_too_great) | |||
4007 | << MaximumAlignment << E->getSourceRange(); | |||
4008 | return; | |||
4009 | } | |||
4010 | ||||
4011 | if (Context.getTargetInfo().isTLSSupported()) { | |||
4012 | unsigned MaxTLSAlign = | |||
4013 | Context.toCharUnitsFromBits(Context.getTargetInfo().getMaxTLSAlign()) | |||
4014 | .getQuantity(); | |||
4015 | const auto *VD = dyn_cast<VarDecl>(D); | |||
4016 | if (MaxTLSAlign && AlignVal > MaxTLSAlign && VD && | |||
4017 | VD->getTLSKind() != VarDecl::TLS_None) { | |||
4018 | Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum) | |||
4019 | << (unsigned)AlignVal << VD << MaxTLSAlign; | |||
4020 | return; | |||
4021 | } | |||
4022 | } | |||
4023 | ||||
4024 | AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, true, ICE.get()); | |||
4025 | AA->setPackExpansion(IsPackExpansion); | |||
4026 | D->addAttr(AA); | |||
4027 | } | |||
4028 | ||||
4029 | void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, | |||
4030 | TypeSourceInfo *TS, bool IsPackExpansion) { | |||
4031 | // FIXME: Cache the number on the AL object if non-dependent? | |||
4032 | // FIXME: Perform checking of type validity | |||
4033 | AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, false, TS); | |||
4034 | AA->setPackExpansion(IsPackExpansion); | |||
4035 | D->addAttr(AA); | |||
4036 | } | |||
4037 | ||||
4038 | void Sema::CheckAlignasUnderalignment(Decl *D) { | |||
4039 | assert(D->hasAttrs() && "no attributes on decl")((D->hasAttrs() && "no attributes on decl") ? static_cast <void> (0) : __assert_fail ("D->hasAttrs() && \"no attributes on decl\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 4039, __PRETTY_FUNCTION__)); | |||
4040 | ||||
4041 | QualType UnderlyingTy, DiagTy; | |||
4042 | if (const auto *VD = dyn_cast<ValueDecl>(D)) { | |||
4043 | UnderlyingTy = DiagTy = VD->getType(); | |||
4044 | } else { | |||
4045 | UnderlyingTy = DiagTy = Context.getTagDeclType(cast<TagDecl>(D)); | |||
4046 | if (const auto *ED = dyn_cast<EnumDecl>(D)) | |||
4047 | UnderlyingTy = ED->getIntegerType(); | |||
4048 | } | |||
4049 | if (DiagTy->isDependentType() || DiagTy->isIncompleteType()) | |||
4050 | return; | |||
4051 | ||||
4052 | // C++11 [dcl.align]p5, C11 6.7.5/4: | |||
4053 | // The combined effect of all alignment attributes in a declaration shall | |||
4054 | // not specify an alignment that is less strict than the alignment that | |||
4055 | // would otherwise be required for the entity being declared. | |||
4056 | AlignedAttr *AlignasAttr = nullptr; | |||
4057 | AlignedAttr *LastAlignedAttr = nullptr; | |||
4058 | unsigned Align = 0; | |||
4059 | for (auto *I : D->specific_attrs<AlignedAttr>()) { | |||
4060 | if (I->isAlignmentDependent()) | |||
4061 | return; | |||
4062 | if (I->isAlignas()) | |||
4063 | AlignasAttr = I; | |||
4064 | Align = std::max(Align, I->getAlignment(Context)); | |||
4065 | LastAlignedAttr = I; | |||
4066 | } | |||
4067 | ||||
4068 | if (Align && DiagTy->isSizelessType()) { | |||
4069 | Diag(LastAlignedAttr->getLocation(), diag::err_attribute_sizeless_type) | |||
4070 | << LastAlignedAttr << DiagTy; | |||
4071 | } else if (AlignasAttr && Align) { | |||
4072 | CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align); | |||
4073 | CharUnits NaturalAlign = Context.getTypeAlignInChars(UnderlyingTy); | |||
4074 | if (NaturalAlign > RequestedAlign) | |||
4075 | Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned) | |||
4076 | << DiagTy << (unsigned)NaturalAlign.getQuantity(); | |||
4077 | } | |||
4078 | } | |||
4079 | ||||
4080 | bool Sema::checkMSInheritanceAttrOnDefinition( | |||
4081 | CXXRecordDecl *RD, SourceRange Range, bool BestCase, | |||
4082 | MSInheritanceModel ExplicitModel) { | |||
4083 | assert(RD->hasDefinition() && "RD has no definition!")((RD->hasDefinition() && "RD has no definition!") ? static_cast<void> (0) : __assert_fail ("RD->hasDefinition() && \"RD has no definition!\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 4083, __PRETTY_FUNCTION__)); | |||
4084 | ||||
4085 | // We may not have seen base specifiers or any virtual methods yet. We will | |||
4086 | // have to wait until the record is defined to catch any mismatches. | |||
4087 | if (!RD->getDefinition()->isCompleteDefinition()) | |||
4088 | return false; | |||
4089 | ||||
4090 | // The unspecified model never matches what a definition could need. | |||
4091 | if (ExplicitModel == MSInheritanceModel::Unspecified) | |||
4092 | return false; | |||
4093 | ||||
4094 | if (BestCase) { | |||
4095 | if (RD->calculateInheritanceModel() == ExplicitModel) | |||
4096 | return false; | |||
4097 | } else { | |||
4098 | if (RD->calculateInheritanceModel() <= ExplicitModel) | |||
4099 | return false; | |||
4100 | } | |||
4101 | ||||
4102 | Diag(Range.getBegin(), diag::err_mismatched_ms_inheritance) | |||
4103 | << 0 /*definition*/; | |||
4104 | Diag(RD->getDefinition()->getLocation(), diag::note_defined_here) << RD; | |||
4105 | return true; | |||
4106 | } | |||
4107 | ||||
4108 | /// parseModeAttrArg - Parses attribute mode string and returns parsed type | |||
4109 | /// attribute. | |||
4110 | static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth, | |||
4111 | bool &IntegerMode, bool &ComplexMode, | |||
4112 | bool &ExplicitIEEE) { | |||
4113 | IntegerMode = true; | |||
4114 | ComplexMode = false; | |||
4115 | switch (Str.size()) { | |||
4116 | case 2: | |||
4117 | switch (Str[0]) { | |||
4118 | case 'Q': | |||
4119 | DestWidth = 8; | |||
4120 | break; | |||
4121 | case 'H': | |||
4122 | DestWidth = 16; | |||
4123 | break; | |||
4124 | case 'S': | |||
4125 | DestWidth = 32; | |||
4126 | break; | |||
4127 | case 'D': | |||
4128 | DestWidth = 64; | |||
4129 | break; | |||
4130 | case 'X': | |||
4131 | DestWidth = 96; | |||
4132 | break; | |||
4133 | case 'K': // KFmode - IEEE quad precision (__float128) | |||
4134 | ExplicitIEEE = true; | |||
4135 | DestWidth = Str[1] == 'I' ? 0 : 128; | |||
4136 | break; | |||
4137 | case 'T': | |||
4138 | ExplicitIEEE = false; | |||
4139 | DestWidth = 128; | |||
4140 | break; | |||
4141 | } | |||
4142 | if (Str[1] == 'F') { | |||
4143 | IntegerMode = false; | |||
4144 | } else if (Str[1] == 'C') { | |||
4145 | IntegerMode = false; | |||
4146 | ComplexMode = true; | |||
4147 | } else if (Str[1] != 'I') { | |||
4148 | DestWidth = 0; | |||
4149 | } | |||
4150 | break; | |||
4151 | case 4: | |||
4152 | // FIXME: glibc uses 'word' to define register_t; this is narrower than a | |||
4153 | // pointer on PIC16 and other embedded platforms. | |||
4154 | if (Str == "word") | |||
4155 | DestWidth = S.Context.getTargetInfo().getRegisterWidth(); | |||
4156 | else if (Str == "byte") | |||
4157 | DestWidth = S.Context.getTargetInfo().getCharWidth(); | |||
4158 | break; | |||
4159 | case 7: | |||
4160 | if (Str == "pointer") | |||
4161 | DestWidth = S.Context.getTargetInfo().getPointerWidth(0); | |||
4162 | break; | |||
4163 | case 11: | |||
4164 | if (Str == "unwind_word") | |||
4165 | DestWidth = S.Context.getTargetInfo().getUnwindWordWidth(); | |||
4166 | break; | |||
4167 | } | |||
4168 | } | |||
4169 | ||||
4170 | /// handleModeAttr - This attribute modifies the width of a decl with primitive | |||
4171 | /// type. | |||
4172 | /// | |||
4173 | /// Despite what would be logical, the mode attribute is a decl attribute, not a | |||
4174 | /// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be | |||
4175 | /// HImode, not an intermediate pointer. | |||
4176 | static void handleModeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4177 | // This attribute isn't documented, but glibc uses it. It changes | |||
4178 | // the width of an int or unsigned int to the specified size. | |||
4179 | if (!AL.isArgIdent(0)) { | |||
4180 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
4181 | << AL << AANT_ArgumentIdentifier; | |||
4182 | return; | |||
4183 | } | |||
4184 | ||||
4185 | IdentifierInfo *Name = AL.getArgAsIdent(0)->Ident; | |||
4186 | ||||
4187 | S.AddModeAttr(D, AL, Name); | |||
4188 | } | |||
4189 | ||||
4190 | void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI, | |||
4191 | IdentifierInfo *Name, bool InInstantiation) { | |||
4192 | StringRef Str = Name->getName(); | |||
4193 | normalizeName(Str); | |||
4194 | SourceLocation AttrLoc = CI.getLoc(); | |||
4195 | ||||
4196 | unsigned DestWidth = 0; | |||
4197 | bool IntegerMode = true; | |||
4198 | bool ComplexMode = false; | |||
4199 | bool ExplicitIEEE = false; | |||
4200 | llvm::APInt VectorSize(64, 0); | |||
4201 | if (Str.size() >= 4 && Str[0] == 'V') { | |||
4202 | // Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2). | |||
4203 | size_t StrSize = Str.size(); | |||
4204 | size_t VectorStringLength = 0; | |||
4205 | while ((VectorStringLength + 1) < StrSize && | |||
4206 | isdigit(Str[VectorStringLength + 1])) | |||
4207 | ++VectorStringLength; | |||
4208 | if (VectorStringLength && | |||
4209 | !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) && | |||
4210 | VectorSize.isPowerOf2()) { | |||
4211 | parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth, | |||
4212 | IntegerMode, ComplexMode, ExplicitIEEE); | |||
4213 | // Avoid duplicate warning from template instantiation. | |||
4214 | if (!InInstantiation) | |||
4215 | Diag(AttrLoc, diag::warn_vector_mode_deprecated); | |||
4216 | } else { | |||
4217 | VectorSize = 0; | |||
4218 | } | |||
4219 | } | |||
4220 | ||||
4221 | if (!VectorSize) | |||
4222 | parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode, | |||
4223 | ExplicitIEEE); | |||
4224 | ||||
4225 | // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t | |||
4226 | // and friends, at least with glibc. | |||
4227 | // FIXME: Make sure floating-point mappings are accurate | |||
4228 | // FIXME: Support XF and TF types | |||
4229 | if (!DestWidth) { | |||
4230 | Diag(AttrLoc, diag::err_machine_mode) << 0 /*Unknown*/ << Name; | |||
4231 | return; | |||
4232 | } | |||
4233 | ||||
4234 | QualType OldTy; | |||
4235 | if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) | |||
4236 | OldTy = TD->getUnderlyingType(); | |||
4237 | else if (const auto *ED = dyn_cast<EnumDecl>(D)) { | |||
4238 | // Something like 'typedef enum { X } __attribute__((mode(XX))) T;'. | |||
4239 | // Try to get type from enum declaration, default to int. | |||
4240 | OldTy = ED->getIntegerType(); | |||
4241 | if (OldTy.isNull()) | |||
4242 | OldTy = Context.IntTy; | |||
4243 | } else | |||
4244 | OldTy = cast<ValueDecl>(D)->getType(); | |||
4245 | ||||
4246 | if (OldTy->isDependentType()) { | |||
4247 | D->addAttr(::new (Context) ModeAttr(Context, CI, Name)); | |||
4248 | return; | |||
4249 | } | |||
4250 | ||||
4251 | // Base type can also be a vector type (see PR17453). | |||
4252 | // Distinguish between base type and base element type. | |||
4253 | QualType OldElemTy = OldTy; | |||
4254 | if (const auto *VT = OldTy->getAs<VectorType>()) | |||
4255 | OldElemTy = VT->getElementType(); | |||
4256 | ||||
4257 | // GCC allows 'mode' attribute on enumeration types (even incomplete), except | |||
4258 | // for vector modes. So, 'enum X __attribute__((mode(QI)));' forms a complete | |||
4259 | // type, 'enum { A } __attribute__((mode(V4SI)))' is rejected. | |||
4260 | if ((isa<EnumDecl>(D) || OldElemTy->getAs<EnumType>()) && | |||
4261 | VectorSize.getBoolValue()) { | |||
4262 | Diag(AttrLoc, diag::err_enum_mode_vector_type) << Name << CI.getRange(); | |||
4263 | return; | |||
4264 | } | |||
4265 | bool IntegralOrAnyEnumType = (OldElemTy->isIntegralOrEnumerationType() && | |||
4266 | !OldElemTy->isExtIntType()) || | |||
4267 | OldElemTy->getAs<EnumType>(); | |||
4268 | ||||
4269 | if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType() && | |||
4270 | !IntegralOrAnyEnumType) | |||
4271 | Diag(AttrLoc, diag::err_mode_not_primitive); | |||
4272 | else if (IntegerMode) { | |||
4273 | if (!IntegralOrAnyEnumType) | |||
4274 | Diag(AttrLoc, diag::err_mode_wrong_type); | |||
4275 | } else if (ComplexMode) { | |||
4276 | if (!OldElemTy->isComplexType()) | |||
4277 | Diag(AttrLoc, diag::err_mode_wrong_type); | |||
4278 | } else { | |||
4279 | if (!OldElemTy->isFloatingType()) | |||
4280 | Diag(AttrLoc, diag::err_mode_wrong_type); | |||
4281 | } | |||
4282 | ||||
4283 | QualType NewElemTy; | |||
4284 | ||||
4285 | if (IntegerMode) | |||
4286 | NewElemTy = Context.getIntTypeForBitwidth(DestWidth, | |||
4287 | OldElemTy->isSignedIntegerType()); | |||
4288 | else | |||
4289 | NewElemTy = Context.getRealTypeForBitwidth(DestWidth, ExplicitIEEE); | |||
4290 | ||||
4291 | if (NewElemTy.isNull()) { | |||
4292 | Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name; | |||
4293 | return; | |||
4294 | } | |||
4295 | ||||
4296 | if (ComplexMode) { | |||
4297 | NewElemTy = Context.getComplexType(NewElemTy); | |||
4298 | } | |||
4299 | ||||
4300 | QualType NewTy = NewElemTy; | |||
4301 | if (VectorSize.getBoolValue()) { | |||
4302 | NewTy = Context.getVectorType(NewTy, VectorSize.getZExtValue(), | |||
4303 | VectorType::GenericVector); | |||
4304 | } else if (const auto *OldVT = OldTy->getAs<VectorType>()) { | |||
4305 | // Complex machine mode does not support base vector types. | |||
4306 | if (ComplexMode) { | |||
4307 | Diag(AttrLoc, diag::err_complex_mode_vector_type); | |||
4308 | return; | |||
4309 | } | |||
4310 | unsigned NumElements = Context.getTypeSize(OldElemTy) * | |||
4311 | OldVT->getNumElements() / | |||
4312 | Context.getTypeSize(NewElemTy); | |||
4313 | NewTy = | |||
4314 | Context.getVectorType(NewElemTy, NumElements, OldVT->getVectorKind()); | |||
4315 | } | |||
4316 | ||||
4317 | if (NewTy.isNull()) { | |||
4318 | Diag(AttrLoc, diag::err_mode_wrong_type); | |||
4319 | return; | |||
4320 | } | |||
4321 | ||||
4322 | // Install the new type. | |||
4323 | if (auto *TD = dyn_cast<TypedefNameDecl>(D)) | |||
4324 | TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy); | |||
4325 | else if (auto *ED = dyn_cast<EnumDecl>(D)) | |||
4326 | ED->setIntegerType(NewTy); | |||
4327 | else | |||
4328 | cast<ValueDecl>(D)->setType(NewTy); | |||
4329 | ||||
4330 | D->addAttr(::new (Context) ModeAttr(Context, CI, Name)); | |||
4331 | } | |||
4332 | ||||
4333 | static void handleNoDebugAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4334 | D->addAttr(::new (S.Context) NoDebugAttr(S.Context, AL)); | |||
4335 | } | |||
4336 | ||||
4337 | AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, | |||
4338 | const AttributeCommonInfo &CI, | |||
4339 | const IdentifierInfo *Ident) { | |||
4340 | if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) { | |||
4341 | Diag(CI.getLoc(), diag::warn_attribute_ignored) << Ident; | |||
4342 | Diag(Optnone->getLocation(), diag::note_conflicting_attribute); | |||
4343 | return nullptr; | |||
4344 | } | |||
4345 | ||||
4346 | if (D->hasAttr<AlwaysInlineAttr>()) | |||
4347 | return nullptr; | |||
4348 | ||||
4349 | return ::new (Context) AlwaysInlineAttr(Context, CI); | |||
4350 | } | |||
4351 | ||||
4352 | CommonAttr *Sema::mergeCommonAttr(Decl *D, const ParsedAttr &AL) { | |||
4353 | if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, AL)) | |||
4354 | return nullptr; | |||
4355 | ||||
4356 | return ::new (Context) CommonAttr(Context, AL); | |||
4357 | } | |||
4358 | ||||
4359 | CommonAttr *Sema::mergeCommonAttr(Decl *D, const CommonAttr &AL) { | |||
4360 | if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, AL)) | |||
4361 | return nullptr; | |||
4362 | ||||
4363 | return ::new (Context) CommonAttr(Context, AL); | |||
4364 | } | |||
4365 | ||||
4366 | InternalLinkageAttr *Sema::mergeInternalLinkageAttr(Decl *D, | |||
4367 | const ParsedAttr &AL) { | |||
4368 | if (const auto *VD = dyn_cast<VarDecl>(D)) { | |||
4369 | // Attribute applies to Var but not any subclass of it (like ParmVar, | |||
4370 | // ImplicitParm or VarTemplateSpecialization). | |||
4371 | if (VD->getKind() != Decl::Var) { | |||
4372 | Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) | |||
4373 | << AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass | |||
4374 | : ExpectedVariableOrFunction); | |||
4375 | return nullptr; | |||
4376 | } | |||
4377 | // Attribute does not apply to non-static local variables. | |||
4378 | if (VD->hasLocalStorage()) { | |||
4379 | Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage); | |||
4380 | return nullptr; | |||
4381 | } | |||
4382 | } | |||
4383 | ||||
4384 | if (checkAttrMutualExclusion<CommonAttr>(*this, D, AL)) | |||
4385 | return nullptr; | |||
4386 | ||||
4387 | return ::new (Context) InternalLinkageAttr(Context, AL); | |||
4388 | } | |||
4389 | InternalLinkageAttr * | |||
4390 | Sema::mergeInternalLinkageAttr(Decl *D, const InternalLinkageAttr &AL) { | |||
4391 | if (const auto *VD = dyn_cast<VarDecl>(D)) { | |||
4392 | // Attribute applies to Var but not any subclass of it (like ParmVar, | |||
4393 | // ImplicitParm or VarTemplateSpecialization). | |||
4394 | if (VD->getKind() != Decl::Var) { | |||
4395 | Diag(AL.getLocation(), diag::warn_attribute_wrong_decl_type) | |||
4396 | << &AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass | |||
4397 | : ExpectedVariableOrFunction); | |||
4398 | return nullptr; | |||
4399 | } | |||
4400 | // Attribute does not apply to non-static local variables. | |||
4401 | if (VD->hasLocalStorage()) { | |||
4402 | Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage); | |||
4403 | return nullptr; | |||
4404 | } | |||
4405 | } | |||
4406 | ||||
4407 | if (checkAttrMutualExclusion<CommonAttr>(*this, D, AL)) | |||
4408 | return nullptr; | |||
4409 | ||||
4410 | return ::new (Context) InternalLinkageAttr(Context, AL); | |||
4411 | } | |||
4412 | ||||
4413 | MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI) { | |||
4414 | if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) { | |||
4415 | Diag(CI.getLoc(), diag::warn_attribute_ignored) << "'minsize'"; | |||
4416 | Diag(Optnone->getLocation(), diag::note_conflicting_attribute); | |||
4417 | return nullptr; | |||
4418 | } | |||
4419 | ||||
4420 | if (D->hasAttr<MinSizeAttr>()) | |||
4421 | return nullptr; | |||
4422 | ||||
4423 | return ::new (Context) MinSizeAttr(Context, CI); | |||
4424 | } | |||
4425 | ||||
4426 | NoSpeculativeLoadHardeningAttr *Sema::mergeNoSpeculativeLoadHardeningAttr( | |||
4427 | Decl *D, const NoSpeculativeLoadHardeningAttr &AL) { | |||
4428 | if (checkAttrMutualExclusion<SpeculativeLoadHardeningAttr>(*this, D, AL)) | |||
4429 | return nullptr; | |||
4430 | ||||
4431 | return ::new (Context) NoSpeculativeLoadHardeningAttr(Context, AL); | |||
4432 | } | |||
4433 | ||||
4434 | SwiftNameAttr *Sema::mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA, | |||
4435 | StringRef Name) { | |||
4436 | if (const auto *PrevSNA = D->getAttr<SwiftNameAttr>()) { | |||
4437 | if (PrevSNA->getName() != Name && !PrevSNA->isImplicit()) { | |||
4438 | Diag(PrevSNA->getLocation(), diag::err_attributes_are_not_compatible) | |||
4439 | << PrevSNA << &SNA; | |||
4440 | Diag(SNA.getLoc(), diag::note_conflicting_attribute); | |||
4441 | } | |||
4442 | ||||
4443 | D->dropAttr<SwiftNameAttr>(); | |||
4444 | } | |||
4445 | return ::new (Context) SwiftNameAttr(Context, SNA, Name); | |||
4446 | } | |||
4447 | ||||
4448 | OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, | |||
4449 | const AttributeCommonInfo &CI) { | |||
4450 | if (AlwaysInlineAttr *Inline = D->getAttr<AlwaysInlineAttr>()) { | |||
4451 | Diag(Inline->getLocation(), diag::warn_attribute_ignored) << Inline; | |||
4452 | Diag(CI.getLoc(), diag::note_conflicting_attribute); | |||
4453 | D->dropAttr<AlwaysInlineAttr>(); | |||
4454 | } | |||
4455 | if (MinSizeAttr *MinSize = D->getAttr<MinSizeAttr>()) { | |||
4456 | Diag(MinSize->getLocation(), diag::warn_attribute_ignored) << MinSize; | |||
4457 | Diag(CI.getLoc(), diag::note_conflicting_attribute); | |||
4458 | D->dropAttr<MinSizeAttr>(); | |||
4459 | } | |||
4460 | ||||
4461 | if (D->hasAttr<OptimizeNoneAttr>()) | |||
4462 | return nullptr; | |||
4463 | ||||
4464 | return ::new (Context) OptimizeNoneAttr(Context, CI); | |||
4465 | } | |||
4466 | ||||
4467 | SpeculativeLoadHardeningAttr *Sema::mergeSpeculativeLoadHardeningAttr( | |||
4468 | Decl *D, const SpeculativeLoadHardeningAttr &AL) { | |||
4469 | if (checkAttrMutualExclusion<NoSpeculativeLoadHardeningAttr>(*this, D, AL)) | |||
4470 | return nullptr; | |||
4471 | ||||
4472 | return ::new (Context) SpeculativeLoadHardeningAttr(Context, AL); | |||
4473 | } | |||
4474 | ||||
4475 | static void handleAlwaysInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4476 | if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, AL)) | |||
4477 | return; | |||
4478 | ||||
4479 | if (AlwaysInlineAttr *Inline = | |||
4480 | S.mergeAlwaysInlineAttr(D, AL, AL.getAttrName())) | |||
4481 | D->addAttr(Inline); | |||
4482 | } | |||
4483 | ||||
4484 | static void handleMinSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4485 | if (MinSizeAttr *MinSize = S.mergeMinSizeAttr(D, AL)) | |||
4486 | D->addAttr(MinSize); | |||
4487 | } | |||
4488 | ||||
4489 | static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4490 | if (OptimizeNoneAttr *Optnone = S.mergeOptimizeNoneAttr(D, AL)) | |||
4491 | D->addAttr(Optnone); | |||
4492 | } | |||
4493 | ||||
4494 | static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4495 | if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL) || | |||
4496 | checkAttrMutualExclusion<HIPManagedAttr>(S, D, AL)) | |||
4497 | return; | |||
4498 | const auto *VD = cast<VarDecl>(D); | |||
4499 | if (VD->hasLocalStorage()) { | |||
4500 | S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev); | |||
4501 | return; | |||
4502 | } | |||
4503 | D->addAttr(::new (S.Context) CUDAConstantAttr(S.Context, AL)); | |||
4504 | } | |||
4505 | ||||
4506 | static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4507 | if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL) || | |||
4508 | checkAttrMutualExclusion<HIPManagedAttr>(S, D, AL)) | |||
4509 | return; | |||
4510 | const auto *VD = cast<VarDecl>(D); | |||
4511 | // extern __shared__ is only allowed on arrays with no length (e.g. | |||
4512 | // "int x[]"). | |||
4513 | if (!S.getLangOpts().GPURelocatableDeviceCode && VD->hasExternalStorage() && | |||
4514 | !isa<IncompleteArrayType>(VD->getType())) { | |||
4515 | S.Diag(AL.getLoc(), diag::err_cuda_extern_shared) << VD; | |||
4516 | return; | |||
4517 | } | |||
4518 | if (S.getLangOpts().CUDA && VD->hasLocalStorage() && | |||
4519 | S.CUDADiagIfHostCode(AL.getLoc(), diag::err_cuda_host_shared) | |||
4520 | << S.CurrentCUDATarget()) | |||
4521 | return; | |||
4522 | D->addAttr(::new (S.Context) CUDASharedAttr(S.Context, AL)); | |||
4523 | } | |||
4524 | ||||
4525 | static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4526 | if (checkAttrMutualExclusion<CUDADeviceAttr>(S, D, AL) || | |||
4527 | checkAttrMutualExclusion<CUDAHostAttr>(S, D, AL)) { | |||
4528 | return; | |||
4529 | } | |||
4530 | const auto *FD = cast<FunctionDecl>(D); | |||
4531 | if (!FD->getReturnType()->isVoidType() && | |||
4532 | !FD->getReturnType()->getAs<AutoType>() && | |||
4533 | !FD->getReturnType()->isInstantiationDependentType()) { | |||
4534 | SourceRange RTRange = FD->getReturnTypeSourceRange(); | |||
4535 | S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) | |||
4536 | << FD->getType() | |||
4537 | << (RTRange.isValid() ? FixItHint::CreateReplacement(RTRange, "void") | |||
4538 | : FixItHint()); | |||
4539 | return; | |||
4540 | } | |||
4541 | if (const auto *Method = dyn_cast<CXXMethodDecl>(FD)) { | |||
4542 | if (Method->isInstance()) { | |||
4543 | S.Diag(Method->getBeginLoc(), diag::err_kern_is_nonstatic_method) | |||
4544 | << Method; | |||
4545 | return; | |||
4546 | } | |||
4547 | S.Diag(Method->getBeginLoc(), diag::warn_kern_is_method) << Method; | |||
4548 | } | |||
4549 | // Only warn for "inline" when compiling for host, to cut down on noise. | |||
4550 | if (FD->isInlineSpecified() && !S.getLangOpts().CUDAIsDevice) | |||
4551 | S.Diag(FD->getBeginLoc(), diag::warn_kern_is_inline) << FD; | |||
4552 | ||||
4553 | D->addAttr(::new (S.Context) CUDAGlobalAttr(S.Context, AL)); | |||
4554 | // In host compilation the kernel is emitted as a stub function, which is | |||
4555 | // a helper function for launching the kernel. The instructions in the helper | |||
4556 | // function has nothing to do with the source code of the kernel. Do not emit | |||
4557 | // debug info for the stub function to avoid confusing the debugger. | |||
4558 | if (S.LangOpts.HIP && !S.LangOpts.CUDAIsDevice) | |||
4559 | D->addAttr(NoDebugAttr::CreateImplicit(S.Context)); | |||
4560 | } | |||
4561 | ||||
4562 | static void handleDeviceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4563 | if (checkAttrMutualExclusion<CUDAGlobalAttr>(S, D, AL)) { | |||
4564 | return; | |||
4565 | } | |||
4566 | ||||
4567 | if (const auto *VD = dyn_cast<VarDecl>(D)) { | |||
4568 | if (VD->hasLocalStorage()) { | |||
4569 | S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev); | |||
4570 | return; | |||
4571 | } | |||
4572 | } | |||
4573 | ||||
4574 | if (auto *A = D->getAttr<CUDADeviceAttr>()) { | |||
4575 | if (!A->isImplicit()) | |||
4576 | return; | |||
4577 | D->dropAttr<CUDADeviceAttr>(); | |||
4578 | } | |||
4579 | D->addAttr(::new (S.Context) CUDADeviceAttr(S.Context, AL)); | |||
4580 | } | |||
4581 | ||||
4582 | static void handleManagedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4583 | if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL) || | |||
4584 | checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL)) { | |||
4585 | return; | |||
4586 | } | |||
4587 | ||||
4588 | if (const auto *VD = dyn_cast<VarDecl>(D)) { | |||
4589 | if (VD->hasLocalStorage()) { | |||
4590 | S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev); | |||
4591 | return; | |||
4592 | } | |||
4593 | } | |||
4594 | if (!D->hasAttr<HIPManagedAttr>()) | |||
4595 | D->addAttr(::new (S.Context) HIPManagedAttr(S.Context, AL)); | |||
4596 | if (!D->hasAttr<CUDADeviceAttr>()) | |||
4597 | D->addAttr(CUDADeviceAttr::CreateImplicit(S.Context)); | |||
4598 | } | |||
4599 | ||||
4600 | static void handleGNUInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4601 | const auto *Fn = cast<FunctionDecl>(D); | |||
4602 | if (!Fn->isInlineSpecified()) { | |||
4603 | S.Diag(AL.getLoc(), diag::warn_gnu_inline_attribute_requires_inline); | |||
4604 | return; | |||
4605 | } | |||
4606 | ||||
4607 | if (S.LangOpts.CPlusPlus && Fn->getStorageClass() != SC_Extern) | |||
4608 | S.Diag(AL.getLoc(), diag::warn_gnu_inline_cplusplus_without_extern); | |||
4609 | ||||
4610 | D->addAttr(::new (S.Context) GNUInlineAttr(S.Context, AL)); | |||
4611 | } | |||
4612 | ||||
4613 | static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4614 | if (hasDeclarator(D)) return; | |||
4615 | ||||
4616 | // Diagnostic is emitted elsewhere: here we store the (valid) AL | |||
4617 | // in the Decl node for syntactic reasoning, e.g., pretty-printing. | |||
4618 | CallingConv CC; | |||
4619 | if (S.CheckCallingConvAttr(AL, CC, /*FD*/nullptr)) | |||
4620 | return; | |||
4621 | ||||
4622 | if (!isa<ObjCMethodDecl>(D)) { | |||
4623 | S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) | |||
4624 | << AL << ExpectedFunctionOrMethod; | |||
4625 | return; | |||
4626 | } | |||
4627 | ||||
4628 | switch (AL.getKind()) { | |||
4629 | case ParsedAttr::AT_FastCall: | |||
4630 | D->addAttr(::new (S.Context) FastCallAttr(S.Context, AL)); | |||
4631 | return; | |||
4632 | case ParsedAttr::AT_StdCall: | |||
4633 | D->addAttr(::new (S.Context) StdCallAttr(S.Context, AL)); | |||
4634 | return; | |||
4635 | case ParsedAttr::AT_ThisCall: | |||
4636 | D->addAttr(::new (S.Context) ThisCallAttr(S.Context, AL)); | |||
4637 | return; | |||
4638 | case ParsedAttr::AT_CDecl: | |||
4639 | D->addAttr(::new (S.Context) CDeclAttr(S.Context, AL)); | |||
4640 | return; | |||
4641 | case ParsedAttr::AT_Pascal: | |||
4642 | D->addAttr(::new (S.Context) PascalAttr(S.Context, AL)); | |||
4643 | return; | |||
4644 | case ParsedAttr::AT_SwiftCall: | |||
4645 | D->addAttr(::new (S.Context) SwiftCallAttr(S.Context, AL)); | |||
4646 | return; | |||
4647 | case ParsedAttr::AT_VectorCall: | |||
4648 | D->addAttr(::new (S.Context) VectorCallAttr(S.Context, AL)); | |||
4649 | return; | |||
4650 | case ParsedAttr::AT_MSABI: | |||
4651 | D->addAttr(::new (S.Context) MSABIAttr(S.Context, AL)); | |||
4652 | return; | |||
4653 | case ParsedAttr::AT_SysVABI: | |||
4654 | D->addAttr(::new (S.Context) SysVABIAttr(S.Context, AL)); | |||
4655 | return; | |||
4656 | case ParsedAttr::AT_RegCall: | |||
4657 | D->addAttr(::new (S.Context) RegCallAttr(S.Context, AL)); | |||
4658 | return; | |||
4659 | case ParsedAttr::AT_Pcs: { | |||
4660 | PcsAttr::PCSType PCS; | |||
4661 | switch (CC) { | |||
4662 | case CC_AAPCS: | |||
4663 | PCS = PcsAttr::AAPCS; | |||
4664 | break; | |||
4665 | case CC_AAPCS_VFP: | |||
4666 | PCS = PcsAttr::AAPCS_VFP; | |||
4667 | break; | |||
4668 | default: | |||
4669 | llvm_unreachable("unexpected calling convention in pcs attribute")::llvm::llvm_unreachable_internal("unexpected calling convention in pcs attribute" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 4669); | |||
4670 | } | |||
4671 | ||||
4672 | D->addAttr(::new (S.Context) PcsAttr(S.Context, AL, PCS)); | |||
4673 | return; | |||
4674 | } | |||
4675 | case ParsedAttr::AT_AArch64VectorPcs: | |||
4676 | D->addAttr(::new (S.Context) AArch64VectorPcsAttr(S.Context, AL)); | |||
4677 | return; | |||
4678 | case ParsedAttr::AT_IntelOclBicc: | |||
4679 | D->addAttr(::new (S.Context) IntelOclBiccAttr(S.Context, AL)); | |||
4680 | return; | |||
4681 | case ParsedAttr::AT_PreserveMost: | |||
4682 | D->addAttr(::new (S.Context) PreserveMostAttr(S.Context, AL)); | |||
4683 | return; | |||
4684 | case ParsedAttr::AT_PreserveAll: | |||
4685 | D->addAttr(::new (S.Context) PreserveAllAttr(S.Context, AL)); | |||
4686 | return; | |||
4687 | default: | |||
4688 | llvm_unreachable("unexpected attribute kind")::llvm::llvm_unreachable_internal("unexpected attribute kind" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 4688); | |||
4689 | } | |||
4690 | } | |||
4691 | ||||
4692 | static void handleSuppressAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4693 | if (!checkAttributeAtLeastNumArgs(S, AL, 1)) | |||
4694 | return; | |||
4695 | ||||
4696 | std::vector<StringRef> DiagnosticIdentifiers; | |||
4697 | for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { | |||
4698 | StringRef RuleName; | |||
4699 | ||||
4700 | if (!S.checkStringLiteralArgumentAttr(AL, I, RuleName, nullptr)) | |||
4701 | return; | |||
4702 | ||||
4703 | // FIXME: Warn if the rule name is unknown. This is tricky because only | |||
4704 | // clang-tidy knows about available rules. | |||
4705 | DiagnosticIdentifiers.push_back(RuleName); | |||
4706 | } | |||
4707 | D->addAttr(::new (S.Context) | |||
4708 | SuppressAttr(S.Context, AL, DiagnosticIdentifiers.data(), | |||
4709 | DiagnosticIdentifiers.size())); | |||
4710 | } | |||
4711 | ||||
4712 | static void handleLifetimeCategoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4713 | TypeSourceInfo *DerefTypeLoc = nullptr; | |||
4714 | QualType ParmType; | |||
4715 | if (AL.hasParsedType()) { | |||
4716 | ParmType = S.GetTypeFromParser(AL.getTypeArg(), &DerefTypeLoc); | |||
4717 | ||||
4718 | unsigned SelectIdx = ~0U; | |||
4719 | if (ParmType->isReferenceType()) | |||
4720 | SelectIdx = 0; | |||
4721 | else if (ParmType->isArrayType()) | |||
4722 | SelectIdx = 1; | |||
4723 | ||||
4724 | if (SelectIdx != ~0U) { | |||
4725 | S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument) | |||
4726 | << SelectIdx << AL; | |||
4727 | return; | |||
4728 | } | |||
4729 | } | |||
4730 | ||||
4731 | // To check if earlier decl attributes do not conflict the newly parsed ones | |||
4732 | // we always add (and check) the attribute to the cannonical decl. | |||
4733 | D = D->getCanonicalDecl(); | |||
4734 | if (AL.getKind() == ParsedAttr::AT_Owner) { | |||
4735 | if (checkAttrMutualExclusion<PointerAttr>(S, D, AL)) | |||
4736 | return; | |||
4737 | if (const auto *OAttr = D->getAttr<OwnerAttr>()) { | |||
4738 | const Type *ExistingDerefType = OAttr->getDerefTypeLoc() | |||
4739 | ? OAttr->getDerefType().getTypePtr() | |||
4740 | : nullptr; | |||
4741 | if (ExistingDerefType != ParmType.getTypePtrOrNull()) { | |||
4742 | S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) | |||
4743 | << AL << OAttr; | |||
4744 | S.Diag(OAttr->getLocation(), diag::note_conflicting_attribute); | |||
4745 | } | |||
4746 | return; | |||
4747 | } | |||
4748 | for (Decl *Redecl : D->redecls()) { | |||
4749 | Redecl->addAttr(::new (S.Context) OwnerAttr(S.Context, AL, DerefTypeLoc)); | |||
4750 | } | |||
4751 | } else { | |||
4752 | if (checkAttrMutualExclusion<OwnerAttr>(S, D, AL)) | |||
4753 | return; | |||
4754 | if (const auto *PAttr = D->getAttr<PointerAttr>()) { | |||
4755 | const Type *ExistingDerefType = PAttr->getDerefTypeLoc() | |||
4756 | ? PAttr->getDerefType().getTypePtr() | |||
4757 | : nullptr; | |||
4758 | if (ExistingDerefType != ParmType.getTypePtrOrNull()) { | |||
4759 | S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) | |||
4760 | << AL << PAttr; | |||
4761 | S.Diag(PAttr->getLocation(), diag::note_conflicting_attribute); | |||
4762 | } | |||
4763 | return; | |||
4764 | } | |||
4765 | for (Decl *Redecl : D->redecls()) { | |||
4766 | Redecl->addAttr(::new (S.Context) | |||
4767 | PointerAttr(S.Context, AL, DerefTypeLoc)); | |||
4768 | } | |||
4769 | } | |||
4770 | } | |||
4771 | ||||
4772 | bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, | |||
4773 | const FunctionDecl *FD) { | |||
4774 | if (Attrs.isInvalid()) | |||
4775 | return true; | |||
4776 | ||||
4777 | if (Attrs.hasProcessingCache()) { | |||
4778 | CC = (CallingConv) Attrs.getProcessingCache(); | |||
4779 | return false; | |||
4780 | } | |||
4781 | ||||
4782 | unsigned ReqArgs = Attrs.getKind() == ParsedAttr::AT_Pcs ? 1 : 0; | |||
4783 | if (!checkAttributeNumArgs(*this, Attrs, ReqArgs)) { | |||
4784 | Attrs.setInvalid(); | |||
4785 | return true; | |||
4786 | } | |||
4787 | ||||
4788 | // TODO: diagnose uses of these conventions on the wrong target. | |||
4789 | switch (Attrs.getKind()) { | |||
4790 | case ParsedAttr::AT_CDecl: | |||
4791 | CC = CC_C; | |||
4792 | break; | |||
4793 | case ParsedAttr::AT_FastCall: | |||
4794 | CC = CC_X86FastCall; | |||
4795 | break; | |||
4796 | case ParsedAttr::AT_StdCall: | |||
4797 | CC = CC_X86StdCall; | |||
4798 | break; | |||
4799 | case ParsedAttr::AT_ThisCall: | |||
4800 | CC = CC_X86ThisCall; | |||
4801 | break; | |||
4802 | case ParsedAttr::AT_Pascal: | |||
4803 | CC = CC_X86Pascal; | |||
4804 | break; | |||
4805 | case ParsedAttr::AT_SwiftCall: | |||
4806 | CC = CC_Swift; | |||
4807 | break; | |||
4808 | case ParsedAttr::AT_VectorCall: | |||
4809 | CC = CC_X86VectorCall; | |||
4810 | break; | |||
4811 | case ParsedAttr::AT_AArch64VectorPcs: | |||
4812 | CC = CC_AArch64VectorCall; | |||
4813 | break; | |||
4814 | case ParsedAttr::AT_RegCall: | |||
4815 | CC = CC_X86RegCall; | |||
4816 | break; | |||
4817 | case ParsedAttr::AT_MSABI: | |||
4818 | CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C : | |||
4819 | CC_Win64; | |||
4820 | break; | |||
4821 | case ParsedAttr::AT_SysVABI: | |||
4822 | CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV : | |||
4823 | CC_C; | |||
4824 | break; | |||
4825 | case ParsedAttr::AT_Pcs: { | |||
4826 | StringRef StrRef; | |||
4827 | if (!checkStringLiteralArgumentAttr(Attrs, 0, StrRef)) { | |||
4828 | Attrs.setInvalid(); | |||
4829 | return true; | |||
4830 | } | |||
4831 | if (StrRef == "aapcs") { | |||
4832 | CC = CC_AAPCS; | |||
4833 | break; | |||
4834 | } else if (StrRef == "aapcs-vfp") { | |||
4835 | CC = CC_AAPCS_VFP; | |||
4836 | break; | |||
4837 | } | |||
4838 | ||||
4839 | Attrs.setInvalid(); | |||
4840 | Diag(Attrs.getLoc(), diag::err_invalid_pcs); | |||
4841 | return true; | |||
4842 | } | |||
4843 | case ParsedAttr::AT_IntelOclBicc: | |||
4844 | CC = CC_IntelOclBicc; | |||
4845 | break; | |||
4846 | case ParsedAttr::AT_PreserveMost: | |||
4847 | CC = CC_PreserveMost; | |||
4848 | break; | |||
4849 | case ParsedAttr::AT_PreserveAll: | |||
4850 | CC = CC_PreserveAll; | |||
4851 | break; | |||
4852 | default: llvm_unreachable("unexpected attribute kind")::llvm::llvm_unreachable_internal("unexpected attribute kind" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 4852); | |||
4853 | } | |||
4854 | ||||
4855 | TargetInfo::CallingConvCheckResult A = TargetInfo::CCCR_OK; | |||
4856 | const TargetInfo &TI = Context.getTargetInfo(); | |||
4857 | // CUDA functions may have host and/or device attributes which indicate | |||
4858 | // their targeted execution environment, therefore the calling convention | |||
4859 | // of functions in CUDA should be checked against the target deduced based | |||
4860 | // on their host/device attributes. | |||
4861 | if (LangOpts.CUDA) { | |||
4862 | auto *Aux = Context.getAuxTargetInfo(); | |||
4863 | auto CudaTarget = IdentifyCUDATarget(FD); | |||
4864 | bool CheckHost = false, CheckDevice = false; | |||
4865 | switch (CudaTarget) { | |||
4866 | case CFT_HostDevice: | |||
4867 | CheckHost = true; | |||
4868 | CheckDevice = true; | |||
4869 | break; | |||
4870 | case CFT_Host: | |||
4871 | CheckHost = true; | |||
4872 | break; | |||
4873 | case CFT_Device: | |||
4874 | case CFT_Global: | |||
4875 | CheckDevice = true; | |||
4876 | break; | |||
4877 | case CFT_InvalidTarget: | |||
4878 | llvm_unreachable("unexpected cuda target")::llvm::llvm_unreachable_internal("unexpected cuda target", "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 4878); | |||
4879 | } | |||
4880 | auto *HostTI = LangOpts.CUDAIsDevice ? Aux : &TI; | |||
4881 | auto *DeviceTI = LangOpts.CUDAIsDevice ? &TI : Aux; | |||
4882 | if (CheckHost && HostTI) | |||
4883 | A = HostTI->checkCallingConvention(CC); | |||
4884 | if (A == TargetInfo::CCCR_OK && CheckDevice && DeviceTI) | |||
4885 | A = DeviceTI->checkCallingConvention(CC); | |||
4886 | } else { | |||
4887 | A = TI.checkCallingConvention(CC); | |||
4888 | } | |||
4889 | ||||
4890 | switch (A) { | |||
4891 | case TargetInfo::CCCR_OK: | |||
4892 | break; | |||
4893 | ||||
4894 | case TargetInfo::CCCR_Ignore: | |||
4895 | // Treat an ignored convention as if it was an explicit C calling convention | |||
4896 | // attribute. For example, __stdcall on Win x64 functions as __cdecl, so | |||
4897 | // that command line flags that change the default convention to | |||
4898 | // __vectorcall don't affect declarations marked __stdcall. | |||
4899 | CC = CC_C; | |||
4900 | break; | |||
4901 | ||||
4902 | case TargetInfo::CCCR_Error: | |||
4903 | Diag(Attrs.getLoc(), diag::error_cconv_unsupported) | |||
4904 | << Attrs << (int)CallingConventionIgnoredReason::ForThisTarget; | |||
4905 | break; | |||
4906 | ||||
4907 | case TargetInfo::CCCR_Warning: { | |||
4908 | Diag(Attrs.getLoc(), diag::warn_cconv_unsupported) | |||
4909 | << Attrs << (int)CallingConventionIgnoredReason::ForThisTarget; | |||
4910 | ||||
4911 | // This convention is not valid for the target. Use the default function or | |||
4912 | // method calling convention. | |||
4913 | bool IsCXXMethod = false, IsVariadic = false; | |||
4914 | if (FD) { | |||
4915 | IsCXXMethod = FD->isCXXInstanceMember(); | |||
4916 | IsVariadic = FD->isVariadic(); | |||
4917 | } | |||
4918 | CC = Context.getDefaultCallingConvention(IsVariadic, IsCXXMethod); | |||
4919 | break; | |||
4920 | } | |||
4921 | } | |||
4922 | ||||
4923 | Attrs.setProcessingCache((unsigned) CC); | |||
4924 | return false; | |||
4925 | } | |||
4926 | ||||
4927 | /// Pointer-like types in the default address space. | |||
4928 | static bool isValidSwiftContextType(QualType Ty) { | |||
4929 | if (!Ty->hasPointerRepresentation()) | |||
4930 | return Ty->isDependentType(); | |||
4931 | return Ty->getPointeeType().getAddressSpace() == LangAS::Default; | |||
4932 | } | |||
4933 | ||||
4934 | /// Pointers and references in the default address space. | |||
4935 | static bool isValidSwiftIndirectResultType(QualType Ty) { | |||
4936 | if (const auto *PtrType = Ty->getAs<PointerType>()) { | |||
4937 | Ty = PtrType->getPointeeType(); | |||
4938 | } else if (const auto *RefType = Ty->getAs<ReferenceType>()) { | |||
4939 | Ty = RefType->getPointeeType(); | |||
4940 | } else { | |||
4941 | return Ty->isDependentType(); | |||
4942 | } | |||
4943 | return Ty.getAddressSpace() == LangAS::Default; | |||
4944 | } | |||
4945 | ||||
4946 | /// Pointers and references to pointers in the default address space. | |||
4947 | static bool isValidSwiftErrorResultType(QualType Ty) { | |||
4948 | if (const auto *PtrType = Ty->getAs<PointerType>()) { | |||
4949 | Ty = PtrType->getPointeeType(); | |||
4950 | } else if (const auto *RefType = Ty->getAs<ReferenceType>()) { | |||
4951 | Ty = RefType->getPointeeType(); | |||
4952 | } else { | |||
4953 | return Ty->isDependentType(); | |||
4954 | } | |||
4955 | if (!Ty.getQualifiers().empty()) | |||
4956 | return false; | |||
4957 | return isValidSwiftContextType(Ty); | |||
4958 | } | |||
4959 | ||||
4960 | void Sema::AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI, | |||
4961 | ParameterABI abi) { | |||
4962 | ||||
4963 | QualType type = cast<ParmVarDecl>(D)->getType(); | |||
4964 | ||||
4965 | if (auto existingAttr = D->getAttr<ParameterABIAttr>()) { | |||
4966 | if (existingAttr->getABI() != abi) { | |||
4967 | Diag(CI.getLoc(), diag::err_attributes_are_not_compatible) | |||
4968 | << getParameterABISpelling(abi) << existingAttr; | |||
4969 | Diag(existingAttr->getLocation(), diag::note_conflicting_attribute); | |||
4970 | return; | |||
4971 | } | |||
4972 | } | |||
4973 | ||||
4974 | switch (abi) { | |||
4975 | case ParameterABI::Ordinary: | |||
4976 | llvm_unreachable("explicit attribute for ordinary parameter ABI?")::llvm::llvm_unreachable_internal("explicit attribute for ordinary parameter ABI?" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 4976); | |||
4977 | ||||
4978 | case ParameterABI::SwiftContext: | |||
4979 | if (!isValidSwiftContextType(type)) { | |||
4980 | Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) | |||
4981 | << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type; | |||
4982 | } | |||
4983 | D->addAttr(::new (Context) SwiftContextAttr(Context, CI)); | |||
4984 | return; | |||
4985 | ||||
4986 | case ParameterABI::SwiftErrorResult: | |||
4987 | if (!isValidSwiftErrorResultType(type)) { | |||
4988 | Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) | |||
4989 | << getParameterABISpelling(abi) << /*pointer to pointer */ 1 << type; | |||
4990 | } | |||
4991 | D->addAttr(::new (Context) SwiftErrorResultAttr(Context, CI)); | |||
4992 | return; | |||
4993 | ||||
4994 | case ParameterABI::SwiftIndirectResult: | |||
4995 | if (!isValidSwiftIndirectResultType(type)) { | |||
4996 | Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) | |||
4997 | << getParameterABISpelling(abi) << /*pointer*/ 0 << type; | |||
4998 | } | |||
4999 | D->addAttr(::new (Context) SwiftIndirectResultAttr(Context, CI)); | |||
5000 | return; | |||
5001 | } | |||
5002 | llvm_unreachable("bad parameter ABI attribute")::llvm::llvm_unreachable_internal("bad parameter ABI attribute" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 5002); | |||
5003 | } | |||
5004 | ||||
5005 | /// Checks a regparm attribute, returning true if it is ill-formed and | |||
5006 | /// otherwise setting numParams to the appropriate value. | |||
5007 | bool Sema::CheckRegparmAttr(const ParsedAttr &AL, unsigned &numParams) { | |||
5008 | if (AL.isInvalid()) | |||
5009 | return true; | |||
5010 | ||||
5011 | if (!checkAttributeNumArgs(*this, AL, 1)) { | |||
5012 | AL.setInvalid(); | |||
5013 | return true; | |||
5014 | } | |||
5015 | ||||
5016 | uint32_t NP; | |||
5017 | Expr *NumParamsExpr = AL.getArgAsExpr(0); | |||
5018 | if (!checkUInt32Argument(*this, AL, NumParamsExpr, NP)) { | |||
5019 | AL.setInvalid(); | |||
5020 | return true; | |||
5021 | } | |||
5022 | ||||
5023 | if (Context.getTargetInfo().getRegParmMax() == 0) { | |||
5024 | Diag(AL.getLoc(), diag::err_attribute_regparm_wrong_platform) | |||
5025 | << NumParamsExpr->getSourceRange(); | |||
5026 | AL.setInvalid(); | |||
5027 | return true; | |||
5028 | } | |||
5029 | ||||
5030 | numParams = NP; | |||
5031 | if (numParams > Context.getTargetInfo().getRegParmMax()) { | |||
5032 | Diag(AL.getLoc(), diag::err_attribute_regparm_invalid_number) | |||
5033 | << Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange(); | |||
5034 | AL.setInvalid(); | |||
5035 | return true; | |||
5036 | } | |||
5037 | ||||
5038 | return false; | |||
5039 | } | |||
5040 | ||||
5041 | // Checks whether an argument of launch_bounds attribute is | |||
5042 | // acceptable, performs implicit conversion to Rvalue, and returns | |||
5043 | // non-nullptr Expr result on success. Otherwise, it returns nullptr | |||
5044 | // and may output an error. | |||
5045 | static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E, | |||
5046 | const CUDALaunchBoundsAttr &AL, | |||
5047 | const unsigned Idx) { | |||
5048 | if (S.DiagnoseUnexpandedParameterPack(E)) | |||
5049 | return nullptr; | |||
5050 | ||||
5051 | // Accept template arguments for now as they depend on something else. | |||
5052 | // We'll get to check them when they eventually get instantiated. | |||
5053 | if (E->isValueDependent()) | |||
5054 | return E; | |||
5055 | ||||
5056 | Optional<llvm::APSInt> I = llvm::APSInt(64); | |||
5057 | if (!(I = E->getIntegerConstantExpr(S.Context))) { | |||
5058 | S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type) | |||
5059 | << &AL << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange(); | |||
5060 | return nullptr; | |||
5061 | } | |||
5062 | // Make sure we can fit it in 32 bits. | |||
5063 | if (!I->isIntN(32)) { | |||
5064 | S.Diag(E->getExprLoc(), diag::err_ice_too_large) | |||
5065 | << I->toString(10, false) << 32 << /* Unsigned */ 1; | |||
5066 | return nullptr; | |||
5067 | } | |||
5068 | if (*I < 0) | |||
5069 | S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative) | |||
5070 | << &AL << Idx << E->getSourceRange(); | |||
5071 | ||||
5072 | // We may need to perform implicit conversion of the argument. | |||
5073 | InitializedEntity Entity = InitializedEntity::InitializeParameter( | |||
5074 | S.Context, S.Context.getConstType(S.Context.IntTy), /*consume*/ false); | |||
5075 | ExprResult ValArg = S.PerformCopyInitialization(Entity, SourceLocation(), E); | |||
5076 | assert(!ValArg.isInvalid() &&((!ValArg.isInvalid() && "Unexpected PerformCopyInitialization() failure." ) ? static_cast<void> (0) : __assert_fail ("!ValArg.isInvalid() && \"Unexpected PerformCopyInitialization() failure.\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 5077, __PRETTY_FUNCTION__)) | |||
5077 | "Unexpected PerformCopyInitialization() failure.")((!ValArg.isInvalid() && "Unexpected PerformCopyInitialization() failure." ) ? static_cast<void> (0) : __assert_fail ("!ValArg.isInvalid() && \"Unexpected PerformCopyInitialization() failure.\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 5077, __PRETTY_FUNCTION__)); | |||
5078 | ||||
5079 | return ValArg.getAs<Expr>(); | |||
5080 | } | |||
5081 | ||||
5082 | void Sema::AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI, | |||
5083 | Expr *MaxThreads, Expr *MinBlocks) { | |||
5084 | CUDALaunchBoundsAttr TmpAttr(Context, CI, MaxThreads, MinBlocks); | |||
5085 | MaxThreads = makeLaunchBoundsArgExpr(*this, MaxThreads, TmpAttr, 0); | |||
5086 | if (MaxThreads == nullptr) | |||
5087 | return; | |||
5088 | ||||
5089 | if (MinBlocks) { | |||
5090 | MinBlocks = makeLaunchBoundsArgExpr(*this, MinBlocks, TmpAttr, 1); | |||
5091 | if (MinBlocks == nullptr) | |||
5092 | return; | |||
5093 | } | |||
5094 | ||||
5095 | D->addAttr(::new (Context) | |||
5096 | CUDALaunchBoundsAttr(Context, CI, MaxThreads, MinBlocks)); | |||
5097 | } | |||
5098 | ||||
5099 | static void handleLaunchBoundsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5100 | if (!checkAttributeAtLeastNumArgs(S, AL, 1) || | |||
5101 | !checkAttributeAtMostNumArgs(S, AL, 2)) | |||
5102 | return; | |||
5103 | ||||
5104 | S.AddLaunchBoundsAttr(D, AL, AL.getArgAsExpr(0), | |||
5105 | AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr); | |||
5106 | } | |||
5107 | ||||
5108 | static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, | |||
5109 | const ParsedAttr &AL) { | |||
5110 | if (!AL.isArgIdent(0)) { | |||
5111 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
5112 | << AL << /* arg num = */ 1 << AANT_ArgumentIdentifier; | |||
5113 | return; | |||
5114 | } | |||
5115 | ||||
5116 | ParamIdx ArgumentIdx; | |||
5117 | if (!checkFunctionOrMethodParameterIndex(S, D, AL, 2, AL.getArgAsExpr(1), | |||
5118 | ArgumentIdx)) | |||
5119 | return; | |||
5120 | ||||
5121 | ParamIdx TypeTagIdx; | |||
5122 | if (!checkFunctionOrMethodParameterIndex(S, D, AL, 3, AL.getArgAsExpr(2), | |||
5123 | TypeTagIdx)) | |||
5124 | return; | |||
5125 | ||||
5126 | bool IsPointer = AL.getAttrName()->getName() == "pointer_with_type_tag"; | |||
5127 | if (IsPointer) { | |||
5128 | // Ensure that buffer has a pointer type. | |||
5129 | unsigned ArgumentIdxAST = ArgumentIdx.getASTIndex(); | |||
5130 | if (ArgumentIdxAST >= getFunctionOrMethodNumParams(D) || | |||
5131 | !getFunctionOrMethodParamType(D, ArgumentIdxAST)->isPointerType()) | |||
5132 | S.Diag(AL.getLoc(), diag::err_attribute_pointers_only) << AL << 0; | |||
5133 | } | |||
5134 | ||||
5135 | D->addAttr(::new (S.Context) ArgumentWithTypeTagAttr( | |||
5136 | S.Context, AL, AL.getArgAsIdent(0)->Ident, ArgumentIdx, TypeTagIdx, | |||
5137 | IsPointer)); | |||
5138 | } | |||
5139 | ||||
5140 | static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, | |||
5141 | const ParsedAttr &AL) { | |||
5142 | if (!AL.isArgIdent(0)) { | |||
5143 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
5144 | << AL << 1 << AANT_ArgumentIdentifier; | |||
5145 | return; | |||
5146 | } | |||
5147 | ||||
5148 | if (!checkAttributeNumArgs(S, AL, 1)) | |||
5149 | return; | |||
5150 | ||||
5151 | if (!isa<VarDecl>(D)) { | |||
5152 | S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type) | |||
5153 | << AL << ExpectedVariable; | |||
5154 | return; | |||
5155 | } | |||
5156 | ||||
5157 | IdentifierInfo *PointerKind = AL.getArgAsIdent(0)->Ident; | |||
5158 | TypeSourceInfo *MatchingCTypeLoc = nullptr; | |||
5159 | S.GetTypeFromParser(AL.getMatchingCType(), &MatchingCTypeLoc); | |||
5160 | assert(MatchingCTypeLoc && "no type source info for attribute argument")((MatchingCTypeLoc && "no type source info for attribute argument" ) ? static_cast<void> (0) : __assert_fail ("MatchingCTypeLoc && \"no type source info for attribute argument\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 5160, __PRETTY_FUNCTION__)); | |||
5161 | ||||
5162 | D->addAttr(::new (S.Context) TypeTagForDatatypeAttr( | |||
5163 | S.Context, AL, PointerKind, MatchingCTypeLoc, AL.getLayoutCompatible(), | |||
5164 | AL.getMustBeNull())); | |||
5165 | } | |||
5166 | ||||
5167 | static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5168 | ParamIdx ArgCount; | |||
5169 | ||||
5170 | if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, AL.getArgAsExpr(0), | |||
5171 | ArgCount, | |||
5172 | true /* CanIndexImplicitThis */)) | |||
5173 | return; | |||
5174 | ||||
5175 | // ArgCount isn't a parameter index [0;n), it's a count [1;n] | |||
5176 | D->addAttr(::new (S.Context) | |||
5177 | XRayLogArgsAttr(S.Context, AL, ArgCount.getSourceIndex())); | |||
5178 | } | |||
5179 | ||||
5180 | static void handlePatchableFunctionEntryAttr(Sema &S, Decl *D, | |||
5181 | const ParsedAttr &AL) { | |||
5182 | uint32_t Count = 0, Offset = 0; | |||
5183 | if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), Count, 0, true)) | |||
5184 | return; | |||
5185 | if (AL.getNumArgs() == 2) { | |||
5186 | Expr *Arg = AL.getArgAsExpr(1); | |||
5187 | if (!checkUInt32Argument(S, AL, Arg, Offset, 1, true)) | |||
5188 | return; | |||
5189 | if (Count < Offset) { | |||
5190 | S.Diag(getAttrLoc(AL), diag::err_attribute_argument_out_of_range) | |||
5191 | << &AL << 0 << Count << Arg->getBeginLoc(); | |||
5192 | return; | |||
5193 | } | |||
5194 | } | |||
5195 | D->addAttr(::new (S.Context) | |||
5196 | PatchableFunctionEntryAttr(S.Context, AL, Count, Offset)); | |||
5197 | } | |||
5198 | ||||
5199 | namespace { | |||
5200 | struct IntrinToName { | |||
5201 | uint32_t Id; | |||
5202 | int32_t FullName; | |||
5203 | int32_t ShortName; | |||
5204 | }; | |||
5205 | } // unnamed namespace | |||
5206 | ||||
5207 | static bool ArmBuiltinAliasValid(unsigned BuiltinID, StringRef AliasName, | |||
5208 | ArrayRef<IntrinToName> Map, | |||
5209 | const char *IntrinNames) { | |||
5210 | if (AliasName.startswith("__arm_")) | |||
5211 | AliasName = AliasName.substr(6); | |||
5212 | const IntrinToName *It = std::lower_bound( | |||
5213 | Map.begin(), Map.end(), BuiltinID, | |||
5214 | [](const IntrinToName &L, unsigned Id) { return L.Id < Id; }); | |||
5215 | if (It == Map.end() || It->Id != BuiltinID) | |||
5216 | return false; | |||
5217 | StringRef FullName(&IntrinNames[It->FullName]); | |||
5218 | if (AliasName == FullName) | |||
5219 | return true; | |||
5220 | if (It->ShortName == -1) | |||
5221 | return false; | |||
5222 | StringRef ShortName(&IntrinNames[It->ShortName]); | |||
5223 | return AliasName == ShortName; | |||
5224 | } | |||
5225 | ||||
5226 | static bool ArmMveAliasValid(unsigned BuiltinID, StringRef AliasName) { | |||
5227 | #include "clang/Basic/arm_mve_builtin_aliases.inc" | |||
5228 | // The included file defines: | |||
5229 | // - ArrayRef<IntrinToName> Map | |||
5230 | // - const char IntrinNames[] | |||
5231 | return ArmBuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames); | |||
5232 | } | |||
5233 | ||||
5234 | static bool ArmCdeAliasValid(unsigned BuiltinID, StringRef AliasName) { | |||
5235 | #include "clang/Basic/arm_cde_builtin_aliases.inc" | |||
5236 | return ArmBuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames); | |||
5237 | } | |||
5238 | ||||
5239 | static bool ArmSveAliasValid(unsigned BuiltinID, StringRef AliasName) { | |||
5240 | switch (BuiltinID) { | |||
5241 | default: | |||
5242 | return false; | |||
5243 | #define GET_SVE_BUILTINS | |||
5244 | #define BUILTIN(name, types, attr)case SVE::BIname: case SVE::BI##name: | |||
5245 | #include "clang/Basic/arm_sve_builtins.inc" | |||
5246 | return true; | |||
5247 | } | |||
5248 | } | |||
5249 | ||||
5250 | static void handleArmBuiltinAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5251 | if (!AL.isArgIdent(0)) { | |||
5252 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
5253 | << AL << 1 << AANT_ArgumentIdentifier; | |||
5254 | return; | |||
5255 | } | |||
5256 | ||||
5257 | IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident; | |||
5258 | unsigned BuiltinID = Ident->getBuiltinID(); | |||
5259 | StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName(); | |||
5260 | ||||
5261 | bool IsAArch64 = S.Context.getTargetInfo().getTriple().isAArch64(); | |||
5262 | if ((IsAArch64 && !ArmSveAliasValid(BuiltinID, AliasName)) || | |||
5263 | (!IsAArch64 && !ArmMveAliasValid(BuiltinID, AliasName) && | |||
5264 | !ArmCdeAliasValid(BuiltinID, AliasName))) { | |||
5265 | S.Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias); | |||
5266 | return; | |||
5267 | } | |||
5268 | ||||
5269 | D->addAttr(::new (S.Context) ArmBuiltinAliasAttr(S.Context, AL, Ident)); | |||
5270 | } | |||
5271 | ||||
5272 | //===----------------------------------------------------------------------===// | |||
5273 | // Checker-specific attribute handlers. | |||
5274 | //===----------------------------------------------------------------------===// | |||
5275 | static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType QT) { | |||
5276 | return QT->isDependentType() || QT->isObjCRetainableType(); | |||
5277 | } | |||
5278 | ||||
5279 | static bool isValidSubjectOfNSAttribute(QualType QT) { | |||
5280 | return QT->isDependentType() || QT->isObjCObjectPointerType() || | |||
5281 | QT->isObjCNSObjectType(); | |||
5282 | } | |||
5283 | ||||
5284 | static bool isValidSubjectOfCFAttribute(QualType QT) { | |||
5285 | return QT->isDependentType() || QT->isPointerType() || | |||
5286 | isValidSubjectOfNSAttribute(QT); | |||
5287 | } | |||
5288 | ||||
5289 | static bool isValidSubjectOfOSAttribute(QualType QT) { | |||
5290 | if (QT->isDependentType()) | |||
5291 | return true; | |||
5292 | QualType PT = QT->getPointeeType(); | |||
5293 | return !PT.isNull() && PT->getAsCXXRecordDecl() != nullptr; | |||
5294 | } | |||
5295 | ||||
5296 | void Sema::AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI, | |||
5297 | RetainOwnershipKind K, | |||
5298 | bool IsTemplateInstantiation) { | |||
5299 | ValueDecl *VD = cast<ValueDecl>(D); | |||
5300 | switch (K) { | |||
5301 | case RetainOwnershipKind::OS: | |||
5302 | handleSimpleAttributeOrDiagnose<OSConsumedAttr>( | |||
5303 | *this, VD, CI, isValidSubjectOfOSAttribute(VD->getType()), | |||
5304 | diag::warn_ns_attribute_wrong_parameter_type, | |||
5305 | /*ExtraArgs=*/CI.getRange(), "os_consumed", /*pointers*/ 1); | |||
5306 | return; | |||
5307 | case RetainOwnershipKind::NS: | |||
5308 | handleSimpleAttributeOrDiagnose<NSConsumedAttr>( | |||
5309 | *this, VD, CI, isValidSubjectOfNSAttribute(VD->getType()), | |||
5310 | ||||
5311 | // These attributes are normally just advisory, but in ARC, ns_consumed | |||
5312 | // is significant. Allow non-dependent code to contain inappropriate | |||
5313 | // attributes even in ARC, but require template instantiations to be | |||
5314 | // set up correctly. | |||
5315 | ((IsTemplateInstantiation && getLangOpts().ObjCAutoRefCount) | |||
5316 | ? diag::err_ns_attribute_wrong_parameter_type | |||
5317 | : diag::warn_ns_attribute_wrong_parameter_type), | |||
5318 | /*ExtraArgs=*/CI.getRange(), "ns_consumed", /*objc pointers*/ 0); | |||
5319 | return; | |||
5320 | case RetainOwnershipKind::CF: | |||
5321 | handleSimpleAttributeOrDiagnose<CFConsumedAttr>( | |||
5322 | *this, VD, CI, isValidSubjectOfCFAttribute(VD->getType()), | |||
5323 | diag::warn_ns_attribute_wrong_parameter_type, | |||
5324 | /*ExtraArgs=*/CI.getRange(), "cf_consumed", /*pointers*/ 1); | |||
5325 | return; | |||
5326 | } | |||
5327 | } | |||
5328 | ||||
5329 | static Sema::RetainOwnershipKind | |||
5330 | parsedAttrToRetainOwnershipKind(const ParsedAttr &AL) { | |||
5331 | switch (AL.getKind()) { | |||
5332 | case ParsedAttr::AT_CFConsumed: | |||
5333 | case ParsedAttr::AT_CFReturnsRetained: | |||
5334 | case ParsedAttr::AT_CFReturnsNotRetained: | |||
5335 | return Sema::RetainOwnershipKind::CF; | |||
5336 | case ParsedAttr::AT_OSConsumesThis: | |||
5337 | case ParsedAttr::AT_OSConsumed: | |||
5338 | case ParsedAttr::AT_OSReturnsRetained: | |||
5339 | case ParsedAttr::AT_OSReturnsNotRetained: | |||
5340 | case ParsedAttr::AT_OSReturnsRetainedOnZero: | |||
5341 | case ParsedAttr::AT_OSReturnsRetainedOnNonZero: | |||
5342 | return Sema::RetainOwnershipKind::OS; | |||
5343 | case ParsedAttr::AT_NSConsumesSelf: | |||
5344 | case ParsedAttr::AT_NSConsumed: | |||
5345 | case ParsedAttr::AT_NSReturnsRetained: | |||
5346 | case ParsedAttr::AT_NSReturnsNotRetained: | |||
5347 | case ParsedAttr::AT_NSReturnsAutoreleased: | |||
5348 | return Sema::RetainOwnershipKind::NS; | |||
5349 | default: | |||
5350 | llvm_unreachable("Wrong argument supplied")::llvm::llvm_unreachable_internal("Wrong argument supplied", "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 5350); | |||
5351 | } | |||
5352 | } | |||
5353 | ||||
5354 | bool Sema::checkNSReturnsRetainedReturnType(SourceLocation Loc, QualType QT) { | |||
5355 | if (isValidSubjectOfNSReturnsRetainedAttribute(QT)) | |||
5356 | return false; | |||
5357 | ||||
5358 | Diag(Loc, diag::warn_ns_attribute_wrong_return_type) | |||
5359 | << "'ns_returns_retained'" << 0 << 0; | |||
5360 | return true; | |||
5361 | } | |||
5362 | ||||
5363 | /// \return whether the parameter is a pointer to OSObject pointer. | |||
5364 | static bool isValidOSObjectOutParameter(const Decl *D) { | |||
5365 | const auto *PVD = dyn_cast<ParmVarDecl>(D); | |||
5366 | if (!PVD) | |||
5367 | return false; | |||
5368 | QualType QT = PVD->getType(); | |||
5369 | QualType PT = QT->getPointeeType(); | |||
5370 | return !PT.isNull() && isValidSubjectOfOSAttribute(PT); | |||
5371 | } | |||
5372 | ||||
5373 | static void handleXReturnsXRetainedAttr(Sema &S, Decl *D, | |||
5374 | const ParsedAttr &AL) { | |||
5375 | QualType ReturnType; | |||
5376 | Sema::RetainOwnershipKind K = parsedAttrToRetainOwnershipKind(AL); | |||
5377 | ||||
5378 | if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { | |||
5379 | ReturnType = MD->getReturnType(); | |||
5380 | } else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) && | |||
5381 | (AL.getKind() == ParsedAttr::AT_NSReturnsRetained)) { | |||
5382 | return; // ignore: was handled as a type attribute | |||
5383 | } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) { | |||
5384 | ReturnType = PD->getType(); | |||
5385 | } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
5386 | ReturnType = FD->getReturnType(); | |||
5387 | } else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) { | |||
5388 | // Attributes on parameters are used for out-parameters, | |||
5389 | // passed as pointers-to-pointers. | |||
5390 | unsigned DiagID = K == Sema::RetainOwnershipKind::CF | |||
5391 | ? /*pointer-to-CF-pointer*/2 | |||
5392 | : /*pointer-to-OSObject-pointer*/3; | |||
5393 | ReturnType = Param->getType()->getPointeeType(); | |||
5394 | if (ReturnType.isNull()) { | |||
5395 | S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type) | |||
5396 | << AL << DiagID << AL.getRange(); | |||
5397 | return; | |||
5398 | } | |||
5399 | } else if (AL.isUsedAsTypeAttr()) { | |||
5400 | return; | |||
5401 | } else { | |||
5402 | AttributeDeclKind ExpectedDeclKind; | |||
5403 | switch (AL.getKind()) { | |||
5404 | default: llvm_unreachable("invalid ownership attribute")::llvm::llvm_unreachable_internal("invalid ownership attribute" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 5404); | |||
5405 | case ParsedAttr::AT_NSReturnsRetained: | |||
5406 | case ParsedAttr::AT_NSReturnsAutoreleased: | |||
5407 | case ParsedAttr::AT_NSReturnsNotRetained: | |||
5408 | ExpectedDeclKind = ExpectedFunctionOrMethod; | |||
5409 | break; | |||
5410 | ||||
5411 | case ParsedAttr::AT_OSReturnsRetained: | |||
5412 | case ParsedAttr::AT_OSReturnsNotRetained: | |||
5413 | case ParsedAttr::AT_CFReturnsRetained: | |||
5414 | case ParsedAttr::AT_CFReturnsNotRetained: | |||
5415 | ExpectedDeclKind = ExpectedFunctionMethodOrParameter; | |||
5416 | break; | |||
5417 | } | |||
5418 | S.Diag(D->getBeginLoc(), diag::warn_attribute_wrong_decl_type) | |||
5419 | << AL.getRange() << AL << ExpectedDeclKind; | |||
5420 | return; | |||
5421 | } | |||
5422 | ||||
5423 | bool TypeOK; | |||
5424 | bool Cf; | |||
5425 | unsigned ParmDiagID = 2; // Pointer-to-CF-pointer | |||
5426 | switch (AL.getKind()) { | |||
5427 | default: llvm_unreachable("invalid ownership attribute")::llvm::llvm_unreachable_internal("invalid ownership attribute" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 5427); | |||
5428 | case ParsedAttr::AT_NSReturnsRetained: | |||
5429 | TypeOK = isValidSubjectOfNSReturnsRetainedAttribute(ReturnType); | |||
5430 | Cf = false; | |||
5431 | break; | |||
5432 | ||||
5433 | case ParsedAttr::AT_NSReturnsAutoreleased: | |||
5434 | case ParsedAttr::AT_NSReturnsNotRetained: | |||
5435 | TypeOK = isValidSubjectOfNSAttribute(ReturnType); | |||
5436 | Cf = false; | |||
5437 | break; | |||
5438 | ||||
5439 | case ParsedAttr::AT_CFReturnsRetained: | |||
5440 | case ParsedAttr::AT_CFReturnsNotRetained: | |||
5441 | TypeOK = isValidSubjectOfCFAttribute(ReturnType); | |||
5442 | Cf = true; | |||
5443 | break; | |||
5444 | ||||
5445 | case ParsedAttr::AT_OSReturnsRetained: | |||
5446 | case ParsedAttr::AT_OSReturnsNotRetained: | |||
5447 | TypeOK = isValidSubjectOfOSAttribute(ReturnType); | |||
5448 | Cf = true; | |||
5449 | ParmDiagID = 3; // Pointer-to-OSObject-pointer | |||
5450 | break; | |||
5451 | } | |||
5452 | ||||
5453 | if (!TypeOK) { | |||
5454 | if (AL.isUsedAsTypeAttr()) | |||
5455 | return; | |||
5456 | ||||
5457 | if (isa<ParmVarDecl>(D)) { | |||
5458 | S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type) | |||
5459 | << AL << ParmDiagID << AL.getRange(); | |||
5460 | } else { | |||
5461 | // Needs to be kept in sync with warn_ns_attribute_wrong_return_type. | |||
5462 | enum : unsigned { | |||
5463 | Function, | |||
5464 | Method, | |||
5465 | Property | |||
5466 | } SubjectKind = Function; | |||
5467 | if (isa<ObjCMethodDecl>(D)) | |||
5468 | SubjectKind = Method; | |||
5469 | else if (isa<ObjCPropertyDecl>(D)) | |||
5470 | SubjectKind = Property; | |||
5471 | S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type) | |||
5472 | << AL << SubjectKind << Cf << AL.getRange(); | |||
5473 | } | |||
5474 | return; | |||
5475 | } | |||
5476 | ||||
5477 | switch (AL.getKind()) { | |||
5478 | default: | |||
5479 | llvm_unreachable("invalid ownership attribute")::llvm::llvm_unreachable_internal("invalid ownership attribute" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 5479); | |||
5480 | case ParsedAttr::AT_NSReturnsAutoreleased: | |||
5481 | handleSimpleAttribute<NSReturnsAutoreleasedAttr>(S, D, AL); | |||
5482 | return; | |||
5483 | case ParsedAttr::AT_CFReturnsNotRetained: | |||
5484 | handleSimpleAttribute<CFReturnsNotRetainedAttr>(S, D, AL); | |||
5485 | return; | |||
5486 | case ParsedAttr::AT_NSReturnsNotRetained: | |||
5487 | handleSimpleAttribute<NSReturnsNotRetainedAttr>(S, D, AL); | |||
5488 | return; | |||
5489 | case ParsedAttr::AT_CFReturnsRetained: | |||
5490 | handleSimpleAttribute<CFReturnsRetainedAttr>(S, D, AL); | |||
5491 | return; | |||
5492 | case ParsedAttr::AT_NSReturnsRetained: | |||
5493 | handleSimpleAttribute<NSReturnsRetainedAttr>(S, D, AL); | |||
5494 | return; | |||
5495 | case ParsedAttr::AT_OSReturnsRetained: | |||
5496 | handleSimpleAttribute<OSReturnsRetainedAttr>(S, D, AL); | |||
5497 | return; | |||
5498 | case ParsedAttr::AT_OSReturnsNotRetained: | |||
5499 | handleSimpleAttribute<OSReturnsNotRetainedAttr>(S, D, AL); | |||
5500 | return; | |||
5501 | }; | |||
5502 | } | |||
5503 | ||||
5504 | static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, | |||
5505 | const ParsedAttr &Attrs) { | |||
5506 | const int EP_ObjCMethod = 1; | |||
5507 | const int EP_ObjCProperty = 2; | |||
5508 | ||||
5509 | SourceLocation loc = Attrs.getLoc(); | |||
5510 | QualType resultType; | |||
5511 | if (isa<ObjCMethodDecl>(D)) | |||
5512 | resultType = cast<ObjCMethodDecl>(D)->getReturnType(); | |||
5513 | else | |||
5514 | resultType = cast<ObjCPropertyDecl>(D)->getType(); | |||
5515 | ||||
5516 | if (!resultType->isReferenceType() && | |||
5517 | (!resultType->isPointerType() || resultType->isObjCRetainableType())) { | |||
5518 | S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type) | |||
5519 | << SourceRange(loc) << Attrs | |||
5520 | << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty) | |||
5521 | << /*non-retainable pointer*/ 2; | |||
5522 | ||||
5523 | // Drop the attribute. | |||
5524 | return; | |||
5525 | } | |||
5526 | ||||
5527 | D->addAttr(::new (S.Context) ObjCReturnsInnerPointerAttr(S.Context, Attrs)); | |||
5528 | } | |||
5529 | ||||
5530 | static void handleObjCRequiresSuperAttr(Sema &S, Decl *D, | |||
5531 | const ParsedAttr &Attrs) { | |||
5532 | const auto *Method = cast<ObjCMethodDecl>(D); | |||
5533 | ||||
5534 | const DeclContext *DC = Method->getDeclContext(); | |||
5535 | if (const auto *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) { | |||
5536 | S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs | |||
5537 | << 0; | |||
5538 | S.Diag(PDecl->getLocation(), diag::note_protocol_decl); | |||
5539 | return; | |||
5540 | } | |||
5541 | if (Method->getMethodFamily() == OMF_dealloc) { | |||
5542 | S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs | |||
5543 | << 1; | |||
5544 | return; | |||
5545 | } | |||
5546 | ||||
5547 | D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(S.Context, Attrs)); | |||
5548 | } | |||
5549 | ||||
5550 | static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5551 | auto *E = AL.getArgAsExpr(0); | |||
5552 | auto Loc = E ? E->getBeginLoc() : AL.getLoc(); | |||
5553 | ||||
5554 | auto *DRE = dyn_cast<DeclRefExpr>(AL.getArgAsExpr(0)); | |||
5555 | if (!DRE) { | |||
5556 | S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0; | |||
5557 | return; | |||
5558 | } | |||
5559 | ||||
5560 | auto *VD = dyn_cast<VarDecl>(DRE->getDecl()); | |||
5561 | if (!VD) { | |||
5562 | S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 1 << DRE->getDecl(); | |||
5563 | return; | |||
5564 | } | |||
5565 | ||||
5566 | if (!isNSStringType(VD->getType(), S.Context) && | |||
5567 | !isCFStringType(VD->getType(), S.Context)) { | |||
5568 | S.Diag(Loc, diag::err_nserrordomain_wrong_type) << VD; | |||
5569 | return; | |||
5570 | } | |||
5571 | ||||
5572 | D->addAttr(::new (S.Context) NSErrorDomainAttr(S.Context, AL, VD)); | |||
5573 | } | |||
5574 | ||||
5575 | static void handleObjCBridgeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5576 | IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr; | |||
5577 | ||||
5578 | if (!Parm) { | |||
5579 | S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0; | |||
5580 | return; | |||
5581 | } | |||
5582 | ||||
5583 | // Typedefs only allow objc_bridge(id) and have some additional checking. | |||
5584 | if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) { | |||
5585 | if (!Parm->Ident->isStr("id")) { | |||
5586 | S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id) << AL; | |||
5587 | return; | |||
5588 | } | |||
5589 | ||||
5590 | // Only allow 'cv void *'. | |||
5591 | QualType T = TD->getUnderlyingType(); | |||
5592 | if (!T->isVoidPointerType()) { | |||
5593 | S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_void_pointer); | |||
5594 | return; | |||
5595 | } | |||
5596 | } | |||
5597 | ||||
5598 | D->addAttr(::new (S.Context) ObjCBridgeAttr(S.Context, AL, Parm->Ident)); | |||
5599 | } | |||
5600 | ||||
5601 | static void handleObjCBridgeMutableAttr(Sema &S, Decl *D, | |||
5602 | const ParsedAttr &AL) { | |||
5603 | IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr; | |||
5604 | ||||
5605 | if (!Parm) { | |||
5606 | S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0; | |||
5607 | return; | |||
5608 | } | |||
5609 | ||||
5610 | D->addAttr(::new (S.Context) | |||
5611 | ObjCBridgeMutableAttr(S.Context, AL, Parm->Ident)); | |||
5612 | } | |||
5613 | ||||
5614 | static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D, | |||
5615 | const ParsedAttr &AL) { | |||
5616 | IdentifierInfo *RelatedClass = | |||
5617 | AL.isArgIdent(0) ? AL.getArgAsIdent(0)->Ident : nullptr; | |||
5618 | if (!RelatedClass) { | |||
5619 | S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0; | |||
5620 | return; | |||
5621 | } | |||
5622 | IdentifierInfo *ClassMethod = | |||
5623 | AL.getArgAsIdent(1) ? AL.getArgAsIdent(1)->Ident : nullptr; | |||
5624 | IdentifierInfo *InstanceMethod = | |||
5625 | AL.getArgAsIdent(2) ? AL.getArgAsIdent(2)->Ident : nullptr; | |||
5626 | D->addAttr(::new (S.Context) ObjCBridgeRelatedAttr( | |||
5627 | S.Context, AL, RelatedClass, ClassMethod, InstanceMethod)); | |||
5628 | } | |||
5629 | ||||
5630 | static void handleObjCDesignatedInitializer(Sema &S, Decl *D, | |||
5631 | const ParsedAttr &AL) { | |||
5632 | DeclContext *Ctx = D->getDeclContext(); | |||
5633 | ||||
5634 | // This attribute can only be applied to methods in interfaces or class | |||
5635 | // extensions. | |||
5636 | if (!isa<ObjCInterfaceDecl>(Ctx) && | |||
5637 | !(isa<ObjCCategoryDecl>(Ctx) && | |||
5638 | cast<ObjCCategoryDecl>(Ctx)->IsClassExtension())) { | |||
5639 | S.Diag(D->getLocation(), diag::err_designated_init_attr_non_init); | |||
5640 | return; | |||
5641 | } | |||
5642 | ||||
5643 | ObjCInterfaceDecl *IFace; | |||
5644 | if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(Ctx)) | |||
5645 | IFace = CatDecl->getClassInterface(); | |||
5646 | else | |||
5647 | IFace = cast<ObjCInterfaceDecl>(Ctx); | |||
5648 | ||||
5649 | if (!IFace) | |||
5650 | return; | |||
5651 | ||||
5652 | IFace->setHasDesignatedInitializers(); | |||
5653 | D->addAttr(::new (S.Context) ObjCDesignatedInitializerAttr(S.Context, AL)); | |||
5654 | } | |||
5655 | ||||
5656 | static void handleObjCRuntimeName(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5657 | StringRef MetaDataName; | |||
5658 | if (!S.checkStringLiteralArgumentAttr(AL, 0, MetaDataName)) | |||
5659 | return; | |||
5660 | D->addAttr(::new (S.Context) | |||
5661 | ObjCRuntimeNameAttr(S.Context, AL, MetaDataName)); | |||
5662 | } | |||
5663 | ||||
5664 | // When a user wants to use objc_boxable with a union or struct | |||
5665 | // but they don't have access to the declaration (legacy/third-party code) | |||
5666 | // then they can 'enable' this feature with a typedef: | |||
5667 | // typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct; | |||
5668 | static void handleObjCBoxable(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5669 | bool notify = false; | |||
5670 | ||||
5671 | auto *RD = dyn_cast<RecordDecl>(D); | |||
5672 | if (RD && RD->getDefinition()) { | |||
5673 | RD = RD->getDefinition(); | |||
5674 | notify = true; | |||
5675 | } | |||
5676 | ||||
5677 | if (RD) { | |||
5678 | ObjCBoxableAttr *BoxableAttr = | |||
5679 | ::new (S.Context) ObjCBoxableAttr(S.Context, AL); | |||
5680 | RD->addAttr(BoxableAttr); | |||
5681 | if (notify) { | |||
5682 | // we need to notify ASTReader/ASTWriter about | |||
5683 | // modification of existing declaration | |||
5684 | if (ASTMutationListener *L = S.getASTMutationListener()) | |||
5685 | L->AddedAttributeToRecord(BoxableAttr, RD); | |||
5686 | } | |||
5687 | } | |||
5688 | } | |||
5689 | ||||
5690 | static void handleObjCOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5691 | if (hasDeclarator(D)) return; | |||
5692 | ||||
5693 | S.Diag(D->getBeginLoc(), diag::err_attribute_wrong_decl_type) | |||
5694 | << AL.getRange() << AL << ExpectedVariable; | |||
5695 | } | |||
5696 | ||||
5697 | static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, | |||
5698 | const ParsedAttr &AL) { | |||
5699 | const auto *VD = cast<ValueDecl>(D); | |||
5700 | QualType QT = VD->getType(); | |||
5701 | ||||
5702 | if (!QT->isDependentType() && | |||
5703 | !QT->isObjCLifetimeType()) { | |||
5704 | S.Diag(AL.getLoc(), diag::err_objc_precise_lifetime_bad_type) | |||
5705 | << QT; | |||
5706 | return; | |||
5707 | } | |||
5708 | ||||
5709 | Qualifiers::ObjCLifetime Lifetime = QT.getObjCLifetime(); | |||
5710 | ||||
5711 | // If we have no lifetime yet, check the lifetime we're presumably | |||
5712 | // going to infer. | |||
5713 | if (Lifetime == Qualifiers::OCL_None && !QT->isDependentType()) | |||
5714 | Lifetime = QT->getObjCARCImplicitLifetime(); | |||
5715 | ||||
5716 | switch (Lifetime) { | |||
5717 | case Qualifiers::OCL_None: | |||
5718 | assert(QT->isDependentType() &&((QT->isDependentType() && "didn't infer lifetime for non-dependent type?" ) ? static_cast<void> (0) : __assert_fail ("QT->isDependentType() && \"didn't infer lifetime for non-dependent type?\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 5719, __PRETTY_FUNCTION__)) | |||
5719 | "didn't infer lifetime for non-dependent type?")((QT->isDependentType() && "didn't infer lifetime for non-dependent type?" ) ? static_cast<void> (0) : __assert_fail ("QT->isDependentType() && \"didn't infer lifetime for non-dependent type?\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 5719, __PRETTY_FUNCTION__)); | |||
5720 | break; | |||
5721 | ||||
5722 | case Qualifiers::OCL_Weak: // meaningful | |||
5723 | case Qualifiers::OCL_Strong: // meaningful | |||
5724 | break; | |||
5725 | ||||
5726 | case Qualifiers::OCL_ExplicitNone: | |||
5727 | case Qualifiers::OCL_Autoreleasing: | |||
5728 | S.Diag(AL.getLoc(), diag::warn_objc_precise_lifetime_meaningless) | |||
5729 | << (Lifetime == Qualifiers::OCL_Autoreleasing); | |||
5730 | break; | |||
5731 | } | |||
5732 | ||||
5733 | D->addAttr(::new (S.Context) ObjCPreciseLifetimeAttr(S.Context, AL)); | |||
5734 | } | |||
5735 | ||||
5736 | static void handleSwiftAttrAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5737 | // Make sure that there is a string literal as the annotation's single | |||
5738 | // argument. | |||
5739 | StringRef Str; | |||
5740 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) | |||
5741 | return; | |||
5742 | ||||
5743 | D->addAttr(::new (S.Context) SwiftAttrAttr(S.Context, AL, Str)); | |||
5744 | } | |||
5745 | ||||
5746 | static void handleSwiftBridge(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5747 | // Make sure that there is a string literal as the annotation's single | |||
5748 | // argument. | |||
5749 | StringRef BT; | |||
5750 | if (!S.checkStringLiteralArgumentAttr(AL, 0, BT)) | |||
5751 | return; | |||
5752 | ||||
5753 | // Warn about duplicate attributes if they have different arguments, but drop | |||
5754 | // any duplicate attributes regardless. | |||
5755 | if (const auto *Other = D->getAttr<SwiftBridgeAttr>()) { | |||
5756 | if (Other->getSwiftType() != BT) | |||
5757 | S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; | |||
5758 | return; | |||
5759 | } | |||
5760 | ||||
5761 | D->addAttr(::new (S.Context) SwiftBridgeAttr(S.Context, AL, BT)); | |||
5762 | } | |||
5763 | ||||
5764 | static bool isErrorParameter(Sema &S, QualType QT) { | |||
5765 | const auto *PT = QT->getAs<PointerType>(); | |||
5766 | if (!PT) | |||
5767 | return false; | |||
5768 | ||||
5769 | QualType Pointee = PT->getPointeeType(); | |||
5770 | ||||
5771 | // Check for NSError**. | |||
5772 | if (const auto *OPT = Pointee->getAs<ObjCObjectPointerType>()) | |||
5773 | if (const auto *ID = OPT->getInterfaceDecl()) | |||
5774 | if (ID->getIdentifier() == S.getNSErrorIdent()) | |||
5775 | return true; | |||
5776 | ||||
5777 | // Check for CFError**. | |||
5778 | if (const auto *PT = Pointee->getAs<PointerType>()) | |||
5779 | if (const auto *RT = PT->getPointeeType()->getAs<RecordType>()) | |||
5780 | if (S.isCFError(RT->getDecl())) | |||
5781 | return true; | |||
5782 | ||||
5783 | return false; | |||
5784 | } | |||
5785 | ||||
5786 | static void handleSwiftError(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5787 | auto hasErrorParameter = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool { | |||
5788 | for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) { | |||
5789 | if (isErrorParameter(S, getFunctionOrMethodParamType(D, I))) | |||
5790 | return true; | |||
5791 | } | |||
5792 | ||||
5793 | S.Diag(AL.getLoc(), diag::err_attr_swift_error_no_error_parameter) | |||
5794 | << AL << isa<ObjCMethodDecl>(D); | |||
5795 | return false; | |||
5796 | }; | |||
5797 | ||||
5798 | auto hasPointerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool { | |||
5799 | // - C, ObjC, and block pointers are definitely okay. | |||
5800 | // - References are definitely not okay. | |||
5801 | // - nullptr_t is weird, but acceptable. | |||
5802 | QualType RT = getFunctionOrMethodResultType(D); | |||
5803 | if (RT->hasPointerRepresentation() && !RT->isReferenceType()) | |||
5804 | return true; | |||
5805 | ||||
5806 | S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type) | |||
5807 | << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D) | |||
5808 | << /*pointer*/ 1; | |||
5809 | return false; | |||
5810 | }; | |||
5811 | ||||
5812 | auto hasIntegerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool { | |||
5813 | QualType RT = getFunctionOrMethodResultType(D); | |||
5814 | if (RT->isIntegralType(S.Context)) | |||
5815 | return true; | |||
5816 | ||||
5817 | S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type) | |||
5818 | << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D) | |||
5819 | << /*integral*/ 0; | |||
5820 | return false; | |||
5821 | }; | |||
5822 | ||||
5823 | if (D->isInvalidDecl()) | |||
5824 | return; | |||
5825 | ||||
5826 | IdentifierLoc *Loc = AL.getArgAsIdent(0); | |||
5827 | SwiftErrorAttr::ConventionKind Convention; | |||
5828 | if (!SwiftErrorAttr::ConvertStrToConventionKind(Loc->Ident->getName(), | |||
5829 | Convention)) { | |||
5830 | S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) | |||
5831 | << AL << Loc->Ident; | |||
5832 | return; | |||
5833 | } | |||
5834 | ||||
5835 | switch (Convention) { | |||
5836 | case SwiftErrorAttr::None: | |||
5837 | // No additional validation required. | |||
5838 | break; | |||
5839 | ||||
5840 | case SwiftErrorAttr::NonNullError: | |||
5841 | if (!hasErrorParameter(S, D, AL)) | |||
5842 | return; | |||
5843 | break; | |||
5844 | ||||
5845 | case SwiftErrorAttr::NullResult: | |||
5846 | if (!hasErrorParameter(S, D, AL) || !hasPointerResult(S, D, AL)) | |||
5847 | return; | |||
5848 | break; | |||
5849 | ||||
5850 | case SwiftErrorAttr::NonZeroResult: | |||
5851 | case SwiftErrorAttr::ZeroResult: | |||
5852 | if (!hasErrorParameter(S, D, AL) || !hasIntegerResult(S, D, AL)) | |||
5853 | return; | |||
5854 | break; | |||
5855 | } | |||
5856 | ||||
5857 | D->addAttr(::new (S.Context) SwiftErrorAttr(S.Context, AL, Convention)); | |||
5858 | } | |||
5859 | ||||
5860 | static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D, | |||
5861 | const SwiftAsyncErrorAttr *ErrorAttr, | |||
5862 | const SwiftAsyncAttr *AsyncAttr) { | |||
5863 | if (AsyncAttr->getKind() == SwiftAsyncAttr::None) { | |||
| ||||
5864 | if (ErrorAttr->getConvention() != SwiftAsyncErrorAttr::None) { | |||
5865 | S.Diag(AsyncAttr->getLocation(), | |||
5866 | diag::err_swift_async_error_without_swift_async) | |||
5867 | << AsyncAttr << isa<ObjCMethodDecl>(D); | |||
5868 | } | |||
5869 | return; | |||
5870 | } | |||
5871 | ||||
5872 | const ParmVarDecl *HandlerParam = getFunctionOrMethodParam( | |||
5873 | D, AsyncAttr->getCompletionHandlerIndex().getASTIndex()); | |||
5874 | // handleSwiftAsyncAttr already verified the type is correct, so no need to | |||
5875 | // double-check it here. | |||
5876 | const auto *FuncTy = HandlerParam->getType() | |||
| ||||
5877 | ->getAs<BlockPointerType>() | |||
5878 | ->getPointeeType() | |||
5879 | ->getAs<FunctionProtoType>(); | |||
5880 | ArrayRef<QualType> BlockParams; | |||
5881 | if (FuncTy) | |||
5882 | BlockParams = FuncTy->getParamTypes(); | |||
5883 | ||||
5884 | switch (ErrorAttr->getConvention()) { | |||
5885 | case SwiftAsyncErrorAttr::ZeroArgument: | |||
5886 | case SwiftAsyncErrorAttr::NonZeroArgument: { | |||
5887 | uint32_t ParamIdx = ErrorAttr->getHandlerParamIdx(); | |||
5888 | if (ParamIdx == 0 || ParamIdx > BlockParams.size()) { | |||
5889 | S.Diag(ErrorAttr->getLocation(), | |||
5890 | diag::err_attribute_argument_out_of_bounds) << ErrorAttr << 2; | |||
5891 | return; | |||
5892 | } | |||
5893 | QualType ErrorParam = BlockParams[ParamIdx - 1]; | |||
5894 | if (!ErrorParam->isIntegralType(S.Context)) { | |||
5895 | StringRef ConvStr = | |||
5896 | ErrorAttr->getConvention() == SwiftAsyncErrorAttr::ZeroArgument | |||
5897 | ? "zero_argument" | |||
5898 | : "nonzero_argument"; | |||
5899 | S.Diag(ErrorAttr->getLocation(), diag::err_swift_async_error_non_integral) | |||
5900 | << ErrorAttr << ConvStr << ParamIdx << ErrorParam; | |||
5901 | return; | |||
5902 | } | |||
5903 | break; | |||
5904 | } | |||
5905 | case SwiftAsyncErrorAttr::NonNullError: { | |||
5906 | bool AnyErrorParams = false; | |||
5907 | for (QualType Param : BlockParams) { | |||
5908 | // Check for NSError *. | |||
5909 | if (const auto *ObjCPtrTy = Param->getAs<ObjCObjectPointerType>()) { | |||
5910 | if (const auto *ID = ObjCPtrTy->getInterfaceDecl()) { | |||
5911 | if (ID->getIdentifier() == S.getNSErrorIdent()) { | |||
5912 | AnyErrorParams = true; | |||
5913 | break; | |||
5914 | } | |||
5915 | } | |||
5916 | } | |||
5917 | // Check for CFError *. | |||
5918 | if (const auto *PtrTy = Param->getAs<PointerType>()) { | |||
5919 | if (const auto *RT = PtrTy->getPointeeType()->getAs<RecordType>()) { | |||
5920 | if (S.isCFError(RT->getDecl())) { | |||
5921 | AnyErrorParams = true; | |||
5922 | break; | |||
5923 | } | |||
5924 | } | |||
5925 | } | |||
5926 | } | |||
5927 | ||||
5928 | if (!AnyErrorParams) { | |||
5929 | S.Diag(ErrorAttr->getLocation(), | |||
5930 | diag::err_swift_async_error_no_error_parameter) | |||
5931 | << ErrorAttr << isa<ObjCMethodDecl>(D); | |||
5932 | return; | |||
5933 | } | |||
5934 | break; | |||
5935 | } | |||
5936 | case SwiftAsyncErrorAttr::None: | |||
5937 | break; | |||
5938 | } | |||
5939 | } | |||
5940 | ||||
5941 | static void handleSwiftAsyncError(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5942 | IdentifierLoc *IDLoc = AL.getArgAsIdent(0); | |||
5943 | SwiftAsyncErrorAttr::ConventionKind ConvKind; | |||
5944 | if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind(IDLoc->Ident->getName(), | |||
5945 | ConvKind)) { | |||
5946 | S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) | |||
5947 | << AL << IDLoc->Ident; | |||
5948 | return; | |||
5949 | } | |||
5950 | ||||
5951 | uint32_t ParamIdx = 0; | |||
5952 | switch (ConvKind) { | |||
5953 | case SwiftAsyncErrorAttr::ZeroArgument: | |||
5954 | case SwiftAsyncErrorAttr::NonZeroArgument: { | |||
5955 | if (!checkAttributeNumArgs(S, AL, 2)) | |||
5956 | return; | |||
5957 | ||||
5958 | Expr *IdxExpr = AL.getArgAsExpr(1); | |||
5959 | if (!checkUInt32Argument(S, AL, IdxExpr, ParamIdx)) | |||
5960 | return; | |||
5961 | break; | |||
5962 | } | |||
5963 | case SwiftAsyncErrorAttr::NonNullError: | |||
5964 | case SwiftAsyncErrorAttr::None: { | |||
5965 | if (!checkAttributeNumArgs(S, AL, 1)) | |||
5966 | return; | |||
5967 | break; | |||
5968 | } | |||
5969 | } | |||
5970 | ||||
5971 | auto *ErrorAttr = | |||
5972 | ::new (S.Context) SwiftAsyncErrorAttr(S.Context, AL, ConvKind, ParamIdx); | |||
5973 | D->addAttr(ErrorAttr); | |||
5974 | ||||
5975 | if (auto *AsyncAttr = D->getAttr<SwiftAsyncAttr>()) | |||
5976 | checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr); | |||
5977 | } | |||
5978 | ||||
5979 | // For a function, this will validate a compound Swift name, e.g. | |||
5980 | // <code>init(foo:bar:baz:)</code> or <code>controllerForName(_:)</code>, and | |||
5981 | // the function will output the number of parameter names, and whether this is a | |||
5982 | // single-arg initializer. | |||
5983 | // | |||
5984 | // For a type, enum constant, property, or variable declaration, this will | |||
5985 | // validate either a simple identifier, or a qualified | |||
5986 | // <code>context.identifier</code> name. | |||
5987 | static bool | |||
5988 | validateSwiftFunctionName(Sema &S, const ParsedAttr &AL, SourceLocation Loc, | |||
5989 | StringRef Name, unsigned &SwiftParamCount, | |||
5990 | bool &IsSingleParamInit) { | |||
5991 | SwiftParamCount = 0; | |||
5992 | IsSingleParamInit = false; | |||
5993 | ||||
5994 | // Check whether this will be mapped to a getter or setter of a property. | |||
5995 | bool IsGetter = false, IsSetter = false; | |||
5996 | if (Name.startswith("getter:")) { | |||
5997 | IsGetter = true; | |||
5998 | Name = Name.substr(7); | |||
5999 | } else if (Name.startswith("setter:")) { | |||
6000 | IsSetter = true; | |||
6001 | Name = Name.substr(7); | |||
6002 | } | |||
6003 | ||||
6004 | if (Name.back() != ')') { | |||
6005 | S.Diag(Loc, diag::warn_attr_swift_name_function) << AL; | |||
6006 | return false; | |||
6007 | } | |||
6008 | ||||
6009 | bool IsMember = false; | |||
6010 | StringRef ContextName, BaseName, Parameters; | |||
6011 | ||||
6012 | std::tie(BaseName, Parameters) = Name.split('('); | |||
6013 | ||||
6014 | // Split at the first '.', if it exists, which separates the context name | |||
6015 | // from the base name. | |||
6016 | std::tie(ContextName, BaseName) = BaseName.split('.'); | |||
6017 | if (BaseName.empty()) { | |||
6018 | BaseName = ContextName; | |||
6019 | ContextName = StringRef(); | |||
6020 | } else if (ContextName.empty() || !isValidIdentifier(ContextName)) { | |||
6021 | S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) | |||
6022 | << AL << /*context*/ 1; | |||
6023 | return false; | |||
6024 | } else { | |||
6025 | IsMember = true; | |||
6026 | } | |||
6027 | ||||
6028 | if (!isValidIdentifier(BaseName) || BaseName == "_") { | |||
6029 | S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) | |||
6030 | << AL << /*basename*/ 0; | |||
6031 | return false; | |||
6032 | } | |||
6033 | ||||
6034 | bool IsSubscript = BaseName == "subscript"; | |||
6035 | // A subscript accessor must be a getter or setter. | |||
6036 | if (IsSubscript && !IsGetter && !IsSetter) { | |||
6037 | S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter) | |||
6038 | << AL << /* getter or setter */ 0; | |||
6039 | return false; | |||
6040 | } | |||
6041 | ||||
6042 | if (Parameters.empty()) { | |||
6043 | S.Diag(Loc, diag::warn_attr_swift_name_missing_parameters) << AL; | |||
6044 | return false; | |||
6045 | } | |||
6046 | ||||
6047 | assert(Parameters.back() == ')' && "expected ')'")((Parameters.back() == ')' && "expected ')'") ? static_cast <void> (0) : __assert_fail ("Parameters.back() == ')' && \"expected ')'\"" , "/build/llvm-toolchain-snapshot-13~++20210308111132+66e3a4abe99c/clang/lib/Sema/SemaDeclAttr.cpp" , 6047, __PRETTY_FUNCTION__)); | |||
6048 | Parameters = Parameters.drop_back(); // ')' | |||
6049 | ||||
6050 | if (Parameters.empty()) { | |||
6051 | // Setters and subscripts must have at least one parameter. | |||
6052 | if (IsSubscript) { | |||
6053 | S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter) | |||
6054 | << AL << /* have at least one parameter */1; | |||
6055 | return false; | |||
6056 | } | |||
6057 | ||||
6058 | if (IsSetter) { | |||
6059 | S.Diag(Loc, diag::warn_attr_swift_name_setter_parameters) << AL; | |||
6060 | return false; | |||
6061 | } | |||
6062 | ||||
6063 | return true; | |||
6064 | } | |||
6065 | ||||
6066 | if (Parameters.back() != ':') { | |||
6067 | S.Diag(Loc, diag::warn_attr_swift_name_function) << AL; | |||
6068 | return false; | |||
6069 | } | |||
6070 | ||||
6071 | StringRef CurrentParam; | |||
6072 | llvm::Optional<unsigned> SelfLocation; | |||
6073 | unsigned NewValueCount = 0; | |||
6074 | llvm::Optional<unsigned> NewValueLocation; | |||
6075 | do { | |||
6076 | std::tie(CurrentParam, Parameters) = Parameters.split(':'); | |||
6077 | ||||
6078 | if (!isValidIdentifier(CurrentParam)) { | |||
6079 | S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) | |||
6080 | << AL << /*parameter*/2; | |||
6081 | return false; | |||
6082 | } | |||
6083 | ||||
6084 | if (IsMember && CurrentParam == "self") { | |||
6085 | // "self" indicates the "self" argument for a member. | |||
6086 | ||||
6087 | // More than one "self"? | |||
6088 | if (SelfLocation) { | |||
6089 | S.Diag(Loc, diag::warn_attr_swift_name_multiple_selfs) << AL; | |||
6090 | return false; | |||
6091 | } | |||
6092 | ||||
6093 | // The "self" location is the current parameter. | |||
6094 | SelfLocation = SwiftParamCount; | |||
6095 | } else if (CurrentParam == "newValue") { | |||
6096 | // "newValue" indicates the "newValue" argument for a setter. | |||
6097 | ||||
6098 | // There should only be one 'newValue', but it's only significant for | |||
6099 | // subscript accessors, so don't error right away. | |||
6100 | ++NewValueCount; | |||
6101 | ||||
6102 | NewValueLocation = SwiftParamCount; | |||
6103 | } | |||
6104 | ||||
6105 | ++SwiftParamCount; | |||
6106 | } while (!Parameters.empty()); | |||
6107 | ||||
6108 | // Only instance subscripts are currently supported. | |||
6109 | if (IsSubscript && !SelfLocation) { | |||
6110 | S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter) | |||
6111 | << AL << /*have a 'self:' parameter*/2; | |||
6112 | return false; | |||
6113 | } | |||
6114 | ||||
6115 | IsSingleParamInit = | |||
6116 | SwiftParamCount == 1 && BaseName == "init" && CurrentParam != "_"; | |||
6117 | ||||
6118 | // Check the number of parameters for a getter/setter. | |||
6119 | if (IsGetter || IsSetter) { | |||
6120 | // Setters have one parameter for the new value. | |||
6121 | unsigned NumExpectedParams = IsGetter ? 0 : 1; | |||
6122 | unsigned ParamDiag = | |||
6123 | IsGetter ? diag::warn_attr_swift_name_getter_parameters | |||
6124 | : diag::warn_attr_swift_name_setter_parameters; | |||
6125 | ||||
6126 | // Instance methods have one parameter for "self". | |||
6127 | if (SelfLocation) | |||
6128 | ++NumExpectedParams; | |||
6129 | ||||
6130 | // Subscripts may have additional parameters beyond the expected params for | |||
6131 | // the index. | |||
6132 | if (IsSubscript) { | |||
6133 | if (SwiftParamCount < NumExpectedParams) { | |||
6134 | S.Diag(Loc, ParamDiag) << AL; | |||
6135 | return false; | |||
6136 | } | |||
6137 | ||||
6138 | // A subscript setter must explicitly label its newValue parameter to | |||
6139 | // distinguish it from index parameters. | |||
6140 | if (IsSetter) { | |||
6141 | if (!NewValueLocation) { | |||
6142 | S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_no_newValue) | |||
6143 | << AL; | |||
6144 | return false; | |||
6145 | } | |||
6146 | if (NewValueCount > 1) { | |||
6147 | S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_multiple_newValues) | |||
6148 | << AL; | |||
6149 | return false; | |||
6150 | } | |||
6151 | } else { | |||
6152 | // Subscript getters should have no 'newValue:' parameter. | |||
6153 | if (NewValueLocation) { | |||
6154 | S.Diag(Loc, diag::warn_attr_swift_name_subscript_getter_newValue) | |||
6155 | << AL; | |||
6156 | return false; | |||
6157 | } | |||
6158 | } | |||
6159 | } else { | |||
6160 | // Property accessors must have exactly the number of expected params. | |||
6161 | if (SwiftParamCount != NumExpectedParams) { | |||
6162 | S.Diag(Loc, ParamDiag) << AL; | |||
6163 | return false; | |||
6164 | } | |||
6165 | } | |||
6166 | } | |||
6167 | ||||
6168 | return true; | |||
6169 | } | |||
6170 | ||||
6171 | bool Sema::DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc, | |||
6172 | const ParsedAttr &AL, bool IsAsync) { | |||
6173 | if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) { | |||
6174 | ArrayRef<ParmVarDecl*> Params; | |||
6175 | unsigned ParamCount; | |||
6176 | ||||
6177 | if (const auto *Method = dyn_cast<ObjCMethodDecl>(D)) { | |||
6178 | ParamCount = Method->getSelector().getNumArgs(); | |||
6179 | Params = Method->parameters().slice(0, ParamCount); | |||
6180 | } else { | |||
6181 | const auto *F = cast<FunctionDecl>(D); | |||
6182 | ||||
6183 | ParamCount = F->getNumParams(); | |||
6184 | Params = F->parameters(); | |||
6185 | ||||
6186 | if (!F->hasWrittenPrototype()) { | |||
6187 | Diag(Loc, diag::warn_attribute_wrong_decl_type) << AL | |||
6188 | << ExpectedFunctionWithProtoType; | |||
6189 | return false; | |||
6190 | } | |||
6191 | } | |||
6192 | ||||
6193 | // The async name drops the last callback parameter. | |||
6194 | if (IsAsync) { | |||
6195 | if (ParamCount == 0) { | |||
6196 | Diag(Loc, diag::warn_attr_swift_name_decl_missing_params) | |||
6197 | << AL << isa<ObjCMethodDecl>(D); | |||
6198 | return false; | |||
6199 | } | |||
6200 | ParamCount -= 1; | |||
6201 | } | |||
6202 | ||||
6203 | unsigned SwiftParamCount; | |||
6204 | bool IsSingleParamInit; | |||
6205 | if (!validateSwiftFunctionName(*this, AL, Loc, Name, | |||
6206 | SwiftParamCount, IsSingleParamInit)) | |||
6207 | return false; | |||
6208 | ||||
6209 | bool ParamCountValid; | |||
6210 | if (SwiftParamCount == ParamCount) { | |||
6211 | ParamCountValid = true; | |||
6212 | } else if (SwiftParamCount > ParamCount) { | |||
6213 | ParamCountValid = IsSingleParamInit && ParamCount == 0; | |||
6214 | } else { | |||
6215 | // We have fewer Swift parameters than Objective-C parameters, but that | |||
6216 | // might be because we've transformed some of them. Check for potential | |||
6217 | // "out" parameters and err on the side of not warning. | |||
6218 | unsigned MaybeOutParamCount = | |||
6219 | std::count_if(Params.begin(), Params.end(), | |||
6220 | [](const ParmVarDecl *Param) -> bool { | |||
6221 | QualType ParamTy = Param->getType(); | |||