File: | clang/lib/Sema/SemaDeclAttr.cpp |
Warning: | line 5838, 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 | bool AllowNSAttributedString = false) { | |||
159 | const auto *PT = T->getAs<ObjCObjectPointerType>(); | |||
160 | if (!PT) | |||
161 | return false; | |||
162 | ||||
163 | ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface(); | |||
164 | if (!Cls) | |||
165 | return false; | |||
166 | ||||
167 | IdentifierInfo* ClsName = Cls->getIdentifier(); | |||
168 | ||||
169 | if (AllowNSAttributedString && | |||
170 | ClsName == &Ctx.Idents.get("NSAttributedString")) | |||
171 | return true; | |||
172 | // FIXME: Should we walk the chain of classes? | |||
173 | return ClsName == &Ctx.Idents.get("NSString") || | |||
174 | ClsName == &Ctx.Idents.get("NSMutableString"); | |||
175 | } | |||
176 | ||||
177 | static inline bool isCFStringType(QualType T, ASTContext &Ctx) { | |||
178 | const auto *PT = T->getAs<PointerType>(); | |||
179 | if (!PT) | |||
180 | return false; | |||
181 | ||||
182 | const auto *RT = PT->getPointeeType()->getAs<RecordType>(); | |||
183 | if (!RT) | |||
184 | return false; | |||
185 | ||||
186 | const RecordDecl *RD = RT->getDecl(); | |||
187 | if (RD->getTagKind() != TTK_Struct) | |||
188 | return false; | |||
189 | ||||
190 | return RD->getIdentifier() == &Ctx.Idents.get("__CFString"); | |||
191 | } | |||
192 | ||||
193 | static unsigned getNumAttributeArgs(const ParsedAttr &AL) { | |||
194 | // FIXME: Include the type in the argument list. | |||
195 | return AL.getNumArgs() + AL.hasParsedType(); | |||
196 | } | |||
197 | ||||
198 | /// A helper function to provide Attribute Location for the Attr types | |||
199 | /// AND the ParsedAttr. | |||
200 | template <typename AttrInfo> | |||
201 | static std::enable_if_t<std::is_base_of<Attr, AttrInfo>::value, SourceLocation> | |||
202 | getAttrLoc(const AttrInfo &AL) { | |||
203 | return AL.getLocation(); | |||
204 | } | |||
205 | static SourceLocation getAttrLoc(const ParsedAttr &AL) { return AL.getLoc(); } | |||
206 | ||||
207 | /// If Expr is a valid integer constant, get the value of the integer | |||
208 | /// expression and return success or failure. May output an error. | |||
209 | /// | |||
210 | /// Negative argument is implicitly converted to unsigned, unless | |||
211 | /// \p StrictlyUnsigned is true. | |||
212 | template <typename AttrInfo> | |||
213 | static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr, | |||
214 | uint32_t &Val, unsigned Idx = UINT_MAX(2147483647 *2U +1U), | |||
215 | bool StrictlyUnsigned = false) { | |||
216 | Optional<llvm::APSInt> I = llvm::APSInt(32); | |||
217 | if (Expr->isTypeDependent() || Expr->isValueDependent() || | |||
218 | !(I = Expr->getIntegerConstantExpr(S.Context))) { | |||
219 | if (Idx != UINT_MAX(2147483647 *2U +1U)) | |||
220 | S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type) | |||
221 | << &AI << Idx << AANT_ArgumentIntegerConstant | |||
222 | << Expr->getSourceRange(); | |||
223 | else | |||
224 | S.Diag(getAttrLoc(AI), diag::err_attribute_argument_type) | |||
225 | << &AI << AANT_ArgumentIntegerConstant << Expr->getSourceRange(); | |||
226 | return false; | |||
227 | } | |||
228 | ||||
229 | if (!I->isIntN(32)) { | |||
230 | S.Diag(Expr->getExprLoc(), diag::err_ice_too_large) | |||
231 | << I->toString(10, false) << 32 << /* Unsigned */ 1; | |||
232 | return false; | |||
233 | } | |||
234 | ||||
235 | if (StrictlyUnsigned && I->isSigned() && I->isNegative()) { | |||
236 | S.Diag(getAttrLoc(AI), diag::err_attribute_requires_positive_integer) | |||
237 | << &AI << /*non-negative*/ 1; | |||
238 | return false; | |||
239 | } | |||
240 | ||||
241 | Val = (uint32_t)I->getZExtValue(); | |||
242 | return true; | |||
243 | } | |||
244 | ||||
245 | /// Wrapper around checkUInt32Argument, with an extra check to be sure | |||
246 | /// that the result will fit into a regular (signed) int. All args have the same | |||
247 | /// purpose as they do in checkUInt32Argument. | |||
248 | template <typename AttrInfo> | |||
249 | static bool checkPositiveIntArgument(Sema &S, const AttrInfo &AI, const Expr *Expr, | |||
250 | int &Val, unsigned Idx = UINT_MAX(2147483647 *2U +1U)) { | |||
251 | uint32_t UVal; | |||
252 | if (!checkUInt32Argument(S, AI, Expr, UVal, Idx)) | |||
253 | return false; | |||
254 | ||||
255 | if (UVal > (uint32_t)std::numeric_limits<int>::max()) { | |||
256 | llvm::APSInt I(32); // for toString | |||
257 | I = UVal; | |||
258 | S.Diag(Expr->getExprLoc(), diag::err_ice_too_large) | |||
259 | << I.toString(10, false) << 32 << /* Unsigned */ 0; | |||
260 | return false; | |||
261 | } | |||
262 | ||||
263 | Val = UVal; | |||
264 | return true; | |||
265 | } | |||
266 | ||||
267 | /// Diagnose mutually exclusive attributes when present on a given | |||
268 | /// declaration. Returns true if diagnosed. | |||
269 | template <typename AttrTy> | |||
270 | static bool checkAttrMutualExclusion(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
271 | if (const auto *A = D->getAttr<AttrTy>()) { | |||
272 | S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << A; | |||
273 | S.Diag(A->getLocation(), diag::note_conflicting_attribute); | |||
274 | return true; | |||
275 | } | |||
276 | return false; | |||
277 | } | |||
278 | ||||
279 | template <typename AttrTy> | |||
280 | static bool checkAttrMutualExclusion(Sema &S, Decl *D, const Attr &AL) { | |||
281 | if (const auto *A = D->getAttr<AttrTy>()) { | |||
282 | S.Diag(AL.getLocation(), diag::err_attributes_are_not_compatible) << &AL | |||
283 | << A; | |||
284 | S.Diag(A->getLocation(), diag::note_conflicting_attribute); | |||
285 | return true; | |||
286 | } | |||
287 | return false; | |||
288 | } | |||
289 | ||||
290 | /// Check if IdxExpr is a valid parameter index for a function or | |||
291 | /// instance method D. May output an error. | |||
292 | /// | |||
293 | /// \returns true if IdxExpr is a valid index. | |||
294 | template <typename AttrInfo> | |||
295 | static bool checkFunctionOrMethodParameterIndex( | |||
296 | Sema &S, const Decl *D, const AttrInfo &AI, unsigned AttrArgNum, | |||
297 | const Expr *IdxExpr, ParamIdx &Idx, bool CanIndexImplicitThis = false) { | |||
298 | assert(isFunctionOrMethodOrBlock(D))((isFunctionOrMethodOrBlock(D)) ? static_cast<void> (0) : __assert_fail ("isFunctionOrMethodOrBlock(D)", "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 298, __PRETTY_FUNCTION__)); | |||
299 | ||||
300 | // In C++ the implicit 'this' function parameter also counts. | |||
301 | // Parameters are counted from one. | |||
302 | bool HP = hasFunctionProto(D); | |||
303 | bool HasImplicitThisParam = isInstanceMethod(D); | |||
304 | bool IV = HP && isFunctionOrMethodVariadic(D); | |||
305 | unsigned NumParams = | |||
306 | (HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam; | |||
307 | ||||
308 | Optional<llvm::APSInt> IdxInt; | |||
309 | if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || | |||
310 | !(IdxInt = IdxExpr->getIntegerConstantExpr(S.Context))) { | |||
311 | S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type) | |||
312 | << &AI << AttrArgNum << AANT_ArgumentIntegerConstant | |||
313 | << IdxExpr->getSourceRange(); | |||
314 | return false; | |||
315 | } | |||
316 | ||||
317 | unsigned IdxSource = IdxInt->getLimitedValue(UINT_MAX(2147483647 *2U +1U)); | |||
318 | if (IdxSource < 1 || (!IV && IdxSource > NumParams)) { | |||
319 | S.Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds) | |||
320 | << &AI << AttrArgNum << IdxExpr->getSourceRange(); | |||
321 | return false; | |||
322 | } | |||
323 | if (HasImplicitThisParam && !CanIndexImplicitThis) { | |||
324 | if (IdxSource == 1) { | |||
325 | S.Diag(getAttrLoc(AI), diag::err_attribute_invalid_implicit_this_argument) | |||
326 | << &AI << IdxExpr->getSourceRange(); | |||
327 | return false; | |||
328 | } | |||
329 | } | |||
330 | ||||
331 | Idx = ParamIdx(IdxSource, D); | |||
332 | return true; | |||
333 | } | |||
334 | ||||
335 | /// Check if the argument \p ArgNum of \p Attr is a ASCII string literal. | |||
336 | /// If not emit an error and return false. If the argument is an identifier it | |||
337 | /// will emit an error with a fixit hint and treat it as if it was a string | |||
338 | /// literal. | |||
339 | bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum, | |||
340 | StringRef &Str, | |||
341 | SourceLocation *ArgLocation) { | |||
342 | // Look for identifiers. If we have one emit a hint to fix it to a literal. | |||
343 | if (AL.isArgIdent(ArgNum)) { | |||
344 | IdentifierLoc *Loc = AL.getArgAsIdent(ArgNum); | |||
345 | Diag(Loc->Loc, diag::err_attribute_argument_type) | |||
346 | << AL << AANT_ArgumentString | |||
347 | << FixItHint::CreateInsertion(Loc->Loc, "\"") | |||
348 | << FixItHint::CreateInsertion(getLocForEndOfToken(Loc->Loc), "\""); | |||
349 | Str = Loc->Ident->getName(); | |||
350 | if (ArgLocation) | |||
351 | *ArgLocation = Loc->Loc; | |||
352 | return true; | |||
353 | } | |||
354 | ||||
355 | // Now check for an actual string literal. | |||
356 | Expr *ArgExpr = AL.getArgAsExpr(ArgNum); | |||
357 | const auto *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts()); | |||
358 | if (ArgLocation) | |||
359 | *ArgLocation = ArgExpr->getBeginLoc(); | |||
360 | ||||
361 | if (!Literal || !Literal->isAscii()) { | |||
362 | Diag(ArgExpr->getBeginLoc(), diag::err_attribute_argument_type) | |||
363 | << AL << AANT_ArgumentString; | |||
364 | return false; | |||
365 | } | |||
366 | ||||
367 | Str = Literal->getString(); | |||
368 | return true; | |||
369 | } | |||
370 | ||||
371 | /// Applies the given attribute to the Decl without performing any | |||
372 | /// additional semantic checking. | |||
373 | template <typename AttrType> | |||
374 | static void handleSimpleAttribute(Sema &S, Decl *D, | |||
375 | const AttributeCommonInfo &CI) { | |||
376 | D->addAttr(::new (S.Context) AttrType(S.Context, CI)); | |||
377 | } | |||
378 | ||||
379 | template <typename... DiagnosticArgs> | |||
380 | static const Sema::SemaDiagnosticBuilder& | |||
381 | appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr) { | |||
382 | return Bldr; | |||
383 | } | |||
384 | ||||
385 | template <typename T, typename... DiagnosticArgs> | |||
386 | static const Sema::SemaDiagnosticBuilder& | |||
387 | appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr, T &&ExtraArg, | |||
388 | DiagnosticArgs &&... ExtraArgs) { | |||
389 | return appendDiagnostics(Bldr << std::forward<T>(ExtraArg), | |||
390 | std::forward<DiagnosticArgs>(ExtraArgs)...); | |||
391 | } | |||
392 | ||||
393 | /// Add an attribute {@code AttrType} to declaration {@code D}, provided that | |||
394 | /// {@code PassesCheck} is true. | |||
395 | /// Otherwise, emit diagnostic {@code DiagID}, passing in all parameters | |||
396 | /// specified in {@code ExtraArgs}. | |||
397 | template <typename AttrType, typename... DiagnosticArgs> | |||
398 | static void handleSimpleAttributeOrDiagnose(Sema &S, Decl *D, | |||
399 | const AttributeCommonInfo &CI, | |||
400 | bool PassesCheck, unsigned DiagID, | |||
401 | DiagnosticArgs &&... ExtraArgs) { | |||
402 | if (!PassesCheck) { | |||
403 | Sema::SemaDiagnosticBuilder DB = S.Diag(D->getBeginLoc(), DiagID); | |||
404 | appendDiagnostics(DB, std::forward<DiagnosticArgs>(ExtraArgs)...); | |||
405 | return; | |||
406 | } | |||
407 | handleSimpleAttribute<AttrType>(S, D, CI); | |||
408 | } | |||
409 | ||||
410 | template <typename AttrType> | |||
411 | static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D, | |||
412 | const ParsedAttr &AL) { | |||
413 | handleSimpleAttribute<AttrType>(S, D, AL); | |||
414 | } | |||
415 | ||||
416 | /// Applies the given attribute to the Decl so long as the Decl doesn't | |||
417 | /// already have one of the given incompatible attributes. | |||
418 | template <typename AttrType, typename IncompatibleAttrType, | |||
419 | typename... IncompatibleAttrTypes> | |||
420 | static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D, | |||
421 | const ParsedAttr &AL) { | |||
422 | if (checkAttrMutualExclusion<IncompatibleAttrType>(S, D, AL)) | |||
423 | return; | |||
424 | handleSimpleAttributeWithExclusions<AttrType, IncompatibleAttrTypes...>(S, D, | |||
425 | AL); | |||
426 | } | |||
427 | ||||
428 | /// Check if the passed-in expression is of type int or bool. | |||
429 | static bool isIntOrBool(Expr *Exp) { | |||
430 | QualType QT = Exp->getType(); | |||
431 | return QT->isBooleanType() || QT->isIntegerType(); | |||
432 | } | |||
433 | ||||
434 | ||||
435 | // Check to see if the type is a smart pointer of some kind. We assume | |||
436 | // it's a smart pointer if it defines both operator-> and operator*. | |||
437 | static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) { | |||
438 | auto IsOverloadedOperatorPresent = [&S](const RecordDecl *Record, | |||
439 | OverloadedOperatorKind Op) { | |||
440 | DeclContextLookupResult Result = | |||
441 | Record->lookup(S.Context.DeclarationNames.getCXXOperatorName(Op)); | |||
442 | return !Result.empty(); | |||
443 | }; | |||
444 | ||||
445 | const RecordDecl *Record = RT->getDecl(); | |||
446 | bool foundStarOperator = IsOverloadedOperatorPresent(Record, OO_Star); | |||
447 | bool foundArrowOperator = IsOverloadedOperatorPresent(Record, OO_Arrow); | |||
448 | if (foundStarOperator && foundArrowOperator) | |||
449 | return true; | |||
450 | ||||
451 | const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record); | |||
452 | if (!CXXRecord) | |||
453 | return false; | |||
454 | ||||
455 | for (auto BaseSpecifier : CXXRecord->bases()) { | |||
456 | if (!foundStarOperator) | |||
457 | foundStarOperator = IsOverloadedOperatorPresent( | |||
458 | BaseSpecifier.getType()->getAsRecordDecl(), OO_Star); | |||
459 | if (!foundArrowOperator) | |||
460 | foundArrowOperator = IsOverloadedOperatorPresent( | |||
461 | BaseSpecifier.getType()->getAsRecordDecl(), OO_Arrow); | |||
462 | } | |||
463 | ||||
464 | if (foundStarOperator && foundArrowOperator) | |||
465 | return true; | |||
466 | ||||
467 | return false; | |||
468 | } | |||
469 | ||||
470 | /// Check if passed in Decl is a pointer type. | |||
471 | /// Note that this function may produce an error message. | |||
472 | /// \return true if the Decl is a pointer type; false otherwise | |||
473 | static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D, | |||
474 | const ParsedAttr &AL) { | |||
475 | const auto *VD = cast<ValueDecl>(D); | |||
476 | QualType QT = VD->getType(); | |||
477 | if (QT->isAnyPointerType()) | |||
478 | return true; | |||
479 | ||||
480 | if (const auto *RT = QT->getAs<RecordType>()) { | |||
481 | // If it's an incomplete type, it could be a smart pointer; skip it. | |||
482 | // (We don't want to force template instantiation if we can avoid it, | |||
483 | // since that would alter the order in which templates are instantiated.) | |||
484 | if (RT->isIncompleteType()) | |||
485 | return true; | |||
486 | ||||
487 | if (threadSafetyCheckIsSmartPointer(S, RT)) | |||
488 | return true; | |||
489 | } | |||
490 | ||||
491 | S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_pointer) << AL << QT; | |||
492 | return false; | |||
493 | } | |||
494 | ||||
495 | /// Checks that the passed in QualType either is of RecordType or points | |||
496 | /// to RecordType. Returns the relevant RecordType, null if it does not exit. | |||
497 | static const RecordType *getRecordType(QualType QT) { | |||
498 | if (const auto *RT = QT->getAs<RecordType>()) | |||
499 | return RT; | |||
500 | ||||
501 | // Now check if we point to record type. | |||
502 | if (const auto *PT = QT->getAs<PointerType>()) | |||
503 | return PT->getPointeeType()->getAs<RecordType>(); | |||
504 | ||||
505 | return nullptr; | |||
506 | } | |||
507 | ||||
508 | template <typename AttrType> | |||
509 | static bool checkRecordDeclForAttr(const RecordDecl *RD) { | |||
510 | // Check if the record itself has the attribute. | |||
511 | if (RD->hasAttr<AttrType>()) | |||
512 | return true; | |||
513 | ||||
514 | // Else check if any base classes have the attribute. | |||
515 | if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) { | |||
516 | CXXBasePaths BPaths(false, false); | |||
517 | if (CRD->lookupInBases( | |||
518 | [](const CXXBaseSpecifier *BS, CXXBasePath &) { | |||
519 | const auto &Ty = *BS->getType(); | |||
520 | // If it's type-dependent, we assume it could have the attribute. | |||
521 | if (Ty.isDependentType()) | |||
522 | return true; | |||
523 | return Ty.castAs<RecordType>()->getDecl()->hasAttr<AttrType>(); | |||
524 | }, | |||
525 | BPaths, true)) | |||
526 | return true; | |||
527 | } | |||
528 | return false; | |||
529 | } | |||
530 | ||||
531 | static bool checkRecordTypeForCapability(Sema &S, QualType Ty) { | |||
532 | const RecordType *RT = getRecordType(Ty); | |||
533 | ||||
534 | if (!RT) | |||
535 | return false; | |||
536 | ||||
537 | // Don't check for the capability if the class hasn't been defined yet. | |||
538 | if (RT->isIncompleteType()) | |||
539 | return true; | |||
540 | ||||
541 | // Allow smart pointers to be used as capability objects. | |||
542 | // FIXME -- Check the type that the smart pointer points to. | |||
543 | if (threadSafetyCheckIsSmartPointer(S, RT)) | |||
544 | return true; | |||
545 | ||||
546 | return checkRecordDeclForAttr<CapabilityAttr>(RT->getDecl()); | |||
547 | } | |||
548 | ||||
549 | static bool checkTypedefTypeForCapability(QualType Ty) { | |||
550 | const auto *TD = Ty->getAs<TypedefType>(); | |||
551 | if (!TD) | |||
552 | return false; | |||
553 | ||||
554 | TypedefNameDecl *TN = TD->getDecl(); | |||
555 | if (!TN) | |||
556 | return false; | |||
557 | ||||
558 | return TN->hasAttr<CapabilityAttr>(); | |||
559 | } | |||
560 | ||||
561 | static bool typeHasCapability(Sema &S, QualType Ty) { | |||
562 | if (checkTypedefTypeForCapability(Ty)) | |||
563 | return true; | |||
564 | ||||
565 | if (checkRecordTypeForCapability(S, Ty)) | |||
566 | return true; | |||
567 | ||||
568 | return false; | |||
569 | } | |||
570 | ||||
571 | static bool isCapabilityExpr(Sema &S, const Expr *Ex) { | |||
572 | // Capability expressions are simple expressions involving the boolean logic | |||
573 | // operators &&, || or !, a simple DeclRefExpr, CastExpr or a ParenExpr. Once | |||
574 | // a DeclRefExpr is found, its type should be checked to determine whether it | |||
575 | // is a capability or not. | |||
576 | ||||
577 | if (const auto *E = dyn_cast<CastExpr>(Ex)) | |||
578 | return isCapabilityExpr(S, E->getSubExpr()); | |||
579 | else if (const auto *E = dyn_cast<ParenExpr>(Ex)) | |||
580 | return isCapabilityExpr(S, E->getSubExpr()); | |||
581 | else if (const auto *E = dyn_cast<UnaryOperator>(Ex)) { | |||
582 | if (E->getOpcode() == UO_LNot || E->getOpcode() == UO_AddrOf || | |||
583 | E->getOpcode() == UO_Deref) | |||
584 | return isCapabilityExpr(S, E->getSubExpr()); | |||
585 | return false; | |||
586 | } else if (const auto *E = dyn_cast<BinaryOperator>(Ex)) { | |||
587 | if (E->getOpcode() == BO_LAnd || E->getOpcode() == BO_LOr) | |||
588 | return isCapabilityExpr(S, E->getLHS()) && | |||
589 | isCapabilityExpr(S, E->getRHS()); | |||
590 | return false; | |||
591 | } | |||
592 | ||||
593 | return typeHasCapability(S, Ex->getType()); | |||
594 | } | |||
595 | ||||
596 | /// Checks that all attribute arguments, starting from Sidx, resolve to | |||
597 | /// a capability object. | |||
598 | /// \param Sidx The attribute argument index to start checking with. | |||
599 | /// \param ParamIdxOk Whether an argument can be indexing into a function | |||
600 | /// parameter list. | |||
601 | static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D, | |||
602 | const ParsedAttr &AL, | |||
603 | SmallVectorImpl<Expr *> &Args, | |||
604 | unsigned Sidx = 0, | |||
605 | bool ParamIdxOk = false) { | |||
606 | if (Sidx == AL.getNumArgs()) { | |||
607 | // If we don't have any capability arguments, the attribute implicitly | |||
608 | // refers to 'this'. So we need to make sure that 'this' exists, i.e. we're | |||
609 | // a non-static method, and that the class is a (scoped) capability. | |||
610 | const auto *MD = dyn_cast<const CXXMethodDecl>(D); | |||
611 | if (MD && !MD->isStatic()) { | |||
612 | const CXXRecordDecl *RD = MD->getParent(); | |||
613 | // FIXME -- need to check this again on template instantiation | |||
614 | if (!checkRecordDeclForAttr<CapabilityAttr>(RD) && | |||
615 | !checkRecordDeclForAttr<ScopedLockableAttr>(RD)) | |||
616 | S.Diag(AL.getLoc(), | |||
617 | diag::warn_thread_attribute_not_on_capability_member) | |||
618 | << AL << MD->getParent(); | |||
619 | } else { | |||
620 | S.Diag(AL.getLoc(), diag::warn_thread_attribute_not_on_non_static_member) | |||
621 | << AL; | |||
622 | } | |||
623 | } | |||
624 | ||||
625 | for (unsigned Idx = Sidx; Idx < AL.getNumArgs(); ++Idx) { | |||
626 | Expr *ArgExp = AL.getArgAsExpr(Idx); | |||
627 | ||||
628 | if (ArgExp->isTypeDependent()) { | |||
629 | // FIXME -- need to check this again on template instantiation | |||
630 | Args.push_back(ArgExp); | |||
631 | continue; | |||
632 | } | |||
633 | ||||
634 | if (const auto *StrLit = dyn_cast<StringLiteral>(ArgExp)) { | |||
635 | if (StrLit->getLength() == 0 || | |||
636 | (StrLit->isAscii() && StrLit->getString() == StringRef("*"))) { | |||
637 | // Pass empty strings to the analyzer without warnings. | |||
638 | // Treat "*" as the universal lock. | |||
639 | Args.push_back(ArgExp); | |||
640 | continue; | |||
641 | } | |||
642 | ||||
643 | // We allow constant strings to be used as a placeholder for expressions | |||
644 | // that are not valid C++ syntax, but warn that they are ignored. | |||
645 | S.Diag(AL.getLoc(), diag::warn_thread_attribute_ignored) << AL; | |||
646 | Args.push_back(ArgExp); | |||
647 | continue; | |||
648 | } | |||
649 | ||||
650 | QualType ArgTy = ArgExp->getType(); | |||
651 | ||||
652 | // A pointer to member expression of the form &MyClass::mu is treated | |||
653 | // specially -- we need to look at the type of the member. | |||
654 | if (const auto *UOp = dyn_cast<UnaryOperator>(ArgExp)) | |||
655 | if (UOp->getOpcode() == UO_AddrOf) | |||
656 | if (const auto *DRE = dyn_cast<DeclRefExpr>(UOp->getSubExpr())) | |||
657 | if (DRE->getDecl()->isCXXInstanceMember()) | |||
658 | ArgTy = DRE->getDecl()->getType(); | |||
659 | ||||
660 | // First see if we can just cast to record type, or pointer to record type. | |||
661 | const RecordType *RT = getRecordType(ArgTy); | |||
662 | ||||
663 | // Now check if we index into a record type function param. | |||
664 | if(!RT && ParamIdxOk) { | |||
665 | const auto *FD = dyn_cast<FunctionDecl>(D); | |||
666 | const auto *IL = dyn_cast<IntegerLiteral>(ArgExp); | |||
667 | if(FD && IL) { | |||
668 | unsigned int NumParams = FD->getNumParams(); | |||
669 | llvm::APInt ArgValue = IL->getValue(); | |||
670 | uint64_t ParamIdxFromOne = ArgValue.getZExtValue(); | |||
671 | uint64_t ParamIdxFromZero = ParamIdxFromOne - 1; | |||
672 | if (!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) { | |||
673 | S.Diag(AL.getLoc(), | |||
674 | diag::err_attribute_argument_out_of_bounds_extra_info) | |||
675 | << AL << Idx + 1 << NumParams; | |||
676 | continue; | |||
677 | } | |||
678 | ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType(); | |||
679 | } | |||
680 | } | |||
681 | ||||
682 | // If the type does not have a capability, see if the components of the | |||
683 | // expression have capabilities. This allows for writing C code where the | |||
684 | // capability may be on the type, and the expression is a capability | |||
685 | // boolean logic expression. Eg) requires_capability(A || B && !C) | |||
686 | if (!typeHasCapability(S, ArgTy) && !isCapabilityExpr(S, ArgExp)) | |||
687 | S.Diag(AL.getLoc(), diag::warn_thread_attribute_argument_not_lockable) | |||
688 | << AL << ArgTy; | |||
689 | ||||
690 | Args.push_back(ArgExp); | |||
691 | } | |||
692 | } | |||
693 | ||||
694 | //===----------------------------------------------------------------------===// | |||
695 | // Attribute Implementations | |||
696 | //===----------------------------------------------------------------------===// | |||
697 | ||||
698 | static void handlePtGuardedVarAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
699 | if (!threadSafetyCheckIsPointer(S, D, AL)) | |||
700 | return; | |||
701 | ||||
702 | D->addAttr(::new (S.Context) PtGuardedVarAttr(S.Context, AL)); | |||
703 | } | |||
704 | ||||
705 | static bool checkGuardedByAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, | |||
706 | Expr *&Arg) { | |||
707 | SmallVector<Expr *, 1> Args; | |||
708 | // check that all arguments are lockable objects | |||
709 | checkAttrArgsAreCapabilityObjs(S, D, AL, Args); | |||
710 | unsigned Size = Args.size(); | |||
711 | if (Size != 1) | |||
712 | return false; | |||
713 | ||||
714 | Arg = Args[0]; | |||
715 | ||||
716 | return true; | |||
717 | } | |||
718 | ||||
719 | static void handleGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
720 | Expr *Arg = nullptr; | |||
721 | if (!checkGuardedByAttrCommon(S, D, AL, Arg)) | |||
722 | return; | |||
723 | ||||
724 | D->addAttr(::new (S.Context) GuardedByAttr(S.Context, AL, Arg)); | |||
725 | } | |||
726 | ||||
727 | static void handlePtGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
728 | Expr *Arg = nullptr; | |||
729 | if (!checkGuardedByAttrCommon(S, D, AL, Arg)) | |||
730 | return; | |||
731 | ||||
732 | if (!threadSafetyCheckIsPointer(S, D, AL)) | |||
733 | return; | |||
734 | ||||
735 | D->addAttr(::new (S.Context) PtGuardedByAttr(S.Context, AL, Arg)); | |||
736 | } | |||
737 | ||||
738 | static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, | |||
739 | SmallVectorImpl<Expr *> &Args) { | |||
740 | if (!AL.checkAtLeastNumArgs(S, 1)) | |||
741 | return false; | |||
742 | ||||
743 | // Check that this attribute only applies to lockable types. | |||
744 | QualType QT = cast<ValueDecl>(D)->getType(); | |||
745 | if (!QT->isDependentType() && !typeHasCapability(S, QT)) { | |||
746 | S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_lockable) << AL; | |||
747 | return false; | |||
748 | } | |||
749 | ||||
750 | // Check that all arguments are lockable objects. | |||
751 | checkAttrArgsAreCapabilityObjs(S, D, AL, Args); | |||
752 | if (Args.empty()) | |||
753 | return false; | |||
754 | ||||
755 | return true; | |||
756 | } | |||
757 | ||||
758 | static void handleAcquiredAfterAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
759 | SmallVector<Expr *, 1> Args; | |||
760 | if (!checkAcquireOrderAttrCommon(S, D, AL, Args)) | |||
761 | return; | |||
762 | ||||
763 | Expr **StartArg = &Args[0]; | |||
764 | D->addAttr(::new (S.Context) | |||
765 | AcquiredAfterAttr(S.Context, AL, StartArg, Args.size())); | |||
766 | } | |||
767 | ||||
768 | static void handleAcquiredBeforeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
769 | SmallVector<Expr *, 1> Args; | |||
770 | if (!checkAcquireOrderAttrCommon(S, D, AL, Args)) | |||
771 | return; | |||
772 | ||||
773 | Expr **StartArg = &Args[0]; | |||
774 | D->addAttr(::new (S.Context) | |||
775 | AcquiredBeforeAttr(S.Context, AL, StartArg, Args.size())); | |||
776 | } | |||
777 | ||||
778 | static bool checkLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, | |||
779 | SmallVectorImpl<Expr *> &Args) { | |||
780 | // zero or more arguments ok | |||
781 | // check that all arguments are lockable objects | |||
782 | checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, /*ParamIdxOk=*/true); | |||
783 | ||||
784 | return true; | |||
785 | } | |||
786 | ||||
787 | static void handleAssertSharedLockAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
788 | SmallVector<Expr *, 1> Args; | |||
789 | if (!checkLockFunAttrCommon(S, D, AL, Args)) | |||
790 | return; | |||
791 | ||||
792 | unsigned Size = Args.size(); | |||
793 | Expr **StartArg = Size == 0 ? nullptr : &Args[0]; | |||
794 | D->addAttr(::new (S.Context) | |||
795 | AssertSharedLockAttr(S.Context, AL, StartArg, Size)); | |||
796 | } | |||
797 | ||||
798 | static void handleAssertExclusiveLockAttr(Sema &S, Decl *D, | |||
799 | const ParsedAttr &AL) { | |||
800 | SmallVector<Expr *, 1> Args; | |||
801 | if (!checkLockFunAttrCommon(S, D, AL, Args)) | |||
802 | return; | |||
803 | ||||
804 | unsigned Size = Args.size(); | |||
805 | Expr **StartArg = Size == 0 ? nullptr : &Args[0]; | |||
806 | D->addAttr(::new (S.Context) | |||
807 | AssertExclusiveLockAttr(S.Context, AL, StartArg, Size)); | |||
808 | } | |||
809 | ||||
810 | /// Checks to be sure that the given parameter number is in bounds, and | |||
811 | /// is an integral type. Will emit appropriate diagnostics if this returns | |||
812 | /// false. | |||
813 | /// | |||
814 | /// AttrArgNo is used to actually retrieve the argument, so it's base-0. | |||
815 | template <typename AttrInfo> | |||
816 | static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD, | |||
817 | const AttrInfo &AI, unsigned AttrArgNo) { | |||
818 | 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~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 818, __PRETTY_FUNCTION__)); | |||
819 | Expr *AttrArg = AI.getArgAsExpr(AttrArgNo); | |||
820 | ParamIdx Idx; | |||
821 | if (!checkFunctionOrMethodParameterIndex(S, FD, AI, AttrArgNo + 1, AttrArg, | |||
822 | Idx)) | |||
823 | return false; | |||
824 | ||||
825 | const ParmVarDecl *Param = FD->getParamDecl(Idx.getASTIndex()); | |||
826 | if (!Param->getType()->isIntegerType() && !Param->getType()->isCharType()) { | |||
827 | SourceLocation SrcLoc = AttrArg->getBeginLoc(); | |||
828 | S.Diag(SrcLoc, diag::err_attribute_integers_only) | |||
829 | << AI << Param->getSourceRange(); | |||
830 | return false; | |||
831 | } | |||
832 | return true; | |||
833 | } | |||
834 | ||||
835 | static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
836 | if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2)) | |||
837 | return; | |||
838 | ||||
839 | const auto *FD = cast<FunctionDecl>(D); | |||
840 | if (!FD->getReturnType()->isPointerType()) { | |||
841 | S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) << AL; | |||
842 | return; | |||
843 | } | |||
844 | ||||
845 | const Expr *SizeExpr = AL.getArgAsExpr(0); | |||
846 | int SizeArgNoVal; | |||
847 | // Parameter indices are 1-indexed, hence Index=1 | |||
848 | if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNoVal, /*Idx=*/1)) | |||
849 | return; | |||
850 | if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/0)) | |||
851 | return; | |||
852 | ParamIdx SizeArgNo(SizeArgNoVal, D); | |||
853 | ||||
854 | ParamIdx NumberArgNo; | |||
855 | if (AL.getNumArgs() == 2) { | |||
856 | const Expr *NumberExpr = AL.getArgAsExpr(1); | |||
857 | int Val; | |||
858 | // Parameter indices are 1-based, hence Index=2 | |||
859 | if (!checkPositiveIntArgument(S, AL, NumberExpr, Val, /*Idx=*/2)) | |||
860 | return; | |||
861 | if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/1)) | |||
862 | return; | |||
863 | NumberArgNo = ParamIdx(Val, D); | |||
864 | } | |||
865 | ||||
866 | D->addAttr(::new (S.Context) | |||
867 | AllocSizeAttr(S.Context, AL, SizeArgNo, NumberArgNo)); | |||
868 | } | |||
869 | ||||
870 | static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, | |||
871 | SmallVectorImpl<Expr *> &Args) { | |||
872 | if (!AL.checkAtLeastNumArgs(S, 1)) | |||
873 | return false; | |||
874 | ||||
875 | if (!isIntOrBool(AL.getArgAsExpr(0))) { | |||
876 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
877 | << AL << 1 << AANT_ArgumentIntOrBool; | |||
878 | return false; | |||
879 | } | |||
880 | ||||
881 | // check that all arguments are lockable objects | |||
882 | checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 1); | |||
883 | ||||
884 | return true; | |||
885 | } | |||
886 | ||||
887 | static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D, | |||
888 | const ParsedAttr &AL) { | |||
889 | SmallVector<Expr*, 2> Args; | |||
890 | if (!checkTryLockFunAttrCommon(S, D, AL, Args)) | |||
891 | return; | |||
892 | ||||
893 | D->addAttr(::new (S.Context) SharedTrylockFunctionAttr( | |||
894 | S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size())); | |||
895 | } | |||
896 | ||||
897 | static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, | |||
898 | const ParsedAttr &AL) { | |||
899 | SmallVector<Expr*, 2> Args; | |||
900 | if (!checkTryLockFunAttrCommon(S, D, AL, Args)) | |||
901 | return; | |||
902 | ||||
903 | D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr( | |||
904 | S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size())); | |||
905 | } | |||
906 | ||||
907 | static void handleLockReturnedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
908 | // check that the argument is lockable object | |||
909 | SmallVector<Expr*, 1> Args; | |||
910 | checkAttrArgsAreCapabilityObjs(S, D, AL, Args); | |||
911 | unsigned Size = Args.size(); | |||
912 | if (Size == 0) | |||
913 | return; | |||
914 | ||||
915 | D->addAttr(::new (S.Context) LockReturnedAttr(S.Context, AL, Args[0])); | |||
916 | } | |||
917 | ||||
918 | static void handleLocksExcludedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
919 | if (!AL.checkAtLeastNumArgs(S, 1)) | |||
920 | return; | |||
921 | ||||
922 | // check that all arguments are lockable objects | |||
923 | SmallVector<Expr*, 1> Args; | |||
924 | checkAttrArgsAreCapabilityObjs(S, D, AL, Args); | |||
925 | unsigned Size = Args.size(); | |||
926 | if (Size == 0) | |||
927 | return; | |||
928 | Expr **StartArg = &Args[0]; | |||
929 | ||||
930 | D->addAttr(::new (S.Context) | |||
931 | LocksExcludedAttr(S.Context, AL, StartArg, Size)); | |||
932 | } | |||
933 | ||||
934 | static bool checkFunctionConditionAttr(Sema &S, Decl *D, const ParsedAttr &AL, | |||
935 | Expr *&Cond, StringRef &Msg) { | |||
936 | Cond = AL.getArgAsExpr(0); | |||
937 | if (!Cond->isTypeDependent()) { | |||
938 | ExprResult Converted = S.PerformContextuallyConvertToBool(Cond); | |||
939 | if (Converted.isInvalid()) | |||
940 | return false; | |||
941 | Cond = Converted.get(); | |||
942 | } | |||
943 | ||||
944 | if (!S.checkStringLiteralArgumentAttr(AL, 1, Msg)) | |||
945 | return false; | |||
946 | ||||
947 | if (Msg.empty()) | |||
948 | Msg = "<no message provided>"; | |||
949 | ||||
950 | SmallVector<PartialDiagnosticAt, 8> Diags; | |||
951 | if (isa<FunctionDecl>(D) && !Cond->isValueDependent() && | |||
952 | !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D), | |||
953 | Diags)) { | |||
954 | S.Diag(AL.getLoc(), diag::err_attr_cond_never_constant_expr) << AL; | |||
955 | for (const PartialDiagnosticAt &PDiag : Diags) | |||
956 | S.Diag(PDiag.first, PDiag.second); | |||
957 | return false; | |||
958 | } | |||
959 | return true; | |||
960 | } | |||
961 | ||||
962 | static void handleEnableIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
963 | S.Diag(AL.getLoc(), diag::ext_clang_enable_if); | |||
964 | ||||
965 | Expr *Cond; | |||
966 | StringRef Msg; | |||
967 | if (checkFunctionConditionAttr(S, D, AL, Cond, Msg)) | |||
968 | D->addAttr(::new (S.Context) EnableIfAttr(S.Context, AL, Cond, Msg)); | |||
969 | } | |||
970 | ||||
971 | namespace { | |||
972 | /// Determines if a given Expr references any of the given function's | |||
973 | /// ParmVarDecls, or the function's implicit `this` parameter (if applicable). | |||
974 | class ArgumentDependenceChecker | |||
975 | : public RecursiveASTVisitor<ArgumentDependenceChecker> { | |||
976 | #ifndef NDEBUG | |||
977 | const CXXRecordDecl *ClassType; | |||
978 | #endif | |||
979 | llvm::SmallPtrSet<const ParmVarDecl *, 16> Parms; | |||
980 | bool Result; | |||
981 | ||||
982 | public: | |||
983 | ArgumentDependenceChecker(const FunctionDecl *FD) { | |||
984 | #ifndef NDEBUG | |||
985 | if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) | |||
986 | ClassType = MD->getParent(); | |||
987 | else | |||
988 | ClassType = nullptr; | |||
989 | #endif | |||
990 | Parms.insert(FD->param_begin(), FD->param_end()); | |||
991 | } | |||
992 | ||||
993 | bool referencesArgs(Expr *E) { | |||
994 | Result = false; | |||
995 | TraverseStmt(E); | |||
996 | return Result; | |||
997 | } | |||
998 | ||||
999 | bool VisitCXXThisExpr(CXXThisExpr *E) { | |||
1000 | 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~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 1001, __PRETTY_FUNCTION__)) | |||
1001 | "`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~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 1001, __PRETTY_FUNCTION__)); | |||
1002 | Result = true; | |||
1003 | return false; | |||
1004 | } | |||
1005 | ||||
1006 | bool VisitDeclRefExpr(DeclRefExpr *DRE) { | |||
1007 | if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) | |||
1008 | if (Parms.count(PVD)) { | |||
1009 | Result = true; | |||
1010 | return false; | |||
1011 | } | |||
1012 | return true; | |||
1013 | } | |||
1014 | }; | |||
1015 | } | |||
1016 | ||||
1017 | static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1018 | S.Diag(AL.getLoc(), diag::ext_clang_diagnose_if); | |||
1019 | ||||
1020 | Expr *Cond; | |||
1021 | StringRef Msg; | |||
1022 | if (!checkFunctionConditionAttr(S, D, AL, Cond, Msg)) | |||
1023 | return; | |||
1024 | ||||
1025 | StringRef DiagTypeStr; | |||
1026 | if (!S.checkStringLiteralArgumentAttr(AL, 2, DiagTypeStr)) | |||
1027 | return; | |||
1028 | ||||
1029 | DiagnoseIfAttr::DiagnosticType DiagType; | |||
1030 | if (!DiagnoseIfAttr::ConvertStrToDiagnosticType(DiagTypeStr, DiagType)) { | |||
1031 | S.Diag(AL.getArgAsExpr(2)->getBeginLoc(), | |||
1032 | diag::err_diagnose_if_invalid_diagnostic_type); | |||
1033 | return; | |||
1034 | } | |||
1035 | ||||
1036 | bool ArgDependent = false; | |||
1037 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) | |||
1038 | ArgDependent = ArgumentDependenceChecker(FD).referencesArgs(Cond); | |||
1039 | D->addAttr(::new (S.Context) DiagnoseIfAttr( | |||
1040 | S.Context, AL, Cond, Msg, DiagType, ArgDependent, cast<NamedDecl>(D))); | |||
1041 | } | |||
1042 | ||||
1043 | static void handleNoBuiltinAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1044 | static constexpr const StringRef kWildcard = "*"; | |||
1045 | ||||
1046 | llvm::SmallVector<StringRef, 16> Names; | |||
1047 | bool HasWildcard = false; | |||
1048 | ||||
1049 | const auto AddBuiltinName = [&Names, &HasWildcard](StringRef Name) { | |||
1050 | if (Name == kWildcard) | |||
1051 | HasWildcard = true; | |||
1052 | Names.push_back(Name); | |||
1053 | }; | |||
1054 | ||||
1055 | // Add previously defined attributes. | |||
1056 | if (const auto *NBA = D->getAttr<NoBuiltinAttr>()) | |||
1057 | for (StringRef BuiltinName : NBA->builtinNames()) | |||
1058 | AddBuiltinName(BuiltinName); | |||
1059 | ||||
1060 | // Add current attributes. | |||
1061 | if (AL.getNumArgs() == 0) | |||
1062 | AddBuiltinName(kWildcard); | |||
1063 | else | |||
1064 | for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { | |||
1065 | StringRef BuiltinName; | |||
1066 | SourceLocation LiteralLoc; | |||
1067 | if (!S.checkStringLiteralArgumentAttr(AL, I, BuiltinName, &LiteralLoc)) | |||
1068 | return; | |||
1069 | ||||
1070 | if (Builtin::Context::isBuiltinFunc(BuiltinName)) | |||
1071 | AddBuiltinName(BuiltinName); | |||
1072 | else | |||
1073 | S.Diag(LiteralLoc, diag::warn_attribute_no_builtin_invalid_builtin_name) | |||
1074 | << BuiltinName << AL; | |||
1075 | } | |||
1076 | ||||
1077 | // Repeating the same attribute is fine. | |||
1078 | llvm::sort(Names); | |||
1079 | Names.erase(std::unique(Names.begin(), Names.end()), Names.end()); | |||
1080 | ||||
1081 | // Empty no_builtin must be on its own. | |||
1082 | if (HasWildcard && Names.size() > 1) | |||
1083 | S.Diag(D->getLocation(), | |||
1084 | diag::err_attribute_no_builtin_wildcard_or_builtin_name) | |||
1085 | << AL; | |||
1086 | ||||
1087 | if (D->hasAttr<NoBuiltinAttr>()) | |||
1088 | D->dropAttr<NoBuiltinAttr>(); | |||
1089 | D->addAttr(::new (S.Context) | |||
1090 | NoBuiltinAttr(S.Context, AL, Names.data(), Names.size())); | |||
1091 | } | |||
1092 | ||||
1093 | static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1094 | if (D->hasAttr<PassObjectSizeAttr>()) { | |||
1095 | S.Diag(D->getBeginLoc(), diag::err_attribute_only_once_per_parameter) << AL; | |||
1096 | return; | |||
1097 | } | |||
1098 | ||||
1099 | Expr *E = AL.getArgAsExpr(0); | |||
1100 | uint32_t Type; | |||
1101 | if (!checkUInt32Argument(S, AL, E, Type, /*Idx=*/1)) | |||
1102 | return; | |||
1103 | ||||
1104 | // pass_object_size's argument is passed in as the second argument of | |||
1105 | // __builtin_object_size. So, it has the same constraints as that second | |||
1106 | // argument; namely, it must be in the range [0, 3]. | |||
1107 | if (Type > 3) { | |||
1108 | S.Diag(E->getBeginLoc(), diag::err_attribute_argument_out_of_range) | |||
1109 | << AL << 0 << 3 << E->getSourceRange(); | |||
1110 | return; | |||
1111 | } | |||
1112 | ||||
1113 | // pass_object_size is only supported on constant pointer parameters; as a | |||
1114 | // kindness to users, we allow the parameter to be non-const for declarations. | |||
1115 | // At this point, we have no clue if `D` belongs to a function declaration or | |||
1116 | // definition, so we defer the constness check until later. | |||
1117 | if (!cast<ParmVarDecl>(D)->getType()->isPointerType()) { | |||
1118 | S.Diag(D->getBeginLoc(), diag::err_attribute_pointers_only) << AL << 1; | |||
1119 | return; | |||
1120 | } | |||
1121 | ||||
1122 | D->addAttr(::new (S.Context) PassObjectSizeAttr(S.Context, AL, (int)Type)); | |||
1123 | } | |||
1124 | ||||
1125 | static void handleConsumableAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1126 | ConsumableAttr::ConsumedState DefaultState; | |||
1127 | ||||
1128 | if (AL.isArgIdent(0)) { | |||
1129 | IdentifierLoc *IL = AL.getArgAsIdent(0); | |||
1130 | if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(), | |||
1131 | DefaultState)) { | |||
1132 | S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL | |||
1133 | << IL->Ident; | |||
1134 | return; | |||
1135 | } | |||
1136 | } else { | |||
1137 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
1138 | << AL << AANT_ArgumentIdentifier; | |||
1139 | return; | |||
1140 | } | |||
1141 | ||||
1142 | D->addAttr(::new (S.Context) ConsumableAttr(S.Context, AL, DefaultState)); | |||
1143 | } | |||
1144 | ||||
1145 | static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, | |||
1146 | const ParsedAttr &AL) { | |||
1147 | QualType ThisType = MD->getThisType()->getPointeeType(); | |||
1148 | ||||
1149 | if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) { | |||
1150 | if (!RD->hasAttr<ConsumableAttr>()) { | |||
1151 | S.Diag(AL.getLoc(), diag::warn_attr_on_unconsumable_class) << RD; | |||
1152 | ||||
1153 | return false; | |||
1154 | } | |||
1155 | } | |||
1156 | ||||
1157 | return true; | |||
1158 | } | |||
1159 | ||||
1160 | static void handleCallableWhenAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1161 | if (!AL.checkAtLeastNumArgs(S, 1)) | |||
1162 | return; | |||
1163 | ||||
1164 | if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL)) | |||
1165 | return; | |||
1166 | ||||
1167 | SmallVector<CallableWhenAttr::ConsumedState, 3> States; | |||
1168 | for (unsigned ArgIndex = 0; ArgIndex < AL.getNumArgs(); ++ArgIndex) { | |||
1169 | CallableWhenAttr::ConsumedState CallableState; | |||
1170 | ||||
1171 | StringRef StateString; | |||
1172 | SourceLocation Loc; | |||
1173 | if (AL.isArgIdent(ArgIndex)) { | |||
1174 | IdentifierLoc *Ident = AL.getArgAsIdent(ArgIndex); | |||
1175 | StateString = Ident->Ident->getName(); | |||
1176 | Loc = Ident->Loc; | |||
1177 | } else { | |||
1178 | if (!S.checkStringLiteralArgumentAttr(AL, ArgIndex, StateString, &Loc)) | |||
1179 | return; | |||
1180 | } | |||
1181 | ||||
1182 | if (!CallableWhenAttr::ConvertStrToConsumedState(StateString, | |||
1183 | CallableState)) { | |||
1184 | S.Diag(Loc, diag::warn_attribute_type_not_supported) << AL << StateString; | |||
1185 | return; | |||
1186 | } | |||
1187 | ||||
1188 | States.push_back(CallableState); | |||
1189 | } | |||
1190 | ||||
1191 | D->addAttr(::new (S.Context) | |||
1192 | CallableWhenAttr(S.Context, AL, States.data(), States.size())); | |||
1193 | } | |||
1194 | ||||
1195 | static void handleParamTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1196 | ParamTypestateAttr::ConsumedState ParamState; | |||
1197 | ||||
1198 | if (AL.isArgIdent(0)) { | |||
1199 | IdentifierLoc *Ident = AL.getArgAsIdent(0); | |||
1200 | StringRef StateString = Ident->Ident->getName(); | |||
1201 | ||||
1202 | if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString, | |||
1203 | ParamState)) { | |||
1204 | S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) | |||
1205 | << AL << StateString; | |||
1206 | return; | |||
1207 | } | |||
1208 | } else { | |||
1209 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
1210 | << AL << AANT_ArgumentIdentifier; | |||
1211 | return; | |||
1212 | } | |||
1213 | ||||
1214 | // FIXME: This check is currently being done in the analysis. It can be | |||
1215 | // enabled here only after the parser propagates attributes at | |||
1216 | // template specialization definition, not declaration. | |||
1217 | //QualType ReturnType = cast<ParmVarDecl>(D)->getType(); | |||
1218 | //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); | |||
1219 | // | |||
1220 | //if (!RD || !RD->hasAttr<ConsumableAttr>()) { | |||
1221 | // S.Diag(AL.getLoc(), diag::warn_return_state_for_unconsumable_type) << | |||
1222 | // ReturnType.getAsString(); | |||
1223 | // return; | |||
1224 | //} | |||
1225 | ||||
1226 | D->addAttr(::new (S.Context) ParamTypestateAttr(S.Context, AL, ParamState)); | |||
1227 | } | |||
1228 | ||||
1229 | static void handleReturnTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1230 | ReturnTypestateAttr::ConsumedState ReturnState; | |||
1231 | ||||
1232 | if (AL.isArgIdent(0)) { | |||
1233 | IdentifierLoc *IL = AL.getArgAsIdent(0); | |||
1234 | if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(), | |||
1235 | ReturnState)) { | |||
1236 | S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL | |||
1237 | << IL->Ident; | |||
1238 | return; | |||
1239 | } | |||
1240 | } else { | |||
1241 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
1242 | << AL << AANT_ArgumentIdentifier; | |||
1243 | return; | |||
1244 | } | |||
1245 | ||||
1246 | // FIXME: This check is currently being done in the analysis. It can be | |||
1247 | // enabled here only after the parser propagates attributes at | |||
1248 | // template specialization definition, not declaration. | |||
1249 | //QualType ReturnType; | |||
1250 | // | |||
1251 | //if (const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D)) { | |||
1252 | // ReturnType = Param->getType(); | |||
1253 | // | |||
1254 | //} else if (const CXXConstructorDecl *Constructor = | |||
1255 | // dyn_cast<CXXConstructorDecl>(D)) { | |||
1256 | // ReturnType = Constructor->getThisType()->getPointeeType(); | |||
1257 | // | |||
1258 | //} else { | |||
1259 | // | |||
1260 | // ReturnType = cast<FunctionDecl>(D)->getCallResultType(); | |||
1261 | //} | |||
1262 | // | |||
1263 | //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); | |||
1264 | // | |||
1265 | //if (!RD || !RD->hasAttr<ConsumableAttr>()) { | |||
1266 | // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) << | |||
1267 | // ReturnType.getAsString(); | |||
1268 | // return; | |||
1269 | //} | |||
1270 | ||||
1271 | D->addAttr(::new (S.Context) ReturnTypestateAttr(S.Context, AL, ReturnState)); | |||
1272 | } | |||
1273 | ||||
1274 | static void handleSetTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1275 | if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL)) | |||
1276 | return; | |||
1277 | ||||
1278 | SetTypestateAttr::ConsumedState NewState; | |||
1279 | if (AL.isArgIdent(0)) { | |||
1280 | IdentifierLoc *Ident = AL.getArgAsIdent(0); | |||
1281 | StringRef Param = Ident->Ident->getName(); | |||
1282 | if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) { | |||
1283 | S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL | |||
1284 | << Param; | |||
1285 | return; | |||
1286 | } | |||
1287 | } else { | |||
1288 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
1289 | << AL << AANT_ArgumentIdentifier; | |||
1290 | return; | |||
1291 | } | |||
1292 | ||||
1293 | D->addAttr(::new (S.Context) SetTypestateAttr(S.Context, AL, NewState)); | |||
1294 | } | |||
1295 | ||||
1296 | static void handleTestTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1297 | if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL)) | |||
1298 | return; | |||
1299 | ||||
1300 | TestTypestateAttr::ConsumedState TestState; | |||
1301 | if (AL.isArgIdent(0)) { | |||
1302 | IdentifierLoc *Ident = AL.getArgAsIdent(0); | |||
1303 | StringRef Param = Ident->Ident->getName(); | |||
1304 | if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) { | |||
1305 | S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL | |||
1306 | << Param; | |||
1307 | return; | |||
1308 | } | |||
1309 | } else { | |||
1310 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
1311 | << AL << AANT_ArgumentIdentifier; | |||
1312 | return; | |||
1313 | } | |||
1314 | ||||
1315 | D->addAttr(::new (S.Context) TestTypestateAttr(S.Context, AL, TestState)); | |||
1316 | } | |||
1317 | ||||
1318 | static void handleExtVectorTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1319 | // Remember this typedef decl, we will need it later for diagnostics. | |||
1320 | S.ExtVectorDecls.push_back(cast<TypedefNameDecl>(D)); | |||
1321 | } | |||
1322 | ||||
1323 | static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1324 | if (auto *TD = dyn_cast<TagDecl>(D)) | |||
1325 | TD->addAttr(::new (S.Context) PackedAttr(S.Context, AL)); | |||
1326 | else if (auto *FD = dyn_cast<FieldDecl>(D)) { | |||
1327 | bool BitfieldByteAligned = (!FD->getType()->isDependentType() && | |||
1328 | !FD->getType()->isIncompleteType() && | |||
1329 | FD->isBitField() && | |||
1330 | S.Context.getTypeAlign(FD->getType()) <= 8); | |||
1331 | ||||
1332 | if (S.getASTContext().getTargetInfo().getTriple().isPS4()) { | |||
1333 | if (BitfieldByteAligned) | |||
1334 | // The PS4 target needs to maintain ABI backwards compatibility. | |||
1335 | S.Diag(AL.getLoc(), diag::warn_attribute_ignored_for_field_of_type) | |||
1336 | << AL << FD->getType(); | |||
1337 | else | |||
1338 | FD->addAttr(::new (S.Context) PackedAttr(S.Context, AL)); | |||
1339 | } else { | |||
1340 | // Report warning about changed offset in the newer compiler versions. | |||
1341 | if (BitfieldByteAligned) | |||
1342 | S.Diag(AL.getLoc(), diag::warn_attribute_packed_for_bitfield); | |||
1343 | ||||
1344 | FD->addAttr(::new (S.Context) PackedAttr(S.Context, AL)); | |||
1345 | } | |||
1346 | ||||
1347 | } else | |||
1348 | S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL; | |||
1349 | } | |||
1350 | ||||
1351 | static void handlePreferredName(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1352 | auto *RD = cast<CXXRecordDecl>(D); | |||
1353 | ClassTemplateDecl *CTD = RD->getDescribedClassTemplate(); | |||
1354 | 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~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 1354, __PRETTY_FUNCTION__)); | |||
1355 | ||||
1356 | ParsedType PT = AL.getTypeArg(); | |||
1357 | TypeSourceInfo *TSI = nullptr; | |||
1358 | QualType T = S.GetTypeFromParser(PT, &TSI); | |||
1359 | if (!TSI) | |||
1360 | TSI = S.Context.getTrivialTypeSourceInfo(T, AL.getLoc()); | |||
1361 | ||||
1362 | if (!T.hasQualifiers() && T->isTypedefNameType()) { | |||
1363 | // Find the template name, if this type names a template specialization. | |||
1364 | const TemplateDecl *Template = nullptr; | |||
1365 | if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>( | |||
1366 | T->getAsCXXRecordDecl())) { | |||
1367 | Template = CTSD->getSpecializedTemplate(); | |||
1368 | } else if (const auto *TST = T->getAs<TemplateSpecializationType>()) { | |||
1369 | while (TST && TST->isTypeAlias()) | |||
1370 | TST = TST->getAliasedType()->getAs<TemplateSpecializationType>(); | |||
1371 | if (TST) | |||
1372 | Template = TST->getTemplateName().getAsTemplateDecl(); | |||
1373 | } | |||
1374 | ||||
1375 | if (Template && declaresSameEntity(Template, CTD)) { | |||
1376 | D->addAttr(::new (S.Context) PreferredNameAttr(S.Context, AL, TSI)); | |||
1377 | return; | |||
1378 | } | |||
1379 | } | |||
1380 | ||||
1381 | S.Diag(AL.getLoc(), diag::err_attribute_preferred_name_arg_invalid) | |||
1382 | << T << CTD; | |||
1383 | if (const auto *TT = T->getAs<TypedefType>()) | |||
1384 | S.Diag(TT->getDecl()->getLocation(), diag::note_entity_declared_at) | |||
1385 | << TT->getDecl(); | |||
1386 | } | |||
1387 | ||||
1388 | static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1389 | // The IBOutlet/IBOutletCollection attributes only apply to instance | |||
1390 | // variables or properties of Objective-C classes. The outlet must also | |||
1391 | // have an object reference type. | |||
1392 | if (const auto *VD = dyn_cast<ObjCIvarDecl>(D)) { | |||
1393 | if (!VD->getType()->getAs<ObjCObjectPointerType>()) { | |||
1394 | S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type) | |||
1395 | << AL << VD->getType() << 0; | |||
1396 | return false; | |||
1397 | } | |||
1398 | } | |||
1399 | else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) { | |||
1400 | if (!PD->getType()->getAs<ObjCObjectPointerType>()) { | |||
1401 | S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type) | |||
1402 | << AL << PD->getType() << 1; | |||
1403 | return false; | |||
1404 | } | |||
1405 | } | |||
1406 | else { | |||
1407 | S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL; | |||
1408 | return false; | |||
1409 | } | |||
1410 | ||||
1411 | return true; | |||
1412 | } | |||
1413 | ||||
1414 | static void handleIBOutlet(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1415 | if (!checkIBOutletCommon(S, D, AL)) | |||
1416 | return; | |||
1417 | ||||
1418 | D->addAttr(::new (S.Context) IBOutletAttr(S.Context, AL)); | |||
1419 | } | |||
1420 | ||||
1421 | static void handleIBOutletCollection(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1422 | ||||
1423 | // The iboutletcollection attribute can have zero or one arguments. | |||
1424 | if (AL.getNumArgs() > 1) { | |||
1425 | S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; | |||
1426 | return; | |||
1427 | } | |||
1428 | ||||
1429 | if (!checkIBOutletCommon(S, D, AL)) | |||
1430 | return; | |||
1431 | ||||
1432 | ParsedType PT; | |||
1433 | ||||
1434 | if (AL.hasParsedType()) | |||
1435 | PT = AL.getTypeArg(); | |||
1436 | else { | |||
1437 | PT = S.getTypeName(S.Context.Idents.get("NSObject"), AL.getLoc(), | |||
1438 | S.getScopeForContext(D->getDeclContext()->getParent())); | |||
1439 | if (!PT) { | |||
1440 | S.Diag(AL.getLoc(), diag::err_iboutletcollection_type) << "NSObject"; | |||
1441 | return; | |||
1442 | } | |||
1443 | } | |||
1444 | ||||
1445 | TypeSourceInfo *QTLoc = nullptr; | |||
1446 | QualType QT = S.GetTypeFromParser(PT, &QTLoc); | |||
1447 | if (!QTLoc) | |||
1448 | QTLoc = S.Context.getTrivialTypeSourceInfo(QT, AL.getLoc()); | |||
1449 | ||||
1450 | // Diagnose use of non-object type in iboutletcollection attribute. | |||
1451 | // FIXME. Gnu attribute extension ignores use of builtin types in | |||
1452 | // attributes. So, __attribute__((iboutletcollection(char))) will be | |||
1453 | // treated as __attribute__((iboutletcollection())). | |||
1454 | if (!QT->isObjCIdType() && !QT->isObjCObjectType()) { | |||
1455 | S.Diag(AL.getLoc(), | |||
1456 | QT->isBuiltinType() ? diag::err_iboutletcollection_builtintype | |||
1457 | : diag::err_iboutletcollection_type) << QT; | |||
1458 | return; | |||
1459 | } | |||
1460 | ||||
1461 | D->addAttr(::new (S.Context) IBOutletCollectionAttr(S.Context, AL, QTLoc)); | |||
1462 | } | |||
1463 | ||||
1464 | bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) { | |||
1465 | if (RefOkay) { | |||
1466 | if (T->isReferenceType()) | |||
1467 | return true; | |||
1468 | } else { | |||
1469 | T = T.getNonReferenceType(); | |||
1470 | } | |||
1471 | ||||
1472 | // The nonnull attribute, and other similar attributes, can be applied to a | |||
1473 | // transparent union that contains a pointer type. | |||
1474 | if (const RecordType *UT = T->getAsUnionType()) { | |||
1475 | if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) { | |||
1476 | RecordDecl *UD = UT->getDecl(); | |||
1477 | for (const auto *I : UD->fields()) { | |||
1478 | QualType QT = I->getType(); | |||
1479 | if (QT->isAnyPointerType() || QT->isBlockPointerType()) | |||
1480 | return true; | |||
1481 | } | |||
1482 | } | |||
1483 | } | |||
1484 | ||||
1485 | return T->isAnyPointerType() || T->isBlockPointerType(); | |||
1486 | } | |||
1487 | ||||
1488 | static bool attrNonNullArgCheck(Sema &S, QualType T, const ParsedAttr &AL, | |||
1489 | SourceRange AttrParmRange, | |||
1490 | SourceRange TypeRange, | |||
1491 | bool isReturnValue = false) { | |||
1492 | if (!S.isValidPointerAttrType(T)) { | |||
1493 | if (isReturnValue) | |||
1494 | S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) | |||
1495 | << AL << AttrParmRange << TypeRange; | |||
1496 | else | |||
1497 | S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only) | |||
1498 | << AL << AttrParmRange << TypeRange << 0; | |||
1499 | return false; | |||
1500 | } | |||
1501 | return true; | |||
1502 | } | |||
1503 | ||||
1504 | static void handleNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1505 | SmallVector<ParamIdx, 8> NonNullArgs; | |||
1506 | for (unsigned I = 0; I < AL.getNumArgs(); ++I) { | |||
1507 | Expr *Ex = AL.getArgAsExpr(I); | |||
1508 | ParamIdx Idx; | |||
1509 | if (!checkFunctionOrMethodParameterIndex(S, D, AL, I + 1, Ex, Idx)) | |||
1510 | return; | |||
1511 | ||||
1512 | // Is the function argument a pointer type? | |||
1513 | if (Idx.getASTIndex() < getFunctionOrMethodNumParams(D) && | |||
1514 | !attrNonNullArgCheck( | |||
1515 | S, getFunctionOrMethodParamType(D, Idx.getASTIndex()), AL, | |||
1516 | Ex->getSourceRange(), | |||
1517 | getFunctionOrMethodParamRange(D, Idx.getASTIndex()))) | |||
1518 | continue; | |||
1519 | ||||
1520 | NonNullArgs.push_back(Idx); | |||
1521 | } | |||
1522 | ||||
1523 | // If no arguments were specified to __attribute__((nonnull)) then all pointer | |||
1524 | // arguments have a nonnull attribute; warn if there aren't any. Skip this | |||
1525 | // check if the attribute came from a macro expansion or a template | |||
1526 | // instantiation. | |||
1527 | if (NonNullArgs.empty() && AL.getLoc().isFileID() && | |||
1528 | !S.inTemplateInstantiation()) { | |||
1529 | bool AnyPointers = isFunctionOrMethodVariadic(D); | |||
1530 | for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); | |||
1531 | I != E && !AnyPointers; ++I) { | |||
1532 | QualType T = getFunctionOrMethodParamType(D, I); | |||
1533 | if (T->isDependentType() || S.isValidPointerAttrType(T)) | |||
1534 | AnyPointers = true; | |||
1535 | } | |||
1536 | ||||
1537 | if (!AnyPointers) | |||
1538 | S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_no_pointers); | |||
1539 | } | |||
1540 | ||||
1541 | ParamIdx *Start = NonNullArgs.data(); | |||
1542 | unsigned Size = NonNullArgs.size(); | |||
1543 | llvm::array_pod_sort(Start, Start + Size); | |||
1544 | D->addAttr(::new (S.Context) NonNullAttr(S.Context, AL, Start, Size)); | |||
1545 | } | |||
1546 | ||||
1547 | static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D, | |||
1548 | const ParsedAttr &AL) { | |||
1549 | if (AL.getNumArgs() > 0) { | |||
1550 | if (D->getFunctionType()) { | |||
1551 | handleNonNullAttr(S, D, AL); | |||
1552 | } else { | |||
1553 | S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_parm_no_args) | |||
1554 | << D->getSourceRange(); | |||
1555 | } | |||
1556 | return; | |||
1557 | } | |||
1558 | ||||
1559 | // Is the argument a pointer type? | |||
1560 | if (!attrNonNullArgCheck(S, D->getType(), AL, SourceRange(), | |||
1561 | D->getSourceRange())) | |||
1562 | return; | |||
1563 | ||||
1564 | D->addAttr(::new (S.Context) NonNullAttr(S.Context, AL, nullptr, 0)); | |||
1565 | } | |||
1566 | ||||
1567 | static void handleReturnsNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1568 | QualType ResultType = getFunctionOrMethodResultType(D); | |||
1569 | SourceRange SR = getFunctionOrMethodResultSourceRange(D); | |||
1570 | if (!attrNonNullArgCheck(S, ResultType, AL, SourceRange(), SR, | |||
1571 | /* isReturnValue */ true)) | |||
1572 | return; | |||
1573 | ||||
1574 | D->addAttr(::new (S.Context) ReturnsNonNullAttr(S.Context, AL)); | |||
1575 | } | |||
1576 | ||||
1577 | static void handleNoEscapeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1578 | if (D->isInvalidDecl()) | |||
1579 | return; | |||
1580 | ||||
1581 | // noescape only applies to pointer types. | |||
1582 | QualType T = cast<ParmVarDecl>(D)->getType(); | |||
1583 | if (!S.isValidPointerAttrType(T, /* RefOkay */ true)) { | |||
1584 | S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only) | |||
1585 | << AL << AL.getRange() << 0; | |||
1586 | return; | |||
1587 | } | |||
1588 | ||||
1589 | D->addAttr(::new (S.Context) NoEscapeAttr(S.Context, AL)); | |||
1590 | } | |||
1591 | ||||
1592 | static void handleAssumeAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1593 | Expr *E = AL.getArgAsExpr(0), | |||
1594 | *OE = AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr; | |||
1595 | S.AddAssumeAlignedAttr(D, AL, E, OE); | |||
1596 | } | |||
1597 | ||||
1598 | static void handleAllocAlignAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1599 | S.AddAllocAlignAttr(D, AL, AL.getArgAsExpr(0)); | |||
1600 | } | |||
1601 | ||||
1602 | void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, | |||
1603 | Expr *OE) { | |||
1604 | QualType ResultType = getFunctionOrMethodResultType(D); | |||
1605 | SourceRange SR = getFunctionOrMethodResultSourceRange(D); | |||
1606 | ||||
1607 | AssumeAlignedAttr TmpAttr(Context, CI, E, OE); | |||
1608 | SourceLocation AttrLoc = TmpAttr.getLocation(); | |||
1609 | ||||
1610 | if (!isValidPointerAttrType(ResultType, /* RefOkay */ true)) { | |||
1611 | Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only) | |||
1612 | << &TmpAttr << TmpAttr.getRange() << SR; | |||
1613 | return; | |||
1614 | } | |||
1615 | ||||
1616 | if (!E->isValueDependent()) { | |||
1617 | Optional<llvm::APSInt> I = llvm::APSInt(64); | |||
1618 | if (!(I = E->getIntegerConstantExpr(Context))) { | |||
1619 | if (OE) | |||
1620 | Diag(AttrLoc, diag::err_attribute_argument_n_type) | |||
1621 | << &TmpAttr << 1 << AANT_ArgumentIntegerConstant | |||
1622 | << E->getSourceRange(); | |||
1623 | else | |||
1624 | Diag(AttrLoc, diag::err_attribute_argument_type) | |||
1625 | << &TmpAttr << AANT_ArgumentIntegerConstant | |||
1626 | << E->getSourceRange(); | |||
1627 | return; | |||
1628 | } | |||
1629 | ||||
1630 | if (!I->isPowerOf2()) { | |||
1631 | Diag(AttrLoc, diag::err_alignment_not_power_of_two) | |||
1632 | << E->getSourceRange(); | |||
1633 | return; | |||
1634 | } | |||
1635 | ||||
1636 | if (*I > Sema::MaximumAlignment) | |||
1637 | Diag(CI.getLoc(), diag::warn_assume_aligned_too_great) | |||
1638 | << CI.getRange() << Sema::MaximumAlignment; | |||
1639 | } | |||
1640 | ||||
1641 | if (OE && !OE->isValueDependent() && !OE->isIntegerConstantExpr(Context)) { | |||
1642 | Diag(AttrLoc, diag::err_attribute_argument_n_type) | |||
1643 | << &TmpAttr << 2 << AANT_ArgumentIntegerConstant | |||
1644 | << OE->getSourceRange(); | |||
1645 | return; | |||
1646 | } | |||
1647 | ||||
1648 | D->addAttr(::new (Context) AssumeAlignedAttr(Context, CI, E, OE)); | |||
1649 | } | |||
1650 | ||||
1651 | void Sema::AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI, | |||
1652 | Expr *ParamExpr) { | |||
1653 | QualType ResultType = getFunctionOrMethodResultType(D); | |||
1654 | ||||
1655 | AllocAlignAttr TmpAttr(Context, CI, ParamIdx()); | |||
1656 | SourceLocation AttrLoc = CI.getLoc(); | |||
1657 | ||||
1658 | if (!ResultType->isDependentType() && | |||
1659 | !isValidPointerAttrType(ResultType, /* RefOkay */ true)) { | |||
1660 | Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only) | |||
1661 | << &TmpAttr << CI.getRange() << getFunctionOrMethodResultSourceRange(D); | |||
1662 | return; | |||
1663 | } | |||
1664 | ||||
1665 | ParamIdx Idx; | |||
1666 | const auto *FuncDecl = cast<FunctionDecl>(D); | |||
1667 | if (!checkFunctionOrMethodParameterIndex(*this, FuncDecl, TmpAttr, | |||
1668 | /*AttrArgNum=*/1, ParamExpr, Idx)) | |||
1669 | return; | |||
1670 | ||||
1671 | QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex()); | |||
1672 | if (!Ty->isDependentType() && !Ty->isIntegralType(Context) && | |||
1673 | !Ty->isAlignValT()) { | |||
1674 | Diag(ParamExpr->getBeginLoc(), diag::err_attribute_integers_only) | |||
1675 | << &TmpAttr | |||
1676 | << FuncDecl->getParamDecl(Idx.getASTIndex())->getSourceRange(); | |||
1677 | return; | |||
1678 | } | |||
1679 | ||||
1680 | D->addAttr(::new (Context) AllocAlignAttr(Context, CI, Idx)); | |||
1681 | } | |||
1682 | ||||
1683 | /// Check if \p AssumptionStr is a known assumption and warn if not. | |||
1684 | static void checkAssumptionAttr(Sema &S, SourceLocation Loc, | |||
1685 | StringRef AssumptionStr) { | |||
1686 | if (llvm::KnownAssumptionStrings.count(AssumptionStr)) | |||
1687 | return; | |||
1688 | ||||
1689 | unsigned BestEditDistance = 3; | |||
1690 | StringRef Suggestion; | |||
1691 | for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) { | |||
1692 | unsigned EditDistance = | |||
1693 | AssumptionStr.edit_distance(KnownAssumptionIt.getKey()); | |||
1694 | if (EditDistance < BestEditDistance) { | |||
1695 | Suggestion = KnownAssumptionIt.getKey(); | |||
1696 | BestEditDistance = EditDistance; | |||
1697 | } | |||
1698 | } | |||
1699 | ||||
1700 | if (!Suggestion.empty()) | |||
1701 | S.Diag(Loc, diag::warn_assume_attribute_string_unknown_suggested) | |||
1702 | << AssumptionStr << Suggestion; | |||
1703 | else | |||
1704 | S.Diag(Loc, diag::warn_assume_attribute_string_unknown) << AssumptionStr; | |||
1705 | } | |||
1706 | ||||
1707 | static void handleAssumumptionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1708 | // Handle the case where the attribute has a text message. | |||
1709 | StringRef Str; | |||
1710 | SourceLocation AttrStrLoc; | |||
1711 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc)) | |||
1712 | return; | |||
1713 | ||||
1714 | checkAssumptionAttr(S, AttrStrLoc, Str); | |||
1715 | ||||
1716 | D->addAttr(::new (S.Context) AssumptionAttr(S.Context, AL, Str)); | |||
1717 | } | |||
1718 | ||||
1719 | /// Normalize the attribute, __foo__ becomes foo. | |||
1720 | /// Returns true if normalization was applied. | |||
1721 | static bool normalizeName(StringRef &AttrName) { | |||
1722 | if (AttrName.size() > 4 && AttrName.startswith("__") && | |||
1723 | AttrName.endswith("__")) { | |||
1724 | AttrName = AttrName.drop_front(2).drop_back(2); | |||
1725 | return true; | |||
1726 | } | |||
1727 | return false; | |||
1728 | } | |||
1729 | ||||
1730 | static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1731 | // This attribute must be applied to a function declaration. The first | |||
1732 | // argument to the attribute must be an identifier, the name of the resource, | |||
1733 | // for example: malloc. The following arguments must be argument indexes, the | |||
1734 | // arguments must be of integer type for Returns, otherwise of pointer type. | |||
1735 | // The difference between Holds and Takes is that a pointer may still be used | |||
1736 | // after being held. free() should be __attribute((ownership_takes)), whereas | |||
1737 | // a list append function may well be __attribute((ownership_holds)). | |||
1738 | ||||
1739 | if (!AL.isArgIdent(0)) { | |||
1740 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
1741 | << AL << 1 << AANT_ArgumentIdentifier; | |||
1742 | return; | |||
1743 | } | |||
1744 | ||||
1745 | // Figure out our Kind. | |||
1746 | OwnershipAttr::OwnershipKind K = | |||
1747 | OwnershipAttr(S.Context, AL, nullptr, nullptr, 0).getOwnKind(); | |||
1748 | ||||
1749 | // Check arguments. | |||
1750 | switch (K) { | |||
1751 | case OwnershipAttr::Takes: | |||
1752 | case OwnershipAttr::Holds: | |||
1753 | if (AL.getNumArgs() < 2) { | |||
1754 | S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << AL << 2; | |||
1755 | return; | |||
1756 | } | |||
1757 | break; | |||
1758 | case OwnershipAttr::Returns: | |||
1759 | if (AL.getNumArgs() > 2) { | |||
1760 | S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1; | |||
1761 | return; | |||
1762 | } | |||
1763 | break; | |||
1764 | } | |||
1765 | ||||
1766 | IdentifierInfo *Module = AL.getArgAsIdent(0)->Ident; | |||
1767 | ||||
1768 | StringRef ModuleName = Module->getName(); | |||
1769 | if (normalizeName(ModuleName)) { | |||
1770 | Module = &S.PP.getIdentifierTable().get(ModuleName); | |||
1771 | } | |||
1772 | ||||
1773 | SmallVector<ParamIdx, 8> OwnershipArgs; | |||
1774 | for (unsigned i = 1; i < AL.getNumArgs(); ++i) { | |||
1775 | Expr *Ex = AL.getArgAsExpr(i); | |||
1776 | ParamIdx Idx; | |||
1777 | if (!checkFunctionOrMethodParameterIndex(S, D, AL, i, Ex, Idx)) | |||
1778 | return; | |||
1779 | ||||
1780 | // Is the function argument a pointer type? | |||
1781 | QualType T = getFunctionOrMethodParamType(D, Idx.getASTIndex()); | |||
1782 | int Err = -1; // No error | |||
1783 | switch (K) { | |||
1784 | case OwnershipAttr::Takes: | |||
1785 | case OwnershipAttr::Holds: | |||
1786 | if (!T->isAnyPointerType() && !T->isBlockPointerType()) | |||
1787 | Err = 0; | |||
1788 | break; | |||
1789 | case OwnershipAttr::Returns: | |||
1790 | if (!T->isIntegerType()) | |||
1791 | Err = 1; | |||
1792 | break; | |||
1793 | } | |||
1794 | if (-1 != Err) { | |||
1795 | S.Diag(AL.getLoc(), diag::err_ownership_type) << AL << Err | |||
1796 | << Ex->getSourceRange(); | |||
1797 | return; | |||
1798 | } | |||
1799 | ||||
1800 | // Check we don't have a conflict with another ownership attribute. | |||
1801 | for (const auto *I : D->specific_attrs<OwnershipAttr>()) { | |||
1802 | // Cannot have two ownership attributes of different kinds for the same | |||
1803 | // index. | |||
1804 | if (I->getOwnKind() != K && I->args_end() != | |||
1805 | std::find(I->args_begin(), I->args_end(), Idx)) { | |||
1806 | S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << I; | |||
1807 | return; | |||
1808 | } else if (K == OwnershipAttr::Returns && | |||
1809 | I->getOwnKind() == OwnershipAttr::Returns) { | |||
1810 | // A returns attribute conflicts with any other returns attribute using | |||
1811 | // a different index. | |||
1812 | if (std::find(I->args_begin(), I->args_end(), Idx) == I->args_end()) { | |||
1813 | S.Diag(I->getLocation(), diag::err_ownership_returns_index_mismatch) | |||
1814 | << I->args_begin()->getSourceIndex(); | |||
1815 | if (I->args_size()) | |||
1816 | S.Diag(AL.getLoc(), diag::note_ownership_returns_index_mismatch) | |||
1817 | << Idx.getSourceIndex() << Ex->getSourceRange(); | |||
1818 | return; | |||
1819 | } | |||
1820 | } | |||
1821 | } | |||
1822 | OwnershipArgs.push_back(Idx); | |||
1823 | } | |||
1824 | ||||
1825 | ParamIdx *Start = OwnershipArgs.data(); | |||
1826 | unsigned Size = OwnershipArgs.size(); | |||
1827 | llvm::array_pod_sort(Start, Start + Size); | |||
1828 | D->addAttr(::new (S.Context) | |||
1829 | OwnershipAttr(S.Context, AL, Module, Start, Size)); | |||
1830 | } | |||
1831 | ||||
1832 | static void handleWeakRefAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1833 | // Check the attribute arguments. | |||
1834 | if (AL.getNumArgs() > 1) { | |||
1835 | S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; | |||
1836 | return; | |||
1837 | } | |||
1838 | ||||
1839 | // gcc rejects | |||
1840 | // class c { | |||
1841 | // static int a __attribute__((weakref ("v2"))); | |||
1842 | // static int b() __attribute__((weakref ("f3"))); | |||
1843 | // }; | |||
1844 | // and ignores the attributes of | |||
1845 | // void f(void) { | |||
1846 | // static int a __attribute__((weakref ("v2"))); | |||
1847 | // } | |||
1848 | // we reject them | |||
1849 | const DeclContext *Ctx = D->getDeclContext()->getRedeclContext(); | |||
1850 | if (!Ctx->isFileContext()) { | |||
1851 | S.Diag(AL.getLoc(), diag::err_attribute_weakref_not_global_context) | |||
1852 | << cast<NamedDecl>(D); | |||
1853 | return; | |||
1854 | } | |||
1855 | ||||
1856 | // The GCC manual says | |||
1857 | // | |||
1858 | // At present, a declaration to which `weakref' is attached can only | |||
1859 | // be `static'. | |||
1860 | // | |||
1861 | // It also says | |||
1862 | // | |||
1863 | // Without a TARGET, | |||
1864 | // given as an argument to `weakref' or to `alias', `weakref' is | |||
1865 | // equivalent to `weak'. | |||
1866 | // | |||
1867 | // gcc 4.4.1 will accept | |||
1868 | // int a7 __attribute__((weakref)); | |||
1869 | // as | |||
1870 | // int a7 __attribute__((weak)); | |||
1871 | // This looks like a bug in gcc. We reject that for now. We should revisit | |||
1872 | // it if this behaviour is actually used. | |||
1873 | ||||
1874 | // GCC rejects | |||
1875 | // static ((alias ("y"), weakref)). | |||
1876 | // Should we? How to check that weakref is before or after alias? | |||
1877 | ||||
1878 | // FIXME: it would be good for us to keep the WeakRefAttr as-written instead | |||
1879 | // of transforming it into an AliasAttr. The WeakRefAttr never uses the | |||
1880 | // StringRef parameter it was given anyway. | |||
1881 | StringRef Str; | |||
1882 | if (AL.getNumArgs() && S.checkStringLiteralArgumentAttr(AL, 0, Str)) | |||
1883 | // GCC will accept anything as the argument of weakref. Should we | |||
1884 | // check for an existing decl? | |||
1885 | D->addAttr(::new (S.Context) AliasAttr(S.Context, AL, Str)); | |||
1886 | ||||
1887 | D->addAttr(::new (S.Context) WeakRefAttr(S.Context, AL)); | |||
1888 | } | |||
1889 | ||||
1890 | static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1891 | StringRef Str; | |||
1892 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) | |||
1893 | return; | |||
1894 | ||||
1895 | // Aliases should be on declarations, not definitions. | |||
1896 | const auto *FD = cast<FunctionDecl>(D); | |||
1897 | if (FD->isThisDeclarationADefinition()) { | |||
1898 | S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 1; | |||
1899 | return; | |||
1900 | } | |||
1901 | ||||
1902 | D->addAttr(::new (S.Context) IFuncAttr(S.Context, AL, Str)); | |||
1903 | } | |||
1904 | ||||
1905 | static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1906 | StringRef Str; | |||
1907 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) | |||
1908 | return; | |||
1909 | ||||
1910 | if (S.Context.getTargetInfo().getTriple().isOSDarwin()) { | |||
1911 | S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_darwin); | |||
1912 | return; | |||
1913 | } | |||
1914 | if (S.Context.getTargetInfo().getTriple().isNVPTX()) { | |||
1915 | S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_nvptx); | |||
1916 | } | |||
1917 | ||||
1918 | // Aliases should be on declarations, not definitions. | |||
1919 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
1920 | if (FD->isThisDeclarationADefinition()) { | |||
1921 | S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 0; | |||
1922 | return; | |||
1923 | } | |||
1924 | } else { | |||
1925 | const auto *VD = cast<VarDecl>(D); | |||
1926 | if (VD->isThisDeclarationADefinition() && VD->isExternallyVisible()) { | |||
1927 | S.Diag(AL.getLoc(), diag::err_alias_is_definition) << VD << 0; | |||
1928 | return; | |||
1929 | } | |||
1930 | } | |||
1931 | ||||
1932 | // Mark target used to prevent unneeded-internal-declaration warnings. | |||
1933 | if (!S.LangOpts.CPlusPlus) { | |||
1934 | // FIXME: demangle Str for C++, as the attribute refers to the mangled | |||
1935 | // linkage name, not the pre-mangled identifier. | |||
1936 | const DeclarationNameInfo target(&S.Context.Idents.get(Str), AL.getLoc()); | |||
1937 | LookupResult LR(S, target, Sema::LookupOrdinaryName); | |||
1938 | if (S.LookupQualifiedName(LR, S.getCurLexicalContext())) | |||
1939 | for (NamedDecl *ND : LR) | |||
1940 | ND->markUsed(S.Context); | |||
1941 | } | |||
1942 | ||||
1943 | D->addAttr(::new (S.Context) AliasAttr(S.Context, AL, Str)); | |||
1944 | } | |||
1945 | ||||
1946 | static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1947 | StringRef Model; | |||
1948 | SourceLocation LiteralLoc; | |||
1949 | // Check that it is a string. | |||
1950 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Model, &LiteralLoc)) | |||
1951 | return; | |||
1952 | ||||
1953 | // Check that the value. | |||
1954 | if (Model != "global-dynamic" && Model != "local-dynamic" | |||
1955 | && Model != "initial-exec" && Model != "local-exec") { | |||
1956 | S.Diag(LiteralLoc, diag::err_attr_tlsmodel_arg); | |||
1957 | return; | |||
1958 | } | |||
1959 | ||||
1960 | D->addAttr(::new (S.Context) TLSModelAttr(S.Context, AL, Model)); | |||
1961 | } | |||
1962 | ||||
1963 | static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1964 | QualType ResultType = getFunctionOrMethodResultType(D); | |||
1965 | if (ResultType->isAnyPointerType() || ResultType->isBlockPointerType()) { | |||
1966 | D->addAttr(::new (S.Context) RestrictAttr(S.Context, AL)); | |||
1967 | return; | |||
1968 | } | |||
1969 | ||||
1970 | S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) | |||
1971 | << AL << getFunctionOrMethodResultSourceRange(D); | |||
1972 | } | |||
1973 | ||||
1974 | static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
1975 | FunctionDecl *FD = cast<FunctionDecl>(D); | |||
1976 | ||||
1977 | if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { | |||
1978 | if (MD->getParent()->isLambda()) { | |||
1979 | S.Diag(AL.getLoc(), diag::err_attribute_dll_lambda) << AL; | |||
1980 | return; | |||
1981 | } | |||
1982 | } | |||
1983 | ||||
1984 | if (!AL.checkAtLeastNumArgs(S, 1)) | |||
1985 | return; | |||
1986 | ||||
1987 | SmallVector<IdentifierInfo *, 8> CPUs; | |||
1988 | for (unsigned ArgNo = 0; ArgNo < getNumAttributeArgs(AL); ++ArgNo) { | |||
1989 | if (!AL.isArgIdent(ArgNo)) { | |||
1990 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
1991 | << AL << AANT_ArgumentIdentifier; | |||
1992 | return; | |||
1993 | } | |||
1994 | ||||
1995 | IdentifierLoc *CPUArg = AL.getArgAsIdent(ArgNo); | |||
1996 | StringRef CPUName = CPUArg->Ident->getName().trim(); | |||
1997 | ||||
1998 | if (!S.Context.getTargetInfo().validateCPUSpecificCPUDispatch(CPUName)) { | |||
1999 | S.Diag(CPUArg->Loc, diag::err_invalid_cpu_specific_dispatch_value) | |||
2000 | << CPUName << (AL.getKind() == ParsedAttr::AT_CPUDispatch); | |||
2001 | return; | |||
2002 | } | |||
2003 | ||||
2004 | const TargetInfo &Target = S.Context.getTargetInfo(); | |||
2005 | if (llvm::any_of(CPUs, [CPUName, &Target](const IdentifierInfo *Cur) { | |||
2006 | return Target.CPUSpecificManglingCharacter(CPUName) == | |||
2007 | Target.CPUSpecificManglingCharacter(Cur->getName()); | |||
2008 | })) { | |||
2009 | S.Diag(AL.getLoc(), diag::warn_multiversion_duplicate_entries); | |||
2010 | return; | |||
2011 | } | |||
2012 | CPUs.push_back(CPUArg->Ident); | |||
2013 | } | |||
2014 | ||||
2015 | FD->setIsMultiVersion(true); | |||
2016 | if (AL.getKind() == ParsedAttr::AT_CPUSpecific) | |||
2017 | D->addAttr(::new (S.Context) | |||
2018 | CPUSpecificAttr(S.Context, AL, CPUs.data(), CPUs.size())); | |||
2019 | else | |||
2020 | D->addAttr(::new (S.Context) | |||
2021 | CPUDispatchAttr(S.Context, AL, CPUs.data(), CPUs.size())); | |||
2022 | } | |||
2023 | ||||
2024 | static void handleCommonAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2025 | if (S.LangOpts.CPlusPlus) { | |||
2026 | S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) | |||
2027 | << AL << AttributeLangSupport::Cpp; | |||
2028 | return; | |||
2029 | } | |||
2030 | ||||
2031 | if (CommonAttr *CA = S.mergeCommonAttr(D, AL)) | |||
2032 | D->addAttr(CA); | |||
2033 | } | |||
2034 | ||||
2035 | static void handleCmseNSEntryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2036 | if (S.LangOpts.CPlusPlus && !D->getDeclContext()->isExternCContext()) { | |||
2037 | S.Diag(AL.getLoc(), diag::err_attribute_not_clinkage) << AL; | |||
2038 | return; | |||
2039 | } | |||
2040 | ||||
2041 | const auto *FD = cast<FunctionDecl>(D); | |||
2042 | if (!FD->isExternallyVisible()) { | |||
2043 | S.Diag(AL.getLoc(), diag::warn_attribute_cmse_entry_static); | |||
2044 | return; | |||
2045 | } | |||
2046 | ||||
2047 | D->addAttr(::new (S.Context) CmseNSEntryAttr(S.Context, AL)); | |||
2048 | } | |||
2049 | ||||
2050 | static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2051 | if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, AL)) | |||
2052 | return; | |||
2053 | ||||
2054 | if (AL.isDeclspecAttribute()) { | |||
2055 | const auto &Triple = S.getASTContext().getTargetInfo().getTriple(); | |||
2056 | const auto &Arch = Triple.getArch(); | |||
2057 | if (Arch != llvm::Triple::x86 && | |||
2058 | (Arch != llvm::Triple::arm && Arch != llvm::Triple::thumb)) { | |||
2059 | S.Diag(AL.getLoc(), diag::err_attribute_not_supported_on_arch) | |||
2060 | << AL << Triple.getArchName(); | |||
2061 | return; | |||
2062 | } | |||
2063 | } | |||
2064 | ||||
2065 | D->addAttr(::new (S.Context) NakedAttr(S.Context, AL)); | |||
2066 | } | |||
2067 | ||||
2068 | static void handleNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) { | |||
2069 | if (hasDeclarator(D)) return; | |||
2070 | ||||
2071 | if (!isa<ObjCMethodDecl>(D)) { | |||
2072 | S.Diag(Attrs.getLoc(), diag::warn_attribute_wrong_decl_type) | |||
2073 | << Attrs << ExpectedFunctionOrMethod; | |||
2074 | return; | |||
2075 | } | |||
2076 | ||||
2077 | D->addAttr(::new (S.Context) NoReturnAttr(S.Context, Attrs)); | |||
2078 | } | |||
2079 | ||||
2080 | static void handleNoCfCheckAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) { | |||
2081 | if (!S.getLangOpts().CFProtectionBranch) | |||
2082 | S.Diag(Attrs.getLoc(), diag::warn_nocf_check_attribute_ignored); | |||
2083 | else | |||
2084 | handleSimpleAttribute<AnyX86NoCfCheckAttr>(S, D, Attrs); | |||
2085 | } | |||
2086 | ||||
2087 | bool Sema::CheckAttrNoArgs(const ParsedAttr &Attrs) { | |||
2088 | if (!Attrs.checkExactlyNumArgs(*this, 0)) { | |||
2089 | Attrs.setInvalid(); | |||
2090 | return true; | |||
2091 | } | |||
2092 | ||||
2093 | return false; | |||
2094 | } | |||
2095 | ||||
2096 | bool Sema::CheckAttrTarget(const ParsedAttr &AL) { | |||
2097 | // Check whether the attribute is valid on the current target. | |||
2098 | if (!AL.existsInTarget(Context.getTargetInfo())) { | |||
2099 | Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) | |||
2100 | << AL << AL.getRange(); | |||
2101 | AL.setInvalid(); | |||
2102 | return true; | |||
2103 | } | |||
2104 | ||||
2105 | return false; | |||
2106 | } | |||
2107 | ||||
2108 | static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2109 | ||||
2110 | // The checking path for 'noreturn' and 'analyzer_noreturn' are different | |||
2111 | // because 'analyzer_noreturn' does not impact the type. | |||
2112 | if (!isFunctionOrMethodOrBlock(D)) { | |||
2113 | ValueDecl *VD = dyn_cast<ValueDecl>(D); | |||
2114 | if (!VD || (!VD->getType()->isBlockPointerType() && | |||
2115 | !VD->getType()->isFunctionPointerType())) { | |||
2116 | S.Diag(AL.getLoc(), AL.isCXX11Attribute() | |||
2117 | ? diag::err_attribute_wrong_decl_type | |||
2118 | : diag::warn_attribute_wrong_decl_type) | |||
2119 | << AL << ExpectedFunctionMethodOrBlock; | |||
2120 | return; | |||
2121 | } | |||
2122 | } | |||
2123 | ||||
2124 | D->addAttr(::new (S.Context) AnalyzerNoReturnAttr(S.Context, AL)); | |||
2125 | } | |||
2126 | ||||
2127 | // PS3 PPU-specific. | |||
2128 | static void handleVecReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2129 | /* | |||
2130 | Returning a Vector Class in Registers | |||
2131 | ||||
2132 | According to the PPU ABI specifications, a class with a single member of | |||
2133 | vector type is returned in memory when used as the return value of a | |||
2134 | function. | |||
2135 | This results in inefficient code when implementing vector classes. To return | |||
2136 | the value in a single vector register, add the vecreturn attribute to the | |||
2137 | class definition. This attribute is also applicable to struct types. | |||
2138 | ||||
2139 | Example: | |||
2140 | ||||
2141 | struct Vector | |||
2142 | { | |||
2143 | __vector float xyzw; | |||
2144 | } __attribute__((vecreturn)); | |||
2145 | ||||
2146 | Vector Add(Vector lhs, Vector rhs) | |||
2147 | { | |||
2148 | Vector result; | |||
2149 | result.xyzw = vec_add(lhs.xyzw, rhs.xyzw); | |||
2150 | return result; // This will be returned in a register | |||
2151 | } | |||
2152 | */ | |||
2153 | if (VecReturnAttr *A = D->getAttr<VecReturnAttr>()) { | |||
2154 | S.Diag(AL.getLoc(), diag::err_repeat_attribute) << A; | |||
2155 | return; | |||
2156 | } | |||
2157 | ||||
2158 | const auto *R = cast<RecordDecl>(D); | |||
2159 | int count = 0; | |||
2160 | ||||
2161 | if (!isa<CXXRecordDecl>(R)) { | |||
2162 | S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member); | |||
2163 | return; | |||
2164 | } | |||
2165 | ||||
2166 | if (!cast<CXXRecordDecl>(R)->isPOD()) { | |||
2167 | S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_pod_record); | |||
2168 | return; | |||
2169 | } | |||
2170 | ||||
2171 | for (const auto *I : R->fields()) { | |||
2172 | if ((count == 1) || !I->getType()->isVectorType()) { | |||
2173 | S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member); | |||
2174 | return; | |||
2175 | } | |||
2176 | count++; | |||
2177 | } | |||
2178 | ||||
2179 | D->addAttr(::new (S.Context) VecReturnAttr(S.Context, AL)); | |||
2180 | } | |||
2181 | ||||
2182 | static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, | |||
2183 | const ParsedAttr &AL) { | |||
2184 | if (isa<ParmVarDecl>(D)) { | |||
2185 | // [[carries_dependency]] can only be applied to a parameter if it is a | |||
2186 | // parameter of a function declaration or lambda. | |||
2187 | if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) { | |||
2188 | S.Diag(AL.getLoc(), | |||
2189 | diag::err_carries_dependency_param_not_function_decl); | |||
2190 | return; | |||
2191 | } | |||
2192 | } | |||
2193 | ||||
2194 | D->addAttr(::new (S.Context) CarriesDependencyAttr(S.Context, AL)); | |||
2195 | } | |||
2196 | ||||
2197 | static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2198 | bool IsCXX17Attr = AL.isCXX11Attribute() && !AL.getScopeName(); | |||
2199 | ||||
2200 | // If this is spelled as the standard C++17 attribute, but not in C++17, warn | |||
2201 | // about using it as an extension. | |||
2202 | if (!S.getLangOpts().CPlusPlus17 && IsCXX17Attr) | |||
2203 | S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL; | |||
2204 | ||||
2205 | D->addAttr(::new (S.Context) UnusedAttr(S.Context, AL)); | |||
2206 | } | |||
2207 | ||||
2208 | static void handleConstructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2209 | uint32_t priority = ConstructorAttr::DefaultPriority; | |||
2210 | if (AL.getNumArgs() && | |||
2211 | !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority)) | |||
2212 | return; | |||
2213 | ||||
2214 | D->addAttr(::new (S.Context) ConstructorAttr(S.Context, AL, priority)); | |||
2215 | } | |||
2216 | ||||
2217 | static void handleDestructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2218 | uint32_t priority = DestructorAttr::DefaultPriority; | |||
2219 | if (AL.getNumArgs() && | |||
2220 | !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority)) | |||
2221 | return; | |||
2222 | ||||
2223 | D->addAttr(::new (S.Context) DestructorAttr(S.Context, AL, priority)); | |||
2224 | } | |||
2225 | ||||
2226 | template <typename AttrTy> | |||
2227 | static void handleAttrWithMessage(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2228 | // Handle the case where the attribute has a text message. | |||
2229 | StringRef Str; | |||
2230 | if (AL.getNumArgs() == 1 && !S.checkStringLiteralArgumentAttr(AL, 0, Str)) | |||
2231 | return; | |||
2232 | ||||
2233 | D->addAttr(::new (S.Context) AttrTy(S.Context, AL, Str)); | |||
2234 | } | |||
2235 | ||||
2236 | static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D, | |||
2237 | const ParsedAttr &AL) { | |||
2238 | if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) { | |||
2239 | S.Diag(AL.getLoc(), diag::err_objc_attr_protocol_requires_definition) | |||
2240 | << AL << AL.getRange(); | |||
2241 | return; | |||
2242 | } | |||
2243 | ||||
2244 | D->addAttr(::new (S.Context) ObjCExplicitProtocolImplAttr(S.Context, AL)); | |||
2245 | } | |||
2246 | ||||
2247 | static bool checkAvailabilityAttr(Sema &S, SourceRange Range, | |||
2248 | IdentifierInfo *Platform, | |||
2249 | VersionTuple Introduced, | |||
2250 | VersionTuple Deprecated, | |||
2251 | VersionTuple Obsoleted) { | |||
2252 | StringRef PlatformName | |||
2253 | = AvailabilityAttr::getPrettyPlatformName(Platform->getName()); | |||
2254 | if (PlatformName.empty()) | |||
2255 | PlatformName = Platform->getName(); | |||
2256 | ||||
2257 | // Ensure that Introduced <= Deprecated <= Obsoleted (although not all | |||
2258 | // of these steps are needed). | |||
2259 | if (!Introduced.empty() && !Deprecated.empty() && | |||
2260 | !(Introduced <= Deprecated)) { | |||
2261 | S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) | |||
2262 | << 1 << PlatformName << Deprecated.getAsString() | |||
2263 | << 0 << Introduced.getAsString(); | |||
2264 | return true; | |||
2265 | } | |||
2266 | ||||
2267 | if (!Introduced.empty() && !Obsoleted.empty() && | |||
2268 | !(Introduced <= Obsoleted)) { | |||
2269 | S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) | |||
2270 | << 2 << PlatformName << Obsoleted.getAsString() | |||
2271 | << 0 << Introduced.getAsString(); | |||
2272 | return true; | |||
2273 | } | |||
2274 | ||||
2275 | if (!Deprecated.empty() && !Obsoleted.empty() && | |||
2276 | !(Deprecated <= Obsoleted)) { | |||
2277 | S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) | |||
2278 | << 2 << PlatformName << Obsoleted.getAsString() | |||
2279 | << 1 << Deprecated.getAsString(); | |||
2280 | return true; | |||
2281 | } | |||
2282 | ||||
2283 | return false; | |||
2284 | } | |||
2285 | ||||
2286 | /// Check whether the two versions match. | |||
2287 | /// | |||
2288 | /// If either version tuple is empty, then they are assumed to match. If | |||
2289 | /// \p BeforeIsOkay is true, then \p X can be less than or equal to \p Y. | |||
2290 | static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y, | |||
2291 | bool BeforeIsOkay) { | |||
2292 | if (X.empty() || Y.empty()) | |||
2293 | return true; | |||
2294 | ||||
2295 | if (X == Y) | |||
2296 | return true; | |||
2297 | ||||
2298 | if (BeforeIsOkay && X < Y) | |||
2299 | return true; | |||
2300 | ||||
2301 | return false; | |||
2302 | } | |||
2303 | ||||
2304 | AvailabilityAttr *Sema::mergeAvailabilityAttr( | |||
2305 | NamedDecl *D, const AttributeCommonInfo &CI, IdentifierInfo *Platform, | |||
2306 | bool Implicit, VersionTuple Introduced, VersionTuple Deprecated, | |||
2307 | VersionTuple Obsoleted, bool IsUnavailable, StringRef Message, | |||
2308 | bool IsStrict, StringRef Replacement, AvailabilityMergeKind AMK, | |||
2309 | int Priority) { | |||
2310 | VersionTuple MergedIntroduced = Introduced; | |||
2311 | VersionTuple MergedDeprecated = Deprecated; | |||
2312 | VersionTuple MergedObsoleted = Obsoleted; | |||
2313 | bool FoundAny = false; | |||
2314 | bool OverrideOrImpl = false; | |||
2315 | switch (AMK) { | |||
2316 | case AMK_None: | |||
2317 | case AMK_Redeclaration: | |||
2318 | OverrideOrImpl = false; | |||
2319 | break; | |||
2320 | ||||
2321 | case AMK_Override: | |||
2322 | case AMK_ProtocolImplementation: | |||
2323 | OverrideOrImpl = true; | |||
2324 | break; | |||
2325 | } | |||
2326 | ||||
2327 | if (D->hasAttrs()) { | |||
2328 | AttrVec &Attrs = D->getAttrs(); | |||
2329 | for (unsigned i = 0, e = Attrs.size(); i != e;) { | |||
2330 | const auto *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]); | |||
2331 | if (!OldAA) { | |||
2332 | ++i; | |||
2333 | continue; | |||
2334 | } | |||
2335 | ||||
2336 | IdentifierInfo *OldPlatform = OldAA->getPlatform(); | |||
2337 | if (OldPlatform != Platform) { | |||
2338 | ++i; | |||
2339 | continue; | |||
2340 | } | |||
2341 | ||||
2342 | // If there is an existing availability attribute for this platform that | |||
2343 | // has a lower priority use the existing one and discard the new | |||
2344 | // attribute. | |||
2345 | if (OldAA->getPriority() < Priority) | |||
2346 | return nullptr; | |||
2347 | ||||
2348 | // If there is an existing attribute for this platform that has a higher | |||
2349 | // priority than the new attribute then erase the old one and continue | |||
2350 | // processing the attributes. | |||
2351 | if (OldAA->getPriority() > Priority) { | |||
2352 | Attrs.erase(Attrs.begin() + i); | |||
2353 | --e; | |||
2354 | continue; | |||
2355 | } | |||
2356 | ||||
2357 | FoundAny = true; | |||
2358 | VersionTuple OldIntroduced = OldAA->getIntroduced(); | |||
2359 | VersionTuple OldDeprecated = OldAA->getDeprecated(); | |||
2360 | VersionTuple OldObsoleted = OldAA->getObsoleted(); | |||
2361 | bool OldIsUnavailable = OldAA->getUnavailable(); | |||
2362 | ||||
2363 | if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl) || | |||
2364 | !versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl) || | |||
2365 | !versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl) || | |||
2366 | !(OldIsUnavailable == IsUnavailable || | |||
2367 | (OverrideOrImpl && !OldIsUnavailable && IsUnavailable))) { | |||
2368 | if (OverrideOrImpl) { | |||
2369 | int Which = -1; | |||
2370 | VersionTuple FirstVersion; | |||
2371 | VersionTuple SecondVersion; | |||
2372 | if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl)) { | |||
2373 | Which = 0; | |||
2374 | FirstVersion = OldIntroduced; | |||
2375 | SecondVersion = Introduced; | |||
2376 | } else if (!versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl)) { | |||
2377 | Which = 1; | |||
2378 | FirstVersion = Deprecated; | |||
2379 | SecondVersion = OldDeprecated; | |||
2380 | } else if (!versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl)) { | |||
2381 | Which = 2; | |||
2382 | FirstVersion = Obsoleted; | |||
2383 | SecondVersion = OldObsoleted; | |||
2384 | } | |||
2385 | ||||
2386 | if (Which == -1) { | |||
2387 | Diag(OldAA->getLocation(), | |||
2388 | diag::warn_mismatched_availability_override_unavail) | |||
2389 | << AvailabilityAttr::getPrettyPlatformName(Platform->getName()) | |||
2390 | << (AMK == AMK_Override); | |||
2391 | } else { | |||
2392 | Diag(OldAA->getLocation(), | |||
2393 | diag::warn_mismatched_availability_override) | |||
2394 | << Which | |||
2395 | << AvailabilityAttr::getPrettyPlatformName(Platform->getName()) | |||
2396 | << FirstVersion.getAsString() << SecondVersion.getAsString() | |||
2397 | << (AMK == AMK_Override); | |||
2398 | } | |||
2399 | if (AMK == AMK_Override) | |||
2400 | Diag(CI.getLoc(), diag::note_overridden_method); | |||
2401 | else | |||
2402 | Diag(CI.getLoc(), diag::note_protocol_method); | |||
2403 | } else { | |||
2404 | Diag(OldAA->getLocation(), diag::warn_mismatched_availability); | |||
2405 | Diag(CI.getLoc(), diag::note_previous_attribute); | |||
2406 | } | |||
2407 | ||||
2408 | Attrs.erase(Attrs.begin() + i); | |||
2409 | --e; | |||
2410 | continue; | |||
2411 | } | |||
2412 | ||||
2413 | VersionTuple MergedIntroduced2 = MergedIntroduced; | |||
2414 | VersionTuple MergedDeprecated2 = MergedDeprecated; | |||
2415 | VersionTuple MergedObsoleted2 = MergedObsoleted; | |||
2416 | ||||
2417 | if (MergedIntroduced2.empty()) | |||
2418 | MergedIntroduced2 = OldIntroduced; | |||
2419 | if (MergedDeprecated2.empty()) | |||
2420 | MergedDeprecated2 = OldDeprecated; | |||
2421 | if (MergedObsoleted2.empty()) | |||
2422 | MergedObsoleted2 = OldObsoleted; | |||
2423 | ||||
2424 | if (checkAvailabilityAttr(*this, OldAA->getRange(), Platform, | |||
2425 | MergedIntroduced2, MergedDeprecated2, | |||
2426 | MergedObsoleted2)) { | |||
2427 | Attrs.erase(Attrs.begin() + i); | |||
2428 | --e; | |||
2429 | continue; | |||
2430 | } | |||
2431 | ||||
2432 | MergedIntroduced = MergedIntroduced2; | |||
2433 | MergedDeprecated = MergedDeprecated2; | |||
2434 | MergedObsoleted = MergedObsoleted2; | |||
2435 | ++i; | |||
2436 | } | |||
2437 | } | |||
2438 | ||||
2439 | if (FoundAny && | |||
2440 | MergedIntroduced == Introduced && | |||
2441 | MergedDeprecated == Deprecated && | |||
2442 | MergedObsoleted == Obsoleted) | |||
2443 | return nullptr; | |||
2444 | ||||
2445 | // Only create a new attribute if !OverrideOrImpl, but we want to do | |||
2446 | // the checking. | |||
2447 | if (!checkAvailabilityAttr(*this, CI.getRange(), Platform, MergedIntroduced, | |||
2448 | MergedDeprecated, MergedObsoleted) && | |||
2449 | !OverrideOrImpl) { | |||
2450 | auto *Avail = ::new (Context) AvailabilityAttr( | |||
2451 | Context, CI, Platform, Introduced, Deprecated, Obsoleted, IsUnavailable, | |||
2452 | Message, IsStrict, Replacement, Priority); | |||
2453 | Avail->setImplicit(Implicit); | |||
2454 | return Avail; | |||
2455 | } | |||
2456 | return nullptr; | |||
2457 | } | |||
2458 | ||||
2459 | static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2460 | if (!AL.checkExactlyNumArgs(S, 1)) | |||
2461 | return; | |||
2462 | IdentifierLoc *Platform = AL.getArgAsIdent(0); | |||
2463 | ||||
2464 | IdentifierInfo *II = Platform->Ident; | |||
2465 | if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty()) | |||
2466 | S.Diag(Platform->Loc, diag::warn_availability_unknown_platform) | |||
2467 | << Platform->Ident; | |||
2468 | ||||
2469 | auto *ND = dyn_cast<NamedDecl>(D); | |||
2470 | if (!ND) // We warned about this already, so just return. | |||
2471 | return; | |||
2472 | ||||
2473 | AvailabilityChange Introduced = AL.getAvailabilityIntroduced(); | |||
2474 | AvailabilityChange Deprecated = AL.getAvailabilityDeprecated(); | |||
2475 | AvailabilityChange Obsoleted = AL.getAvailabilityObsoleted(); | |||
2476 | bool IsUnavailable = AL.getUnavailableLoc().isValid(); | |||
2477 | bool IsStrict = AL.getStrictLoc().isValid(); | |||
2478 | StringRef Str; | |||
2479 | if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getMessageExpr())) | |||
2480 | Str = SE->getString(); | |||
2481 | StringRef Replacement; | |||
2482 | if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getReplacementExpr())) | |||
2483 | Replacement = SE->getString(); | |||
2484 | ||||
2485 | if (II->isStr("swift")) { | |||
2486 | if (Introduced.isValid() || Obsoleted.isValid() || | |||
2487 | (!IsUnavailable && !Deprecated.isValid())) { | |||
2488 | S.Diag(AL.getLoc(), | |||
2489 | diag::warn_availability_swift_unavailable_deprecated_only); | |||
2490 | return; | |||
2491 | } | |||
2492 | } | |||
2493 | ||||
2494 | int PriorityModifier = AL.isPragmaClangAttribute() | |||
2495 | ? Sema::AP_PragmaClangAttribute | |||
2496 | : Sema::AP_Explicit; | |||
2497 | AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( | |||
2498 | ND, AL, II, false /*Implicit*/, Introduced.Version, Deprecated.Version, | |||
2499 | Obsoleted.Version, IsUnavailable, Str, IsStrict, Replacement, | |||
2500 | Sema::AMK_None, PriorityModifier); | |||
2501 | if (NewAttr) | |||
2502 | D->addAttr(NewAttr); | |||
2503 | ||||
2504 | // Transcribe "ios" to "watchos" (and add a new attribute) if the versioning | |||
2505 | // matches before the start of the watchOS platform. | |||
2506 | if (S.Context.getTargetInfo().getTriple().isWatchOS()) { | |||
2507 | IdentifierInfo *NewII = nullptr; | |||
2508 | if (II->getName() == "ios") | |||
2509 | NewII = &S.Context.Idents.get("watchos"); | |||
2510 | else if (II->getName() == "ios_app_extension") | |||
2511 | NewII = &S.Context.Idents.get("watchos_app_extension"); | |||
2512 | ||||
2513 | if (NewII) { | |||
2514 | auto adjustWatchOSVersion = [](VersionTuple Version) -> VersionTuple { | |||
2515 | if (Version.empty()) | |||
2516 | return Version; | |||
2517 | auto Major = Version.getMajor(); | |||
2518 | auto NewMajor = Major >= 9 ? Major - 7 : 0; | |||
2519 | if (NewMajor >= 2) { | |||
2520 | if (Version.getMinor().hasValue()) { | |||
2521 | if (Version.getSubminor().hasValue()) | |||
2522 | return VersionTuple(NewMajor, Version.getMinor().getValue(), | |||
2523 | Version.getSubminor().getValue()); | |||
2524 | else | |||
2525 | return VersionTuple(NewMajor, Version.getMinor().getValue()); | |||
2526 | } | |||
2527 | return VersionTuple(NewMajor); | |||
2528 | } | |||
2529 | ||||
2530 | return VersionTuple(2, 0); | |||
2531 | }; | |||
2532 | ||||
2533 | auto NewIntroduced = adjustWatchOSVersion(Introduced.Version); | |||
2534 | auto NewDeprecated = adjustWatchOSVersion(Deprecated.Version); | |||
2535 | auto NewObsoleted = adjustWatchOSVersion(Obsoleted.Version); | |||
2536 | ||||
2537 | AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( | |||
2538 | ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated, | |||
2539 | NewObsoleted, IsUnavailable, Str, IsStrict, Replacement, | |||
2540 | Sema::AMK_None, | |||
2541 | PriorityModifier + Sema::AP_InferredFromOtherPlatform); | |||
2542 | if (NewAttr) | |||
2543 | D->addAttr(NewAttr); | |||
2544 | } | |||
2545 | } else if (S.Context.getTargetInfo().getTriple().isTvOS()) { | |||
2546 | // Transcribe "ios" to "tvos" (and add a new attribute) if the versioning | |||
2547 | // matches before the start of the tvOS platform. | |||
2548 | IdentifierInfo *NewII = nullptr; | |||
2549 | if (II->getName() == "ios") | |||
2550 | NewII = &S.Context.Idents.get("tvos"); | |||
2551 | else if (II->getName() == "ios_app_extension") | |||
2552 | NewII = &S.Context.Idents.get("tvos_app_extension"); | |||
2553 | ||||
2554 | if (NewII) { | |||
2555 | AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( | |||
2556 | ND, AL, NewII, true /*Implicit*/, Introduced.Version, | |||
2557 | Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, IsStrict, | |||
2558 | Replacement, Sema::AMK_None, | |||
2559 | PriorityModifier + Sema::AP_InferredFromOtherPlatform); | |||
2560 | if (NewAttr) | |||
2561 | D->addAttr(NewAttr); | |||
2562 | } | |||
2563 | } | |||
2564 | } | |||
2565 | ||||
2566 | static void handleExternalSourceSymbolAttr(Sema &S, Decl *D, | |||
2567 | const ParsedAttr &AL) { | |||
2568 | if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 3)) | |||
2569 | return; | |||
2570 | ||||
2571 | StringRef Language; | |||
2572 | if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(0))) | |||
2573 | Language = SE->getString(); | |||
2574 | StringRef DefinedIn; | |||
2575 | if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(1))) | |||
2576 | DefinedIn = SE->getString(); | |||
2577 | bool IsGeneratedDeclaration = AL.getArgAsIdent(2) != nullptr; | |||
2578 | ||||
2579 | D->addAttr(::new (S.Context) ExternalSourceSymbolAttr( | |||
2580 | S.Context, AL, Language, DefinedIn, IsGeneratedDeclaration)); | |||
2581 | } | |||
2582 | ||||
2583 | template <class T> | |||
2584 | static T *mergeVisibilityAttr(Sema &S, Decl *D, const AttributeCommonInfo &CI, | |||
2585 | typename T::VisibilityType value) { | |||
2586 | T *existingAttr = D->getAttr<T>(); | |||
2587 | if (existingAttr) { | |||
2588 | typename T::VisibilityType existingValue = existingAttr->getVisibility(); | |||
2589 | if (existingValue == value) | |||
2590 | return nullptr; | |||
2591 | S.Diag(existingAttr->getLocation(), diag::err_mismatched_visibility); | |||
2592 | S.Diag(CI.getLoc(), diag::note_previous_attribute); | |||
2593 | D->dropAttr<T>(); | |||
2594 | } | |||
2595 | return ::new (S.Context) T(S.Context, CI, value); | |||
2596 | } | |||
2597 | ||||
2598 | VisibilityAttr *Sema::mergeVisibilityAttr(Decl *D, | |||
2599 | const AttributeCommonInfo &CI, | |||
2600 | VisibilityAttr::VisibilityType Vis) { | |||
2601 | return ::mergeVisibilityAttr<VisibilityAttr>(*this, D, CI, Vis); | |||
2602 | } | |||
2603 | ||||
2604 | TypeVisibilityAttr * | |||
2605 | Sema::mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI, | |||
2606 | TypeVisibilityAttr::VisibilityType Vis) { | |||
2607 | return ::mergeVisibilityAttr<TypeVisibilityAttr>(*this, D, CI, Vis); | |||
2608 | } | |||
2609 | ||||
2610 | static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL, | |||
2611 | bool isTypeVisibility) { | |||
2612 | // Visibility attributes don't mean anything on a typedef. | |||
2613 | if (isa<TypedefNameDecl>(D)) { | |||
2614 | S.Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored) << AL; | |||
2615 | return; | |||
2616 | } | |||
2617 | ||||
2618 | // 'type_visibility' can only go on a type or namespace. | |||
2619 | if (isTypeVisibility && | |||
2620 | !(isa<TagDecl>(D) || | |||
2621 | isa<ObjCInterfaceDecl>(D) || | |||
2622 | isa<NamespaceDecl>(D))) { | |||
2623 | S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type) | |||
2624 | << AL << ExpectedTypeOrNamespace; | |||
2625 | return; | |||
2626 | } | |||
2627 | ||||
2628 | // Check that the argument is a string literal. | |||
2629 | StringRef TypeStr; | |||
2630 | SourceLocation LiteralLoc; | |||
2631 | if (!S.checkStringLiteralArgumentAttr(AL, 0, TypeStr, &LiteralLoc)) | |||
2632 | return; | |||
2633 | ||||
2634 | VisibilityAttr::VisibilityType type; | |||
2635 | if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) { | |||
2636 | S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) << AL | |||
2637 | << TypeStr; | |||
2638 | return; | |||
2639 | } | |||
2640 | ||||
2641 | // Complain about attempts to use protected visibility on targets | |||
2642 | // (like Darwin) that don't support it. | |||
2643 | if (type == VisibilityAttr::Protected && | |||
2644 | !S.Context.getTargetInfo().hasProtectedVisibility()) { | |||
2645 | S.Diag(AL.getLoc(), diag::warn_attribute_protected_visibility); | |||
2646 | type = VisibilityAttr::Default; | |||
2647 | } | |||
2648 | ||||
2649 | Attr *newAttr; | |||
2650 | if (isTypeVisibility) { | |||
2651 | newAttr = S.mergeTypeVisibilityAttr( | |||
2652 | D, AL, (TypeVisibilityAttr::VisibilityType)type); | |||
2653 | } else { | |||
2654 | newAttr = S.mergeVisibilityAttr(D, AL, type); | |||
2655 | } | |||
2656 | if (newAttr) | |||
2657 | D->addAttr(newAttr); | |||
2658 | } | |||
2659 | ||||
2660 | static void handleObjCNonRuntimeProtocolAttr(Sema &S, Decl *D, | |||
2661 | const ParsedAttr &AL) { | |||
2662 | handleSimpleAttribute<ObjCNonRuntimeProtocolAttr>(S, D, AL); | |||
2663 | } | |||
2664 | ||||
2665 | static void handleObjCDirectAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2666 | // objc_direct cannot be set on methods declared in the context of a protocol | |||
2667 | if (isa<ObjCProtocolDecl>(D->getDeclContext())) { | |||
2668 | S.Diag(AL.getLoc(), diag::err_objc_direct_on_protocol) << false; | |||
2669 | return; | |||
2670 | } | |||
2671 | ||||
2672 | if (S.getLangOpts().ObjCRuntime.allowsDirectDispatch()) { | |||
2673 | handleSimpleAttribute<ObjCDirectAttr>(S, D, AL); | |||
2674 | } else { | |||
2675 | S.Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL; | |||
2676 | } | |||
2677 | } | |||
2678 | ||||
2679 | static void handleObjCDirectMembersAttr(Sema &S, Decl *D, | |||
2680 | const ParsedAttr &AL) { | |||
2681 | if (S.getLangOpts().ObjCRuntime.allowsDirectDispatch()) { | |||
2682 | handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL); | |||
2683 | } else { | |||
2684 | S.Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL; | |||
2685 | } | |||
2686 | } | |||
2687 | ||||
2688 | static void handleObjCMethodFamilyAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2689 | const auto *M = cast<ObjCMethodDecl>(D); | |||
2690 | if (!AL.isArgIdent(0)) { | |||
2691 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
2692 | << AL << 1 << AANT_ArgumentIdentifier; | |||
2693 | return; | |||
2694 | } | |||
2695 | ||||
2696 | IdentifierLoc *IL = AL.getArgAsIdent(0); | |||
2697 | ObjCMethodFamilyAttr::FamilyKind F; | |||
2698 | if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) { | |||
2699 | S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL << IL->Ident; | |||
2700 | return; | |||
2701 | } | |||
2702 | ||||
2703 | if (F == ObjCMethodFamilyAttr::OMF_init && | |||
2704 | !M->getReturnType()->isObjCObjectPointerType()) { | |||
2705 | S.Diag(M->getLocation(), diag::err_init_method_bad_return_type) | |||
2706 | << M->getReturnType(); | |||
2707 | // Ignore the attribute. | |||
2708 | return; | |||
2709 | } | |||
2710 | ||||
2711 | D->addAttr(new (S.Context) ObjCMethodFamilyAttr(S.Context, AL, F)); | |||
2712 | } | |||
2713 | ||||
2714 | static void handleObjCNSObject(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2715 | if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) { | |||
2716 | QualType T = TD->getUnderlyingType(); | |||
2717 | if (!T->isCARCBridgableType()) { | |||
2718 | S.Diag(TD->getLocation(), diag::err_nsobject_attribute); | |||
2719 | return; | |||
2720 | } | |||
2721 | } | |||
2722 | else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) { | |||
2723 | QualType T = PD->getType(); | |||
2724 | if (!T->isCARCBridgableType()) { | |||
2725 | S.Diag(PD->getLocation(), diag::err_nsobject_attribute); | |||
2726 | return; | |||
2727 | } | |||
2728 | } | |||
2729 | else { | |||
2730 | // It is okay to include this attribute on properties, e.g.: | |||
2731 | // | |||
2732 | // @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject)); | |||
2733 | // | |||
2734 | // In this case it follows tradition and suppresses an error in the above | |||
2735 | // case. | |||
2736 | S.Diag(D->getLocation(), diag::warn_nsobject_attribute); | |||
2737 | } | |||
2738 | D->addAttr(::new (S.Context) ObjCNSObjectAttr(S.Context, AL)); | |||
2739 | } | |||
2740 | ||||
2741 | static void handleObjCIndependentClass(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2742 | if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) { | |||
2743 | QualType T = TD->getUnderlyingType(); | |||
2744 | if (!T->isObjCObjectPointerType()) { | |||
2745 | S.Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute); | |||
2746 | return; | |||
2747 | } | |||
2748 | } else { | |||
2749 | S.Diag(D->getLocation(), diag::warn_independentclass_attribute); | |||
2750 | return; | |||
2751 | } | |||
2752 | D->addAttr(::new (S.Context) ObjCIndependentClassAttr(S.Context, AL)); | |||
2753 | } | |||
2754 | ||||
2755 | static void handleBlocksAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2756 | if (!AL.isArgIdent(0)) { | |||
2757 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
2758 | << AL << 1 << AANT_ArgumentIdentifier; | |||
2759 | return; | |||
2760 | } | |||
2761 | ||||
2762 | IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; | |||
2763 | BlocksAttr::BlockType type; | |||
2764 | if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) { | |||
2765 | S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; | |||
2766 | return; | |||
2767 | } | |||
2768 | ||||
2769 | D->addAttr(::new (S.Context) BlocksAttr(S.Context, AL, type)); | |||
2770 | } | |||
2771 | ||||
2772 | static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2773 | unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel; | |||
2774 | if (AL.getNumArgs() > 0) { | |||
2775 | Expr *E = AL.getArgAsExpr(0); | |||
2776 | Optional<llvm::APSInt> Idx = llvm::APSInt(32); | |||
2777 | if (E->isTypeDependent() || E->isValueDependent() || | |||
2778 | !(Idx = E->getIntegerConstantExpr(S.Context))) { | |||
2779 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
2780 | << AL << 1 << AANT_ArgumentIntegerConstant << E->getSourceRange(); | |||
2781 | return; | |||
2782 | } | |||
2783 | ||||
2784 | if (Idx->isSigned() && Idx->isNegative()) { | |||
2785 | S.Diag(AL.getLoc(), diag::err_attribute_sentinel_less_than_zero) | |||
2786 | << E->getSourceRange(); | |||
2787 | return; | |||
2788 | } | |||
2789 | ||||
2790 | sentinel = Idx->getZExtValue(); | |||
2791 | } | |||
2792 | ||||
2793 | unsigned nullPos = (unsigned)SentinelAttr::DefaultNullPos; | |||
2794 | if (AL.getNumArgs() > 1) { | |||
2795 | Expr *E = AL.getArgAsExpr(1); | |||
2796 | Optional<llvm::APSInt> Idx = llvm::APSInt(32); | |||
2797 | if (E->isTypeDependent() || E->isValueDependent() || | |||
2798 | !(Idx = E->getIntegerConstantExpr(S.Context))) { | |||
2799 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
2800 | << AL << 2 << AANT_ArgumentIntegerConstant << E->getSourceRange(); | |||
2801 | return; | |||
2802 | } | |||
2803 | nullPos = Idx->getZExtValue(); | |||
2804 | ||||
2805 | if ((Idx->isSigned() && Idx->isNegative()) || nullPos > 1) { | |||
2806 | // FIXME: This error message could be improved, it would be nice | |||
2807 | // to say what the bounds actually are. | |||
2808 | S.Diag(AL.getLoc(), diag::err_attribute_sentinel_not_zero_or_one) | |||
2809 | << E->getSourceRange(); | |||
2810 | return; | |||
2811 | } | |||
2812 | } | |||
2813 | ||||
2814 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
2815 | const FunctionType *FT = FD->getType()->castAs<FunctionType>(); | |||
2816 | if (isa<FunctionNoProtoType>(FT)) { | |||
2817 | S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_named_arguments); | |||
2818 | return; | |||
2819 | } | |||
2820 | ||||
2821 | if (!cast<FunctionProtoType>(FT)->isVariadic()) { | |||
2822 | S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; | |||
2823 | return; | |||
2824 | } | |||
2825 | } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { | |||
2826 | if (!MD->isVariadic()) { | |||
2827 | S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; | |||
2828 | return; | |||
2829 | } | |||
2830 | } else if (const auto *BD = dyn_cast<BlockDecl>(D)) { | |||
2831 | if (!BD->isVariadic()) { | |||
2832 | S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; | |||
2833 | return; | |||
2834 | } | |||
2835 | } else if (const auto *V = dyn_cast<VarDecl>(D)) { | |||
2836 | QualType Ty = V->getType(); | |||
2837 | if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) { | |||
2838 | const FunctionType *FT = Ty->isFunctionPointerType() | |||
2839 | ? D->getFunctionType() | |||
2840 | : Ty->castAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>(); | |||
2841 | if (!cast<FunctionProtoType>(FT)->isVariadic()) { | |||
2842 | int m = Ty->isFunctionPointerType() ? 0 : 1; | |||
2843 | S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m; | |||
2844 | return; | |||
2845 | } | |||
2846 | } else { | |||
2847 | S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) | |||
2848 | << AL << ExpectedFunctionMethodOrBlock; | |||
2849 | return; | |||
2850 | } | |||
2851 | } else { | |||
2852 | S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) | |||
2853 | << AL << ExpectedFunctionMethodOrBlock; | |||
2854 | return; | |||
2855 | } | |||
2856 | D->addAttr(::new (S.Context) SentinelAttr(S.Context, AL, sentinel, nullPos)); | |||
2857 | } | |||
2858 | ||||
2859 | static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2860 | if (D->getFunctionType() && | |||
2861 | D->getFunctionType()->getReturnType()->isVoidType() && | |||
2862 | !isa<CXXConstructorDecl>(D)) { | |||
2863 | S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 0; | |||
2864 | return; | |||
2865 | } | |||
2866 | if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) | |||
2867 | if (MD->getReturnType()->isVoidType()) { | |||
2868 | S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 1; | |||
2869 | return; | |||
2870 | } | |||
2871 | ||||
2872 | StringRef Str; | |||
2873 | if ((AL.isCXX11Attribute() || AL.isC2xAttribute()) && !AL.getScopeName()) { | |||
2874 | // The standard attribute cannot be applied to variable declarations such | |||
2875 | // as a function pointer. | |||
2876 | if (isa<VarDecl>(D)) | |||
2877 | S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str) | |||
2878 | << AL << "functions, classes, or enumerations"; | |||
2879 | ||||
2880 | // If this is spelled as the standard C++17 attribute, but not in C++17, | |||
2881 | // warn about using it as an extension. If there are attribute arguments, | |||
2882 | // then claim it's a C++2a extension instead. | |||
2883 | // FIXME: If WG14 does not seem likely to adopt the same feature, add an | |||
2884 | // extension warning for C2x mode. | |||
2885 | const LangOptions &LO = S.getLangOpts(); | |||
2886 | if (AL.getNumArgs() == 1) { | |||
2887 | if (LO.CPlusPlus && !LO.CPlusPlus20) | |||
2888 | S.Diag(AL.getLoc(), diag::ext_cxx20_attr) << AL; | |||
2889 | ||||
2890 | // Since this this is spelled [[nodiscard]], get the optional string | |||
2891 | // literal. If in C++ mode, but not in C++2a mode, diagnose as an | |||
2892 | // extension. | |||
2893 | // FIXME: C2x should support this feature as well, even as an extension. | |||
2894 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, nullptr)) | |||
2895 | return; | |||
2896 | } else if (LO.CPlusPlus && !LO.CPlusPlus17) | |||
2897 | S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL; | |||
2898 | } | |||
2899 | ||||
2900 | D->addAttr(::new (S.Context) WarnUnusedResultAttr(S.Context, AL, Str)); | |||
2901 | } | |||
2902 | ||||
2903 | static void handleWeakImportAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2904 | // weak_import only applies to variable & function declarations. | |||
2905 | bool isDef = false; | |||
2906 | if (!D->canBeWeakImported(isDef)) { | |||
2907 | if (isDef) | |||
2908 | S.Diag(AL.getLoc(), diag::warn_attribute_invalid_on_definition) | |||
2909 | << "weak_import"; | |||
2910 | else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) || | |||
2911 | (S.Context.getTargetInfo().getTriple().isOSDarwin() && | |||
2912 | (isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) { | |||
2913 | // Nothing to warn about here. | |||
2914 | } else | |||
2915 | S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) | |||
2916 | << AL << ExpectedVariableOrFunction; | |||
2917 | ||||
2918 | return; | |||
2919 | } | |||
2920 | ||||
2921 | D->addAttr(::new (S.Context) WeakImportAttr(S.Context, AL)); | |||
2922 | } | |||
2923 | ||||
2924 | // Handles reqd_work_group_size and work_group_size_hint. | |||
2925 | template <typename WorkGroupAttr> | |||
2926 | static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2927 | uint32_t WGSize[3]; | |||
2928 | for (unsigned i = 0; i < 3; ++i) { | |||
2929 | const Expr *E = AL.getArgAsExpr(i); | |||
2930 | if (!checkUInt32Argument(S, AL, E, WGSize[i], i, | |||
2931 | /*StrictlyUnsigned=*/true)) | |||
2932 | return; | |||
2933 | if (WGSize[i] == 0) { | |||
2934 | S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero) | |||
2935 | << AL << E->getSourceRange(); | |||
2936 | return; | |||
2937 | } | |||
2938 | } | |||
2939 | ||||
2940 | WorkGroupAttr *Existing = D->getAttr<WorkGroupAttr>(); | |||
2941 | if (Existing && !(Existing->getXDim() == WGSize[0] && | |||
2942 | Existing->getYDim() == WGSize[1] && | |||
2943 | Existing->getZDim() == WGSize[2])) | |||
2944 | S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; | |||
2945 | ||||
2946 | D->addAttr(::new (S.Context) | |||
2947 | WorkGroupAttr(S.Context, AL, WGSize[0], WGSize[1], WGSize[2])); | |||
2948 | } | |||
2949 | ||||
2950 | // Handles intel_reqd_sub_group_size. | |||
2951 | static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2952 | uint32_t SGSize; | |||
2953 | const Expr *E = AL.getArgAsExpr(0); | |||
2954 | if (!checkUInt32Argument(S, AL, E, SGSize)) | |||
2955 | return; | |||
2956 | if (SGSize == 0) { | |||
2957 | S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero) | |||
2958 | << AL << E->getSourceRange(); | |||
2959 | return; | |||
2960 | } | |||
2961 | ||||
2962 | OpenCLIntelReqdSubGroupSizeAttr *Existing = | |||
2963 | D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>(); | |||
2964 | if (Existing && Existing->getSubGroupSize() != SGSize) | |||
2965 | S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; | |||
2966 | ||||
2967 | D->addAttr(::new (S.Context) | |||
2968 | OpenCLIntelReqdSubGroupSizeAttr(S.Context, AL, SGSize)); | |||
2969 | } | |||
2970 | ||||
2971 | static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
2972 | if (!AL.hasParsedType()) { | |||
2973 | S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; | |||
2974 | return; | |||
2975 | } | |||
2976 | ||||
2977 | TypeSourceInfo *ParmTSI = nullptr; | |||
2978 | QualType ParmType = S.GetTypeFromParser(AL.getTypeArg(), &ParmTSI); | |||
2979 | 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~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 2979, __PRETTY_FUNCTION__)); | |||
2980 | ||||
2981 | if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() && | |||
2982 | (ParmType->isBooleanType() || | |||
2983 | !ParmType->isIntegralType(S.getASTContext()))) { | |||
2984 | S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument) << 2 << AL; | |||
2985 | return; | |||
2986 | } | |||
2987 | ||||
2988 | if (VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>()) { | |||
2989 | if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) { | |||
2990 | S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; | |||
2991 | return; | |||
2992 | } | |||
2993 | } | |||
2994 | ||||
2995 | D->addAttr(::new (S.Context) VecTypeHintAttr(S.Context, AL, ParmTSI)); | |||
2996 | } | |||
2997 | ||||
2998 | SectionAttr *Sema::mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI, | |||
2999 | StringRef Name) { | |||
3000 | // Explicit or partial specializations do not inherit | |||
3001 | // the section attribute from the primary template. | |||
3002 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
3003 | if (CI.getAttributeSpellingListIndex() == SectionAttr::Declspec_allocate && | |||
3004 | FD->isFunctionTemplateSpecialization()) | |||
3005 | return nullptr; | |||
3006 | } | |||
3007 | if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) { | |||
3008 | if (ExistingAttr->getName() == Name) | |||
3009 | return nullptr; | |||
3010 | Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section) | |||
3011 | << 1 /*section*/; | |||
3012 | Diag(CI.getLoc(), diag::note_previous_attribute); | |||
3013 | return nullptr; | |||
3014 | } | |||
3015 | return ::new (Context) SectionAttr(Context, CI, Name); | |||
3016 | } | |||
3017 | ||||
3018 | bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) { | |||
3019 | if (llvm::Error E = | |||
3020 | Context.getTargetInfo().isValidSectionSpecifier(SecName)) { | |||
3021 | Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) | |||
3022 | << toString(std::move(E)) << 1 /*'section'*/; | |||
3023 | return false; | |||
3024 | } | |||
3025 | return true; | |||
3026 | } | |||
3027 | ||||
3028 | static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3029 | // Make sure that there is a string literal as the sections's single | |||
3030 | // argument. | |||
3031 | StringRef Str; | |||
3032 | SourceLocation LiteralLoc; | |||
3033 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc)) | |||
3034 | return; | |||
3035 | ||||
3036 | if (!S.checkSectionName(LiteralLoc, Str)) | |||
3037 | return; | |||
3038 | ||||
3039 | // If the target wants to validate the section specifier, make it happen. | |||
3040 | if (llvm::Error E = S.Context.getTargetInfo().isValidSectionSpecifier(Str)) { | |||
3041 | S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) | |||
3042 | << toString(std::move(E)); | |||
3043 | return; | |||
3044 | } | |||
3045 | ||||
3046 | SectionAttr *NewAttr = S.mergeSectionAttr(D, AL, Str); | |||
3047 | if (NewAttr) { | |||
3048 | D->addAttr(NewAttr); | |||
3049 | if (isa<FunctionDecl, FunctionTemplateDecl, ObjCMethodDecl, | |||
3050 | ObjCPropertyDecl>(D)) | |||
3051 | S.UnifySection(NewAttr->getName(), | |||
3052 | ASTContext::PSF_Execute | ASTContext::PSF_Read, | |||
3053 | cast<NamedDecl>(D)); | |||
3054 | } | |||
3055 | } | |||
3056 | ||||
3057 | // This is used for `__declspec(code_seg("segname"))` on a decl. | |||
3058 | // `#pragma code_seg("segname")` uses checkSectionName() instead. | |||
3059 | static bool checkCodeSegName(Sema &S, SourceLocation LiteralLoc, | |||
3060 | StringRef CodeSegName) { | |||
3061 | if (llvm::Error E = | |||
3062 | S.Context.getTargetInfo().isValidSectionSpecifier(CodeSegName)) { | |||
3063 | S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) | |||
3064 | << toString(std::move(E)) << 0 /*'code-seg'*/; | |||
3065 | return false; | |||
3066 | } | |||
3067 | ||||
3068 | return true; | |||
3069 | } | |||
3070 | ||||
3071 | CodeSegAttr *Sema::mergeCodeSegAttr(Decl *D, const AttributeCommonInfo &CI, | |||
3072 | StringRef Name) { | |||
3073 | // Explicit or partial specializations do not inherit | |||
3074 | // the code_seg attribute from the primary template. | |||
3075 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
3076 | if (FD->isFunctionTemplateSpecialization()) | |||
3077 | return nullptr; | |||
3078 | } | |||
3079 | if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) { | |||
3080 | if (ExistingAttr->getName() == Name) | |||
3081 | return nullptr; | |||
3082 | Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section) | |||
3083 | << 0 /*codeseg*/; | |||
3084 | Diag(CI.getLoc(), diag::note_previous_attribute); | |||
3085 | return nullptr; | |||
3086 | } | |||
3087 | return ::new (Context) CodeSegAttr(Context, CI, Name); | |||
3088 | } | |||
3089 | ||||
3090 | static void handleCodeSegAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3091 | StringRef Str; | |||
3092 | SourceLocation LiteralLoc; | |||
3093 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc)) | |||
3094 | return; | |||
3095 | if (!checkCodeSegName(S, LiteralLoc, Str)) | |||
3096 | return; | |||
3097 | if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) { | |||
3098 | if (!ExistingAttr->isImplicit()) { | |||
3099 | S.Diag(AL.getLoc(), | |||
3100 | ExistingAttr->getName() == Str | |||
3101 | ? diag::warn_duplicate_codeseg_attribute | |||
3102 | : diag::err_conflicting_codeseg_attribute); | |||
3103 | return; | |||
3104 | } | |||
3105 | D->dropAttr<CodeSegAttr>(); | |||
3106 | } | |||
3107 | if (CodeSegAttr *CSA = S.mergeCodeSegAttr(D, AL, Str)) | |||
3108 | D->addAttr(CSA); | |||
3109 | } | |||
3110 | ||||
3111 | // Check for things we'd like to warn about. Multiversioning issues are | |||
3112 | // handled later in the process, once we know how many exist. | |||
3113 | bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { | |||
3114 | enum FirstParam { Unsupported, Duplicate, Unknown }; | |||
3115 | enum SecondParam { None, Architecture, Tune }; | |||
3116 | if (AttrStr.find("fpmath=") != StringRef::npos) | |||
3117 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3118 | << Unsupported << None << "fpmath="; | |||
3119 | ||||
3120 | // Diagnose use of tune if target doesn't support it. | |||
3121 | if (!Context.getTargetInfo().supportsTargetAttributeTune() && | |||
3122 | AttrStr.find("tune=") != StringRef::npos) | |||
3123 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3124 | << Unsupported << None << "tune="; | |||
3125 | ||||
3126 | ParsedTargetAttr ParsedAttrs = TargetAttr::parse(AttrStr); | |||
3127 | ||||
3128 | if (!ParsedAttrs.Architecture.empty() && | |||
3129 | !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Architecture)) | |||
3130 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3131 | << Unknown << Architecture << ParsedAttrs.Architecture; | |||
3132 | ||||
3133 | if (!ParsedAttrs.Tune.empty() && | |||
3134 | !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Tune)) | |||
3135 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3136 | << Unknown << Tune << ParsedAttrs.Tune; | |||
3137 | ||||
3138 | if (ParsedAttrs.DuplicateArchitecture) | |||
3139 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3140 | << Duplicate << None << "arch="; | |||
3141 | if (ParsedAttrs.DuplicateTune) | |||
3142 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3143 | << Duplicate << None << "tune="; | |||
3144 | ||||
3145 | for (const auto &Feature : ParsedAttrs.Features) { | |||
3146 | auto CurFeature = StringRef(Feature).drop_front(); // remove + or -. | |||
3147 | if (!Context.getTargetInfo().isValidFeatureName(CurFeature)) | |||
3148 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3149 | << Unsupported << None << CurFeature; | |||
3150 | } | |||
3151 | ||||
3152 | TargetInfo::BranchProtectionInfo BPI; | |||
3153 | StringRef Error; | |||
3154 | if (!ParsedAttrs.BranchProtection.empty() && | |||
3155 | !Context.getTargetInfo().validateBranchProtection( | |||
3156 | ParsedAttrs.BranchProtection, BPI, Error)) { | |||
3157 | if (Error.empty()) | |||
3158 | return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) | |||
3159 | << Unsupported << None << "branch-protection"; | |||
3160 | else | |||
3161 | return Diag(LiteralLoc, diag::err_invalid_branch_protection_spec) | |||
3162 | << Error; | |||
3163 | } | |||
3164 | ||||
3165 | return false; | |||
3166 | } | |||
3167 | ||||
3168 | static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3169 | StringRef Str; | |||
3170 | SourceLocation LiteralLoc; | |||
3171 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) || | |||
3172 | S.checkTargetAttr(LiteralLoc, Str)) | |||
3173 | return; | |||
3174 | ||||
3175 | TargetAttr *NewAttr = ::new (S.Context) TargetAttr(S.Context, AL, Str); | |||
3176 | D->addAttr(NewAttr); | |||
3177 | } | |||
3178 | ||||
3179 | static void handleMinVectorWidthAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3180 | Expr *E = AL.getArgAsExpr(0); | |||
3181 | uint32_t VecWidth; | |||
3182 | if (!checkUInt32Argument(S, AL, E, VecWidth)) { | |||
3183 | AL.setInvalid(); | |||
3184 | return; | |||
3185 | } | |||
3186 | ||||
3187 | MinVectorWidthAttr *Existing = D->getAttr<MinVectorWidthAttr>(); | |||
3188 | if (Existing && Existing->getVectorWidth() != VecWidth) { | |||
3189 | S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; | |||
3190 | return; | |||
3191 | } | |||
3192 | ||||
3193 | D->addAttr(::new (S.Context) MinVectorWidthAttr(S.Context, AL, VecWidth)); | |||
3194 | } | |||
3195 | ||||
3196 | static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3197 | Expr *E = AL.getArgAsExpr(0); | |||
3198 | SourceLocation Loc = E->getExprLoc(); | |||
3199 | FunctionDecl *FD = nullptr; | |||
3200 | DeclarationNameInfo NI; | |||
3201 | ||||
3202 | // gcc only allows for simple identifiers. Since we support more than gcc, we | |||
3203 | // will warn the user. | |||
3204 | if (auto *DRE = dyn_cast<DeclRefExpr>(E)) { | |||
3205 | if (DRE->hasQualifier()) | |||
3206 | S.Diag(Loc, diag::warn_cleanup_ext); | |||
3207 | FD = dyn_cast<FunctionDecl>(DRE->getDecl()); | |||
3208 | NI = DRE->getNameInfo(); | |||
3209 | if (!FD) { | |||
3210 | S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 1 | |||
3211 | << NI.getName(); | |||
3212 | return; | |||
3213 | } | |||
3214 | } else if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(E)) { | |||
3215 | if (ULE->hasExplicitTemplateArgs()) | |||
3216 | S.Diag(Loc, diag::warn_cleanup_ext); | |||
3217 | FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true); | |||
3218 | NI = ULE->getNameInfo(); | |||
3219 | if (!FD) { | |||
3220 | S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2 | |||
3221 | << NI.getName(); | |||
3222 | if (ULE->getType() == S.Context.OverloadTy) | |||
3223 | S.NoteAllOverloadCandidates(ULE); | |||
3224 | return; | |||
3225 | } | |||
3226 | } else { | |||
3227 | S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 0; | |||
3228 | return; | |||
3229 | } | |||
3230 | ||||
3231 | if (FD->getNumParams() != 1) { | |||
3232 | S.Diag(Loc, diag::err_attribute_cleanup_func_must_take_one_arg) | |||
3233 | << NI.getName(); | |||
3234 | return; | |||
3235 | } | |||
3236 | ||||
3237 | // We're currently more strict than GCC about what function types we accept. | |||
3238 | // If this ever proves to be a problem it should be easy to fix. | |||
3239 | QualType Ty = S.Context.getPointerType(cast<VarDecl>(D)->getType()); | |||
3240 | QualType ParamTy = FD->getParamDecl(0)->getType(); | |||
3241 | if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(), | |||
3242 | ParamTy, Ty) != Sema::Compatible) { | |||
3243 | S.Diag(Loc, diag::err_attribute_cleanup_func_arg_incompatible_type) | |||
3244 | << NI.getName() << ParamTy << Ty; | |||
3245 | return; | |||
3246 | } | |||
3247 | ||||
3248 | D->addAttr(::new (S.Context) CleanupAttr(S.Context, AL, FD)); | |||
3249 | } | |||
3250 | ||||
3251 | static void handleEnumExtensibilityAttr(Sema &S, Decl *D, | |||
3252 | const ParsedAttr &AL) { | |||
3253 | if (!AL.isArgIdent(0)) { | |||
3254 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
3255 | << AL << 0 << AANT_ArgumentIdentifier; | |||
3256 | return; | |||
3257 | } | |||
3258 | ||||
3259 | EnumExtensibilityAttr::Kind ExtensibilityKind; | |||
3260 | IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; | |||
3261 | if (!EnumExtensibilityAttr::ConvertStrToKind(II->getName(), | |||
3262 | ExtensibilityKind)) { | |||
3263 | S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; | |||
3264 | return; | |||
3265 | } | |||
3266 | ||||
3267 | D->addAttr(::new (S.Context) | |||
3268 | EnumExtensibilityAttr(S.Context, AL, ExtensibilityKind)); | |||
3269 | } | |||
3270 | ||||
3271 | /// Handle __attribute__((format_arg((idx)))) attribute based on | |||
3272 | /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html | |||
3273 | static void handleFormatArgAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3274 | Expr *IdxExpr = AL.getArgAsExpr(0); | |||
3275 | ParamIdx Idx; | |||
3276 | if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, IdxExpr, Idx)) | |||
3277 | return; | |||
3278 | ||||
3279 | // Make sure the format string is really a string. | |||
3280 | QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex()); | |||
3281 | ||||
3282 | bool NotNSStringTy = !isNSStringType(Ty, S.Context); | |||
3283 | if (NotNSStringTy && | |||
3284 | !isCFStringType(Ty, S.Context) && | |||
3285 | (!Ty->isPointerType() || | |||
3286 | !Ty->castAs<PointerType>()->getPointeeType()->isCharType())) { | |||
3287 | S.Diag(AL.getLoc(), diag::err_format_attribute_not) | |||
3288 | << "a string type" << IdxExpr->getSourceRange() | |||
3289 | << getFunctionOrMethodParamRange(D, 0); | |||
3290 | return; | |||
3291 | } | |||
3292 | Ty = getFunctionOrMethodResultType(D); | |||
3293 | if (!isNSStringType(Ty, S.Context, /*AllowNSAttributedString=*/true) && | |||
3294 | !isCFStringType(Ty, S.Context) && | |||
3295 | (!Ty->isPointerType() || | |||
3296 | !Ty->castAs<PointerType>()->getPointeeType()->isCharType())) { | |||
3297 | S.Diag(AL.getLoc(), diag::err_format_attribute_result_not) | |||
3298 | << (NotNSStringTy ? "string type" : "NSString") | |||
3299 | << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0); | |||
3300 | return; | |||
3301 | } | |||
3302 | ||||
3303 | D->addAttr(::new (S.Context) FormatArgAttr(S.Context, AL, Idx)); | |||
3304 | } | |||
3305 | ||||
3306 | enum FormatAttrKind { | |||
3307 | CFStringFormat, | |||
3308 | NSStringFormat, | |||
3309 | StrftimeFormat, | |||
3310 | SupportedFormat, | |||
3311 | IgnoredFormat, | |||
3312 | InvalidFormat | |||
3313 | }; | |||
3314 | ||||
3315 | /// getFormatAttrKind - Map from format attribute names to supported format | |||
3316 | /// types. | |||
3317 | static FormatAttrKind getFormatAttrKind(StringRef Format) { | |||
3318 | return llvm::StringSwitch<FormatAttrKind>(Format) | |||
3319 | // Check for formats that get handled specially. | |||
3320 | .Case("NSString", NSStringFormat) | |||
3321 | .Case("CFString", CFStringFormat) | |||
3322 | .Case("strftime", StrftimeFormat) | |||
3323 | ||||
3324 | // Otherwise, check for supported formats. | |||
3325 | .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat) | |||
3326 | .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat) | |||
3327 | .Case("kprintf", SupportedFormat) // OpenBSD. | |||
3328 | .Case("freebsd_kprintf", SupportedFormat) // FreeBSD. | |||
3329 | .Case("os_trace", SupportedFormat) | |||
3330 | .Case("os_log", SupportedFormat) | |||
3331 | ||||
3332 | .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat) | |||
3333 | .Default(InvalidFormat); | |||
3334 | } | |||
3335 | ||||
3336 | /// Handle __attribute__((init_priority(priority))) attributes based on | |||
3337 | /// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html | |||
3338 | static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3339 | if (!S.getLangOpts().CPlusPlus) { | |||
3340 | S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL; | |||
3341 | return; | |||
3342 | } | |||
3343 | ||||
3344 | if (S.getCurFunctionOrMethodDecl()) { | |||
3345 | S.Diag(AL.getLoc(), diag::err_init_priority_object_attr); | |||
3346 | AL.setInvalid(); | |||
3347 | return; | |||
3348 | } | |||
3349 | QualType T = cast<VarDecl>(D)->getType(); | |||
3350 | if (S.Context.getAsArrayType(T)) | |||
3351 | T = S.Context.getBaseElementType(T); | |||
3352 | if (!T->getAs<RecordType>()) { | |||
3353 | S.Diag(AL.getLoc(), diag::err_init_priority_object_attr); | |||
3354 | AL.setInvalid(); | |||
3355 | return; | |||
3356 | } | |||
3357 | ||||
3358 | Expr *E = AL.getArgAsExpr(0); | |||
3359 | uint32_t prioritynum; | |||
3360 | if (!checkUInt32Argument(S, AL, E, prioritynum)) { | |||
3361 | AL.setInvalid(); | |||
3362 | return; | |||
3363 | } | |||
3364 | ||||
3365 | // Only perform the priority check if the attribute is outside of a system | |||
3366 | // header. Values <= 100 are reserved for the implementation, and libc++ | |||
3367 | // benefits from being able to specify values in that range. | |||
3368 | if ((prioritynum < 101 || prioritynum > 65535) && | |||
3369 | !S.getSourceManager().isInSystemHeader(AL.getLoc())) { | |||
3370 | S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_range) | |||
3371 | << E->getSourceRange() << AL << 101 << 65535; | |||
3372 | AL.setInvalid(); | |||
3373 | return; | |||
3374 | } | |||
3375 | D->addAttr(::new (S.Context) InitPriorityAttr(S.Context, AL, prioritynum)); | |||
3376 | } | |||
3377 | ||||
3378 | FormatAttr *Sema::mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI, | |||
3379 | IdentifierInfo *Format, int FormatIdx, | |||
3380 | int FirstArg) { | |||
3381 | // Check whether we already have an equivalent format attribute. | |||
3382 | for (auto *F : D->specific_attrs<FormatAttr>()) { | |||
3383 | if (F->getType() == Format && | |||
3384 | F->getFormatIdx() == FormatIdx && | |||
3385 | F->getFirstArg() == FirstArg) { | |||
3386 | // If we don't have a valid location for this attribute, adopt the | |||
3387 | // location. | |||
3388 | if (F->getLocation().isInvalid()) | |||
3389 | F->setRange(CI.getRange()); | |||
3390 | return nullptr; | |||
3391 | } | |||
3392 | } | |||
3393 | ||||
3394 | return ::new (Context) FormatAttr(Context, CI, Format, FormatIdx, FirstArg); | |||
3395 | } | |||
3396 | ||||
3397 | /// Handle __attribute__((format(type,idx,firstarg))) attributes based on | |||
3398 | /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html | |||
3399 | static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3400 | if (!AL.isArgIdent(0)) { | |||
3401 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
3402 | << AL << 1 << AANT_ArgumentIdentifier; | |||
3403 | return; | |||
3404 | } | |||
3405 | ||||
3406 | // In C++ the implicit 'this' function parameter also counts, and they are | |||
3407 | // counted from one. | |||
3408 | bool HasImplicitThisParam = isInstanceMethod(D); | |||
3409 | unsigned NumArgs = getFunctionOrMethodNumParams(D) + HasImplicitThisParam; | |||
3410 | ||||
3411 | IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; | |||
3412 | StringRef Format = II->getName(); | |||
3413 | ||||
3414 | if (normalizeName(Format)) { | |||
3415 | // If we've modified the string name, we need a new identifier for it. | |||
3416 | II = &S.Context.Idents.get(Format); | |||
3417 | } | |||
3418 | ||||
3419 | // Check for supported formats. | |||
3420 | FormatAttrKind Kind = getFormatAttrKind(Format); | |||
3421 | ||||
3422 | if (Kind == IgnoredFormat) | |||
3423 | return; | |||
3424 | ||||
3425 | if (Kind == InvalidFormat) { | |||
3426 | S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) | |||
3427 | << AL << II->getName(); | |||
3428 | return; | |||
3429 | } | |||
3430 | ||||
3431 | // checks for the 2nd argument | |||
3432 | Expr *IdxExpr = AL.getArgAsExpr(1); | |||
3433 | uint32_t Idx; | |||
3434 | if (!checkUInt32Argument(S, AL, IdxExpr, Idx, 2)) | |||
3435 | return; | |||
3436 | ||||
3437 | if (Idx < 1 || Idx > NumArgs) { | |||
3438 | S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) | |||
3439 | << AL << 2 << IdxExpr->getSourceRange(); | |||
3440 | return; | |||
3441 | } | |||
3442 | ||||
3443 | // FIXME: Do we need to bounds check? | |||
3444 | unsigned ArgIdx = Idx - 1; | |||
3445 | ||||
3446 | if (HasImplicitThisParam) { | |||
3447 | if (ArgIdx == 0) { | |||
3448 | S.Diag(AL.getLoc(), | |||
3449 | diag::err_format_attribute_implicit_this_format_string) | |||
3450 | << IdxExpr->getSourceRange(); | |||
3451 | return; | |||
3452 | } | |||
3453 | ArgIdx--; | |||
3454 | } | |||
3455 | ||||
3456 | // make sure the format string is really a string | |||
3457 | QualType Ty = getFunctionOrMethodParamType(D, ArgIdx); | |||
3458 | ||||
3459 | if (Kind == CFStringFormat) { | |||
3460 | if (!isCFStringType(Ty, S.Context)) { | |||
3461 | S.Diag(AL.getLoc(), diag::err_format_attribute_not) | |||
3462 | << "a CFString" << IdxExpr->getSourceRange() | |||
3463 | << getFunctionOrMethodParamRange(D, ArgIdx); | |||
3464 | return; | |||
3465 | } | |||
3466 | } else if (Kind == NSStringFormat) { | |||
3467 | // FIXME: do we need to check if the type is NSString*? What are the | |||
3468 | // semantics? | |||
3469 | if (!isNSStringType(Ty, S.Context)) { | |||
3470 | S.Diag(AL.getLoc(), diag::err_format_attribute_not) | |||
3471 | << "an NSString" << IdxExpr->getSourceRange() | |||
3472 | << getFunctionOrMethodParamRange(D, ArgIdx); | |||
3473 | return; | |||
3474 | } | |||
3475 | } else if (!Ty->isPointerType() || | |||
3476 | !Ty->castAs<PointerType>()->getPointeeType()->isCharType()) { | |||
3477 | S.Diag(AL.getLoc(), diag::err_format_attribute_not) | |||
3478 | << "a string type" << IdxExpr->getSourceRange() | |||
3479 | << getFunctionOrMethodParamRange(D, ArgIdx); | |||
3480 | return; | |||
3481 | } | |||
3482 | ||||
3483 | // check the 3rd argument | |||
3484 | Expr *FirstArgExpr = AL.getArgAsExpr(2); | |||
3485 | uint32_t FirstArg; | |||
3486 | if (!checkUInt32Argument(S, AL, FirstArgExpr, FirstArg, 3)) | |||
3487 | return; | |||
3488 | ||||
3489 | // check if the function is variadic if the 3rd argument non-zero | |||
3490 | if (FirstArg != 0) { | |||
3491 | if (isFunctionOrMethodVariadic(D)) { | |||
3492 | ++NumArgs; // +1 for ... | |||
3493 | } else { | |||
3494 | S.Diag(D->getLocation(), diag::err_format_attribute_requires_variadic); | |||
3495 | return; | |||
3496 | } | |||
3497 | } | |||
3498 | ||||
3499 | // strftime requires FirstArg to be 0 because it doesn't read from any | |||
3500 | // variable the input is just the current time + the format string. | |||
3501 | if (Kind == StrftimeFormat) { | |||
3502 | if (FirstArg != 0) { | |||
3503 | S.Diag(AL.getLoc(), diag::err_format_strftime_third_parameter) | |||
3504 | << FirstArgExpr->getSourceRange(); | |||
3505 | return; | |||
3506 | } | |||
3507 | // if 0 it disables parameter checking (to use with e.g. va_list) | |||
3508 | } else if (FirstArg != 0 && FirstArg != NumArgs) { | |||
3509 | S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) | |||
3510 | << AL << 3 << FirstArgExpr->getSourceRange(); | |||
3511 | return; | |||
3512 | } | |||
3513 | ||||
3514 | FormatAttr *NewAttr = S.mergeFormatAttr(D, AL, II, Idx, FirstArg); | |||
3515 | if (NewAttr) | |||
3516 | D->addAttr(NewAttr); | |||
3517 | } | |||
3518 | ||||
3519 | /// Handle __attribute__((callback(CalleeIdx, PayloadIdx0, ...))) attributes. | |||
3520 | static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3521 | // The index that identifies the callback callee is mandatory. | |||
3522 | if (AL.getNumArgs() == 0) { | |||
3523 | S.Diag(AL.getLoc(), diag::err_callback_attribute_no_callee) | |||
3524 | << AL.getRange(); | |||
3525 | return; | |||
3526 | } | |||
3527 | ||||
3528 | bool HasImplicitThisParam = isInstanceMethod(D); | |||
3529 | int32_t NumArgs = getFunctionOrMethodNumParams(D); | |||
3530 | ||||
3531 | FunctionDecl *FD = D->getAsFunction(); | |||
3532 | 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~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 3532, __PRETTY_FUNCTION__)); | |||
3533 | ||||
3534 | llvm::StringMap<int> NameIdxMapping; | |||
3535 | NameIdxMapping["__"] = -1; | |||
3536 | ||||
3537 | NameIdxMapping["this"] = 0; | |||
3538 | ||||
3539 | int Idx = 1; | |||
3540 | for (const ParmVarDecl *PVD : FD->parameters()) | |||
3541 | NameIdxMapping[PVD->getName()] = Idx++; | |||
3542 | ||||
3543 | auto UnknownName = NameIdxMapping.end(); | |||
3544 | ||||
3545 | SmallVector<int, 8> EncodingIndices; | |||
3546 | for (unsigned I = 0, E = AL.getNumArgs(); I < E; ++I) { | |||
3547 | SourceRange SR; | |||
3548 | int32_t ArgIdx; | |||
3549 | ||||
3550 | if (AL.isArgIdent(I)) { | |||
3551 | IdentifierLoc *IdLoc = AL.getArgAsIdent(I); | |||
3552 | auto It = NameIdxMapping.find(IdLoc->Ident->getName()); | |||
3553 | if (It == UnknownName) { | |||
3554 | S.Diag(AL.getLoc(), diag::err_callback_attribute_argument_unknown) | |||
3555 | << IdLoc->Ident << IdLoc->Loc; | |||
3556 | return; | |||
3557 | } | |||
3558 | ||||
3559 | SR = SourceRange(IdLoc->Loc); | |||
3560 | ArgIdx = It->second; | |||
3561 | } else if (AL.isArgExpr(I)) { | |||
3562 | Expr *IdxExpr = AL.getArgAsExpr(I); | |||
3563 | ||||
3564 | // If the expression is not parseable as an int32_t we have a problem. | |||
3565 | if (!checkUInt32Argument(S, AL, IdxExpr, (uint32_t &)ArgIdx, I + 1, | |||
3566 | false)) { | |||
3567 | S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) | |||
3568 | << AL << (I + 1) << IdxExpr->getSourceRange(); | |||
3569 | return; | |||
3570 | } | |||
3571 | ||||
3572 | // Check oob, excluding the special values, 0 and -1. | |||
3573 | if (ArgIdx < -1 || ArgIdx > NumArgs) { | |||
3574 | S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) | |||
3575 | << AL << (I + 1) << IdxExpr->getSourceRange(); | |||
3576 | return; | |||
3577 | } | |||
3578 | ||||
3579 | SR = IdxExpr->getSourceRange(); | |||
3580 | } else { | |||
3581 | llvm_unreachable("Unexpected ParsedAttr argument type!")::llvm::llvm_unreachable_internal("Unexpected ParsedAttr argument type!" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 3581); | |||
3582 | } | |||
3583 | ||||
3584 | if (ArgIdx == 0 && !HasImplicitThisParam) { | |||
3585 | S.Diag(AL.getLoc(), diag::err_callback_implicit_this_not_available) | |||
3586 | << (I + 1) << SR; | |||
3587 | return; | |||
3588 | } | |||
3589 | ||||
3590 | // Adjust for the case we do not have an implicit "this" parameter. In this | |||
3591 | // case we decrease all positive values by 1 to get LLVM argument indices. | |||
3592 | if (!HasImplicitThisParam && ArgIdx > 0) | |||
3593 | ArgIdx -= 1; | |||
3594 | ||||
3595 | EncodingIndices.push_back(ArgIdx); | |||
3596 | } | |||
3597 | ||||
3598 | int CalleeIdx = EncodingIndices.front(); | |||
3599 | // Check if the callee index is proper, thus not "this" and not "unknown". | |||
3600 | // This means the "CalleeIdx" has to be non-negative if "HasImplicitThisParam" | |||
3601 | // is false and positive if "HasImplicitThisParam" is true. | |||
3602 | if (CalleeIdx < (int)HasImplicitThisParam) { | |||
3603 | S.Diag(AL.getLoc(), diag::err_callback_attribute_invalid_callee) | |||
3604 | << AL.getRange(); | |||
3605 | return; | |||
3606 | } | |||
3607 | ||||
3608 | // Get the callee type, note the index adjustment as the AST doesn't contain | |||
3609 | // the this type (which the callee cannot reference anyway!). | |||
3610 | const Type *CalleeType = | |||
3611 | getFunctionOrMethodParamType(D, CalleeIdx - HasImplicitThisParam) | |||
3612 | .getTypePtr(); | |||
3613 | if (!CalleeType || !CalleeType->isFunctionPointerType()) { | |||
3614 | S.Diag(AL.getLoc(), diag::err_callback_callee_no_function_type) | |||
3615 | << AL.getRange(); | |||
3616 | return; | |||
3617 | } | |||
3618 | ||||
3619 | const Type *CalleeFnType = | |||
3620 | CalleeType->getPointeeType()->getUnqualifiedDesugaredType(); | |||
3621 | ||||
3622 | // TODO: Check the type of the callee arguments. | |||
3623 | ||||
3624 | const auto *CalleeFnProtoType = dyn_cast<FunctionProtoType>(CalleeFnType); | |||
3625 | if (!CalleeFnProtoType) { | |||
3626 | S.Diag(AL.getLoc(), diag::err_callback_callee_no_function_type) | |||
3627 | << AL.getRange(); | |||
3628 | return; | |||
3629 | } | |||
3630 | ||||
3631 | if (CalleeFnProtoType->getNumParams() > EncodingIndices.size() - 1) { | |||
3632 | S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) | |||
3633 | << AL << (unsigned)(EncodingIndices.size() - 1); | |||
3634 | return; | |||
3635 | } | |||
3636 | ||||
3637 | if (CalleeFnProtoType->getNumParams() < EncodingIndices.size() - 1) { | |||
3638 | S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) | |||
3639 | << AL << (unsigned)(EncodingIndices.size() - 1); | |||
3640 | return; | |||
3641 | } | |||
3642 | ||||
3643 | if (CalleeFnProtoType->isVariadic()) { | |||
3644 | S.Diag(AL.getLoc(), diag::err_callback_callee_is_variadic) << AL.getRange(); | |||
3645 | return; | |||
3646 | } | |||
3647 | ||||
3648 | // Do not allow multiple callback attributes. | |||
3649 | if (D->hasAttr<CallbackAttr>()) { | |||
3650 | S.Diag(AL.getLoc(), diag::err_callback_attribute_multiple) << AL.getRange(); | |||
3651 | return; | |||
3652 | } | |||
3653 | ||||
3654 | D->addAttr(::new (S.Context) CallbackAttr( | |||
3655 | S.Context, AL, EncodingIndices.data(), EncodingIndices.size())); | |||
3656 | } | |||
3657 | ||||
3658 | static bool isFunctionLike(const Type &T) { | |||
3659 | // Check for explicit function types. | |||
3660 | // 'called_once' is only supported in Objective-C and it has | |||
3661 | // function pointers and block pointers. | |||
3662 | return T.isFunctionPointerType() || T.isBlockPointerType(); | |||
3663 | } | |||
3664 | ||||
3665 | /// Handle 'called_once' attribute. | |||
3666 | static void handleCalledOnceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3667 | // 'called_once' only applies to parameters representing functions. | |||
3668 | QualType T = cast<ParmVarDecl>(D)->getType(); | |||
3669 | ||||
3670 | if (!isFunctionLike(*T)) { | |||
3671 | S.Diag(AL.getLoc(), diag::err_called_once_attribute_wrong_type); | |||
3672 | return; | |||
3673 | } | |||
3674 | ||||
3675 | D->addAttr(::new (S.Context) CalledOnceAttr(S.Context, AL)); | |||
3676 | } | |||
3677 | ||||
3678 | static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3679 | // Try to find the underlying union declaration. | |||
3680 | RecordDecl *RD = nullptr; | |||
3681 | const auto *TD = dyn_cast<TypedefNameDecl>(D); | |||
3682 | if (TD && TD->getUnderlyingType()->isUnionType()) | |||
3683 | RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); | |||
3684 | else | |||
3685 | RD = dyn_cast<RecordDecl>(D); | |||
3686 | ||||
3687 | if (!RD || !RD->isUnion()) { | |||
3688 | S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL | |||
3689 | << ExpectedUnion; | |||
3690 | return; | |||
3691 | } | |||
3692 | ||||
3693 | if (!RD->isCompleteDefinition()) { | |||
3694 | if (!RD->isBeingDefined()) | |||
3695 | S.Diag(AL.getLoc(), | |||
3696 | diag::warn_transparent_union_attribute_not_definition); | |||
3697 | return; | |||
3698 | } | |||
3699 | ||||
3700 | RecordDecl::field_iterator Field = RD->field_begin(), | |||
3701 | FieldEnd = RD->field_end(); | |||
3702 | if (Field == FieldEnd) { | |||
3703 | S.Diag(AL.getLoc(), diag::warn_transparent_union_attribute_zero_fields); | |||
3704 | return; | |||
3705 | } | |||
3706 | ||||
3707 | FieldDecl *FirstField = *Field; | |||
3708 | QualType FirstType = FirstField->getType(); | |||
3709 | if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) { | |||
3710 | S.Diag(FirstField->getLocation(), | |||
3711 | diag::warn_transparent_union_attribute_floating) | |||
3712 | << FirstType->isVectorType() << FirstType; | |||
3713 | return; | |||
3714 | } | |||
3715 | ||||
3716 | if (FirstType->isIncompleteType()) | |||
3717 | return; | |||
3718 | uint64_t FirstSize = S.Context.getTypeSize(FirstType); | |||
3719 | uint64_t FirstAlign = S.Context.getTypeAlign(FirstType); | |||
3720 | for (; Field != FieldEnd; ++Field) { | |||
3721 | QualType FieldType = Field->getType(); | |||
3722 | if (FieldType->isIncompleteType()) | |||
3723 | return; | |||
3724 | // FIXME: this isn't fully correct; we also need to test whether the | |||
3725 | // members of the union would all have the same calling convention as the | |||
3726 | // first member of the union. Checking just the size and alignment isn't | |||
3727 | // sufficient (consider structs passed on the stack instead of in registers | |||
3728 | // as an example). | |||
3729 | if (S.Context.getTypeSize(FieldType) != FirstSize || | |||
3730 | S.Context.getTypeAlign(FieldType) > FirstAlign) { | |||
3731 | // Warn if we drop the attribute. | |||
3732 | bool isSize = S.Context.getTypeSize(FieldType) != FirstSize; | |||
3733 | unsigned FieldBits = isSize ? S.Context.getTypeSize(FieldType) | |||
3734 | : S.Context.getTypeAlign(FieldType); | |||
3735 | S.Diag(Field->getLocation(), | |||
3736 | diag::warn_transparent_union_attribute_field_size_align) | |||
3737 | << isSize << *Field << FieldBits; | |||
3738 | unsigned FirstBits = isSize ? FirstSize : FirstAlign; | |||
3739 | S.Diag(FirstField->getLocation(), | |||
3740 | diag::note_transparent_union_first_field_size_align) | |||
3741 | << isSize << FirstBits; | |||
3742 | return; | |||
3743 | } | |||
3744 | } | |||
3745 | ||||
3746 | RD->addAttr(::new (S.Context) TransparentUnionAttr(S.Context, AL)); | |||
3747 | } | |||
3748 | ||||
3749 | void Sema::AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI, | |||
3750 | StringRef Str, MutableArrayRef<Expr *> Args) { | |||
3751 | auto *Attr = AnnotateAttr::Create(Context, Str, Args.data(), Args.size(), CI); | |||
3752 | llvm::SmallVector<PartialDiagnosticAt, 8> Notes; | |||
3753 | for (unsigned Idx = 0; Idx < Attr->args_size(); Idx++) { | |||
3754 | Expr *&E = Attr->args_begin()[Idx]; | |||
3755 | 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~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 3755, __PRETTY_FUNCTION__)); | |||
3756 | if (E->isValueDependent() || E->isTypeDependent()) | |||
3757 | continue; | |||
3758 | ||||
3759 | if (E->getType()->isArrayType()) | |||
3760 | E = ImpCastExprToType(E, Context.getPointerType(E->getType()), | |||
3761 | clang::CK_ArrayToPointerDecay) | |||
3762 | .get(); | |||
3763 | if (E->getType()->isFunctionType()) | |||
3764 | E = ImplicitCastExpr::Create(Context, | |||
3765 | Context.getPointerType(E->getType()), | |||
3766 | clang::CK_FunctionToPointerDecay, E, nullptr, | |||
3767 | VK_RValue, FPOptionsOverride()); | |||
3768 | if (E->isLValue()) | |||
3769 | E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(), | |||
3770 | clang::CK_LValueToRValue, E, nullptr, | |||
3771 | VK_RValue, FPOptionsOverride()); | |||
3772 | ||||
3773 | Expr::EvalResult Eval; | |||
3774 | Notes.clear(); | |||
3775 | Eval.Diag = &Notes; | |||
3776 | ||||
3777 | bool Result = | |||
3778 | E->EvaluateAsConstantExpr(Eval, Context); | |||
3779 | ||||
3780 | /// Result means the expression can be folded to a constant. | |||
3781 | /// Note.empty() means the expression is a valid constant expression in the | |||
3782 | /// current language mode. | |||
3783 | if (!Result || !Notes.empty()) { | |||
3784 | Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type) | |||
3785 | << CI << (Idx + 1) << AANT_ArgumentConstantExpr; | |||
3786 | for (auto &Note : Notes) | |||
3787 | Diag(Note.first, Note.second); | |||
3788 | return; | |||
3789 | } | |||
3790 | assert(Eval.Val.hasValue())((Eval.Val.hasValue()) ? static_cast<void> (0) : __assert_fail ("Eval.Val.hasValue()", "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 3790, __PRETTY_FUNCTION__)); | |||
3791 | E = ConstantExpr::Create(Context, E, Eval.Val); | |||
3792 | } | |||
3793 | D->addAttr(Attr); | |||
3794 | } | |||
3795 | ||||
3796 | static void handleAnnotateAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3797 | // Make sure that there is a string literal as the annotation's first | |||
3798 | // argument. | |||
3799 | StringRef Str; | |||
3800 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) | |||
3801 | return; | |||
3802 | ||||
3803 | llvm::SmallVector<Expr *, 4> Args; | |||
3804 | Args.reserve(AL.getNumArgs() - 1); | |||
3805 | for (unsigned Idx = 1; Idx < AL.getNumArgs(); Idx++) { | |||
3806 | assert(!AL.isArgIdent(Idx))((!AL.isArgIdent(Idx)) ? static_cast<void> (0) : __assert_fail ("!AL.isArgIdent(Idx)", "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 3806, __PRETTY_FUNCTION__)); | |||
3807 | Args.push_back(AL.getArgAsExpr(Idx)); | |||
3808 | } | |||
3809 | ||||
3810 | S.AddAnnotationAttr(D, AL, Str, Args); | |||
3811 | } | |||
3812 | ||||
3813 | static void handleAlignValueAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3814 | S.AddAlignValueAttr(D, AL, AL.getArgAsExpr(0)); | |||
3815 | } | |||
3816 | ||||
3817 | void Sema::AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E) { | |||
3818 | AlignValueAttr TmpAttr(Context, CI, E); | |||
3819 | SourceLocation AttrLoc = CI.getLoc(); | |||
3820 | ||||
3821 | QualType T; | |||
3822 | if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) | |||
3823 | T = TD->getUnderlyingType(); | |||
3824 | else if (const auto *VD = dyn_cast<ValueDecl>(D)) | |||
3825 | T = VD->getType(); | |||
3826 | else | |||
3827 | llvm_unreachable("Unknown decl type for align_value")::llvm::llvm_unreachable_internal("Unknown decl type for align_value" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 3827); | |||
3828 | ||||
3829 | if (!T->isDependentType() && !T->isAnyPointerType() && | |||
3830 | !T->isReferenceType() && !T->isMemberPointerType()) { | |||
3831 | Diag(AttrLoc, diag::warn_attribute_pointer_or_reference_only) | |||
3832 | << &TmpAttr << T << D->getSourceRange(); | |||
3833 | return; | |||
3834 | } | |||
3835 | ||||
3836 | if (!E->isValueDependent()) { | |||
3837 | llvm::APSInt Alignment; | |||
3838 | ExprResult ICE = VerifyIntegerConstantExpression( | |||
3839 | E, &Alignment, diag::err_align_value_attribute_argument_not_int); | |||
3840 | if (ICE.isInvalid()) | |||
3841 | return; | |||
3842 | ||||
3843 | if (!Alignment.isPowerOf2()) { | |||
3844 | Diag(AttrLoc, diag::err_alignment_not_power_of_two) | |||
3845 | << E->getSourceRange(); | |||
3846 | return; | |||
3847 | } | |||
3848 | ||||
3849 | D->addAttr(::new (Context) AlignValueAttr(Context, CI, ICE.get())); | |||
3850 | return; | |||
3851 | } | |||
3852 | ||||
3853 | // Save dependent expressions in the AST to be instantiated. | |||
3854 | D->addAttr(::new (Context) AlignValueAttr(Context, CI, E)); | |||
3855 | } | |||
3856 | ||||
3857 | static void handleAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
3858 | // check the attribute arguments. | |||
3859 | if (AL.getNumArgs() > 1) { | |||
3860 | S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; | |||
3861 | return; | |||
3862 | } | |||
3863 | ||||
3864 | if (AL.getNumArgs() == 0) { | |||
3865 | D->addAttr(::new (S.Context) AlignedAttr(S.Context, AL, true, nullptr)); | |||
3866 | return; | |||
3867 | } | |||
3868 | ||||
3869 | Expr *E = AL.getArgAsExpr(0); | |||
3870 | if (AL.isPackExpansion() && !E->containsUnexpandedParameterPack()) { | |||
3871 | S.Diag(AL.getEllipsisLoc(), | |||
3872 | diag::err_pack_expansion_without_parameter_packs); | |||
3873 | return; | |||
3874 | } | |||
3875 | ||||
3876 | if (!AL.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E)) | |||
3877 | return; | |||
3878 | ||||
3879 | S.AddAlignedAttr(D, AL, E, AL.isPackExpansion()); | |||
3880 | } | |||
3881 | ||||
3882 | void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, | |||
3883 | bool IsPackExpansion) { | |||
3884 | AlignedAttr TmpAttr(Context, CI, true, E); | |||
3885 | SourceLocation AttrLoc = CI.getLoc(); | |||
3886 | ||||
3887 | // C++11 alignas(...) and C11 _Alignas(...) have additional requirements. | |||
3888 | if (TmpAttr.isAlignas()) { | |||
3889 | // C++11 [dcl.align]p1: | |||
3890 | // An alignment-specifier may be applied to a variable or to a class | |||
3891 | // data member, but it shall not be applied to a bit-field, a function | |||
3892 | // parameter, the formal parameter of a catch clause, or a variable | |||
3893 | // declared with the register storage class specifier. An | |||
3894 | // alignment-specifier may also be applied to the declaration of a class | |||
3895 | // or enumeration type. | |||
3896 | // C11 6.7.5/2: | |||
3897 | // An alignment attribute shall not be specified in a declaration of | |||
3898 | // a typedef, or a bit-field, or a function, or a parameter, or an | |||
3899 | // object declared with the register storage-class specifier. | |||
3900 | int DiagKind = -1; | |||
3901 | if (isa<ParmVarDecl>(D)) { | |||
3902 | DiagKind = 0; | |||
3903 | } else if (const auto *VD = dyn_cast<VarDecl>(D)) { | |||
3904 | if (VD->getStorageClass() == SC_Register) | |||
3905 | DiagKind = 1; | |||
3906 | if (VD->isExceptionVariable()) | |||
3907 | DiagKind = 2; | |||
3908 | } else if (const auto *FD = dyn_cast<FieldDecl>(D)) { | |||
3909 | if (FD->isBitField()) | |||
3910 | DiagKind = 3; | |||
3911 | } else if (!isa<TagDecl>(D)) { | |||
3912 | Diag(AttrLoc, diag::err_attribute_wrong_decl_type) << &TmpAttr | |||
3913 | << (TmpAttr.isC11() ? ExpectedVariableOrField | |||
3914 | : ExpectedVariableFieldOrTag); | |||
3915 | return; | |||
3916 | } | |||
3917 | if (DiagKind != -1) { | |||
3918 | Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type) | |||
3919 | << &TmpAttr << DiagKind; | |||
3920 | return; | |||
3921 | } | |||
3922 | } | |||
3923 | ||||
3924 | if (E->isValueDependent()) { | |||
3925 | // We can't support a dependent alignment on a non-dependent type, | |||
3926 | // because we have no way to model that a type is "alignment-dependent" | |||
3927 | // but not dependent in any other way. | |||
3928 | if (const auto *TND = dyn_cast<TypedefNameDecl>(D)) { | |||
3929 | if (!TND->getUnderlyingType()->isDependentType()) { | |||
3930 | Diag(AttrLoc, diag::err_alignment_dependent_typedef_name) | |||
3931 | << E->getSourceRange(); | |||
3932 | return; | |||
3933 | } | |||
3934 | } | |||
3935 | ||||
3936 | // Save dependent expressions in the AST to be instantiated. | |||
3937 | AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, true, E); | |||
3938 | AA->setPackExpansion(IsPackExpansion); | |||
3939 | D->addAttr(AA); | |||
3940 | return; | |||
3941 | } | |||
3942 | ||||
3943 | // FIXME: Cache the number on the AL object? | |||
3944 | llvm::APSInt Alignment; | |||
3945 | ExprResult ICE = VerifyIntegerConstantExpression( | |||
3946 | E, &Alignment, diag::err_aligned_attribute_argument_not_int); | |||
3947 | if (ICE.isInvalid()) | |||
3948 | return; | |||
3949 | ||||
3950 | uint64_t AlignVal = Alignment.getZExtValue(); | |||
3951 | ||||
3952 | // C++11 [dcl.align]p2: | |||
3953 | // -- if the constant expression evaluates to zero, the alignment | |||
3954 | // specifier shall have no effect | |||
3955 | // C11 6.7.5p6: | |||
3956 | // An alignment specification of zero has no effect. | |||
3957 | if (!(TmpAttr.isAlignas() && !Alignment)) { | |||
3958 | if (!llvm::isPowerOf2_64(AlignVal)) { | |||
3959 | Diag(AttrLoc, diag::err_alignment_not_power_of_two) | |||
3960 | << E->getSourceRange(); | |||
3961 | return; | |||
3962 | } | |||
3963 | } | |||
3964 | ||||
3965 | unsigned MaximumAlignment = Sema::MaximumAlignment; | |||
3966 | if (Context.getTargetInfo().getTriple().isOSBinFormatCOFF()) | |||
3967 | MaximumAlignment = std::min(MaximumAlignment, 8192u); | |||
3968 | if (AlignVal > MaximumAlignment) { | |||
3969 | Diag(AttrLoc, diag::err_attribute_aligned_too_great) | |||
3970 | << MaximumAlignment << E->getSourceRange(); | |||
3971 | return; | |||
3972 | } | |||
3973 | ||||
3974 | if (Context.getTargetInfo().isTLSSupported()) { | |||
3975 | unsigned MaxTLSAlign = | |||
3976 | Context.toCharUnitsFromBits(Context.getTargetInfo().getMaxTLSAlign()) | |||
3977 | .getQuantity(); | |||
3978 | const auto *VD = dyn_cast<VarDecl>(D); | |||
3979 | if (MaxTLSAlign && AlignVal > MaxTLSAlign && VD && | |||
3980 | VD->getTLSKind() != VarDecl::TLS_None) { | |||
3981 | Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum) | |||
3982 | << (unsigned)AlignVal << VD << MaxTLSAlign; | |||
3983 | return; | |||
3984 | } | |||
3985 | } | |||
3986 | ||||
3987 | AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, true, ICE.get()); | |||
3988 | AA->setPackExpansion(IsPackExpansion); | |||
3989 | D->addAttr(AA); | |||
3990 | } | |||
3991 | ||||
3992 | void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, | |||
3993 | TypeSourceInfo *TS, bool IsPackExpansion) { | |||
3994 | // FIXME: Cache the number on the AL object if non-dependent? | |||
3995 | // FIXME: Perform checking of type validity | |||
3996 | AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, false, TS); | |||
3997 | AA->setPackExpansion(IsPackExpansion); | |||
3998 | D->addAttr(AA); | |||
3999 | } | |||
4000 | ||||
4001 | void Sema::CheckAlignasUnderalignment(Decl *D) { | |||
4002 | 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~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 4002, __PRETTY_FUNCTION__)); | |||
4003 | ||||
4004 | QualType UnderlyingTy, DiagTy; | |||
4005 | if (const auto *VD = dyn_cast<ValueDecl>(D)) { | |||
4006 | UnderlyingTy = DiagTy = VD->getType(); | |||
4007 | } else { | |||
4008 | UnderlyingTy = DiagTy = Context.getTagDeclType(cast<TagDecl>(D)); | |||
4009 | if (const auto *ED = dyn_cast<EnumDecl>(D)) | |||
4010 | UnderlyingTy = ED->getIntegerType(); | |||
4011 | } | |||
4012 | if (DiagTy->isDependentType() || DiagTy->isIncompleteType()) | |||
4013 | return; | |||
4014 | ||||
4015 | // C++11 [dcl.align]p5, C11 6.7.5/4: | |||
4016 | // The combined effect of all alignment attributes in a declaration shall | |||
4017 | // not specify an alignment that is less strict than the alignment that | |||
4018 | // would otherwise be required for the entity being declared. | |||
4019 | AlignedAttr *AlignasAttr = nullptr; | |||
4020 | AlignedAttr *LastAlignedAttr = nullptr; | |||
4021 | unsigned Align = 0; | |||
4022 | for (auto *I : D->specific_attrs<AlignedAttr>()) { | |||
4023 | if (I->isAlignmentDependent()) | |||
4024 | return; | |||
4025 | if (I->isAlignas()) | |||
4026 | AlignasAttr = I; | |||
4027 | Align = std::max(Align, I->getAlignment(Context)); | |||
4028 | LastAlignedAttr = I; | |||
4029 | } | |||
4030 | ||||
4031 | if (Align && DiagTy->isSizelessType()) { | |||
4032 | Diag(LastAlignedAttr->getLocation(), diag::err_attribute_sizeless_type) | |||
4033 | << LastAlignedAttr << DiagTy; | |||
4034 | } else if (AlignasAttr && Align) { | |||
4035 | CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align); | |||
4036 | CharUnits NaturalAlign = Context.getTypeAlignInChars(UnderlyingTy); | |||
4037 | if (NaturalAlign > RequestedAlign) | |||
4038 | Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned) | |||
4039 | << DiagTy << (unsigned)NaturalAlign.getQuantity(); | |||
4040 | } | |||
4041 | } | |||
4042 | ||||
4043 | bool Sema::checkMSInheritanceAttrOnDefinition( | |||
4044 | CXXRecordDecl *RD, SourceRange Range, bool BestCase, | |||
4045 | MSInheritanceModel ExplicitModel) { | |||
4046 | 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~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 4046, __PRETTY_FUNCTION__)); | |||
4047 | ||||
4048 | // We may not have seen base specifiers or any virtual methods yet. We will | |||
4049 | // have to wait until the record is defined to catch any mismatches. | |||
4050 | if (!RD->getDefinition()->isCompleteDefinition()) | |||
4051 | return false; | |||
4052 | ||||
4053 | // The unspecified model never matches what a definition could need. | |||
4054 | if (ExplicitModel == MSInheritanceModel::Unspecified) | |||
4055 | return false; | |||
4056 | ||||
4057 | if (BestCase) { | |||
4058 | if (RD->calculateInheritanceModel() == ExplicitModel) | |||
4059 | return false; | |||
4060 | } else { | |||
4061 | if (RD->calculateInheritanceModel() <= ExplicitModel) | |||
4062 | return false; | |||
4063 | } | |||
4064 | ||||
4065 | Diag(Range.getBegin(), diag::err_mismatched_ms_inheritance) | |||
4066 | << 0 /*definition*/; | |||
4067 | Diag(RD->getDefinition()->getLocation(), diag::note_defined_here) << RD; | |||
4068 | return true; | |||
4069 | } | |||
4070 | ||||
4071 | /// parseModeAttrArg - Parses attribute mode string and returns parsed type | |||
4072 | /// attribute. | |||
4073 | static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth, | |||
4074 | bool &IntegerMode, bool &ComplexMode, | |||
4075 | bool &ExplicitIEEE) { | |||
4076 | IntegerMode = true; | |||
4077 | ComplexMode = false; | |||
4078 | switch (Str.size()) { | |||
4079 | case 2: | |||
4080 | switch (Str[0]) { | |||
4081 | case 'Q': | |||
4082 | DestWidth = 8; | |||
4083 | break; | |||
4084 | case 'H': | |||
4085 | DestWidth = 16; | |||
4086 | break; | |||
4087 | case 'S': | |||
4088 | DestWidth = 32; | |||
4089 | break; | |||
4090 | case 'D': | |||
4091 | DestWidth = 64; | |||
4092 | break; | |||
4093 | case 'X': | |||
4094 | DestWidth = 96; | |||
4095 | break; | |||
4096 | case 'K': // KFmode - IEEE quad precision (__float128) | |||
4097 | ExplicitIEEE = true; | |||
4098 | DestWidth = Str[1] == 'I' ? 0 : 128; | |||
4099 | break; | |||
4100 | case 'T': | |||
4101 | ExplicitIEEE = false; | |||
4102 | DestWidth = 128; | |||
4103 | break; | |||
4104 | } | |||
4105 | if (Str[1] == 'F') { | |||
4106 | IntegerMode = false; | |||
4107 | } else if (Str[1] == 'C') { | |||
4108 | IntegerMode = false; | |||
4109 | ComplexMode = true; | |||
4110 | } else if (Str[1] != 'I') { | |||
4111 | DestWidth = 0; | |||
4112 | } | |||
4113 | break; | |||
4114 | case 4: | |||
4115 | // FIXME: glibc uses 'word' to define register_t; this is narrower than a | |||
4116 | // pointer on PIC16 and other embedded platforms. | |||
4117 | if (Str == "word") | |||
4118 | DestWidth = S.Context.getTargetInfo().getRegisterWidth(); | |||
4119 | else if (Str == "byte") | |||
4120 | DestWidth = S.Context.getTargetInfo().getCharWidth(); | |||
4121 | break; | |||
4122 | case 7: | |||
4123 | if (Str == "pointer") | |||
4124 | DestWidth = S.Context.getTargetInfo().getPointerWidth(0); | |||
4125 | break; | |||
4126 | case 11: | |||
4127 | if (Str == "unwind_word") | |||
4128 | DestWidth = S.Context.getTargetInfo().getUnwindWordWidth(); | |||
4129 | break; | |||
4130 | } | |||
4131 | } | |||
4132 | ||||
4133 | /// handleModeAttr - This attribute modifies the width of a decl with primitive | |||
4134 | /// type. | |||
4135 | /// | |||
4136 | /// Despite what would be logical, the mode attribute is a decl attribute, not a | |||
4137 | /// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be | |||
4138 | /// HImode, not an intermediate pointer. | |||
4139 | static void handleModeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4140 | // This attribute isn't documented, but glibc uses it. It changes | |||
4141 | // the width of an int or unsigned int to the specified size. | |||
4142 | if (!AL.isArgIdent(0)) { | |||
4143 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
4144 | << AL << AANT_ArgumentIdentifier; | |||
4145 | return; | |||
4146 | } | |||
4147 | ||||
4148 | IdentifierInfo *Name = AL.getArgAsIdent(0)->Ident; | |||
4149 | ||||
4150 | S.AddModeAttr(D, AL, Name); | |||
4151 | } | |||
4152 | ||||
4153 | void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI, | |||
4154 | IdentifierInfo *Name, bool InInstantiation) { | |||
4155 | StringRef Str = Name->getName(); | |||
4156 | normalizeName(Str); | |||
4157 | SourceLocation AttrLoc = CI.getLoc(); | |||
4158 | ||||
4159 | unsigned DestWidth = 0; | |||
4160 | bool IntegerMode = true; | |||
4161 | bool ComplexMode = false; | |||
4162 | bool ExplicitIEEE = false; | |||
4163 | llvm::APInt VectorSize(64, 0); | |||
4164 | if (Str.size() >= 4 && Str[0] == 'V') { | |||
4165 | // Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2). | |||
4166 | size_t StrSize = Str.size(); | |||
4167 | size_t VectorStringLength = 0; | |||
4168 | while ((VectorStringLength + 1) < StrSize && | |||
4169 | isdigit(Str[VectorStringLength + 1])) | |||
4170 | ++VectorStringLength; | |||
4171 | if (VectorStringLength && | |||
4172 | !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) && | |||
4173 | VectorSize.isPowerOf2()) { | |||
4174 | parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth, | |||
4175 | IntegerMode, ComplexMode, ExplicitIEEE); | |||
4176 | // Avoid duplicate warning from template instantiation. | |||
4177 | if (!InInstantiation) | |||
4178 | Diag(AttrLoc, diag::warn_vector_mode_deprecated); | |||
4179 | } else { | |||
4180 | VectorSize = 0; | |||
4181 | } | |||
4182 | } | |||
4183 | ||||
4184 | if (!VectorSize) | |||
4185 | parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode, | |||
4186 | ExplicitIEEE); | |||
4187 | ||||
4188 | // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t | |||
4189 | // and friends, at least with glibc. | |||
4190 | // FIXME: Make sure floating-point mappings are accurate | |||
4191 | // FIXME: Support XF and TF types | |||
4192 | if (!DestWidth) { | |||
4193 | Diag(AttrLoc, diag::err_machine_mode) << 0 /*Unknown*/ << Name; | |||
4194 | return; | |||
4195 | } | |||
4196 | ||||
4197 | QualType OldTy; | |||
4198 | if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) | |||
4199 | OldTy = TD->getUnderlyingType(); | |||
4200 | else if (const auto *ED = dyn_cast<EnumDecl>(D)) { | |||
4201 | // Something like 'typedef enum { X } __attribute__((mode(XX))) T;'. | |||
4202 | // Try to get type from enum declaration, default to int. | |||
4203 | OldTy = ED->getIntegerType(); | |||
4204 | if (OldTy.isNull()) | |||
4205 | OldTy = Context.IntTy; | |||
4206 | } else | |||
4207 | OldTy = cast<ValueDecl>(D)->getType(); | |||
4208 | ||||
4209 | if (OldTy->isDependentType()) { | |||
4210 | D->addAttr(::new (Context) ModeAttr(Context, CI, Name)); | |||
4211 | return; | |||
4212 | } | |||
4213 | ||||
4214 | // Base type can also be a vector type (see PR17453). | |||
4215 | // Distinguish between base type and base element type. | |||
4216 | QualType OldElemTy = OldTy; | |||
4217 | if (const auto *VT = OldTy->getAs<VectorType>()) | |||
4218 | OldElemTy = VT->getElementType(); | |||
4219 | ||||
4220 | // GCC allows 'mode' attribute on enumeration types (even incomplete), except | |||
4221 | // for vector modes. So, 'enum X __attribute__((mode(QI)));' forms a complete | |||
4222 | // type, 'enum { A } __attribute__((mode(V4SI)))' is rejected. | |||
4223 | if ((isa<EnumDecl>(D) || OldElemTy->getAs<EnumType>()) && | |||
4224 | VectorSize.getBoolValue()) { | |||
4225 | Diag(AttrLoc, diag::err_enum_mode_vector_type) << Name << CI.getRange(); | |||
4226 | return; | |||
4227 | } | |||
4228 | bool IntegralOrAnyEnumType = (OldElemTy->isIntegralOrEnumerationType() && | |||
4229 | !OldElemTy->isExtIntType()) || | |||
4230 | OldElemTy->getAs<EnumType>(); | |||
4231 | ||||
4232 | if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType() && | |||
4233 | !IntegralOrAnyEnumType) | |||
4234 | Diag(AttrLoc, diag::err_mode_not_primitive); | |||
4235 | else if (IntegerMode) { | |||
4236 | if (!IntegralOrAnyEnumType) | |||
4237 | Diag(AttrLoc, diag::err_mode_wrong_type); | |||
4238 | } else if (ComplexMode) { | |||
4239 | if (!OldElemTy->isComplexType()) | |||
4240 | Diag(AttrLoc, diag::err_mode_wrong_type); | |||
4241 | } else { | |||
4242 | if (!OldElemTy->isFloatingType()) | |||
4243 | Diag(AttrLoc, diag::err_mode_wrong_type); | |||
4244 | } | |||
4245 | ||||
4246 | QualType NewElemTy; | |||
4247 | ||||
4248 | if (IntegerMode) | |||
4249 | NewElemTy = Context.getIntTypeForBitwidth(DestWidth, | |||
4250 | OldElemTy->isSignedIntegerType()); | |||
4251 | else | |||
4252 | NewElemTy = Context.getRealTypeForBitwidth(DestWidth, ExplicitIEEE); | |||
4253 | ||||
4254 | if (NewElemTy.isNull()) { | |||
4255 | Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name; | |||
4256 | return; | |||
4257 | } | |||
4258 | ||||
4259 | if (ComplexMode) { | |||
4260 | NewElemTy = Context.getComplexType(NewElemTy); | |||
4261 | } | |||
4262 | ||||
4263 | QualType NewTy = NewElemTy; | |||
4264 | if (VectorSize.getBoolValue()) { | |||
4265 | NewTy = Context.getVectorType(NewTy, VectorSize.getZExtValue(), | |||
4266 | VectorType::GenericVector); | |||
4267 | } else if (const auto *OldVT = OldTy->getAs<VectorType>()) { | |||
4268 | // Complex machine mode does not support base vector types. | |||
4269 | if (ComplexMode) { | |||
4270 | Diag(AttrLoc, diag::err_complex_mode_vector_type); | |||
4271 | return; | |||
4272 | } | |||
4273 | unsigned NumElements = Context.getTypeSize(OldElemTy) * | |||
4274 | OldVT->getNumElements() / | |||
4275 | Context.getTypeSize(NewElemTy); | |||
4276 | NewTy = | |||
4277 | Context.getVectorType(NewElemTy, NumElements, OldVT->getVectorKind()); | |||
4278 | } | |||
4279 | ||||
4280 | if (NewTy.isNull()) { | |||
4281 | Diag(AttrLoc, diag::err_mode_wrong_type); | |||
4282 | return; | |||
4283 | } | |||
4284 | ||||
4285 | // Install the new type. | |||
4286 | if (auto *TD = dyn_cast<TypedefNameDecl>(D)) | |||
4287 | TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy); | |||
4288 | else if (auto *ED = dyn_cast<EnumDecl>(D)) | |||
4289 | ED->setIntegerType(NewTy); | |||
4290 | else | |||
4291 | cast<ValueDecl>(D)->setType(NewTy); | |||
4292 | ||||
4293 | D->addAttr(::new (Context) ModeAttr(Context, CI, Name)); | |||
4294 | } | |||
4295 | ||||
4296 | static void handleNoDebugAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4297 | D->addAttr(::new (S.Context) NoDebugAttr(S.Context, AL)); | |||
4298 | } | |||
4299 | ||||
4300 | AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, | |||
4301 | const AttributeCommonInfo &CI, | |||
4302 | const IdentifierInfo *Ident) { | |||
4303 | if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) { | |||
4304 | Diag(CI.getLoc(), diag::warn_attribute_ignored) << Ident; | |||
4305 | Diag(Optnone->getLocation(), diag::note_conflicting_attribute); | |||
4306 | return nullptr; | |||
4307 | } | |||
4308 | ||||
4309 | if (D->hasAttr<AlwaysInlineAttr>()) | |||
4310 | return nullptr; | |||
4311 | ||||
4312 | return ::new (Context) AlwaysInlineAttr(Context, CI); | |||
4313 | } | |||
4314 | ||||
4315 | CommonAttr *Sema::mergeCommonAttr(Decl *D, const ParsedAttr &AL) { | |||
4316 | if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, AL)) | |||
4317 | return nullptr; | |||
4318 | ||||
4319 | return ::new (Context) CommonAttr(Context, AL); | |||
4320 | } | |||
4321 | ||||
4322 | CommonAttr *Sema::mergeCommonAttr(Decl *D, const CommonAttr &AL) { | |||
4323 | if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, AL)) | |||
4324 | return nullptr; | |||
4325 | ||||
4326 | return ::new (Context) CommonAttr(Context, AL); | |||
4327 | } | |||
4328 | ||||
4329 | InternalLinkageAttr *Sema::mergeInternalLinkageAttr(Decl *D, | |||
4330 | const ParsedAttr &AL) { | |||
4331 | if (const auto *VD = dyn_cast<VarDecl>(D)) { | |||
4332 | // Attribute applies to Var but not any subclass of it (like ParmVar, | |||
4333 | // ImplicitParm or VarTemplateSpecialization). | |||
4334 | if (VD->getKind() != Decl::Var) { | |||
4335 | Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) | |||
4336 | << AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass | |||
4337 | : ExpectedVariableOrFunction); | |||
4338 | return nullptr; | |||
4339 | } | |||
4340 | // Attribute does not apply to non-static local variables. | |||
4341 | if (VD->hasLocalStorage()) { | |||
4342 | Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage); | |||
4343 | return nullptr; | |||
4344 | } | |||
4345 | } | |||
4346 | ||||
4347 | if (checkAttrMutualExclusion<CommonAttr>(*this, D, AL)) | |||
4348 | return nullptr; | |||
4349 | ||||
4350 | return ::new (Context) InternalLinkageAttr(Context, AL); | |||
4351 | } | |||
4352 | InternalLinkageAttr * | |||
4353 | Sema::mergeInternalLinkageAttr(Decl *D, const InternalLinkageAttr &AL) { | |||
4354 | if (const auto *VD = dyn_cast<VarDecl>(D)) { | |||
4355 | // Attribute applies to Var but not any subclass of it (like ParmVar, | |||
4356 | // ImplicitParm or VarTemplateSpecialization). | |||
4357 | if (VD->getKind() != Decl::Var) { | |||
4358 | Diag(AL.getLocation(), diag::warn_attribute_wrong_decl_type) | |||
4359 | << &AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass | |||
4360 | : ExpectedVariableOrFunction); | |||
4361 | return nullptr; | |||
4362 | } | |||
4363 | // Attribute does not apply to non-static local variables. | |||
4364 | if (VD->hasLocalStorage()) { | |||
4365 | Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage); | |||
4366 | return nullptr; | |||
4367 | } | |||
4368 | } | |||
4369 | ||||
4370 | if (checkAttrMutualExclusion<CommonAttr>(*this, D, AL)) | |||
4371 | return nullptr; | |||
4372 | ||||
4373 | return ::new (Context) InternalLinkageAttr(Context, AL); | |||
4374 | } | |||
4375 | ||||
4376 | MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI) { | |||
4377 | if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) { | |||
4378 | Diag(CI.getLoc(), diag::warn_attribute_ignored) << "'minsize'"; | |||
4379 | Diag(Optnone->getLocation(), diag::note_conflicting_attribute); | |||
4380 | return nullptr; | |||
4381 | } | |||
4382 | ||||
4383 | if (D->hasAttr<MinSizeAttr>()) | |||
4384 | return nullptr; | |||
4385 | ||||
4386 | return ::new (Context) MinSizeAttr(Context, CI); | |||
4387 | } | |||
4388 | ||||
4389 | NoSpeculativeLoadHardeningAttr *Sema::mergeNoSpeculativeLoadHardeningAttr( | |||
4390 | Decl *D, const NoSpeculativeLoadHardeningAttr &AL) { | |||
4391 | if (checkAttrMutualExclusion<SpeculativeLoadHardeningAttr>(*this, D, AL)) | |||
4392 | return nullptr; | |||
4393 | ||||
4394 | return ::new (Context) NoSpeculativeLoadHardeningAttr(Context, AL); | |||
4395 | } | |||
4396 | ||||
4397 | SwiftNameAttr *Sema::mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA, | |||
4398 | StringRef Name) { | |||
4399 | if (const auto *PrevSNA = D->getAttr<SwiftNameAttr>()) { | |||
4400 | if (PrevSNA->getName() != Name && !PrevSNA->isImplicit()) { | |||
4401 | Diag(PrevSNA->getLocation(), diag::err_attributes_are_not_compatible) | |||
4402 | << PrevSNA << &SNA; | |||
4403 | Diag(SNA.getLoc(), diag::note_conflicting_attribute); | |||
4404 | } | |||
4405 | ||||
4406 | D->dropAttr<SwiftNameAttr>(); | |||
4407 | } | |||
4408 | return ::new (Context) SwiftNameAttr(Context, SNA, Name); | |||
4409 | } | |||
4410 | ||||
4411 | OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, | |||
4412 | const AttributeCommonInfo &CI) { | |||
4413 | if (AlwaysInlineAttr *Inline = D->getAttr<AlwaysInlineAttr>()) { | |||
4414 | Diag(Inline->getLocation(), diag::warn_attribute_ignored) << Inline; | |||
4415 | Diag(CI.getLoc(), diag::note_conflicting_attribute); | |||
4416 | D->dropAttr<AlwaysInlineAttr>(); | |||
4417 | } | |||
4418 | if (MinSizeAttr *MinSize = D->getAttr<MinSizeAttr>()) { | |||
4419 | Diag(MinSize->getLocation(), diag::warn_attribute_ignored) << MinSize; | |||
4420 | Diag(CI.getLoc(), diag::note_conflicting_attribute); | |||
4421 | D->dropAttr<MinSizeAttr>(); | |||
4422 | } | |||
4423 | ||||
4424 | if (D->hasAttr<OptimizeNoneAttr>()) | |||
4425 | return nullptr; | |||
4426 | ||||
4427 | return ::new (Context) OptimizeNoneAttr(Context, CI); | |||
4428 | } | |||
4429 | ||||
4430 | SpeculativeLoadHardeningAttr *Sema::mergeSpeculativeLoadHardeningAttr( | |||
4431 | Decl *D, const SpeculativeLoadHardeningAttr &AL) { | |||
4432 | if (checkAttrMutualExclusion<NoSpeculativeLoadHardeningAttr>(*this, D, AL)) | |||
4433 | return nullptr; | |||
4434 | ||||
4435 | return ::new (Context) SpeculativeLoadHardeningAttr(Context, AL); | |||
4436 | } | |||
4437 | ||||
4438 | static void handleAlwaysInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4439 | if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, AL)) | |||
4440 | return; | |||
4441 | ||||
4442 | if (AlwaysInlineAttr *Inline = | |||
4443 | S.mergeAlwaysInlineAttr(D, AL, AL.getAttrName())) | |||
4444 | D->addAttr(Inline); | |||
4445 | } | |||
4446 | ||||
4447 | static void handleMinSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4448 | if (MinSizeAttr *MinSize = S.mergeMinSizeAttr(D, AL)) | |||
4449 | D->addAttr(MinSize); | |||
4450 | } | |||
4451 | ||||
4452 | static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4453 | if (OptimizeNoneAttr *Optnone = S.mergeOptimizeNoneAttr(D, AL)) | |||
4454 | D->addAttr(Optnone); | |||
4455 | } | |||
4456 | ||||
4457 | static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4458 | if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL) || | |||
4459 | checkAttrMutualExclusion<HIPManagedAttr>(S, D, AL)) | |||
4460 | return; | |||
4461 | const auto *VD = cast<VarDecl>(D); | |||
4462 | if (VD->hasLocalStorage()) { | |||
4463 | S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev); | |||
4464 | return; | |||
4465 | } | |||
4466 | D->addAttr(::new (S.Context) CUDAConstantAttr(S.Context, AL)); | |||
4467 | } | |||
4468 | ||||
4469 | static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4470 | if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL) || | |||
4471 | checkAttrMutualExclusion<HIPManagedAttr>(S, D, AL)) | |||
4472 | return; | |||
4473 | const auto *VD = cast<VarDecl>(D); | |||
4474 | // extern __shared__ is only allowed on arrays with no length (e.g. | |||
4475 | // "int x[]"). | |||
4476 | if (!S.getLangOpts().GPURelocatableDeviceCode && VD->hasExternalStorage() && | |||
4477 | !isa<IncompleteArrayType>(VD->getType())) { | |||
4478 | S.Diag(AL.getLoc(), diag::err_cuda_extern_shared) << VD; | |||
4479 | return; | |||
4480 | } | |||
4481 | if (S.getLangOpts().CUDA && VD->hasLocalStorage() && | |||
4482 | S.CUDADiagIfHostCode(AL.getLoc(), diag::err_cuda_host_shared) | |||
4483 | << S.CurrentCUDATarget()) | |||
4484 | return; | |||
4485 | D->addAttr(::new (S.Context) CUDASharedAttr(S.Context, AL)); | |||
4486 | } | |||
4487 | ||||
4488 | static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4489 | if (checkAttrMutualExclusion<CUDADeviceAttr>(S, D, AL) || | |||
4490 | checkAttrMutualExclusion<CUDAHostAttr>(S, D, AL)) { | |||
4491 | return; | |||
4492 | } | |||
4493 | const auto *FD = cast<FunctionDecl>(D); | |||
4494 | if (!FD->getReturnType()->isVoidType() && | |||
4495 | !FD->getReturnType()->getAs<AutoType>() && | |||
4496 | !FD->getReturnType()->isInstantiationDependentType()) { | |||
4497 | SourceRange RTRange = FD->getReturnTypeSourceRange(); | |||
4498 | S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) | |||
4499 | << FD->getType() | |||
4500 | << (RTRange.isValid() ? FixItHint::CreateReplacement(RTRange, "void") | |||
4501 | : FixItHint()); | |||
4502 | return; | |||
4503 | } | |||
4504 | if (const auto *Method = dyn_cast<CXXMethodDecl>(FD)) { | |||
4505 | if (Method->isInstance()) { | |||
4506 | S.Diag(Method->getBeginLoc(), diag::err_kern_is_nonstatic_method) | |||
4507 | << Method; | |||
4508 | return; | |||
4509 | } | |||
4510 | S.Diag(Method->getBeginLoc(), diag::warn_kern_is_method) << Method; | |||
4511 | } | |||
4512 | // Only warn for "inline" when compiling for host, to cut down on noise. | |||
4513 | if (FD->isInlineSpecified() && !S.getLangOpts().CUDAIsDevice) | |||
4514 | S.Diag(FD->getBeginLoc(), diag::warn_kern_is_inline) << FD; | |||
4515 | ||||
4516 | D->addAttr(::new (S.Context) CUDAGlobalAttr(S.Context, AL)); | |||
4517 | // In host compilation the kernel is emitted as a stub function, which is | |||
4518 | // a helper function for launching the kernel. The instructions in the helper | |||
4519 | // function has nothing to do with the source code of the kernel. Do not emit | |||
4520 | // debug info for the stub function to avoid confusing the debugger. | |||
4521 | if (S.LangOpts.HIP && !S.LangOpts.CUDAIsDevice) | |||
4522 | D->addAttr(NoDebugAttr::CreateImplicit(S.Context)); | |||
4523 | } | |||
4524 | ||||
4525 | static void handleDeviceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4526 | if (checkAttrMutualExclusion<CUDAGlobalAttr>(S, D, AL)) { | |||
4527 | return; | |||
4528 | } | |||
4529 | ||||
4530 | if (const auto *VD = dyn_cast<VarDecl>(D)) { | |||
4531 | if (VD->hasLocalStorage()) { | |||
4532 | S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev); | |||
4533 | return; | |||
4534 | } | |||
4535 | } | |||
4536 | ||||
4537 | if (auto *A = D->getAttr<CUDADeviceAttr>()) { | |||
4538 | if (!A->isImplicit()) | |||
4539 | return; | |||
4540 | D->dropAttr<CUDADeviceAttr>(); | |||
4541 | } | |||
4542 | D->addAttr(::new (S.Context) CUDADeviceAttr(S.Context, AL)); | |||
4543 | } | |||
4544 | ||||
4545 | static void handleManagedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4546 | if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL) || | |||
4547 | checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL)) { | |||
4548 | return; | |||
4549 | } | |||
4550 | ||||
4551 | if (const auto *VD = dyn_cast<VarDecl>(D)) { | |||
4552 | if (VD->hasLocalStorage()) { | |||
4553 | S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev); | |||
4554 | return; | |||
4555 | } | |||
4556 | } | |||
4557 | if (!D->hasAttr<HIPManagedAttr>()) | |||
4558 | D->addAttr(::new (S.Context) HIPManagedAttr(S.Context, AL)); | |||
4559 | if (!D->hasAttr<CUDADeviceAttr>()) | |||
4560 | D->addAttr(CUDADeviceAttr::CreateImplicit(S.Context)); | |||
4561 | } | |||
4562 | ||||
4563 | static void handleGNUInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4564 | const auto *Fn = cast<FunctionDecl>(D); | |||
4565 | if (!Fn->isInlineSpecified()) { | |||
4566 | S.Diag(AL.getLoc(), diag::warn_gnu_inline_attribute_requires_inline); | |||
4567 | return; | |||
4568 | } | |||
4569 | ||||
4570 | if (S.LangOpts.CPlusPlus && Fn->getStorageClass() != SC_Extern) | |||
4571 | S.Diag(AL.getLoc(), diag::warn_gnu_inline_cplusplus_without_extern); | |||
4572 | ||||
4573 | D->addAttr(::new (S.Context) GNUInlineAttr(S.Context, AL)); | |||
4574 | } | |||
4575 | ||||
4576 | static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4577 | if (hasDeclarator(D)) return; | |||
4578 | ||||
4579 | // Diagnostic is emitted elsewhere: here we store the (valid) AL | |||
4580 | // in the Decl node for syntactic reasoning, e.g., pretty-printing. | |||
4581 | CallingConv CC; | |||
4582 | if (S.CheckCallingConvAttr(AL, CC, /*FD*/nullptr)) | |||
4583 | return; | |||
4584 | ||||
4585 | if (!isa<ObjCMethodDecl>(D)) { | |||
4586 | S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) | |||
4587 | << AL << ExpectedFunctionOrMethod; | |||
4588 | return; | |||
4589 | } | |||
4590 | ||||
4591 | switch (AL.getKind()) { | |||
4592 | case ParsedAttr::AT_FastCall: | |||
4593 | D->addAttr(::new (S.Context) FastCallAttr(S.Context, AL)); | |||
4594 | return; | |||
4595 | case ParsedAttr::AT_StdCall: | |||
4596 | D->addAttr(::new (S.Context) StdCallAttr(S.Context, AL)); | |||
4597 | return; | |||
4598 | case ParsedAttr::AT_ThisCall: | |||
4599 | D->addAttr(::new (S.Context) ThisCallAttr(S.Context, AL)); | |||
4600 | return; | |||
4601 | case ParsedAttr::AT_CDecl: | |||
4602 | D->addAttr(::new (S.Context) CDeclAttr(S.Context, AL)); | |||
4603 | return; | |||
4604 | case ParsedAttr::AT_Pascal: | |||
4605 | D->addAttr(::new (S.Context) PascalAttr(S.Context, AL)); | |||
4606 | return; | |||
4607 | case ParsedAttr::AT_SwiftCall: | |||
4608 | D->addAttr(::new (S.Context) SwiftCallAttr(S.Context, AL)); | |||
4609 | return; | |||
4610 | case ParsedAttr::AT_VectorCall: | |||
4611 | D->addAttr(::new (S.Context) VectorCallAttr(S.Context, AL)); | |||
4612 | return; | |||
4613 | case ParsedAttr::AT_MSABI: | |||
4614 | D->addAttr(::new (S.Context) MSABIAttr(S.Context, AL)); | |||
4615 | return; | |||
4616 | case ParsedAttr::AT_SysVABI: | |||
4617 | D->addAttr(::new (S.Context) SysVABIAttr(S.Context, AL)); | |||
4618 | return; | |||
4619 | case ParsedAttr::AT_RegCall: | |||
4620 | D->addAttr(::new (S.Context) RegCallAttr(S.Context, AL)); | |||
4621 | return; | |||
4622 | case ParsedAttr::AT_Pcs: { | |||
4623 | PcsAttr::PCSType PCS; | |||
4624 | switch (CC) { | |||
4625 | case CC_AAPCS: | |||
4626 | PCS = PcsAttr::AAPCS; | |||
4627 | break; | |||
4628 | case CC_AAPCS_VFP: | |||
4629 | PCS = PcsAttr::AAPCS_VFP; | |||
4630 | break; | |||
4631 | default: | |||
4632 | llvm_unreachable("unexpected calling convention in pcs attribute")::llvm::llvm_unreachable_internal("unexpected calling convention in pcs attribute" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 4632); | |||
4633 | } | |||
4634 | ||||
4635 | D->addAttr(::new (S.Context) PcsAttr(S.Context, AL, PCS)); | |||
4636 | return; | |||
4637 | } | |||
4638 | case ParsedAttr::AT_AArch64VectorPcs: | |||
4639 | D->addAttr(::new (S.Context) AArch64VectorPcsAttr(S.Context, AL)); | |||
4640 | return; | |||
4641 | case ParsedAttr::AT_IntelOclBicc: | |||
4642 | D->addAttr(::new (S.Context) IntelOclBiccAttr(S.Context, AL)); | |||
4643 | return; | |||
4644 | case ParsedAttr::AT_PreserveMost: | |||
4645 | D->addAttr(::new (S.Context) PreserveMostAttr(S.Context, AL)); | |||
4646 | return; | |||
4647 | case ParsedAttr::AT_PreserveAll: | |||
4648 | D->addAttr(::new (S.Context) PreserveAllAttr(S.Context, AL)); | |||
4649 | return; | |||
4650 | default: | |||
4651 | llvm_unreachable("unexpected attribute kind")::llvm::llvm_unreachable_internal("unexpected attribute kind" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 4651); | |||
4652 | } | |||
4653 | } | |||
4654 | ||||
4655 | static void handleSuppressAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4656 | if (!AL.checkAtLeastNumArgs(S, 1)) | |||
4657 | return; | |||
4658 | ||||
4659 | std::vector<StringRef> DiagnosticIdentifiers; | |||
4660 | for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { | |||
4661 | StringRef RuleName; | |||
4662 | ||||
4663 | if (!S.checkStringLiteralArgumentAttr(AL, I, RuleName, nullptr)) | |||
4664 | return; | |||
4665 | ||||
4666 | // FIXME: Warn if the rule name is unknown. This is tricky because only | |||
4667 | // clang-tidy knows about available rules. | |||
4668 | DiagnosticIdentifiers.push_back(RuleName); | |||
4669 | } | |||
4670 | D->addAttr(::new (S.Context) | |||
4671 | SuppressAttr(S.Context, AL, DiagnosticIdentifiers.data(), | |||
4672 | DiagnosticIdentifiers.size())); | |||
4673 | } | |||
4674 | ||||
4675 | static void handleLifetimeCategoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
4676 | TypeSourceInfo *DerefTypeLoc = nullptr; | |||
4677 | QualType ParmType; | |||
4678 | if (AL.hasParsedType()) { | |||
4679 | ParmType = S.GetTypeFromParser(AL.getTypeArg(), &DerefTypeLoc); | |||
4680 | ||||
4681 | unsigned SelectIdx = ~0U; | |||
4682 | if (ParmType->isReferenceType()) | |||
4683 | SelectIdx = 0; | |||
4684 | else if (ParmType->isArrayType()) | |||
4685 | SelectIdx = 1; | |||
4686 | ||||
4687 | if (SelectIdx != ~0U) { | |||
4688 | S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument) | |||
4689 | << SelectIdx << AL; | |||
4690 | return; | |||
4691 | } | |||
4692 | } | |||
4693 | ||||
4694 | // To check if earlier decl attributes do not conflict the newly parsed ones | |||
4695 | // we always add (and check) the attribute to the cannonical decl. | |||
4696 | D = D->getCanonicalDecl(); | |||
4697 | if (AL.getKind() == ParsedAttr::AT_Owner) { | |||
4698 | if (checkAttrMutualExclusion<PointerAttr>(S, D, AL)) | |||
4699 | return; | |||
4700 | if (const auto *OAttr = D->getAttr<OwnerAttr>()) { | |||
4701 | const Type *ExistingDerefType = OAttr->getDerefTypeLoc() | |||
4702 | ? OAttr->getDerefType().getTypePtr() | |||
4703 | : nullptr; | |||
4704 | if (ExistingDerefType != ParmType.getTypePtrOrNull()) { | |||
4705 | S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) | |||
4706 | << AL << OAttr; | |||
4707 | S.Diag(OAttr->getLocation(), diag::note_conflicting_attribute); | |||
4708 | } | |||
4709 | return; | |||
4710 | } | |||
4711 | for (Decl *Redecl : D->redecls()) { | |||
4712 | Redecl->addAttr(::new (S.Context) OwnerAttr(S.Context, AL, DerefTypeLoc)); | |||
4713 | } | |||
4714 | } else { | |||
4715 | if (checkAttrMutualExclusion<OwnerAttr>(S, D, AL)) | |||
4716 | return; | |||
4717 | if (const auto *PAttr = D->getAttr<PointerAttr>()) { | |||
4718 | const Type *ExistingDerefType = PAttr->getDerefTypeLoc() | |||
4719 | ? PAttr->getDerefType().getTypePtr() | |||
4720 | : nullptr; | |||
4721 | if (ExistingDerefType != ParmType.getTypePtrOrNull()) { | |||
4722 | S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) | |||
4723 | << AL << PAttr; | |||
4724 | S.Diag(PAttr->getLocation(), diag::note_conflicting_attribute); | |||
4725 | } | |||
4726 | return; | |||
4727 | } | |||
4728 | for (Decl *Redecl : D->redecls()) { | |||
4729 | Redecl->addAttr(::new (S.Context) | |||
4730 | PointerAttr(S.Context, AL, DerefTypeLoc)); | |||
4731 | } | |||
4732 | } | |||
4733 | } | |||
4734 | ||||
4735 | bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, | |||
4736 | const FunctionDecl *FD) { | |||
4737 | if (Attrs.isInvalid()) | |||
4738 | return true; | |||
4739 | ||||
4740 | if (Attrs.hasProcessingCache()) { | |||
4741 | CC = (CallingConv) Attrs.getProcessingCache(); | |||
4742 | return false; | |||
4743 | } | |||
4744 | ||||
4745 | unsigned ReqArgs = Attrs.getKind() == ParsedAttr::AT_Pcs ? 1 : 0; | |||
4746 | if (!Attrs.checkExactlyNumArgs(*this, ReqArgs)) { | |||
4747 | Attrs.setInvalid(); | |||
4748 | return true; | |||
4749 | } | |||
4750 | ||||
4751 | // TODO: diagnose uses of these conventions on the wrong target. | |||
4752 | switch (Attrs.getKind()) { | |||
4753 | case ParsedAttr::AT_CDecl: | |||
4754 | CC = CC_C; | |||
4755 | break; | |||
4756 | case ParsedAttr::AT_FastCall: | |||
4757 | CC = CC_X86FastCall; | |||
4758 | break; | |||
4759 | case ParsedAttr::AT_StdCall: | |||
4760 | CC = CC_X86StdCall; | |||
4761 | break; | |||
4762 | case ParsedAttr::AT_ThisCall: | |||
4763 | CC = CC_X86ThisCall; | |||
4764 | break; | |||
4765 | case ParsedAttr::AT_Pascal: | |||
4766 | CC = CC_X86Pascal; | |||
4767 | break; | |||
4768 | case ParsedAttr::AT_SwiftCall: | |||
4769 | CC = CC_Swift; | |||
4770 | break; | |||
4771 | case ParsedAttr::AT_VectorCall: | |||
4772 | CC = CC_X86VectorCall; | |||
4773 | break; | |||
4774 | case ParsedAttr::AT_AArch64VectorPcs: | |||
4775 | CC = CC_AArch64VectorCall; | |||
4776 | break; | |||
4777 | case ParsedAttr::AT_RegCall: | |||
4778 | CC = CC_X86RegCall; | |||
4779 | break; | |||
4780 | case ParsedAttr::AT_MSABI: | |||
4781 | CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C : | |||
4782 | CC_Win64; | |||
4783 | break; | |||
4784 | case ParsedAttr::AT_SysVABI: | |||
4785 | CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV : | |||
4786 | CC_C; | |||
4787 | break; | |||
4788 | case ParsedAttr::AT_Pcs: { | |||
4789 | StringRef StrRef; | |||
4790 | if (!checkStringLiteralArgumentAttr(Attrs, 0, StrRef)) { | |||
4791 | Attrs.setInvalid(); | |||
4792 | return true; | |||
4793 | } | |||
4794 | if (StrRef == "aapcs") { | |||
4795 | CC = CC_AAPCS; | |||
4796 | break; | |||
4797 | } else if (StrRef == "aapcs-vfp") { | |||
4798 | CC = CC_AAPCS_VFP; | |||
4799 | break; | |||
4800 | } | |||
4801 | ||||
4802 | Attrs.setInvalid(); | |||
4803 | Diag(Attrs.getLoc(), diag::err_invalid_pcs); | |||
4804 | return true; | |||
4805 | } | |||
4806 | case ParsedAttr::AT_IntelOclBicc: | |||
4807 | CC = CC_IntelOclBicc; | |||
4808 | break; | |||
4809 | case ParsedAttr::AT_PreserveMost: | |||
4810 | CC = CC_PreserveMost; | |||
4811 | break; | |||
4812 | case ParsedAttr::AT_PreserveAll: | |||
4813 | CC = CC_PreserveAll; | |||
4814 | break; | |||
4815 | default: llvm_unreachable("unexpected attribute kind")::llvm::llvm_unreachable_internal("unexpected attribute kind" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 4815); | |||
4816 | } | |||
4817 | ||||
4818 | TargetInfo::CallingConvCheckResult A = TargetInfo::CCCR_OK; | |||
4819 | const TargetInfo &TI = Context.getTargetInfo(); | |||
4820 | // CUDA functions may have host and/or device attributes which indicate | |||
4821 | // their targeted execution environment, therefore the calling convention | |||
4822 | // of functions in CUDA should be checked against the target deduced based | |||
4823 | // on their host/device attributes. | |||
4824 | if (LangOpts.CUDA) { | |||
4825 | auto *Aux = Context.getAuxTargetInfo(); | |||
4826 | auto CudaTarget = IdentifyCUDATarget(FD); | |||
4827 | bool CheckHost = false, CheckDevice = false; | |||
4828 | switch (CudaTarget) { | |||
4829 | case CFT_HostDevice: | |||
4830 | CheckHost = true; | |||
4831 | CheckDevice = true; | |||
4832 | break; | |||
4833 | case CFT_Host: | |||
4834 | CheckHost = true; | |||
4835 | break; | |||
4836 | case CFT_Device: | |||
4837 | case CFT_Global: | |||
4838 | CheckDevice = true; | |||
4839 | break; | |||
4840 | case CFT_InvalidTarget: | |||
4841 | llvm_unreachable("unexpected cuda target")::llvm::llvm_unreachable_internal("unexpected cuda target", "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 4841); | |||
4842 | } | |||
4843 | auto *HostTI = LangOpts.CUDAIsDevice ? Aux : &TI; | |||
4844 | auto *DeviceTI = LangOpts.CUDAIsDevice ? &TI : Aux; | |||
4845 | if (CheckHost && HostTI) | |||
4846 | A = HostTI->checkCallingConvention(CC); | |||
4847 | if (A == TargetInfo::CCCR_OK && CheckDevice && DeviceTI) | |||
4848 | A = DeviceTI->checkCallingConvention(CC); | |||
4849 | } else { | |||
4850 | A = TI.checkCallingConvention(CC); | |||
4851 | } | |||
4852 | ||||
4853 | switch (A) { | |||
4854 | case TargetInfo::CCCR_OK: | |||
4855 | break; | |||
4856 | ||||
4857 | case TargetInfo::CCCR_Ignore: | |||
4858 | // Treat an ignored convention as if it was an explicit C calling convention | |||
4859 | // attribute. For example, __stdcall on Win x64 functions as __cdecl, so | |||
4860 | // that command line flags that change the default convention to | |||
4861 | // __vectorcall don't affect declarations marked __stdcall. | |||
4862 | CC = CC_C; | |||
4863 | break; | |||
4864 | ||||
4865 | case TargetInfo::CCCR_Error: | |||
4866 | Diag(Attrs.getLoc(), diag::error_cconv_unsupported) | |||
4867 | << Attrs << (int)CallingConventionIgnoredReason::ForThisTarget; | |||
4868 | break; | |||
4869 | ||||
4870 | case TargetInfo::CCCR_Warning: { | |||
4871 | Diag(Attrs.getLoc(), diag::warn_cconv_unsupported) | |||
4872 | << Attrs << (int)CallingConventionIgnoredReason::ForThisTarget; | |||
4873 | ||||
4874 | // This convention is not valid for the target. Use the default function or | |||
4875 | // method calling convention. | |||
4876 | bool IsCXXMethod = false, IsVariadic = false; | |||
4877 | if (FD) { | |||
4878 | IsCXXMethod = FD->isCXXInstanceMember(); | |||
4879 | IsVariadic = FD->isVariadic(); | |||
4880 | } | |||
4881 | CC = Context.getDefaultCallingConvention(IsVariadic, IsCXXMethod); | |||
4882 | break; | |||
4883 | } | |||
4884 | } | |||
4885 | ||||
4886 | Attrs.setProcessingCache((unsigned) CC); | |||
4887 | return false; | |||
4888 | } | |||
4889 | ||||
4890 | /// Pointer-like types in the default address space. | |||
4891 | static bool isValidSwiftContextType(QualType Ty) { | |||
4892 | if (!Ty->hasPointerRepresentation()) | |||
4893 | return Ty->isDependentType(); | |||
4894 | return Ty->getPointeeType().getAddressSpace() == LangAS::Default; | |||
4895 | } | |||
4896 | ||||
4897 | /// Pointers and references in the default address space. | |||
4898 | static bool isValidSwiftIndirectResultType(QualType Ty) { | |||
4899 | if (const auto *PtrType = Ty->getAs<PointerType>()) { | |||
4900 | Ty = PtrType->getPointeeType(); | |||
4901 | } else if (const auto *RefType = Ty->getAs<ReferenceType>()) { | |||
4902 | Ty = RefType->getPointeeType(); | |||
4903 | } else { | |||
4904 | return Ty->isDependentType(); | |||
4905 | } | |||
4906 | return Ty.getAddressSpace() == LangAS::Default; | |||
4907 | } | |||
4908 | ||||
4909 | /// Pointers and references to pointers in the default address space. | |||
4910 | static bool isValidSwiftErrorResultType(QualType Ty) { | |||
4911 | if (const auto *PtrType = Ty->getAs<PointerType>()) { | |||
4912 | Ty = PtrType->getPointeeType(); | |||
4913 | } else if (const auto *RefType = Ty->getAs<ReferenceType>()) { | |||
4914 | Ty = RefType->getPointeeType(); | |||
4915 | } else { | |||
4916 | return Ty->isDependentType(); | |||
4917 | } | |||
4918 | if (!Ty.getQualifiers().empty()) | |||
4919 | return false; | |||
4920 | return isValidSwiftContextType(Ty); | |||
4921 | } | |||
4922 | ||||
4923 | void Sema::AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI, | |||
4924 | ParameterABI abi) { | |||
4925 | ||||
4926 | QualType type = cast<ParmVarDecl>(D)->getType(); | |||
4927 | ||||
4928 | if (auto existingAttr = D->getAttr<ParameterABIAttr>()) { | |||
4929 | if (existingAttr->getABI() != abi) { | |||
4930 | Diag(CI.getLoc(), diag::err_attributes_are_not_compatible) | |||
4931 | << getParameterABISpelling(abi) << existingAttr; | |||
4932 | Diag(existingAttr->getLocation(), diag::note_conflicting_attribute); | |||
4933 | return; | |||
4934 | } | |||
4935 | } | |||
4936 | ||||
4937 | switch (abi) { | |||
4938 | case ParameterABI::Ordinary: | |||
4939 | llvm_unreachable("explicit attribute for ordinary parameter ABI?")::llvm::llvm_unreachable_internal("explicit attribute for ordinary parameter ABI?" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 4939); | |||
4940 | ||||
4941 | case ParameterABI::SwiftContext: | |||
4942 | if (!isValidSwiftContextType(type)) { | |||
4943 | Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) | |||
4944 | << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type; | |||
4945 | } | |||
4946 | D->addAttr(::new (Context) SwiftContextAttr(Context, CI)); | |||
4947 | return; | |||
4948 | ||||
4949 | case ParameterABI::SwiftErrorResult: | |||
4950 | if (!isValidSwiftErrorResultType(type)) { | |||
4951 | Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) | |||
4952 | << getParameterABISpelling(abi) << /*pointer to pointer */ 1 << type; | |||
4953 | } | |||
4954 | D->addAttr(::new (Context) SwiftErrorResultAttr(Context, CI)); | |||
4955 | return; | |||
4956 | ||||
4957 | case ParameterABI::SwiftIndirectResult: | |||
4958 | if (!isValidSwiftIndirectResultType(type)) { | |||
4959 | Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) | |||
4960 | << getParameterABISpelling(abi) << /*pointer*/ 0 << type; | |||
4961 | } | |||
4962 | D->addAttr(::new (Context) SwiftIndirectResultAttr(Context, CI)); | |||
4963 | return; | |||
4964 | } | |||
4965 | llvm_unreachable("bad parameter ABI attribute")::llvm::llvm_unreachable_internal("bad parameter ABI attribute" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 4965); | |||
4966 | } | |||
4967 | ||||
4968 | /// Checks a regparm attribute, returning true if it is ill-formed and | |||
4969 | /// otherwise setting numParams to the appropriate value. | |||
4970 | bool Sema::CheckRegparmAttr(const ParsedAttr &AL, unsigned &numParams) { | |||
4971 | if (AL.isInvalid()) | |||
4972 | return true; | |||
4973 | ||||
4974 | if (!AL.checkExactlyNumArgs(*this, 1)) { | |||
4975 | AL.setInvalid(); | |||
4976 | return true; | |||
4977 | } | |||
4978 | ||||
4979 | uint32_t NP; | |||
4980 | Expr *NumParamsExpr = AL.getArgAsExpr(0); | |||
4981 | if (!checkUInt32Argument(*this, AL, NumParamsExpr, NP)) { | |||
4982 | AL.setInvalid(); | |||
4983 | return true; | |||
4984 | } | |||
4985 | ||||
4986 | if (Context.getTargetInfo().getRegParmMax() == 0) { | |||
4987 | Diag(AL.getLoc(), diag::err_attribute_regparm_wrong_platform) | |||
4988 | << NumParamsExpr->getSourceRange(); | |||
4989 | AL.setInvalid(); | |||
4990 | return true; | |||
4991 | } | |||
4992 | ||||
4993 | numParams = NP; | |||
4994 | if (numParams > Context.getTargetInfo().getRegParmMax()) { | |||
4995 | Diag(AL.getLoc(), diag::err_attribute_regparm_invalid_number) | |||
4996 | << Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange(); | |||
4997 | AL.setInvalid(); | |||
4998 | return true; | |||
4999 | } | |||
5000 | ||||
5001 | return false; | |||
5002 | } | |||
5003 | ||||
5004 | // Checks whether an argument of launch_bounds attribute is | |||
5005 | // acceptable, performs implicit conversion to Rvalue, and returns | |||
5006 | // non-nullptr Expr result on success. Otherwise, it returns nullptr | |||
5007 | // and may output an error. | |||
5008 | static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E, | |||
5009 | const CUDALaunchBoundsAttr &AL, | |||
5010 | const unsigned Idx) { | |||
5011 | if (S.DiagnoseUnexpandedParameterPack(E)) | |||
5012 | return nullptr; | |||
5013 | ||||
5014 | // Accept template arguments for now as they depend on something else. | |||
5015 | // We'll get to check them when they eventually get instantiated. | |||
5016 | if (E->isValueDependent()) | |||
5017 | return E; | |||
5018 | ||||
5019 | Optional<llvm::APSInt> I = llvm::APSInt(64); | |||
5020 | if (!(I = E->getIntegerConstantExpr(S.Context))) { | |||
5021 | S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type) | |||
5022 | << &AL << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange(); | |||
5023 | return nullptr; | |||
5024 | } | |||
5025 | // Make sure we can fit it in 32 bits. | |||
5026 | if (!I->isIntN(32)) { | |||
5027 | S.Diag(E->getExprLoc(), diag::err_ice_too_large) | |||
5028 | << I->toString(10, false) << 32 << /* Unsigned */ 1; | |||
5029 | return nullptr; | |||
5030 | } | |||
5031 | if (*I < 0) | |||
5032 | S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative) | |||
5033 | << &AL << Idx << E->getSourceRange(); | |||
5034 | ||||
5035 | // We may need to perform implicit conversion of the argument. | |||
5036 | InitializedEntity Entity = InitializedEntity::InitializeParameter( | |||
5037 | S.Context, S.Context.getConstType(S.Context.IntTy), /*consume*/ false); | |||
5038 | ExprResult ValArg = S.PerformCopyInitialization(Entity, SourceLocation(), E); | |||
5039 | assert(!ValArg.isInvalid() &&((!ValArg.isInvalid() && "Unexpected PerformCopyInitialization() failure." ) ? static_cast<void> (0) : __assert_fail ("!ValArg.isInvalid() && \"Unexpected PerformCopyInitialization() failure.\"" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 5040, __PRETTY_FUNCTION__)) | |||
5040 | "Unexpected PerformCopyInitialization() failure.")((!ValArg.isInvalid() && "Unexpected PerformCopyInitialization() failure." ) ? static_cast<void> (0) : __assert_fail ("!ValArg.isInvalid() && \"Unexpected PerformCopyInitialization() failure.\"" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 5040, __PRETTY_FUNCTION__)); | |||
5041 | ||||
5042 | return ValArg.getAs<Expr>(); | |||
5043 | } | |||
5044 | ||||
5045 | void Sema::AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI, | |||
5046 | Expr *MaxThreads, Expr *MinBlocks) { | |||
5047 | CUDALaunchBoundsAttr TmpAttr(Context, CI, MaxThreads, MinBlocks); | |||
5048 | MaxThreads = makeLaunchBoundsArgExpr(*this, MaxThreads, TmpAttr, 0); | |||
5049 | if (MaxThreads == nullptr) | |||
5050 | return; | |||
5051 | ||||
5052 | if (MinBlocks) { | |||
5053 | MinBlocks = makeLaunchBoundsArgExpr(*this, MinBlocks, TmpAttr, 1); | |||
5054 | if (MinBlocks == nullptr) | |||
5055 | return; | |||
5056 | } | |||
5057 | ||||
5058 | D->addAttr(::new (Context) | |||
5059 | CUDALaunchBoundsAttr(Context, CI, MaxThreads, MinBlocks)); | |||
5060 | } | |||
5061 | ||||
5062 | static void handleLaunchBoundsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5063 | if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2)) | |||
5064 | return; | |||
5065 | ||||
5066 | S.AddLaunchBoundsAttr(D, AL, AL.getArgAsExpr(0), | |||
5067 | AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr); | |||
5068 | } | |||
5069 | ||||
5070 | static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, | |||
5071 | const ParsedAttr &AL) { | |||
5072 | if (!AL.isArgIdent(0)) { | |||
5073 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
5074 | << AL << /* arg num = */ 1 << AANT_ArgumentIdentifier; | |||
5075 | return; | |||
5076 | } | |||
5077 | ||||
5078 | ParamIdx ArgumentIdx; | |||
5079 | if (!checkFunctionOrMethodParameterIndex(S, D, AL, 2, AL.getArgAsExpr(1), | |||
5080 | ArgumentIdx)) | |||
5081 | return; | |||
5082 | ||||
5083 | ParamIdx TypeTagIdx; | |||
5084 | if (!checkFunctionOrMethodParameterIndex(S, D, AL, 3, AL.getArgAsExpr(2), | |||
5085 | TypeTagIdx)) | |||
5086 | return; | |||
5087 | ||||
5088 | bool IsPointer = AL.getAttrName()->getName() == "pointer_with_type_tag"; | |||
5089 | if (IsPointer) { | |||
5090 | // Ensure that buffer has a pointer type. | |||
5091 | unsigned ArgumentIdxAST = ArgumentIdx.getASTIndex(); | |||
5092 | if (ArgumentIdxAST >= getFunctionOrMethodNumParams(D) || | |||
5093 | !getFunctionOrMethodParamType(D, ArgumentIdxAST)->isPointerType()) | |||
5094 | S.Diag(AL.getLoc(), diag::err_attribute_pointers_only) << AL << 0; | |||
5095 | } | |||
5096 | ||||
5097 | D->addAttr(::new (S.Context) ArgumentWithTypeTagAttr( | |||
5098 | S.Context, AL, AL.getArgAsIdent(0)->Ident, ArgumentIdx, TypeTagIdx, | |||
5099 | IsPointer)); | |||
5100 | } | |||
5101 | ||||
5102 | static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, | |||
5103 | const ParsedAttr &AL) { | |||
5104 | if (!AL.isArgIdent(0)) { | |||
5105 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
5106 | << AL << 1 << AANT_ArgumentIdentifier; | |||
5107 | return; | |||
5108 | } | |||
5109 | ||||
5110 | if (!AL.checkExactlyNumArgs(S, 1)) | |||
5111 | return; | |||
5112 | ||||
5113 | if (!isa<VarDecl>(D)) { | |||
5114 | S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type) | |||
5115 | << AL << ExpectedVariable; | |||
5116 | return; | |||
5117 | } | |||
5118 | ||||
5119 | IdentifierInfo *PointerKind = AL.getArgAsIdent(0)->Ident; | |||
5120 | TypeSourceInfo *MatchingCTypeLoc = nullptr; | |||
5121 | S.GetTypeFromParser(AL.getMatchingCType(), &MatchingCTypeLoc); | |||
5122 | 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~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 5122, __PRETTY_FUNCTION__)); | |||
5123 | ||||
5124 | D->addAttr(::new (S.Context) TypeTagForDatatypeAttr( | |||
5125 | S.Context, AL, PointerKind, MatchingCTypeLoc, AL.getLayoutCompatible(), | |||
5126 | AL.getMustBeNull())); | |||
5127 | } | |||
5128 | ||||
5129 | static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5130 | ParamIdx ArgCount; | |||
5131 | ||||
5132 | if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, AL.getArgAsExpr(0), | |||
5133 | ArgCount, | |||
5134 | true /* CanIndexImplicitThis */)) | |||
5135 | return; | |||
5136 | ||||
5137 | // ArgCount isn't a parameter index [0;n), it's a count [1;n] | |||
5138 | D->addAttr(::new (S.Context) | |||
5139 | XRayLogArgsAttr(S.Context, AL, ArgCount.getSourceIndex())); | |||
5140 | } | |||
5141 | ||||
5142 | static void handlePatchableFunctionEntryAttr(Sema &S, Decl *D, | |||
5143 | const ParsedAttr &AL) { | |||
5144 | uint32_t Count = 0, Offset = 0; | |||
5145 | if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), Count, 0, true)) | |||
5146 | return; | |||
5147 | if (AL.getNumArgs() == 2) { | |||
5148 | Expr *Arg = AL.getArgAsExpr(1); | |||
5149 | if (!checkUInt32Argument(S, AL, Arg, Offset, 1, true)) | |||
5150 | return; | |||
5151 | if (Count < Offset) { | |||
5152 | S.Diag(getAttrLoc(AL), diag::err_attribute_argument_out_of_range) | |||
5153 | << &AL << 0 << Count << Arg->getBeginLoc(); | |||
5154 | return; | |||
5155 | } | |||
5156 | } | |||
5157 | D->addAttr(::new (S.Context) | |||
5158 | PatchableFunctionEntryAttr(S.Context, AL, Count, Offset)); | |||
5159 | } | |||
5160 | ||||
5161 | namespace { | |||
5162 | struct IntrinToName { | |||
5163 | uint32_t Id; | |||
5164 | int32_t FullName; | |||
5165 | int32_t ShortName; | |||
5166 | }; | |||
5167 | } // unnamed namespace | |||
5168 | ||||
5169 | static bool ArmBuiltinAliasValid(unsigned BuiltinID, StringRef AliasName, | |||
5170 | ArrayRef<IntrinToName> Map, | |||
5171 | const char *IntrinNames) { | |||
5172 | if (AliasName.startswith("__arm_")) | |||
5173 | AliasName = AliasName.substr(6); | |||
5174 | const IntrinToName *It = std::lower_bound( | |||
5175 | Map.begin(), Map.end(), BuiltinID, | |||
5176 | [](const IntrinToName &L, unsigned Id) { return L.Id < Id; }); | |||
5177 | if (It == Map.end() || It->Id != BuiltinID) | |||
5178 | return false; | |||
5179 | StringRef FullName(&IntrinNames[It->FullName]); | |||
5180 | if (AliasName == FullName) | |||
5181 | return true; | |||
5182 | if (It->ShortName == -1) | |||
5183 | return false; | |||
5184 | StringRef ShortName(&IntrinNames[It->ShortName]); | |||
5185 | return AliasName == ShortName; | |||
5186 | } | |||
5187 | ||||
5188 | static bool ArmMveAliasValid(unsigned BuiltinID, StringRef AliasName) { | |||
5189 | #include "clang/Basic/arm_mve_builtin_aliases.inc" | |||
5190 | // The included file defines: | |||
5191 | // - ArrayRef<IntrinToName> Map | |||
5192 | // - const char IntrinNames[] | |||
5193 | return ArmBuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames); | |||
5194 | } | |||
5195 | ||||
5196 | static bool ArmCdeAliasValid(unsigned BuiltinID, StringRef AliasName) { | |||
5197 | #include "clang/Basic/arm_cde_builtin_aliases.inc" | |||
5198 | return ArmBuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames); | |||
5199 | } | |||
5200 | ||||
5201 | static bool ArmSveAliasValid(unsigned BuiltinID, StringRef AliasName) { | |||
5202 | switch (BuiltinID) { | |||
5203 | default: | |||
5204 | return false; | |||
5205 | #define GET_SVE_BUILTINS | |||
5206 | #define BUILTIN(name, types, attr)case SVE::BIname: case SVE::BI##name: | |||
5207 | #include "clang/Basic/arm_sve_builtins.inc" | |||
5208 | return true; | |||
5209 | } | |||
5210 | } | |||
5211 | ||||
5212 | static void handleArmBuiltinAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5213 | if (!AL.isArgIdent(0)) { | |||
5214 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
5215 | << AL << 1 << AANT_ArgumentIdentifier; | |||
5216 | return; | |||
5217 | } | |||
5218 | ||||
5219 | IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident; | |||
5220 | unsigned BuiltinID = Ident->getBuiltinID(); | |||
5221 | StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName(); | |||
5222 | ||||
5223 | bool IsAArch64 = S.Context.getTargetInfo().getTriple().isAArch64(); | |||
5224 | if ((IsAArch64 && !ArmSveAliasValid(BuiltinID, AliasName)) || | |||
5225 | (!IsAArch64 && !ArmMveAliasValid(BuiltinID, AliasName) && | |||
5226 | !ArmCdeAliasValid(BuiltinID, AliasName))) { | |||
5227 | S.Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias); | |||
5228 | return; | |||
5229 | } | |||
5230 | ||||
5231 | D->addAttr(::new (S.Context) ArmBuiltinAliasAttr(S.Context, AL, Ident)); | |||
5232 | } | |||
5233 | ||||
5234 | //===----------------------------------------------------------------------===// | |||
5235 | // Checker-specific attribute handlers. | |||
5236 | //===----------------------------------------------------------------------===// | |||
5237 | static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType QT) { | |||
5238 | return QT->isDependentType() || QT->isObjCRetainableType(); | |||
5239 | } | |||
5240 | ||||
5241 | static bool isValidSubjectOfNSAttribute(QualType QT) { | |||
5242 | return QT->isDependentType() || QT->isObjCObjectPointerType() || | |||
5243 | QT->isObjCNSObjectType(); | |||
5244 | } | |||
5245 | ||||
5246 | static bool isValidSubjectOfCFAttribute(QualType QT) { | |||
5247 | return QT->isDependentType() || QT->isPointerType() || | |||
5248 | isValidSubjectOfNSAttribute(QT); | |||
5249 | } | |||
5250 | ||||
5251 | static bool isValidSubjectOfOSAttribute(QualType QT) { | |||
5252 | if (QT->isDependentType()) | |||
5253 | return true; | |||
5254 | QualType PT = QT->getPointeeType(); | |||
5255 | return !PT.isNull() && PT->getAsCXXRecordDecl() != nullptr; | |||
5256 | } | |||
5257 | ||||
5258 | void Sema::AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI, | |||
5259 | RetainOwnershipKind K, | |||
5260 | bool IsTemplateInstantiation) { | |||
5261 | ValueDecl *VD = cast<ValueDecl>(D); | |||
5262 | switch (K) { | |||
5263 | case RetainOwnershipKind::OS: | |||
5264 | handleSimpleAttributeOrDiagnose<OSConsumedAttr>( | |||
5265 | *this, VD, CI, isValidSubjectOfOSAttribute(VD->getType()), | |||
5266 | diag::warn_ns_attribute_wrong_parameter_type, | |||
5267 | /*ExtraArgs=*/CI.getRange(), "os_consumed", /*pointers*/ 1); | |||
5268 | return; | |||
5269 | case RetainOwnershipKind::NS: | |||
5270 | handleSimpleAttributeOrDiagnose<NSConsumedAttr>( | |||
5271 | *this, VD, CI, isValidSubjectOfNSAttribute(VD->getType()), | |||
5272 | ||||
5273 | // These attributes are normally just advisory, but in ARC, ns_consumed | |||
5274 | // is significant. Allow non-dependent code to contain inappropriate | |||
5275 | // attributes even in ARC, but require template instantiations to be | |||
5276 | // set up correctly. | |||
5277 | ((IsTemplateInstantiation && getLangOpts().ObjCAutoRefCount) | |||
5278 | ? diag::err_ns_attribute_wrong_parameter_type | |||
5279 | : diag::warn_ns_attribute_wrong_parameter_type), | |||
5280 | /*ExtraArgs=*/CI.getRange(), "ns_consumed", /*objc pointers*/ 0); | |||
5281 | return; | |||
5282 | case RetainOwnershipKind::CF: | |||
5283 | handleSimpleAttributeOrDiagnose<CFConsumedAttr>( | |||
5284 | *this, VD, CI, isValidSubjectOfCFAttribute(VD->getType()), | |||
5285 | diag::warn_ns_attribute_wrong_parameter_type, | |||
5286 | /*ExtraArgs=*/CI.getRange(), "cf_consumed", /*pointers*/ 1); | |||
5287 | return; | |||
5288 | } | |||
5289 | } | |||
5290 | ||||
5291 | static Sema::RetainOwnershipKind | |||
5292 | parsedAttrToRetainOwnershipKind(const ParsedAttr &AL) { | |||
5293 | switch (AL.getKind()) { | |||
5294 | case ParsedAttr::AT_CFConsumed: | |||
5295 | case ParsedAttr::AT_CFReturnsRetained: | |||
5296 | case ParsedAttr::AT_CFReturnsNotRetained: | |||
5297 | return Sema::RetainOwnershipKind::CF; | |||
5298 | case ParsedAttr::AT_OSConsumesThis: | |||
5299 | case ParsedAttr::AT_OSConsumed: | |||
5300 | case ParsedAttr::AT_OSReturnsRetained: | |||
5301 | case ParsedAttr::AT_OSReturnsNotRetained: | |||
5302 | case ParsedAttr::AT_OSReturnsRetainedOnZero: | |||
5303 | case ParsedAttr::AT_OSReturnsRetainedOnNonZero: | |||
5304 | return Sema::RetainOwnershipKind::OS; | |||
5305 | case ParsedAttr::AT_NSConsumesSelf: | |||
5306 | case ParsedAttr::AT_NSConsumed: | |||
5307 | case ParsedAttr::AT_NSReturnsRetained: | |||
5308 | case ParsedAttr::AT_NSReturnsNotRetained: | |||
5309 | case ParsedAttr::AT_NSReturnsAutoreleased: | |||
5310 | return Sema::RetainOwnershipKind::NS; | |||
5311 | default: | |||
5312 | llvm_unreachable("Wrong argument supplied")::llvm::llvm_unreachable_internal("Wrong argument supplied", "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 5312); | |||
5313 | } | |||
5314 | } | |||
5315 | ||||
5316 | bool Sema::checkNSReturnsRetainedReturnType(SourceLocation Loc, QualType QT) { | |||
5317 | if (isValidSubjectOfNSReturnsRetainedAttribute(QT)) | |||
5318 | return false; | |||
5319 | ||||
5320 | Diag(Loc, diag::warn_ns_attribute_wrong_return_type) | |||
5321 | << "'ns_returns_retained'" << 0 << 0; | |||
5322 | return true; | |||
5323 | } | |||
5324 | ||||
5325 | /// \return whether the parameter is a pointer to OSObject pointer. | |||
5326 | static bool isValidOSObjectOutParameter(const Decl *D) { | |||
5327 | const auto *PVD = dyn_cast<ParmVarDecl>(D); | |||
5328 | if (!PVD) | |||
5329 | return false; | |||
5330 | QualType QT = PVD->getType(); | |||
5331 | QualType PT = QT->getPointeeType(); | |||
5332 | return !PT.isNull() && isValidSubjectOfOSAttribute(PT); | |||
5333 | } | |||
5334 | ||||
5335 | static void handleXReturnsXRetainedAttr(Sema &S, Decl *D, | |||
5336 | const ParsedAttr &AL) { | |||
5337 | QualType ReturnType; | |||
5338 | Sema::RetainOwnershipKind K = parsedAttrToRetainOwnershipKind(AL); | |||
5339 | ||||
5340 | if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { | |||
5341 | ReturnType = MD->getReturnType(); | |||
5342 | } else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) && | |||
5343 | (AL.getKind() == ParsedAttr::AT_NSReturnsRetained)) { | |||
5344 | return; // ignore: was handled as a type attribute | |||
5345 | } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) { | |||
5346 | ReturnType = PD->getType(); | |||
5347 | } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
5348 | ReturnType = FD->getReturnType(); | |||
5349 | } else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) { | |||
5350 | // Attributes on parameters are used for out-parameters, | |||
5351 | // passed as pointers-to-pointers. | |||
5352 | unsigned DiagID = K == Sema::RetainOwnershipKind::CF | |||
5353 | ? /*pointer-to-CF-pointer*/2 | |||
5354 | : /*pointer-to-OSObject-pointer*/3; | |||
5355 | ReturnType = Param->getType()->getPointeeType(); | |||
5356 | if (ReturnType.isNull()) { | |||
5357 | S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type) | |||
5358 | << AL << DiagID << AL.getRange(); | |||
5359 | return; | |||
5360 | } | |||
5361 | } else if (AL.isUsedAsTypeAttr()) { | |||
5362 | return; | |||
5363 | } else { | |||
5364 | AttributeDeclKind ExpectedDeclKind; | |||
5365 | switch (AL.getKind()) { | |||
5366 | default: llvm_unreachable("invalid ownership attribute")::llvm::llvm_unreachable_internal("invalid ownership attribute" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 5366); | |||
5367 | case ParsedAttr::AT_NSReturnsRetained: | |||
5368 | case ParsedAttr::AT_NSReturnsAutoreleased: | |||
5369 | case ParsedAttr::AT_NSReturnsNotRetained: | |||
5370 | ExpectedDeclKind = ExpectedFunctionOrMethod; | |||
5371 | break; | |||
5372 | ||||
5373 | case ParsedAttr::AT_OSReturnsRetained: | |||
5374 | case ParsedAttr::AT_OSReturnsNotRetained: | |||
5375 | case ParsedAttr::AT_CFReturnsRetained: | |||
5376 | case ParsedAttr::AT_CFReturnsNotRetained: | |||
5377 | ExpectedDeclKind = ExpectedFunctionMethodOrParameter; | |||
5378 | break; | |||
5379 | } | |||
5380 | S.Diag(D->getBeginLoc(), diag::warn_attribute_wrong_decl_type) | |||
5381 | << AL.getRange() << AL << ExpectedDeclKind; | |||
5382 | return; | |||
5383 | } | |||
5384 | ||||
5385 | bool TypeOK; | |||
5386 | bool Cf; | |||
5387 | unsigned ParmDiagID = 2; // Pointer-to-CF-pointer | |||
5388 | switch (AL.getKind()) { | |||
5389 | default: llvm_unreachable("invalid ownership attribute")::llvm::llvm_unreachable_internal("invalid ownership attribute" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 5389); | |||
5390 | case ParsedAttr::AT_NSReturnsRetained: | |||
5391 | TypeOK = isValidSubjectOfNSReturnsRetainedAttribute(ReturnType); | |||
5392 | Cf = false; | |||
5393 | break; | |||
5394 | ||||
5395 | case ParsedAttr::AT_NSReturnsAutoreleased: | |||
5396 | case ParsedAttr::AT_NSReturnsNotRetained: | |||
5397 | TypeOK = isValidSubjectOfNSAttribute(ReturnType); | |||
5398 | Cf = false; | |||
5399 | break; | |||
5400 | ||||
5401 | case ParsedAttr::AT_CFReturnsRetained: | |||
5402 | case ParsedAttr::AT_CFReturnsNotRetained: | |||
5403 | TypeOK = isValidSubjectOfCFAttribute(ReturnType); | |||
5404 | Cf = true; | |||
5405 | break; | |||
5406 | ||||
5407 | case ParsedAttr::AT_OSReturnsRetained: | |||
5408 | case ParsedAttr::AT_OSReturnsNotRetained: | |||
5409 | TypeOK = isValidSubjectOfOSAttribute(ReturnType); | |||
5410 | Cf = true; | |||
5411 | ParmDiagID = 3; // Pointer-to-OSObject-pointer | |||
5412 | break; | |||
5413 | } | |||
5414 | ||||
5415 | if (!TypeOK) { | |||
5416 | if (AL.isUsedAsTypeAttr()) | |||
5417 | return; | |||
5418 | ||||
5419 | if (isa<ParmVarDecl>(D)) { | |||
5420 | S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type) | |||
5421 | << AL << ParmDiagID << AL.getRange(); | |||
5422 | } else { | |||
5423 | // Needs to be kept in sync with warn_ns_attribute_wrong_return_type. | |||
5424 | enum : unsigned { | |||
5425 | Function, | |||
5426 | Method, | |||
5427 | Property | |||
5428 | } SubjectKind = Function; | |||
5429 | if (isa<ObjCMethodDecl>(D)) | |||
5430 | SubjectKind = Method; | |||
5431 | else if (isa<ObjCPropertyDecl>(D)) | |||
5432 | SubjectKind = Property; | |||
5433 | S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type) | |||
5434 | << AL << SubjectKind << Cf << AL.getRange(); | |||
5435 | } | |||
5436 | return; | |||
5437 | } | |||
5438 | ||||
5439 | switch (AL.getKind()) { | |||
5440 | default: | |||
5441 | llvm_unreachable("invalid ownership attribute")::llvm::llvm_unreachable_internal("invalid ownership attribute" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 5441); | |||
5442 | case ParsedAttr::AT_NSReturnsAutoreleased: | |||
5443 | handleSimpleAttribute<NSReturnsAutoreleasedAttr>(S, D, AL); | |||
5444 | return; | |||
5445 | case ParsedAttr::AT_CFReturnsNotRetained: | |||
5446 | handleSimpleAttribute<CFReturnsNotRetainedAttr>(S, D, AL); | |||
5447 | return; | |||
5448 | case ParsedAttr::AT_NSReturnsNotRetained: | |||
5449 | handleSimpleAttribute<NSReturnsNotRetainedAttr>(S, D, AL); | |||
5450 | return; | |||
5451 | case ParsedAttr::AT_CFReturnsRetained: | |||
5452 | handleSimpleAttribute<CFReturnsRetainedAttr>(S, D, AL); | |||
5453 | return; | |||
5454 | case ParsedAttr::AT_NSReturnsRetained: | |||
5455 | handleSimpleAttribute<NSReturnsRetainedAttr>(S, D, AL); | |||
5456 | return; | |||
5457 | case ParsedAttr::AT_OSReturnsRetained: | |||
5458 | handleSimpleAttribute<OSReturnsRetainedAttr>(S, D, AL); | |||
5459 | return; | |||
5460 | case ParsedAttr::AT_OSReturnsNotRetained: | |||
5461 | handleSimpleAttribute<OSReturnsNotRetainedAttr>(S, D, AL); | |||
5462 | return; | |||
5463 | }; | |||
5464 | } | |||
5465 | ||||
5466 | static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, | |||
5467 | const ParsedAttr &Attrs) { | |||
5468 | const int EP_ObjCMethod = 1; | |||
5469 | const int EP_ObjCProperty = 2; | |||
5470 | ||||
5471 | SourceLocation loc = Attrs.getLoc(); | |||
5472 | QualType resultType; | |||
5473 | if (isa<ObjCMethodDecl>(D)) | |||
5474 | resultType = cast<ObjCMethodDecl>(D)->getReturnType(); | |||
5475 | else | |||
5476 | resultType = cast<ObjCPropertyDecl>(D)->getType(); | |||
5477 | ||||
5478 | if (!resultType->isReferenceType() && | |||
5479 | (!resultType->isPointerType() || resultType->isObjCRetainableType())) { | |||
5480 | S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type) | |||
5481 | << SourceRange(loc) << Attrs | |||
5482 | << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty) | |||
5483 | << /*non-retainable pointer*/ 2; | |||
5484 | ||||
5485 | // Drop the attribute. | |||
5486 | return; | |||
5487 | } | |||
5488 | ||||
5489 | D->addAttr(::new (S.Context) ObjCReturnsInnerPointerAttr(S.Context, Attrs)); | |||
5490 | } | |||
5491 | ||||
5492 | static void handleObjCRequiresSuperAttr(Sema &S, Decl *D, | |||
5493 | const ParsedAttr &Attrs) { | |||
5494 | const auto *Method = cast<ObjCMethodDecl>(D); | |||
5495 | ||||
5496 | const DeclContext *DC = Method->getDeclContext(); | |||
5497 | if (const auto *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) { | |||
5498 | S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs | |||
5499 | << 0; | |||
5500 | S.Diag(PDecl->getLocation(), diag::note_protocol_decl); | |||
5501 | return; | |||
5502 | } | |||
5503 | if (Method->getMethodFamily() == OMF_dealloc) { | |||
5504 | S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs | |||
5505 | << 1; | |||
5506 | return; | |||
5507 | } | |||
5508 | ||||
5509 | D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(S.Context, Attrs)); | |||
5510 | } | |||
5511 | ||||
5512 | static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5513 | auto *E = AL.getArgAsExpr(0); | |||
5514 | auto Loc = E ? E->getBeginLoc() : AL.getLoc(); | |||
5515 | ||||
5516 | auto *DRE = dyn_cast<DeclRefExpr>(AL.getArgAsExpr(0)); | |||
5517 | if (!DRE) { | |||
5518 | S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0; | |||
5519 | return; | |||
5520 | } | |||
5521 | ||||
5522 | auto *VD = dyn_cast<VarDecl>(DRE->getDecl()); | |||
5523 | if (!VD) { | |||
5524 | S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 1 << DRE->getDecl(); | |||
5525 | return; | |||
5526 | } | |||
5527 | ||||
5528 | if (!isNSStringType(VD->getType(), S.Context) && | |||
5529 | !isCFStringType(VD->getType(), S.Context)) { | |||
5530 | S.Diag(Loc, diag::err_nserrordomain_wrong_type) << VD; | |||
5531 | return; | |||
5532 | } | |||
5533 | ||||
5534 | D->addAttr(::new (S.Context) NSErrorDomainAttr(S.Context, AL, VD)); | |||
5535 | } | |||
5536 | ||||
5537 | static void handleObjCBridgeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5538 | IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr; | |||
5539 | ||||
5540 | if (!Parm) { | |||
5541 | S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0; | |||
5542 | return; | |||
5543 | } | |||
5544 | ||||
5545 | // Typedefs only allow objc_bridge(id) and have some additional checking. | |||
5546 | if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) { | |||
5547 | if (!Parm->Ident->isStr("id")) { | |||
5548 | S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id) << AL; | |||
5549 | return; | |||
5550 | } | |||
5551 | ||||
5552 | // Only allow 'cv void *'. | |||
5553 | QualType T = TD->getUnderlyingType(); | |||
5554 | if (!T->isVoidPointerType()) { | |||
5555 | S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_void_pointer); | |||
5556 | return; | |||
5557 | } | |||
5558 | } | |||
5559 | ||||
5560 | D->addAttr(::new (S.Context) ObjCBridgeAttr(S.Context, AL, Parm->Ident)); | |||
5561 | } | |||
5562 | ||||
5563 | static void handleObjCBridgeMutableAttr(Sema &S, Decl *D, | |||
5564 | const ParsedAttr &AL) { | |||
5565 | IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr; | |||
5566 | ||||
5567 | if (!Parm) { | |||
5568 | S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0; | |||
5569 | return; | |||
5570 | } | |||
5571 | ||||
5572 | D->addAttr(::new (S.Context) | |||
5573 | ObjCBridgeMutableAttr(S.Context, AL, Parm->Ident)); | |||
5574 | } | |||
5575 | ||||
5576 | static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D, | |||
5577 | const ParsedAttr &AL) { | |||
5578 | IdentifierInfo *RelatedClass = | |||
5579 | AL.isArgIdent(0) ? AL.getArgAsIdent(0)->Ident : nullptr; | |||
5580 | if (!RelatedClass) { | |||
5581 | S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0; | |||
5582 | return; | |||
5583 | } | |||
5584 | IdentifierInfo *ClassMethod = | |||
5585 | AL.getArgAsIdent(1) ? AL.getArgAsIdent(1)->Ident : nullptr; | |||
5586 | IdentifierInfo *InstanceMethod = | |||
5587 | AL.getArgAsIdent(2) ? AL.getArgAsIdent(2)->Ident : nullptr; | |||
5588 | D->addAttr(::new (S.Context) ObjCBridgeRelatedAttr( | |||
5589 | S.Context, AL, RelatedClass, ClassMethod, InstanceMethod)); | |||
5590 | } | |||
5591 | ||||
5592 | static void handleObjCDesignatedInitializer(Sema &S, Decl *D, | |||
5593 | const ParsedAttr &AL) { | |||
5594 | DeclContext *Ctx = D->getDeclContext(); | |||
5595 | ||||
5596 | // This attribute can only be applied to methods in interfaces or class | |||
5597 | // extensions. | |||
5598 | if (!isa<ObjCInterfaceDecl>(Ctx) && | |||
5599 | !(isa<ObjCCategoryDecl>(Ctx) && | |||
5600 | cast<ObjCCategoryDecl>(Ctx)->IsClassExtension())) { | |||
5601 | S.Diag(D->getLocation(), diag::err_designated_init_attr_non_init); | |||
5602 | return; | |||
5603 | } | |||
5604 | ||||
5605 | ObjCInterfaceDecl *IFace; | |||
5606 | if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(Ctx)) | |||
5607 | IFace = CatDecl->getClassInterface(); | |||
5608 | else | |||
5609 | IFace = cast<ObjCInterfaceDecl>(Ctx); | |||
5610 | ||||
5611 | if (!IFace) | |||
5612 | return; | |||
5613 | ||||
5614 | IFace->setHasDesignatedInitializers(); | |||
5615 | D->addAttr(::new (S.Context) ObjCDesignatedInitializerAttr(S.Context, AL)); | |||
5616 | } | |||
5617 | ||||
5618 | static void handleObjCRuntimeName(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5619 | StringRef MetaDataName; | |||
5620 | if (!S.checkStringLiteralArgumentAttr(AL, 0, MetaDataName)) | |||
5621 | return; | |||
5622 | D->addAttr(::new (S.Context) | |||
5623 | ObjCRuntimeNameAttr(S.Context, AL, MetaDataName)); | |||
5624 | } | |||
5625 | ||||
5626 | // When a user wants to use objc_boxable with a union or struct | |||
5627 | // but they don't have access to the declaration (legacy/third-party code) | |||
5628 | // then they can 'enable' this feature with a typedef: | |||
5629 | // typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct; | |||
5630 | static void handleObjCBoxable(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5631 | bool notify = false; | |||
5632 | ||||
5633 | auto *RD = dyn_cast<RecordDecl>(D); | |||
5634 | if (RD && RD->getDefinition()) { | |||
5635 | RD = RD->getDefinition(); | |||
5636 | notify = true; | |||
5637 | } | |||
5638 | ||||
5639 | if (RD) { | |||
5640 | ObjCBoxableAttr *BoxableAttr = | |||
5641 | ::new (S.Context) ObjCBoxableAttr(S.Context, AL); | |||
5642 | RD->addAttr(BoxableAttr); | |||
5643 | if (notify) { | |||
5644 | // we need to notify ASTReader/ASTWriter about | |||
5645 | // modification of existing declaration | |||
5646 | if (ASTMutationListener *L = S.getASTMutationListener()) | |||
5647 | L->AddedAttributeToRecord(BoxableAttr, RD); | |||
5648 | } | |||
5649 | } | |||
5650 | } | |||
5651 | ||||
5652 | static void handleObjCOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5653 | if (hasDeclarator(D)) return; | |||
5654 | ||||
5655 | S.Diag(D->getBeginLoc(), diag::err_attribute_wrong_decl_type) | |||
5656 | << AL.getRange() << AL << ExpectedVariable; | |||
5657 | } | |||
5658 | ||||
5659 | static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, | |||
5660 | const ParsedAttr &AL) { | |||
5661 | const auto *VD = cast<ValueDecl>(D); | |||
5662 | QualType QT = VD->getType(); | |||
5663 | ||||
5664 | if (!QT->isDependentType() && | |||
5665 | !QT->isObjCLifetimeType()) { | |||
5666 | S.Diag(AL.getLoc(), diag::err_objc_precise_lifetime_bad_type) | |||
5667 | << QT; | |||
5668 | return; | |||
5669 | } | |||
5670 | ||||
5671 | Qualifiers::ObjCLifetime Lifetime = QT.getObjCLifetime(); | |||
5672 | ||||
5673 | // If we have no lifetime yet, check the lifetime we're presumably | |||
5674 | // going to infer. | |||
5675 | if (Lifetime == Qualifiers::OCL_None && !QT->isDependentType()) | |||
5676 | Lifetime = QT->getObjCARCImplicitLifetime(); | |||
5677 | ||||
5678 | switch (Lifetime) { | |||
5679 | case Qualifiers::OCL_None: | |||
5680 | 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~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 5681, __PRETTY_FUNCTION__)) | |||
5681 | "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~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 5681, __PRETTY_FUNCTION__)); | |||
5682 | break; | |||
5683 | ||||
5684 | case Qualifiers::OCL_Weak: // meaningful | |||
5685 | case Qualifiers::OCL_Strong: // meaningful | |||
5686 | break; | |||
5687 | ||||
5688 | case Qualifiers::OCL_ExplicitNone: | |||
5689 | case Qualifiers::OCL_Autoreleasing: | |||
5690 | S.Diag(AL.getLoc(), diag::warn_objc_precise_lifetime_meaningless) | |||
5691 | << (Lifetime == Qualifiers::OCL_Autoreleasing); | |||
5692 | break; | |||
5693 | } | |||
5694 | ||||
5695 | D->addAttr(::new (S.Context) ObjCPreciseLifetimeAttr(S.Context, AL)); | |||
5696 | } | |||
5697 | ||||
5698 | static void handleSwiftAttrAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5699 | // Make sure that there is a string literal as the annotation's single | |||
5700 | // argument. | |||
5701 | StringRef Str; | |||
5702 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) | |||
5703 | return; | |||
5704 | ||||
5705 | D->addAttr(::new (S.Context) SwiftAttrAttr(S.Context, AL, Str)); | |||
5706 | } | |||
5707 | ||||
5708 | static void handleSwiftBridge(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5709 | // Make sure that there is a string literal as the annotation's single | |||
5710 | // argument. | |||
5711 | StringRef BT; | |||
5712 | if (!S.checkStringLiteralArgumentAttr(AL, 0, BT)) | |||
5713 | return; | |||
5714 | ||||
5715 | // Warn about duplicate attributes if they have different arguments, but drop | |||
5716 | // any duplicate attributes regardless. | |||
5717 | if (const auto *Other = D->getAttr<SwiftBridgeAttr>()) { | |||
5718 | if (Other->getSwiftType() != BT) | |||
5719 | S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; | |||
5720 | return; | |||
5721 | } | |||
5722 | ||||
5723 | D->addAttr(::new (S.Context) SwiftBridgeAttr(S.Context, AL, BT)); | |||
5724 | } | |||
5725 | ||||
5726 | static bool isErrorParameter(Sema &S, QualType QT) { | |||
5727 | const auto *PT = QT->getAs<PointerType>(); | |||
5728 | if (!PT) | |||
5729 | return false; | |||
5730 | ||||
5731 | QualType Pointee = PT->getPointeeType(); | |||
5732 | ||||
5733 | // Check for NSError**. | |||
5734 | if (const auto *OPT = Pointee->getAs<ObjCObjectPointerType>()) | |||
5735 | if (const auto *ID = OPT->getInterfaceDecl()) | |||
5736 | if (ID->getIdentifier() == S.getNSErrorIdent()) | |||
5737 | return true; | |||
5738 | ||||
5739 | // Check for CFError**. | |||
5740 | if (const auto *PT = Pointee->getAs<PointerType>()) | |||
5741 | if (const auto *RT = PT->getPointeeType()->getAs<RecordType>()) | |||
5742 | if (S.isCFError(RT->getDecl())) | |||
5743 | return true; | |||
5744 | ||||
5745 | return false; | |||
5746 | } | |||
5747 | ||||
5748 | static void handleSwiftError(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5749 | auto hasErrorParameter = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool { | |||
5750 | for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) { | |||
5751 | if (isErrorParameter(S, getFunctionOrMethodParamType(D, I))) | |||
5752 | return true; | |||
5753 | } | |||
5754 | ||||
5755 | S.Diag(AL.getLoc(), diag::err_attr_swift_error_no_error_parameter) | |||
5756 | << AL << isa<ObjCMethodDecl>(D); | |||
5757 | return false; | |||
5758 | }; | |||
5759 | ||||
5760 | auto hasPointerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool { | |||
5761 | // - C, ObjC, and block pointers are definitely okay. | |||
5762 | // - References are definitely not okay. | |||
5763 | // - nullptr_t is weird, but acceptable. | |||
5764 | QualType RT = getFunctionOrMethodResultType(D); | |||
5765 | if (RT->hasPointerRepresentation() && !RT->isReferenceType()) | |||
5766 | return true; | |||
5767 | ||||
5768 | S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type) | |||
5769 | << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D) | |||
5770 | << /*pointer*/ 1; | |||
5771 | return false; | |||
5772 | }; | |||
5773 | ||||
5774 | auto hasIntegerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool { | |||
5775 | QualType RT = getFunctionOrMethodResultType(D); | |||
5776 | if (RT->isIntegralType(S.Context)) | |||
5777 | return true; | |||
5778 | ||||
5779 | S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type) | |||
5780 | << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D) | |||
5781 | << /*integral*/ 0; | |||
5782 | return false; | |||
5783 | }; | |||
5784 | ||||
5785 | if (D->isInvalidDecl()) | |||
5786 | return; | |||
5787 | ||||
5788 | IdentifierLoc *Loc = AL.getArgAsIdent(0); | |||
5789 | SwiftErrorAttr::ConventionKind Convention; | |||
5790 | if (!SwiftErrorAttr::ConvertStrToConventionKind(Loc->Ident->getName(), | |||
5791 | Convention)) { | |||
5792 | S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) | |||
5793 | << AL << Loc->Ident; | |||
5794 | return; | |||
5795 | } | |||
5796 | ||||
5797 | switch (Convention) { | |||
5798 | case SwiftErrorAttr::None: | |||
5799 | // No additional validation required. | |||
5800 | break; | |||
5801 | ||||
5802 | case SwiftErrorAttr::NonNullError: | |||
5803 | if (!hasErrorParameter(S, D, AL)) | |||
5804 | return; | |||
5805 | break; | |||
5806 | ||||
5807 | case SwiftErrorAttr::NullResult: | |||
5808 | if (!hasErrorParameter(S, D, AL) || !hasPointerResult(S, D, AL)) | |||
5809 | return; | |||
5810 | break; | |||
5811 | ||||
5812 | case SwiftErrorAttr::NonZeroResult: | |||
5813 | case SwiftErrorAttr::ZeroResult: | |||
5814 | if (!hasErrorParameter(S, D, AL) || !hasIntegerResult(S, D, AL)) | |||
5815 | return; | |||
5816 | break; | |||
5817 | } | |||
5818 | ||||
5819 | D->addAttr(::new (S.Context) SwiftErrorAttr(S.Context, AL, Convention)); | |||
5820 | } | |||
5821 | ||||
5822 | static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D, | |||
5823 | const SwiftAsyncErrorAttr *ErrorAttr, | |||
5824 | const SwiftAsyncAttr *AsyncAttr) { | |||
5825 | if (AsyncAttr->getKind() == SwiftAsyncAttr::None) { | |||
| ||||
5826 | if (ErrorAttr->getConvention() != SwiftAsyncErrorAttr::None) { | |||
5827 | S.Diag(AsyncAttr->getLocation(), | |||
5828 | diag::err_swift_async_error_without_swift_async) | |||
5829 | << AsyncAttr << isa<ObjCMethodDecl>(D); | |||
5830 | } | |||
5831 | return; | |||
5832 | } | |||
5833 | ||||
5834 | const ParmVarDecl *HandlerParam = getFunctionOrMethodParam( | |||
5835 | D, AsyncAttr->getCompletionHandlerIndex().getASTIndex()); | |||
5836 | // handleSwiftAsyncAttr already verified the type is correct, so no need to | |||
5837 | // double-check it here. | |||
5838 | const auto *FuncTy = HandlerParam->getType() | |||
| ||||
5839 | ->getAs<BlockPointerType>() | |||
5840 | ->getPointeeType() | |||
5841 | ->getAs<FunctionProtoType>(); | |||
5842 | ArrayRef<QualType> BlockParams; | |||
5843 | if (FuncTy) | |||
5844 | BlockParams = FuncTy->getParamTypes(); | |||
5845 | ||||
5846 | switch (ErrorAttr->getConvention()) { | |||
5847 | case SwiftAsyncErrorAttr::ZeroArgument: | |||
5848 | case SwiftAsyncErrorAttr::NonZeroArgument: { | |||
5849 | uint32_t ParamIdx = ErrorAttr->getHandlerParamIdx(); | |||
5850 | if (ParamIdx == 0 || ParamIdx > BlockParams.size()) { | |||
5851 | S.Diag(ErrorAttr->getLocation(), | |||
5852 | diag::err_attribute_argument_out_of_bounds) << ErrorAttr << 2; | |||
5853 | return; | |||
5854 | } | |||
5855 | QualType ErrorParam = BlockParams[ParamIdx - 1]; | |||
5856 | if (!ErrorParam->isIntegralType(S.Context)) { | |||
5857 | StringRef ConvStr = | |||
5858 | ErrorAttr->getConvention() == SwiftAsyncErrorAttr::ZeroArgument | |||
5859 | ? "zero_argument" | |||
5860 | : "nonzero_argument"; | |||
5861 | S.Diag(ErrorAttr->getLocation(), diag::err_swift_async_error_non_integral) | |||
5862 | << ErrorAttr << ConvStr << ParamIdx << ErrorParam; | |||
5863 | return; | |||
5864 | } | |||
5865 | break; | |||
5866 | } | |||
5867 | case SwiftAsyncErrorAttr::NonNullError: { | |||
5868 | bool AnyErrorParams = false; | |||
5869 | for (QualType Param : BlockParams) { | |||
5870 | // Check for NSError *. | |||
5871 | if (const auto *ObjCPtrTy = Param->getAs<ObjCObjectPointerType>()) { | |||
5872 | if (const auto *ID = ObjCPtrTy->getInterfaceDecl()) { | |||
5873 | if (ID->getIdentifier() == S.getNSErrorIdent()) { | |||
5874 | AnyErrorParams = true; | |||
5875 | break; | |||
5876 | } | |||
5877 | } | |||
5878 | } | |||
5879 | // Check for CFError *. | |||
5880 | if (const auto *PtrTy = Param->getAs<PointerType>()) { | |||
5881 | if (const auto *RT = PtrTy->getPointeeType()->getAs<RecordType>()) { | |||
5882 | if (S.isCFError(RT->getDecl())) { | |||
5883 | AnyErrorParams = true; | |||
5884 | break; | |||
5885 | } | |||
5886 | } | |||
5887 | } | |||
5888 | } | |||
5889 | ||||
5890 | if (!AnyErrorParams) { | |||
5891 | S.Diag(ErrorAttr->getLocation(), | |||
5892 | diag::err_swift_async_error_no_error_parameter) | |||
5893 | << ErrorAttr << isa<ObjCMethodDecl>(D); | |||
5894 | return; | |||
5895 | } | |||
5896 | break; | |||
5897 | } | |||
5898 | case SwiftAsyncErrorAttr::None: | |||
5899 | break; | |||
5900 | } | |||
5901 | } | |||
5902 | ||||
5903 | static void handleSwiftAsyncError(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
5904 | IdentifierLoc *IDLoc = AL.getArgAsIdent(0); | |||
5905 | SwiftAsyncErrorAttr::ConventionKind ConvKind; | |||
5906 | if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind(IDLoc->Ident->getName(), | |||
5907 | ConvKind)) { | |||
5908 | S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) | |||
5909 | << AL << IDLoc->Ident; | |||
5910 | return; | |||
5911 | } | |||
5912 | ||||
5913 | uint32_t ParamIdx = 0; | |||
5914 | switch (ConvKind) { | |||
5915 | case SwiftAsyncErrorAttr::ZeroArgument: | |||
5916 | case SwiftAsyncErrorAttr::NonZeroArgument: { | |||
5917 | if (!AL.checkExactlyNumArgs(S, 2)) | |||
5918 | return; | |||
5919 | ||||
5920 | Expr *IdxExpr = AL.getArgAsExpr(1); | |||
5921 | if (!checkUInt32Argument(S, AL, IdxExpr, ParamIdx)) | |||
5922 | return; | |||
5923 | break; | |||
5924 | } | |||
5925 | case SwiftAsyncErrorAttr::NonNullError: | |||
5926 | case SwiftAsyncErrorAttr::None: { | |||
5927 | if (!AL.checkExactlyNumArgs(S, 1)) | |||
5928 | return; | |||
5929 | break; | |||
5930 | } | |||
5931 | } | |||
5932 | ||||
5933 | auto *ErrorAttr = | |||
5934 | ::new (S.Context) SwiftAsyncErrorAttr(S.Context, AL, ConvKind, ParamIdx); | |||
5935 | D->addAttr(ErrorAttr); | |||
5936 | ||||
5937 | if (auto *AsyncAttr = D->getAttr<SwiftAsyncAttr>()) | |||
5938 | checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr); | |||
5939 | } | |||
5940 | ||||
5941 | // For a function, this will validate a compound Swift name, e.g. | |||
5942 | // <code>init(foo:bar:baz:)</code> or <code>controllerForName(_:)</code>, and | |||
5943 | // the function will output the number of parameter names, and whether this is a | |||
5944 | // single-arg initializer. | |||
5945 | // | |||
5946 | // For a type, enum constant, property, or variable declaration, this will | |||
5947 | // validate either a simple identifier, or a qualified | |||
5948 | // <code>context.identifier</code> name. | |||
5949 | static bool | |||
5950 | validateSwiftFunctionName(Sema &S, const ParsedAttr &AL, SourceLocation Loc, | |||
5951 | StringRef Name, unsigned &SwiftParamCount, | |||
5952 | bool &IsSingleParamInit) { | |||
5953 | SwiftParamCount = 0; | |||
5954 | IsSingleParamInit = false; | |||
5955 | ||||
5956 | // Check whether this will be mapped to a getter or setter of a property. | |||
5957 | bool IsGetter = false, IsSetter = false; | |||
5958 | if (Name.startswith("getter:")) { | |||
5959 | IsGetter = true; | |||
5960 | Name = Name.substr(7); | |||
5961 | } else if (Name.startswith("setter:")) { | |||
5962 | IsSetter = true; | |||
5963 | Name = Name.substr(7); | |||
5964 | } | |||
5965 | ||||
5966 | if (Name.back() != ')') { | |||
5967 | S.Diag(Loc, diag::warn_attr_swift_name_function) << AL; | |||
5968 | return false; | |||
5969 | } | |||
5970 | ||||
5971 | bool IsMember = false; | |||
5972 | StringRef ContextName, BaseName, Parameters; | |||
5973 | ||||
5974 | std::tie(BaseName, Parameters) = Name.split('('); | |||
5975 | ||||
5976 | // Split at the first '.', if it exists, which separates the context name | |||
5977 | // from the base name. | |||
5978 | std::tie(ContextName, BaseName) = BaseName.split('.'); | |||
5979 | if (BaseName.empty()) { | |||
5980 | BaseName = ContextName; | |||
5981 | ContextName = StringRef(); | |||
5982 | } else if (ContextName.empty() || !isValidIdentifier(ContextName)) { | |||
5983 | S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) | |||
5984 | << AL << /*context*/ 1; | |||
5985 | return false; | |||
5986 | } else { | |||
5987 | IsMember = true; | |||
5988 | } | |||
5989 | ||||
5990 | if (!isValidIdentifier(BaseName) || BaseName == "_") { | |||
5991 | S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) | |||
5992 | << AL << /*basename*/ 0; | |||
5993 | return false; | |||
5994 | } | |||
5995 | ||||
5996 | bool IsSubscript = BaseName == "subscript"; | |||
5997 | // A subscript accessor must be a getter or setter. | |||
5998 | if (IsSubscript && !IsGetter && !IsSetter) { | |||
5999 | S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter) | |||
6000 | << AL << /* getter or setter */ 0; | |||
6001 | return false; | |||
6002 | } | |||
6003 | ||||
6004 | if (Parameters.empty()) { | |||
6005 | S.Diag(Loc, diag::warn_attr_swift_name_missing_parameters) << AL; | |||
6006 | return false; | |||
6007 | } | |||
6008 | ||||
6009 | assert(Parameters.back() == ')' && "expected ')'")((Parameters.back() == ')' && "expected ')'") ? static_cast <void> (0) : __assert_fail ("Parameters.back() == ')' && \"expected ')'\"" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 6009, __PRETTY_FUNCTION__)); | |||
6010 | Parameters = Parameters.drop_back(); // ')' | |||
6011 | ||||
6012 | if (Parameters.empty()) { | |||
6013 | // Setters and subscripts must have at least one parameter. | |||
6014 | if (IsSubscript) { | |||
6015 | S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter) | |||
6016 | << AL << /* have at least one parameter */1; | |||
6017 | return false; | |||
6018 | } | |||
6019 | ||||
6020 | if (IsSetter) { | |||
6021 | S.Diag(Loc, diag::warn_attr_swift_name_setter_parameters) << AL; | |||
6022 | return false; | |||
6023 | } | |||
6024 | ||||
6025 | return true; | |||
6026 | } | |||
6027 | ||||
6028 | if (Parameters.back() != ':') { | |||
6029 | S.Diag(Loc, diag::warn_attr_swift_name_function) << AL; | |||
6030 | return false; | |||
6031 | } | |||
6032 | ||||
6033 | StringRef CurrentParam; | |||
6034 | llvm::Optional<unsigned> SelfLocation; | |||
6035 | unsigned NewValueCount = 0; | |||
6036 | llvm::Optional<unsigned> NewValueLocation; | |||
6037 | do { | |||
6038 | std::tie(CurrentParam, Parameters) = Parameters.split(':'); | |||
6039 | ||||
6040 | if (!isValidIdentifier(CurrentParam)) { | |||
6041 | S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) | |||
6042 | << AL << /*parameter*/2; | |||
6043 | return false; | |||
6044 | } | |||
6045 | ||||
6046 | if (IsMember && CurrentParam == "self") { | |||
6047 | // "self" indicates the "self" argument for a member. | |||
6048 | ||||
6049 | // More than one "self"? | |||
6050 | if (SelfLocation) { | |||
6051 | S.Diag(Loc, diag::warn_attr_swift_name_multiple_selfs) << AL; | |||
6052 | return false; | |||
6053 | } | |||
6054 | ||||
6055 | // The "self" location is the current parameter. | |||
6056 | SelfLocation = SwiftParamCount; | |||
6057 | } else if (CurrentParam == "newValue") { | |||
6058 | // "newValue" indicates the "newValue" argument for a setter. | |||
6059 | ||||
6060 | // There should only be one 'newValue', but it's only significant for | |||
6061 | // subscript accessors, so don't error right away. | |||
6062 | ++NewValueCount; | |||
6063 | ||||
6064 | NewValueLocation = SwiftParamCount; | |||
6065 | } | |||
6066 | ||||
6067 | ++SwiftParamCount; | |||
6068 | } while (!Parameters.empty()); | |||
6069 | ||||
6070 | // Only instance subscripts are currently supported. | |||
6071 | if (IsSubscript && !SelfLocation) { | |||
6072 | S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter) | |||
6073 | << AL << /*have a 'self:' parameter*/2; | |||
6074 | return false; | |||
6075 | } | |||
6076 | ||||
6077 | IsSingleParamInit = | |||
6078 | SwiftParamCount == 1 && BaseName == "init" && CurrentParam != "_"; | |||
6079 | ||||
6080 | // Check the number of parameters for a getter/setter. | |||
6081 | if (IsGetter || IsSetter) { | |||
6082 | // Setters have one parameter for the new value. | |||
6083 | unsigned NumExpectedParams = IsGetter ? 0 : 1; | |||
6084 | unsigned ParamDiag = | |||
6085 | IsGetter ? diag::warn_attr_swift_name_getter_parameters | |||
6086 | : diag::warn_attr_swift_name_setter_parameters; | |||
6087 | ||||
6088 | // Instance methods have one parameter for "self". | |||
6089 | if (SelfLocation) | |||
6090 | ++NumExpectedParams; | |||
6091 | ||||
6092 | // Subscripts may have additional parameters beyond the expected params for | |||
6093 | // the index. | |||
6094 | if (IsSubscript) { | |||
6095 | if (SwiftParamCount < NumExpectedParams) { | |||
6096 | S.Diag(Loc, ParamDiag) << AL; | |||
6097 | return false; | |||
6098 | } | |||
6099 | ||||
6100 | // A subscript setter must explicitly label its newValue parameter to | |||
6101 | // distinguish it from index parameters. | |||
6102 | if (IsSetter) { | |||
6103 | if (!NewValueLocation) { | |||
6104 | S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_no_newValue) | |||
6105 | << AL; | |||
6106 | return false; | |||
6107 | } | |||
6108 | if (NewValueCount > 1) { | |||
6109 | S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_multiple_newValues) | |||
6110 | << AL; | |||
6111 | return false; | |||
6112 | } | |||
6113 | } else { | |||
6114 | // Subscript getters should have no 'newValue:' parameter. | |||
6115 | if (NewValueLocation) { | |||
6116 | S.Diag(Loc, diag::warn_attr_swift_name_subscript_getter_newValue) | |||
6117 | << AL; | |||
6118 | return false; | |||
6119 | } | |||
6120 | } | |||
6121 | } else { | |||
6122 | // Property accessors must have exactly the number of expected params. | |||
6123 | if (SwiftParamCount != NumExpectedParams) { | |||
6124 | S.Diag(Loc, ParamDiag) << AL; | |||
6125 | return false; | |||
6126 | } | |||
6127 | } | |||
6128 | } | |||
6129 | ||||
6130 | return true; | |||
6131 | } | |||
6132 | ||||
6133 | bool Sema::DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc, | |||
6134 | const ParsedAttr &AL, bool IsAsync) { | |||
6135 | if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) { | |||
6136 | ArrayRef<ParmVarDecl*> Params; | |||
6137 | unsigned ParamCount; | |||
6138 | ||||
6139 | if (const auto *Method = dyn_cast<ObjCMethodDecl>(D)) { | |||
6140 | ParamCount = Method->getSelector().getNumArgs(); | |||
6141 | Params = Method->parameters().slice(0, ParamCount); | |||
6142 | } else { | |||
6143 | const auto *F = cast<FunctionDecl>(D); | |||
6144 | ||||
6145 | ParamCount = F->getNumParams(); | |||
6146 | Params = F->parameters(); | |||
6147 | ||||
6148 | if (!F->hasWrittenPrototype()) { | |||
6149 | Diag(Loc, diag::warn_attribute_wrong_decl_type) << AL | |||
6150 | << ExpectedFunctionWithProtoType; | |||
6151 | return false; | |||
6152 | } | |||
6153 | } | |||
6154 | ||||
6155 | // The async name drops the last callback parameter. | |||
6156 | if (IsAsync) { | |||
6157 | if (ParamCount == 0) { | |||
6158 | Diag(Loc, diag::warn_attr_swift_name_decl_missing_params) | |||
6159 | << AL << isa<ObjCMethodDecl>(D); | |||
6160 | return false; | |||
6161 | } | |||
6162 | ParamCount -= 1; | |||
6163 | } | |||
6164 | ||||
6165 | unsigned SwiftParamCount; | |||
6166 | bool IsSingleParamInit; | |||
6167 | if (!validateSwiftFunctionName(*this, AL, Loc, Name, | |||
6168 | SwiftParamCount, IsSingleParamInit)) | |||
6169 | return false; | |||
6170 | ||||
6171 | bool ParamCountValid; | |||
6172 | if (SwiftParamCount == ParamCount) { | |||
6173 | ParamCountValid = true; | |||
6174 | } else if (SwiftParamCount > ParamCount) { | |||
6175 | ParamCountValid = IsSingleParamInit && ParamCount == 0; | |||
6176 | } else { | |||
6177 | // We have fewer Swift parameters than Objective-C parameters, but that | |||
6178 | // might be because we've transformed some of them. Check for potential | |||
6179 | // "out" parameters and err on the side of not warning. | |||
6180 | unsigned MaybeOutParamCount = | |||
6181 | std::count_if(Params.begin(), Params.end(), | |||
6182 | [](const ParmVarDecl *Param) -> bool { | |||
6183 | QualType ParamTy = Param->getType(); | |||
6184 | if (ParamTy->isReferenceType() || ParamTy->isPointerType()) | |||
6185 | return !ParamTy->getPointeeType().isConstQualified(); | |||
6186 | return false; | |||
6187 | }); | |||
6188 | ||||
6189 | ParamCountValid = SwiftParamCount + MaybeOutParamCount >= ParamCount; | |||
6190 | } | |||
6191 | ||||
6192 | if (!ParamCountValid) { | |||
6193 | Diag(Loc, diag::warn_attr_swift_name_num_params) | |||
6194 | << (SwiftParamCount > ParamCount) << AL << ParamCount | |||
6195 | << SwiftParamCount; | |||
6196 | return false; | |||
6197 | } | |||
6198 | } else if ((isa<EnumConstantDecl>(D) || isa<ObjCProtocolDecl>(D) || | |||
6199 | isa<ObjCInterfaceDecl>(D) || isa<ObjCPropertyDecl>(D) || | |||
6200 | isa<VarDecl>(D) || isa<TypedefNameDecl>(D) || isa<TagDecl>(D) || | |||
6201 | isa<IndirectFieldDecl>(D) || isa<FieldDecl>(D)) && | |||
6202 | !IsAsync) { | |||
6203 | StringRef ContextName, BaseName; | |||
6204 | ||||
6205 | std::tie(ContextName, BaseName) = Name.split('.'); | |||
6206 | if (BaseName.empty()) { | |||
6207 | BaseName = ContextName; | |||
6208 | ContextName = StringRef(); | |||
6209 | } else if (!isValidIdentifier(ContextName)) { | |||
6210 | Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) << AL | |||
6211 | << /*context*/1; | |||
6212 | return false; | |||
6213 | } | |||
6214 | ||||
6215 | if (!isValidIdentifier(BaseName)) { | |||
6216 | Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) << AL | |||
6217 | << /*basename*/0; | |||
6218 | return false; | |||
6219 | } | |||
6220 | } else { | |||
6221 | Diag(Loc, diag::warn_attr_swift_name_decl_kind) << AL; | |||
6222 | return false; | |||
6223 | } | |||
6224 | return true; | |||
6225 | } | |||
6226 | ||||
6227 | static void handleSwiftName(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6228 | StringRef Name; | |||
6229 | SourceLocation Loc; | |||
6230 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc)) | |||
6231 | return; | |||
6232 | ||||
6233 | if (!S.DiagnoseSwiftName(D, Name, Loc, AL, /*IsAsync=*/false)) | |||
6234 | return; | |||
6235 | ||||
6236 | D->addAttr(::new (S.Context) SwiftNameAttr(S.Context, AL, Name)); | |||
6237 | } | |||
6238 | ||||
6239 | static void handleSwiftAsyncName(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6240 | StringRef Name; | |||
6241 | SourceLocation Loc; | |||
6242 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc)) | |||
6243 | return; | |||
6244 | ||||
6245 | if (!S.DiagnoseSwiftName(D, Name, Loc, AL, /*IsAsync=*/true)) | |||
6246 | return; | |||
6247 | ||||
6248 | D->addAttr(::new (S.Context) SwiftAsyncNameAttr(S.Context, AL, Name)); | |||
6249 | } | |||
6250 | ||||
6251 | static void handleSwiftNewType(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6252 | // Make sure that there is an identifier as the annotation's single argument. | |||
6253 | if (!AL.checkExactlyNumArgs(S, 1)) | |||
6254 | return; | |||
6255 | ||||
6256 | if (!AL.isArgIdent(0)) { | |||
6257 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
6258 | << AL << AANT_ArgumentIdentifier; | |||
6259 | return; | |||
6260 | } | |||
6261 | ||||
6262 | SwiftNewTypeAttr::NewtypeKind Kind; | |||
6263 | IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; | |||
6264 | if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) { | |||
6265 | S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; | |||
6266 | return; | |||
6267 | } | |||
6268 | ||||
6269 | if (!isa<TypedefNameDecl>(D)) { | |||
6270 | S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str) | |||
6271 | << AL << "typedefs"; | |||
6272 | return; | |||
6273 | } | |||
6274 | ||||
6275 | D->addAttr(::new (S.Context) SwiftNewTypeAttr(S.Context, AL, Kind)); | |||
6276 | } | |||
6277 | ||||
6278 | static void handleSwiftAsyncAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6279 | if (!AL.isArgIdent(0)) { | |||
6280 | S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) | |||
6281 | << AL << 1 << AANT_ArgumentIdentifier; | |||
6282 | return; | |||
6283 | } | |||
6284 | ||||
6285 | SwiftAsyncAttr::Kind Kind; | |||
6286 | IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; | |||
6287 | if (!SwiftAsyncAttr::ConvertStrToKind(II->getName(), Kind)) { | |||
6288 | S.Diag(AL.getLoc(), diag::err_swift_async_no_access) << AL << II; | |||
6289 | return; | |||
6290 | } | |||
6291 | ||||
6292 | ParamIdx Idx; | |||
6293 | if (Kind == SwiftAsyncAttr::None) { | |||
6294 | // If this is 'none', then there shouldn't be any additional arguments. | |||
6295 | if (!AL.checkExactlyNumArgs(S, 1)) | |||
6296 | return; | |||
6297 | } else { | |||
6298 | // Non-none swift_async requires a completion handler index argument. | |||
6299 | if (!AL.checkExactlyNumArgs(S, 2)) | |||
6300 | return; | |||
6301 | ||||
6302 | Expr *HandlerIdx = AL.getArgAsExpr(1); | |||
6303 | if (!checkFunctionOrMethodParameterIndex(S, D, AL, 2, HandlerIdx, Idx)) | |||
6304 | return; | |||
6305 | ||||
6306 | const ParmVarDecl *CompletionBlock = | |||
6307 | getFunctionOrMethodParam(D, Idx.getASTIndex()); | |||
6308 | QualType CompletionBlockType = CompletionBlock->getType(); | |||
6309 | if (!CompletionBlockType->isBlockPointerType()) { | |||
6310 | S.Diag(CompletionBlock->getLocation(), | |||
6311 | diag::err_swift_async_bad_block_type) | |||
6312 | << CompletionBlock->getType(); | |||
6313 | return; | |||
6314 | } | |||
6315 | QualType BlockTy = | |||
6316 | CompletionBlockType->getAs<BlockPointerType>()->getPointeeType(); | |||
6317 | if (!BlockTy->getAs<FunctionType>()->getReturnType()->isVoidType()) { | |||
6318 | S.Diag(CompletionBlock->getLocation(), | |||
6319 | diag::err_swift_async_bad_block_type) | |||
6320 | << CompletionBlock->getType(); | |||
6321 | return; | |||
6322 | } | |||
6323 | } | |||
6324 | ||||
6325 | auto *AsyncAttr = | |||
6326 | ::new (S.Context) SwiftAsyncAttr(S.Context, AL, Kind, Idx); | |||
6327 | D->addAttr(AsyncAttr); | |||
6328 | ||||
6329 | if (auto *ErrorAttr = D->getAttr<SwiftAsyncErrorAttr>()) | |||
6330 | checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr); | |||
6331 | } | |||
6332 | ||||
6333 | //===----------------------------------------------------------------------===// | |||
6334 | // Microsoft specific attribute handlers. | |||
6335 | //===----------------------------------------------------------------------===// | |||
6336 | ||||
6337 | UuidAttr *Sema::mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI, | |||
6338 | StringRef UuidAsWritten, MSGuidDecl *GuidDecl) { | |||
6339 | if (const auto *UA = D->getAttr<UuidAttr>()) { | |||
6340 | if (declaresSameEntity(UA->getGuidDecl(), GuidDecl)) | |||
6341 | return nullptr; | |||
6342 | if (!UA->getGuid().empty()) { | |||
6343 | Diag(UA->getLocation(), diag::err_mismatched_uuid); | |||
6344 | Diag(CI.getLoc(), diag::note_previous_uuid); | |||
6345 | D->dropAttr<UuidAttr>(); | |||
6346 | } | |||
6347 | } | |||
6348 | ||||
6349 | return ::new (Context) UuidAttr(Context, CI, UuidAsWritten, GuidDecl); | |||
6350 | } | |||
6351 | ||||
6352 | static void handleUuidAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6353 | if (!S.LangOpts.CPlusPlus) { | |||
6354 | S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) | |||
6355 | << AL << AttributeLangSupport::C; | |||
6356 | return; | |||
6357 | } | |||
6358 | ||||
6359 | StringRef OrigStrRef; | |||
6360 | SourceLocation LiteralLoc; | |||
6361 | if (!S.checkStringLiteralArgumentAttr(AL, 0, OrigStrRef, &LiteralLoc)) | |||
6362 | return; | |||
6363 | ||||
6364 | // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or | |||
6365 | // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}", normalize to the former. | |||
6366 | StringRef StrRef = OrigStrRef; | |||
6367 | if (StrRef.size() == 38 && StrRef.front() == '{' && StrRef.back() == '}') | |||
6368 | StrRef = StrRef.drop_front().drop_back(); | |||
6369 | ||||
6370 | // Validate GUID length. | |||
6371 | if (StrRef.size() != 36) { | |||
6372 | S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); | |||
6373 | return; | |||
6374 | } | |||
6375 | ||||
6376 | for (unsigned i = 0; i < 36; ++i) { | |||
6377 | if (i == 8 || i == 13 || i == 18 || i == 23) { | |||
6378 | if (StrRef[i] != '-') { | |||
6379 | S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); | |||
6380 | return; | |||
6381 | } | |||
6382 | } else if (!isHexDigit(StrRef[i])) { | |||
6383 | S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); | |||
6384 | return; | |||
6385 | } | |||
6386 | } | |||
6387 | ||||
6388 | // Convert to our parsed format and canonicalize. | |||
6389 | MSGuidDecl::Parts Parsed; | |||
6390 | StrRef.substr(0, 8).getAsInteger(16, Parsed.Part1); | |||
6391 | StrRef.substr(9, 4).getAsInteger(16, Parsed.Part2); | |||
6392 | StrRef.substr(14, 4).getAsInteger(16, Parsed.Part3); | |||
6393 | for (unsigned i = 0; i != 8; ++i) | |||
6394 | StrRef.substr(19 + 2 * i + (i >= 2 ? 1 : 0), 2) | |||
6395 | .getAsInteger(16, Parsed.Part4And5[i]); | |||
6396 | MSGuidDecl *Guid = S.Context.getMSGuidDecl(Parsed); | |||
6397 | ||||
6398 | // FIXME: It'd be nice to also emit a fixit removing uuid(...) (and, if it's | |||
6399 | // the only thing in the [] list, the [] too), and add an insertion of | |||
6400 | // __declspec(uuid(...)). But sadly, neither the SourceLocs of the commas | |||
6401 | // separating attributes nor of the [ and the ] are in the AST. | |||
6402 | // Cf "SourceLocations of attribute list delimiters - [[ ... , ... ]] etc" | |||
6403 | // on cfe-dev. | |||
6404 | if (AL.isMicrosoftAttribute()) // Check for [uuid(...)] spelling. | |||
6405 | S.Diag(AL.getLoc(), diag::warn_atl_uuid_deprecated); | |||
6406 | ||||
6407 | UuidAttr *UA = S.mergeUuidAttr(D, AL, OrigStrRef, Guid); | |||
6408 | if (UA) | |||
6409 | D->addAttr(UA); | |||
6410 | } | |||
6411 | ||||
6412 | static void handleMSInheritanceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6413 | if (!S.LangOpts.CPlusPlus) { | |||
6414 | S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) | |||
6415 | << AL << AttributeLangSupport::C; | |||
6416 | return; | |||
6417 | } | |||
6418 | MSInheritanceAttr *IA = S.mergeMSInheritanceAttr( | |||
6419 | D, AL, /*BestCase=*/true, (MSInheritanceModel)AL.getSemanticSpelling()); | |||
6420 | if (IA) { | |||
6421 | D->addAttr(IA); | |||
6422 | S.Consumer.AssignInheritanceModel(cast<CXXRecordDecl>(D)); | |||
6423 | } | |||
6424 | } | |||
6425 | ||||
6426 | static void handleDeclspecThreadAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6427 | const auto *VD = cast<VarDecl>(D); | |||
6428 | if (!S.Context.getTargetInfo().isTLSSupported()) { | |||
6429 | S.Diag(AL.getLoc(), diag::err_thread_unsupported); | |||
6430 | return; | |||
6431 | } | |||
6432 | if (VD->getTSCSpec() != TSCS_unspecified) { | |||
6433 | S.Diag(AL.getLoc(), diag::err_declspec_thread_on_thread_variable); | |||
6434 | return; | |||
6435 | } | |||
6436 | if (VD->hasLocalStorage()) { | |||
6437 | S.Diag(AL.getLoc(), diag::err_thread_non_global) << "__declspec(thread)"; | |||
6438 | return; | |||
6439 | } | |||
6440 | D->addAttr(::new (S.Context) ThreadAttr(S.Context, AL)); | |||
6441 | } | |||
6442 | ||||
6443 | static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6444 | SmallVector<StringRef, 4> Tags; | |||
6445 | for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { | |||
6446 | StringRef Tag; | |||
6447 | if (!S.checkStringLiteralArgumentAttr(AL, I, Tag)) | |||
6448 | return; | |||
6449 | Tags.push_back(Tag); | |||
6450 | } | |||
6451 | ||||
6452 | if (const auto *NS = dyn_cast<NamespaceDecl>(D)) { | |||
6453 | if (!NS->isInline()) { | |||
6454 | S.Diag(AL.getLoc(), diag::warn_attr_abi_tag_namespace) << 0; | |||
6455 | return; | |||
6456 | } | |||
6457 | if (NS->isAnonymousNamespace()) { | |||
6458 | S.Diag(AL.getLoc(), diag::warn_attr_abi_tag_namespace) << 1; | |||
6459 | return; | |||
6460 | } | |||
6461 | if (AL.getNumArgs() == 0) | |||
6462 | Tags.push_back(NS->getName()); | |||
6463 | } else if (!AL.checkAtLeastNumArgs(S, 1)) | |||
6464 | return; | |||
6465 | ||||
6466 | // Store tags sorted and without duplicates. | |||
6467 | llvm::sort(Tags); | |||
6468 | Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end()); | |||
6469 | ||||
6470 | D->addAttr(::new (S.Context) | |||
6471 | AbiTagAttr(S.Context, AL, Tags.data(), Tags.size())); | |||
6472 | } | |||
6473 | ||||
6474 | static void handleARMInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6475 | // Check the attribute arguments. | |||
6476 | if (AL.getNumArgs() > 1) { | |||
6477 | S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1; | |||
6478 | return; | |||
6479 | } | |||
6480 | ||||
6481 | StringRef Str; | |||
6482 | SourceLocation ArgLoc; | |||
6483 | ||||
6484 | if (AL.getNumArgs() == 0) | |||
6485 | Str = ""; | |||
6486 | else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc)) | |||
6487 | return; | |||
6488 | ||||
6489 | ARMInterruptAttr::InterruptType Kind; | |||
6490 | if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) { | |||
6491 | S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << Str | |||
6492 | << ArgLoc; | |||
6493 | return; | |||
6494 | } | |||
6495 | ||||
6496 | D->addAttr(::new (S.Context) ARMInterruptAttr(S.Context, AL, Kind)); | |||
6497 | } | |||
6498 | ||||
6499 | static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6500 | // MSP430 'interrupt' attribute is applied to | |||
6501 | // a function with no parameters and void return type. | |||
6502 | if (!isFunctionOrMethod(D)) { | |||
6503 | S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) | |||
6504 | << "'interrupt'" << ExpectedFunctionOrMethod; | |||
6505 | return; | |||
6506 | } | |||
6507 | ||||
6508 | if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) { | |||
6509 | S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid) | |||
6510 | << /*MSP430*/ 1 << 0; | |||
6511 | return; | |||
6512 | } | |||
6513 | ||||
6514 | if (!getFunctionOrMethodResultType(D)->isVoidType()) { | |||
6515 | S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid) | |||
6516 | << /*MSP430*/ 1 << 1; | |||
6517 | return; | |||
6518 | } | |||
6519 | ||||
6520 | // The attribute takes one integer argument. | |||
6521 | if (!AL.checkExactlyNumArgs(S, 1)) | |||
6522 | return; | |||
6523 | ||||
6524 | if (!AL.isArgExpr(0)) { | |||
6525 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
6526 | << AL << AANT_ArgumentIntegerConstant; | |||
6527 | return; | |||
6528 | } | |||
6529 | ||||
6530 | Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0)); | |||
6531 | Optional<llvm::APSInt> NumParams = llvm::APSInt(32); | |||
6532 | if (!(NumParams = NumParamsExpr->getIntegerConstantExpr(S.Context))) { | |||
6533 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
6534 | << AL << AANT_ArgumentIntegerConstant | |||
6535 | << NumParamsExpr->getSourceRange(); | |||
6536 | return; | |||
6537 | } | |||
6538 | // The argument should be in range 0..63. | |||
6539 | unsigned Num = NumParams->getLimitedValue(255); | |||
6540 | if (Num > 63) { | |||
6541 | S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) | |||
6542 | << AL << (int)NumParams->getSExtValue() | |||
6543 | << NumParamsExpr->getSourceRange(); | |||
6544 | return; | |||
6545 | } | |||
6546 | ||||
6547 | D->addAttr(::new (S.Context) MSP430InterruptAttr(S.Context, AL, Num)); | |||
6548 | D->addAttr(UsedAttr::CreateImplicit(S.Context)); | |||
6549 | } | |||
6550 | ||||
6551 | static void handleMipsInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6552 | // Only one optional argument permitted. | |||
6553 | if (AL.getNumArgs() > 1) { | |||
6554 | S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1; | |||
6555 | return; | |||
6556 | } | |||
6557 | ||||
6558 | StringRef Str; | |||
6559 | SourceLocation ArgLoc; | |||
6560 | ||||
6561 | if (AL.getNumArgs() == 0) | |||
6562 | Str = ""; | |||
6563 | else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc)) | |||
6564 | return; | |||
6565 | ||||
6566 | // Semantic checks for a function with the 'interrupt' attribute for MIPS: | |||
6567 | // a) Must be a function. | |||
6568 | // b) Must have no parameters. | |||
6569 | // c) Must have the 'void' return type. | |||
6570 | // d) Cannot have the 'mips16' attribute, as that instruction set | |||
6571 | // lacks the 'eret' instruction. | |||
6572 | // e) The attribute itself must either have no argument or one of the | |||
6573 | // valid interrupt types, see [MipsInterruptDocs]. | |||
6574 | ||||
6575 | if (!isFunctionOrMethod(D)) { | |||
6576 | S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) | |||
6577 | << "'interrupt'" << ExpectedFunctionOrMethod; | |||
6578 | return; | |||
6579 | } | |||
6580 | ||||
6581 | if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) { | |||
6582 | S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid) | |||
6583 | << /*MIPS*/ 0 << 0; | |||
6584 | return; | |||
6585 | } | |||
6586 | ||||
6587 | if (!getFunctionOrMethodResultType(D)->isVoidType()) { | |||
6588 | S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid) | |||
6589 | << /*MIPS*/ 0 << 1; | |||
6590 | return; | |||
6591 | } | |||
6592 | ||||
6593 | if (checkAttrMutualExclusion<Mips16Attr>(S, D, AL)) | |||
6594 | return; | |||
6595 | ||||
6596 | MipsInterruptAttr::InterruptType Kind; | |||
6597 | if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) { | |||
6598 | S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) | |||
6599 | << AL << "'" + std::string(Str) + "'"; | |||
6600 | return; | |||
6601 | } | |||
6602 | ||||
6603 | D->addAttr(::new (S.Context) MipsInterruptAttr(S.Context, AL, Kind)); | |||
6604 | } | |||
6605 | ||||
6606 | static void handleM68kInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6607 | if (!AL.checkExactlyNumArgs(S, 1)) | |||
6608 | return; | |||
6609 | ||||
6610 | if (!AL.isArgExpr(0)) { | |||
6611 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
6612 | << AL << AANT_ArgumentIntegerConstant; | |||
6613 | return; | |||
6614 | } | |||
6615 | ||||
6616 | // FIXME: Check for decl - it should be void ()(void). | |||
6617 | ||||
6618 | Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0)); | |||
6619 | auto MaybeNumParams = NumParamsExpr->getIntegerConstantExpr(S.Context); | |||
6620 | if (!MaybeNumParams) { | |||
6621 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
6622 | << AL << AANT_ArgumentIntegerConstant | |||
6623 | << NumParamsExpr->getSourceRange(); | |||
6624 | return; | |||
6625 | } | |||
6626 | ||||
6627 | unsigned Num = MaybeNumParams->getLimitedValue(255); | |||
6628 | if ((Num & 1) || Num > 30) { | |||
6629 | S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) | |||
6630 | << AL << (int)MaybeNumParams->getSExtValue() | |||
6631 | << NumParamsExpr->getSourceRange(); | |||
6632 | return; | |||
6633 | } | |||
6634 | ||||
6635 | D->addAttr(::new (S.Context) M68kInterruptAttr(S.Context, AL, Num)); | |||
6636 | D->addAttr(UsedAttr::CreateImplicit(S.Context)); | |||
6637 | } | |||
6638 | ||||
6639 | static void handleAnyX86InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6640 | // Semantic checks for a function with the 'interrupt' attribute. | |||
6641 | // a) Must be a function. | |||
6642 | // b) Must have the 'void' return type. | |||
6643 | // c) Must take 1 or 2 arguments. | |||
6644 | // d) The 1st argument must be a pointer. | |||
6645 | // e) The 2nd argument (if any) must be an unsigned integer. | |||
6646 | if (!isFunctionOrMethod(D) || !hasFunctionProto(D) || isInstanceMethod(D) || | |||
6647 | CXXMethodDecl::isStaticOverloadedOperator( | |||
6648 | cast<NamedDecl>(D)->getDeclName().getCXXOverloadedOperator())) { | |||
6649 | S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) | |||
6650 | << AL << ExpectedFunctionWithProtoType; | |||
6651 | return; | |||
6652 | } | |||
6653 | // Interrupt handler must have void return type. | |||
6654 | if (!getFunctionOrMethodResultType(D)->isVoidType()) { | |||
6655 | S.Diag(getFunctionOrMethodResultSourceRange(D).getBegin(), | |||
6656 | diag::err_anyx86_interrupt_attribute) | |||
6657 | << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86 | |||
6658 | ? 0 | |||
6659 | : 1) | |||
6660 | << 0; | |||
6661 | return; | |||
6662 | } | |||
6663 | // Interrupt handler must have 1 or 2 parameters. | |||
6664 | unsigned NumParams = getFunctionOrMethodNumParams(D); | |||
6665 | if (NumParams < 1 || NumParams > 2) { | |||
6666 | S.Diag(D->getBeginLoc(), diag::err_anyx86_interrupt_attribute) | |||
6667 | << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86 | |||
6668 | ? 0 | |||
6669 | : 1) | |||
6670 | << 1; | |||
6671 | return; | |||
6672 | } | |||
6673 | // The first argument must be a pointer. | |||
6674 | if (!getFunctionOrMethodParamType(D, 0)->isPointerType()) { | |||
6675 | S.Diag(getFunctionOrMethodParamRange(D, 0).getBegin(), | |||
6676 | diag::err_anyx86_interrupt_attribute) | |||
6677 | << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86 | |||
6678 | ? 0 | |||
6679 | : 1) | |||
6680 | << 2; | |||
6681 | return; | |||
6682 | } | |||
6683 | // The second argument, if present, must be an unsigned integer. | |||
6684 | unsigned TypeSize = | |||
6685 | S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86_64 | |||
6686 | ? 64 | |||
6687 | : 32; | |||
6688 | if (NumParams == 2 && | |||
6689 | (!getFunctionOrMethodParamType(D, 1)->isUnsignedIntegerType() || | |||
6690 | S.Context.getTypeSize(getFunctionOrMethodParamType(D, 1)) != TypeSize)) { | |||
6691 | S.Diag(getFunctionOrMethodParamRange(D, 1).getBegin(), | |||
6692 | diag::err_anyx86_interrupt_attribute) | |||
6693 | << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86 | |||
6694 | ? 0 | |||
6695 | : 1) | |||
6696 | << 3 << S.Context.getIntTypeForBitwidth(TypeSize, /*Signed=*/false); | |||
6697 | return; | |||
6698 | } | |||
6699 | D->addAttr(::new (S.Context) AnyX86InterruptAttr(S.Context, AL)); | |||
6700 | D->addAttr(UsedAttr::CreateImplicit(S.Context)); | |||
6701 | } | |||
6702 | ||||
6703 | static void handleAVRInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6704 | if (!isFunctionOrMethod(D)) { | |||
6705 | S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) | |||
6706 | << "'interrupt'" << ExpectedFunction; | |||
6707 | return; | |||
6708 | } | |||
6709 | ||||
6710 | if (!AL.checkExactlyNumArgs(S, 0)) | |||
6711 | return; | |||
6712 | ||||
6713 | handleSimpleAttribute<AVRInterruptAttr>(S, D, AL); | |||
6714 | } | |||
6715 | ||||
6716 | static void handleAVRSignalAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6717 | if (!isFunctionOrMethod(D)) { | |||
6718 | S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) | |||
6719 | << "'signal'" << ExpectedFunction; | |||
6720 | return; | |||
6721 | } | |||
6722 | ||||
6723 | if (!AL.checkExactlyNumArgs(S, 0)) | |||
6724 | return; | |||
6725 | ||||
6726 | handleSimpleAttribute<AVRSignalAttr>(S, D, AL); | |||
6727 | } | |||
6728 | ||||
6729 | static void handleBPFPreserveAIRecord(Sema &S, RecordDecl *RD) { | |||
6730 | // Add preserve_access_index attribute to all fields and inner records. | |||
6731 | for (auto D : RD->decls()) { | |||
6732 | if (D->hasAttr<BPFPreserveAccessIndexAttr>()) | |||
6733 | continue; | |||
6734 | ||||
6735 | D->addAttr(BPFPreserveAccessIndexAttr::CreateImplicit(S.Context)); | |||
6736 | if (auto *Rec = dyn_cast<RecordDecl>(D)) | |||
6737 | handleBPFPreserveAIRecord(S, Rec); | |||
6738 | } | |||
6739 | } | |||
6740 | ||||
6741 | static void handleBPFPreserveAccessIndexAttr(Sema &S, Decl *D, | |||
6742 | const ParsedAttr &AL) { | |||
6743 | auto *Rec = cast<RecordDecl>(D); | |||
6744 | handleBPFPreserveAIRecord(S, Rec); | |||
6745 | Rec->addAttr(::new (S.Context) BPFPreserveAccessIndexAttr(S.Context, AL)); | |||
6746 | } | |||
6747 | ||||
6748 | static void handleWebAssemblyExportNameAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6749 | if (!isFunctionOrMethod(D)) { | |||
6750 | S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) | |||
6751 | << "'export_name'" << ExpectedFunction; | |||
6752 | return; | |||
6753 | } | |||
6754 | ||||
6755 | auto *FD = cast<FunctionDecl>(D); | |||
6756 | if (FD->isThisDeclarationADefinition()) { | |||
6757 | S.Diag(D->getLocation(), diag::err_alias_is_definition) << FD << 0; | |||
6758 | return; | |||
6759 | } | |||
6760 | ||||
6761 | StringRef Str; | |||
6762 | SourceLocation ArgLoc; | |||
6763 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc)) | |||
6764 | return; | |||
6765 | ||||
6766 | D->addAttr(::new (S.Context) WebAssemblyExportNameAttr(S.Context, AL, Str)); | |||
6767 | D->addAttr(UsedAttr::CreateImplicit(S.Context)); | |||
6768 | } | |||
6769 | ||||
6770 | WebAssemblyImportModuleAttr * | |||
6771 | Sema::mergeImportModuleAttr(Decl *D, const WebAssemblyImportModuleAttr &AL) { | |||
6772 | auto *FD = cast<FunctionDecl>(D); | |||
6773 | ||||
6774 | if (const auto *ExistingAttr = FD->getAttr<WebAssemblyImportModuleAttr>()) { | |||
6775 | if (ExistingAttr->getImportModule() == AL.getImportModule()) | |||
6776 | return nullptr; | |||
6777 | Diag(ExistingAttr->getLocation(), diag::warn_mismatched_import) << 0 | |||
6778 | << ExistingAttr->getImportModule() << AL.getImportModule(); | |||
6779 | Diag(AL.getLoc(), diag::note_previous_attribute); | |||
6780 | return nullptr; | |||
6781 | } | |||
6782 | if (FD->hasBody()) { | |||
6783 | Diag(AL.getLoc(), diag::warn_import_on_definition) << 0; | |||
6784 | return nullptr; | |||
6785 | } | |||
6786 | return ::new (Context) WebAssemblyImportModuleAttr(Context, AL, | |||
6787 | AL.getImportModule()); | |||
6788 | } | |||
6789 | ||||
6790 | WebAssemblyImportNameAttr * | |||
6791 | Sema::mergeImportNameAttr(Decl *D, const WebAssemblyImportNameAttr &AL) { | |||
6792 | auto *FD = cast<FunctionDecl>(D); | |||
6793 | ||||
6794 | if (const auto *ExistingAttr = FD->getAttr<WebAssemblyImportNameAttr>()) { | |||
6795 | if (ExistingAttr->getImportName() == AL.getImportName()) | |||
6796 | return nullptr; | |||
6797 | Diag(ExistingAttr->getLocation(), diag::warn_mismatched_import) << 1 | |||
6798 | << ExistingAttr->getImportName() << AL.getImportName(); | |||
6799 | Diag(AL.getLoc(), diag::note_previous_attribute); | |||
6800 | return nullptr; | |||
6801 | } | |||
6802 | if (FD->hasBody()) { | |||
6803 | Diag(AL.getLoc(), diag::warn_import_on_definition) << 1; | |||
6804 | return nullptr; | |||
6805 | } | |||
6806 | return ::new (Context) WebAssemblyImportNameAttr(Context, AL, | |||
6807 | AL.getImportName()); | |||
6808 | } | |||
6809 | ||||
6810 | static void | |||
6811 | handleWebAssemblyImportModuleAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6812 | auto *FD = cast<FunctionDecl>(D); | |||
6813 | ||||
6814 | StringRef Str; | |||
6815 | SourceLocation ArgLoc; | |||
6816 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc)) | |||
6817 | return; | |||
6818 | if (FD->hasBody()) { | |||
6819 | S.Diag(AL.getLoc(), diag::warn_import_on_definition) << 0; | |||
6820 | return; | |||
6821 | } | |||
6822 | ||||
6823 | FD->addAttr(::new (S.Context) | |||
6824 | WebAssemblyImportModuleAttr(S.Context, AL, Str)); | |||
6825 | } | |||
6826 | ||||
6827 | static void | |||
6828 | handleWebAssemblyImportNameAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6829 | auto *FD = cast<FunctionDecl>(D); | |||
6830 | ||||
6831 | StringRef Str; | |||
6832 | SourceLocation ArgLoc; | |||
6833 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc)) | |||
6834 | return; | |||
6835 | if (FD->hasBody()) { | |||
6836 | S.Diag(AL.getLoc(), diag::warn_import_on_definition) << 1; | |||
6837 | return; | |||
6838 | } | |||
6839 | ||||
6840 | FD->addAttr(::new (S.Context) WebAssemblyImportNameAttr(S.Context, AL, Str)); | |||
6841 | } | |||
6842 | ||||
6843 | static void handleRISCVInterruptAttr(Sema &S, Decl *D, | |||
6844 | const ParsedAttr &AL) { | |||
6845 | // Warn about repeated attributes. | |||
6846 | if (const auto *A = D->getAttr<RISCVInterruptAttr>()) { | |||
6847 | S.Diag(AL.getRange().getBegin(), | |||
6848 | diag::warn_riscv_repeated_interrupt_attribute); | |||
6849 | S.Diag(A->getLocation(), diag::note_riscv_repeated_interrupt_attribute); | |||
6850 | return; | |||
6851 | } | |||
6852 | ||||
6853 | // Check the attribute argument. Argument is optional. | |||
6854 | if (!AL.checkAtMostNumArgs(S, 1)) | |||
6855 | return; | |||
6856 | ||||
6857 | StringRef Str; | |||
6858 | SourceLocation ArgLoc; | |||
6859 | ||||
6860 | // 'machine'is the default interrupt mode. | |||
6861 | if (AL.getNumArgs() == 0) | |||
6862 | Str = "machine"; | |||
6863 | else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc)) | |||
6864 | return; | |||
6865 | ||||
6866 | // Semantic checks for a function with the 'interrupt' attribute: | |||
6867 | // - Must be a function. | |||
6868 | // - Must have no parameters. | |||
6869 | // - Must have the 'void' return type. | |||
6870 | // - The attribute itself must either have no argument or one of the | |||
6871 | // valid interrupt types, see [RISCVInterruptDocs]. | |||
6872 | ||||
6873 | if (D->getFunctionType() == nullptr) { | |||
6874 | S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) | |||
6875 | << "'interrupt'" << ExpectedFunction; | |||
6876 | return; | |||
6877 | } | |||
6878 | ||||
6879 | if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) { | |||
6880 | S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid) | |||
6881 | << /*RISC-V*/ 2 << 0; | |||
6882 | return; | |||
6883 | } | |||
6884 | ||||
6885 | if (!getFunctionOrMethodResultType(D)->isVoidType()) { | |||
6886 | S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid) | |||
6887 | << /*RISC-V*/ 2 << 1; | |||
6888 | return; | |||
6889 | } | |||
6890 | ||||
6891 | RISCVInterruptAttr::InterruptType Kind; | |||
6892 | if (!RISCVInterruptAttr::ConvertStrToInterruptType(Str, Kind)) { | |||
6893 | S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << Str | |||
6894 | << ArgLoc; | |||
6895 | return; | |||
6896 | } | |||
6897 | ||||
6898 | D->addAttr(::new (S.Context) RISCVInterruptAttr(S.Context, AL, Kind)); | |||
6899 | } | |||
6900 | ||||
6901 | static void handleInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
6902 | // Dispatch the interrupt attribute based on the current target. | |||
6903 | switch (S.Context.getTargetInfo().getTriple().getArch()) { | |||
6904 | case llvm::Triple::msp430: | |||
6905 | handleMSP430InterruptAttr(S, D, AL); | |||
6906 | break; | |||
6907 | case llvm::Triple::mipsel: | |||
6908 | case llvm::Triple::mips: | |||
6909 | handleMipsInterruptAttr(S, D, AL); | |||
6910 | break; | |||
6911 | case llvm::Triple::m68k: | |||
6912 | handleM68kInterruptAttr(S, D, AL); | |||
6913 | break; | |||
6914 | case llvm::Triple::x86: | |||
6915 | case llvm::Triple::x86_64: | |||
6916 | handleAnyX86InterruptAttr(S, D, AL); | |||
6917 | break; | |||
6918 | case llvm::Triple::avr: | |||
6919 | handleAVRInterruptAttr(S, D, AL); | |||
6920 | break; | |||
6921 | case llvm::Triple::riscv32: | |||
6922 | case llvm::Triple::riscv64: | |||
6923 | handleRISCVInterruptAttr(S, D, AL); | |||
6924 | break; | |||
6925 | default: | |||
6926 | handleARMInterruptAttr(S, D, AL); | |||
6927 | break; | |||
6928 | } | |||
6929 | } | |||
6930 | ||||
6931 | static bool | |||
6932 | checkAMDGPUFlatWorkGroupSizeArguments(Sema &S, Expr *MinExpr, Expr *MaxExpr, | |||
6933 | const AMDGPUFlatWorkGroupSizeAttr &Attr) { | |||
6934 | // Accept template arguments for now as they depend on something else. | |||
6935 | // We'll get to check them when they eventually get instantiated. | |||
6936 | if (MinExpr->isValueDependent() || MaxExpr->isValueDependent()) | |||
6937 | return false; | |||
6938 | ||||
6939 | uint32_t Min = 0; | |||
6940 | if (!checkUInt32Argument(S, Attr, MinExpr, Min, 0)) | |||
6941 | return true; | |||
6942 | ||||
6943 | uint32_t Max = 0; | |||
6944 | if (!checkUInt32Argument(S, Attr, MaxExpr, Max, 1)) | |||
6945 | return true; | |||
6946 | ||||
6947 | if (Min == 0 && Max != 0) { | |||
6948 | S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid) | |||
6949 | << &Attr << 0; | |||
6950 | return true; | |||
6951 | } | |||
6952 | if (Min > Max) { | |||
6953 | S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid) | |||
6954 | << &Attr << 1; | |||
6955 | return true; | |||
6956 | } | |||
6957 | ||||
6958 | return false; | |||
6959 | } | |||
6960 | ||||
6961 | void Sema::addAMDGPUFlatWorkGroupSizeAttr(Decl *D, | |||
6962 | const AttributeCommonInfo &CI, | |||
6963 | Expr *MinExpr, Expr *MaxExpr) { | |||
6964 | AMDGPUFlatWorkGroupSizeAttr TmpAttr(Context, CI, MinExpr, MaxExpr); | |||
6965 | ||||
6966 | if (checkAMDGPUFlatWorkGroupSizeArguments(*this, MinExpr, MaxExpr, TmpAttr)) | |||
6967 | return; | |||
6968 | ||||
6969 | D->addAttr(::new (Context) | |||
6970 | AMDGPUFlatWorkGroupSizeAttr(Context, CI, MinExpr, MaxExpr)); | |||
6971 | } | |||
6972 | ||||
6973 | static void handleAMDGPUFlatWorkGroupSizeAttr(Sema &S, Decl *D, | |||
6974 | const ParsedAttr &AL) { | |||
6975 | Expr *MinExpr = AL.getArgAsExpr(0); | |||
6976 | Expr *MaxExpr = AL.getArgAsExpr(1); | |||
6977 | ||||
6978 | S.addAMDGPUFlatWorkGroupSizeAttr(D, AL, MinExpr, MaxExpr); | |||
6979 | } | |||
6980 | ||||
6981 | static bool checkAMDGPUWavesPerEUArguments(Sema &S, Expr *MinExpr, | |||
6982 | Expr *MaxExpr, | |||
6983 | const AMDGPUWavesPerEUAttr &Attr) { | |||
6984 | if (S.DiagnoseUnexpandedParameterPack(MinExpr) || | |||
6985 | (MaxExpr && S.DiagnoseUnexpandedParameterPack(MaxExpr))) | |||
6986 | return true; | |||
6987 | ||||
6988 | // Accept template arguments for now as they depend on something else. | |||
6989 | // We'll get to check them when they eventually get instantiated. | |||
6990 | if (MinExpr->isValueDependent() || (MaxExpr && MaxExpr->isValueDependent())) | |||
6991 | return false; | |||
6992 | ||||
6993 | uint32_t Min = 0; | |||
6994 | if (!checkUInt32Argument(S, Attr, MinExpr, Min, 0)) | |||
6995 | return true; | |||
6996 | ||||
6997 | uint32_t Max = 0; | |||
6998 | if (MaxExpr && !checkUInt32Argument(S, Attr, MaxExpr, Max, 1)) | |||
6999 | return true; | |||
7000 | ||||
7001 | if (Min == 0 && Max != 0) { | |||
7002 | S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid) | |||
7003 | << &Attr << 0; | |||
7004 | return true; | |||
7005 | } | |||
7006 | if (Max != 0 && Min > Max) { | |||
7007 | S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid) | |||
7008 | << &Attr << 1; | |||
7009 | return true; | |||
7010 | } | |||
7011 | ||||
7012 | return false; | |||
7013 | } | |||
7014 | ||||
7015 | void Sema::addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI, | |||
7016 | Expr *MinExpr, Expr *MaxExpr) { | |||
7017 | AMDGPUWavesPerEUAttr TmpAttr(Context, CI, MinExpr, MaxExpr); | |||
7018 | ||||
7019 | if (checkAMDGPUWavesPerEUArguments(*this, MinExpr, MaxExpr, TmpAttr)) | |||
7020 | return; | |||
7021 | ||||
7022 | D->addAttr(::new (Context) | |||
7023 | AMDGPUWavesPerEUAttr(Context, CI, MinExpr, MaxExpr)); | |||
7024 | } | |||
7025 | ||||
7026 | static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7027 | if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2)) | |||
7028 | return; | |||
7029 | ||||
7030 | Expr *MinExpr = AL.getArgAsExpr(0); | |||
7031 | Expr *MaxExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr; | |||
7032 | ||||
7033 | S.addAMDGPUWavesPerEUAttr(D, AL, MinExpr, MaxExpr); | |||
7034 | } | |||
7035 | ||||
7036 | static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7037 | uint32_t NumSGPR = 0; | |||
7038 | Expr *NumSGPRExpr = AL.getArgAsExpr(0); | |||
7039 | if (!checkUInt32Argument(S, AL, NumSGPRExpr, NumSGPR)) | |||
7040 | return; | |||
7041 | ||||
7042 | D->addAttr(::new (S.Context) AMDGPUNumSGPRAttr(S.Context, AL, NumSGPR)); | |||
7043 | } | |||
7044 | ||||
7045 | static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7046 | uint32_t NumVGPR = 0; | |||
7047 | Expr *NumVGPRExpr = AL.getArgAsExpr(0); | |||
7048 | if (!checkUInt32Argument(S, AL, NumVGPRExpr, NumVGPR)) | |||
7049 | return; | |||
7050 | ||||
7051 | D->addAttr(::new (S.Context) AMDGPUNumVGPRAttr(S.Context, AL, NumVGPR)); | |||
7052 | } | |||
7053 | ||||
7054 | static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D, | |||
7055 | const ParsedAttr &AL) { | |||
7056 | // If we try to apply it to a function pointer, don't warn, but don't | |||
7057 | // do anything, either. It doesn't matter anyway, because there's nothing | |||
7058 | // special about calling a force_align_arg_pointer function. | |||
7059 | const auto *VD = dyn_cast<ValueDecl>(D); | |||
7060 | if (VD && VD->getType()->isFunctionPointerType()) | |||
7061 | return; | |||
7062 | // Also don't warn on function pointer typedefs. | |||
7063 | const auto *TD = dyn_cast<TypedefNameDecl>(D); | |||
7064 | if (TD && (TD->getUnderlyingType()->isFunctionPointerType() || | |||
7065 | TD->getUnderlyingType()->isFunctionType())) | |||
7066 | return; | |||
7067 | // Attribute can only be applied to function types. | |||
7068 | if (!isa<FunctionDecl>(D)) { | |||
7069 | S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) | |||
7070 | << AL << ExpectedFunction; | |||
7071 | return; | |||
7072 | } | |||
7073 | ||||
7074 | D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(S.Context, AL)); | |||
7075 | } | |||
7076 | ||||
7077 | static void handleLayoutVersion(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7078 | uint32_t Version; | |||
7079 | Expr *VersionExpr = static_cast<Expr *>(AL.getArgAsExpr(0)); | |||
7080 | if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), Version)) | |||
7081 | return; | |||
7082 | ||||
7083 | // TODO: Investigate what happens with the next major version of MSVC. | |||
7084 | if (Version != LangOptions::MSVC2015 / 100) { | |||
7085 | S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) | |||
7086 | << AL << Version << VersionExpr->getSourceRange(); | |||
7087 | return; | |||
7088 | } | |||
7089 | ||||
7090 | // The attribute expects a "major" version number like 19, but new versions of | |||
7091 | // MSVC have moved to updating the "minor", or less significant numbers, so we | |||
7092 | // have to multiply by 100 now. | |||
7093 | Version *= 100; | |||
7094 | ||||
7095 | D->addAttr(::new (S.Context) LayoutVersionAttr(S.Context, AL, Version)); | |||
7096 | } | |||
7097 | ||||
7098 | DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, | |||
7099 | const AttributeCommonInfo &CI) { | |||
7100 | if (D->hasAttr<DLLExportAttr>()) { | |||
7101 | Diag(CI.getLoc(), diag::warn_attribute_ignored) << "'dllimport'"; | |||
7102 | return nullptr; | |||
7103 | } | |||
7104 | ||||
7105 | if (D->hasAttr<DLLImportAttr>()) | |||
7106 | return nullptr; | |||
7107 | ||||
7108 | return ::new (Context) DLLImportAttr(Context, CI); | |||
7109 | } | |||
7110 | ||||
7111 | DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, | |||
7112 | const AttributeCommonInfo &CI) { | |||
7113 | if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) { | |||
7114 | Diag(Import->getLocation(), diag::warn_attribute_ignored) << Import; | |||
7115 | D->dropAttr<DLLImportAttr>(); | |||
7116 | } | |||
7117 | ||||
7118 | if (D->hasAttr<DLLExportAttr>()) | |||
7119 | return nullptr; | |||
7120 | ||||
7121 | return ::new (Context) DLLExportAttr(Context, CI); | |||
7122 | } | |||
7123 | ||||
7124 | static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { | |||
7125 | if (isa<ClassTemplatePartialSpecializationDecl>(D) && | |||
7126 | (S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) { | |||
7127 | S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) << A; | |||
7128 | return; | |||
7129 | } | |||
7130 | ||||
7131 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
7132 | if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport && | |||
7133 | !(S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) { | |||
7134 | // MinGW doesn't allow dllimport on inline functions. | |||
7135 | S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline) | |||
7136 | << A; | |||
7137 | return; | |||
7138 | } | |||
7139 | } | |||
7140 | ||||
7141 | if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { | |||
7142 | if ((S.Context.getTargetInfo().shouldDLLImportComdatSymbols()) && | |||
7143 | MD->getParent()->isLambda()) { | |||
7144 | S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A; | |||
7145 | return; | |||
7146 | } | |||
7147 | } | |||
7148 | ||||
7149 | Attr *NewAttr = A.getKind() == ParsedAttr::AT_DLLExport | |||
7150 | ? (Attr *)S.mergeDLLExportAttr(D, A) | |||
7151 | : (Attr *)S.mergeDLLImportAttr(D, A); | |||
7152 | if (NewAttr) | |||
7153 | D->addAttr(NewAttr); | |||
7154 | } | |||
7155 | ||||
7156 | MSInheritanceAttr * | |||
7157 | Sema::mergeMSInheritanceAttr(Decl *D, const AttributeCommonInfo &CI, | |||
7158 | bool BestCase, | |||
7159 | MSInheritanceModel Model) { | |||
7160 | if (MSInheritanceAttr *IA = D->getAttr<MSInheritanceAttr>()) { | |||
7161 | if (IA->getInheritanceModel() == Model) | |||
7162 | return nullptr; | |||
7163 | Diag(IA->getLocation(), diag::err_mismatched_ms_inheritance) | |||
7164 | << 1 /*previous declaration*/; | |||
7165 | Diag(CI.getLoc(), diag::note_previous_ms_inheritance); | |||
7166 | D->dropAttr<MSInheritanceAttr>(); | |||
7167 | } | |||
7168 | ||||
7169 | auto *RD = cast<CXXRecordDecl>(D); | |||
7170 | if (RD->hasDefinition()) { | |||
7171 | if (checkMSInheritanceAttrOnDefinition(RD, CI.getRange(), BestCase, | |||
7172 | Model)) { | |||
7173 | return nullptr; | |||
7174 | } | |||
7175 | } else { | |||
7176 | if (isa<ClassTemplatePartialSpecializationDecl>(RD)) { | |||
7177 | Diag(CI.getLoc(), diag::warn_ignored_ms_inheritance) | |||
7178 | << 1 /*partial specialization*/; | |||
7179 | return nullptr; | |||
7180 | } | |||
7181 | if (RD->getDescribedClassTemplate()) { | |||
7182 | Diag(CI.getLoc(), diag::warn_ignored_ms_inheritance) | |||
7183 | << 0 /*primary template*/; | |||
7184 | return nullptr; | |||
7185 | } | |||
7186 | } | |||
7187 | ||||
7188 | return ::new (Context) MSInheritanceAttr(Context, CI, BestCase); | |||
7189 | } | |||
7190 | ||||
7191 | static void handleCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7192 | // The capability attributes take a single string parameter for the name of | |||
7193 | // the capability they represent. The lockable attribute does not take any | |||
7194 | // parameters. However, semantically, both attributes represent the same | |||
7195 | // concept, and so they use the same semantic attribute. Eventually, the | |||
7196 | // lockable attribute will be removed. | |||
7197 | // | |||
7198 | // For backward compatibility, any capability which has no specified string | |||
7199 | // literal will be considered a "mutex." | |||
7200 | StringRef N("mutex"); | |||
7201 | SourceLocation LiteralLoc; | |||
7202 | if (AL.getKind() == ParsedAttr::AT_Capability && | |||
7203 | !S.checkStringLiteralArgumentAttr(AL, 0, N, &LiteralLoc)) | |||
7204 | return; | |||
7205 | ||||
7206 | D->addAttr(::new (S.Context) CapabilityAttr(S.Context, AL, N)); | |||
7207 | } | |||
7208 | ||||
7209 | static void handleAssertCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7210 | SmallVector<Expr*, 1> Args; | |||
7211 | if (!checkLockFunAttrCommon(S, D, AL, Args)) | |||
7212 | return; | |||
7213 | ||||
7214 | D->addAttr(::new (S.Context) | |||
7215 | AssertCapabilityAttr(S.Context, AL, Args.data(), Args.size())); | |||
7216 | } | |||
7217 | ||||
7218 | static void handleAcquireCapabilityAttr(Sema &S, Decl *D, | |||
7219 | const ParsedAttr &AL) { | |||
7220 | SmallVector<Expr*, 1> Args; | |||
7221 | if (!checkLockFunAttrCommon(S, D, AL, Args)) | |||
7222 | return; | |||
7223 | ||||
7224 | D->addAttr(::new (S.Context) AcquireCapabilityAttr(S.Context, AL, Args.data(), | |||
7225 | Args.size())); | |||
7226 | } | |||
7227 | ||||
7228 | static void handleTryAcquireCapabilityAttr(Sema &S, Decl *D, | |||
7229 | const ParsedAttr &AL) { | |||
7230 | SmallVector<Expr*, 2> Args; | |||
7231 | if (!checkTryLockFunAttrCommon(S, D, AL, Args)) | |||
7232 | return; | |||
7233 | ||||
7234 | D->addAttr(::new (S.Context) TryAcquireCapabilityAttr( | |||
7235 | S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size())); | |||
7236 | } | |||
7237 | ||||
7238 | static void handleReleaseCapabilityAttr(Sema &S, Decl *D, | |||
7239 | const ParsedAttr &AL) { | |||
7240 | // Check that all arguments are lockable objects. | |||
7241 | SmallVector<Expr *, 1> Args; | |||
7242 | checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, true); | |||
7243 | ||||
7244 | D->addAttr(::new (S.Context) ReleaseCapabilityAttr(S.Context, AL, Args.data(), | |||
7245 | Args.size())); | |||
7246 | } | |||
7247 | ||||
7248 | static void handleRequiresCapabilityAttr(Sema &S, Decl *D, | |||
7249 | const ParsedAttr &AL) { | |||
7250 | if (!AL.checkAtLeastNumArgs(S, 1)) | |||
7251 | return; | |||
7252 | ||||
7253 | // check that all arguments are lockable objects | |||
7254 | SmallVector<Expr*, 1> Args; | |||
7255 | checkAttrArgsAreCapabilityObjs(S, D, AL, Args); | |||
7256 | if (Args.empty()) | |||
7257 | return; | |||
7258 | ||||
7259 | RequiresCapabilityAttr *RCA = ::new (S.Context) | |||
7260 | RequiresCapabilityAttr(S.Context, AL, Args.data(), Args.size()); | |||
7261 | ||||
7262 | D->addAttr(RCA); | |||
7263 | } | |||
7264 | ||||
7265 | static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7266 | if (const auto *NSD = dyn_cast<NamespaceDecl>(D)) { | |||
7267 | if (NSD->isAnonymousNamespace()) { | |||
7268 | S.Diag(AL.getLoc(), diag::warn_deprecated_anonymous_namespace); | |||
7269 | // Do not want to attach the attribute to the namespace because that will | |||
7270 | // cause confusing diagnostic reports for uses of declarations within the | |||
7271 | // namespace. | |||
7272 | return; | |||
7273 | } | |||
7274 | } | |||
7275 | ||||
7276 | // Handle the cases where the attribute has a text message. | |||
7277 | StringRef Str, Replacement; | |||
7278 | if (AL.isArgExpr(0) && AL.getArgAsExpr(0) && | |||
7279 | !S.checkStringLiteralArgumentAttr(AL, 0, Str)) | |||
7280 | return; | |||
7281 | ||||
7282 | // Only support a single optional message for Declspec and CXX11. | |||
7283 | if (AL.isDeclspecAttribute() || AL.isCXX11Attribute()) | |||
7284 | AL.checkAtMostNumArgs(S, 1); | |||
7285 | else if (AL.isArgExpr(1) && AL.getArgAsExpr(1) && | |||
7286 | !S.checkStringLiteralArgumentAttr(AL, 1, Replacement)) | |||
7287 | return; | |||
7288 | ||||
7289 | if (!S.getLangOpts().CPlusPlus14 && AL.isCXX11Attribute() && !AL.isGNUScope()) | |||
7290 | S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL; | |||
7291 | ||||
7292 | D->addAttr(::new (S.Context) DeprecatedAttr(S.Context, AL, Str, Replacement)); | |||
7293 | } | |||
7294 | ||||
7295 | static bool isGlobalVar(const Decl *D) { | |||
7296 | if (const auto *S = dyn_cast<VarDecl>(D)) | |||
7297 | return S->hasGlobalStorage(); | |||
7298 | return false; | |||
7299 | } | |||
7300 | ||||
7301 | static void handleNoSanitizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7302 | if (!AL.checkAtLeastNumArgs(S, 1)) | |||
7303 | return; | |||
7304 | ||||
7305 | std::vector<StringRef> Sanitizers; | |||
7306 | ||||
7307 | for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { | |||
7308 | StringRef SanitizerName; | |||
7309 | SourceLocation LiteralLoc; | |||
7310 | ||||
7311 | if (!S.checkStringLiteralArgumentAttr(AL, I, SanitizerName, &LiteralLoc)) | |||
7312 | return; | |||
7313 | ||||
7314 | if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) == | |||
7315 | SanitizerMask()) | |||
7316 | S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName; | |||
7317 | else if (isGlobalVar(D) && SanitizerName != "address") | |||
7318 | S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) | |||
7319 | << AL << ExpectedFunctionOrMethod; | |||
7320 | Sanitizers.push_back(SanitizerName); | |||
7321 | } | |||
7322 | ||||
7323 | D->addAttr(::new (S.Context) NoSanitizeAttr(S.Context, AL, Sanitizers.data(), | |||
7324 | Sanitizers.size())); | |||
7325 | } | |||
7326 | ||||
7327 | static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D, | |||
7328 | const ParsedAttr &AL) { | |||
7329 | StringRef AttrName = AL.getAttrName()->getName(); | |||
7330 | normalizeName(AttrName); | |||
7331 | StringRef SanitizerName = llvm::StringSwitch<StringRef>(AttrName) | |||
7332 | .Case("no_address_safety_analysis", "address") | |||
7333 | .Case("no_sanitize_address", "address") | |||
7334 | .Case("no_sanitize_thread", "thread") | |||
7335 | .Case("no_sanitize_memory", "memory"); | |||
7336 | if (isGlobalVar(D) && SanitizerName != "address") | |||
7337 | S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) | |||
7338 | << AL << ExpectedFunction; | |||
7339 | ||||
7340 | // FIXME: Rather than create a NoSanitizeSpecificAttr, this creates a | |||
7341 | // NoSanitizeAttr object; but we need to calculate the correct spelling list | |||
7342 | // index rather than incorrectly assume the index for NoSanitizeSpecificAttr | |||
7343 | // has the same spellings as the index for NoSanitizeAttr. We don't have a | |||
7344 | // general way to "translate" between the two, so this hack attempts to work | |||
7345 | // around the issue with hard-coded indicies. This is critical for calling | |||
7346 | // getSpelling() or prettyPrint() on the resulting semantic attribute object | |||
7347 | // without failing assertions. | |||
7348 | unsigned TranslatedSpellingIndex = 0; | |||
7349 | if (AL.isC2xAttribute() || AL.isCXX11Attribute()) | |||
7350 | TranslatedSpellingIndex = 1; | |||
7351 | ||||
7352 | AttributeCommonInfo Info = AL; | |||
7353 | Info.setAttributeSpellingListIndex(TranslatedSpellingIndex); | |||
7354 | D->addAttr(::new (S.Context) | |||
7355 | NoSanitizeAttr(S.Context, Info, &SanitizerName, 1)); | |||
7356 | } | |||
7357 | ||||
7358 | static void handleInternalLinkageAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7359 | if (InternalLinkageAttr *Internal = S.mergeInternalLinkageAttr(D, AL)) | |||
7360 | D->addAttr(Internal); | |||
7361 | } | |||
7362 | ||||
7363 | static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7364 | if (S.LangOpts.OpenCLVersion != 200) | |||
7365 | S.Diag(AL.getLoc(), diag::err_attribute_requires_opencl_version) | |||
7366 | << AL << "2.0" << 0; | |||
7367 | else | |||
7368 | S.Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored) << AL | |||
7369 | << "2.0"; | |||
7370 | } | |||
7371 | ||||
7372 | /// Handles semantic checking for features that are common to all attributes, | |||
7373 | /// such as checking whether a parameter was properly specified, or the correct | |||
7374 | /// number of arguments were passed, etc. | |||
7375 | static bool handleCommonAttributeFeatures(Sema &S, Decl *D, | |||
7376 | const ParsedAttr &AL) { | |||
7377 | // Several attributes carry different semantics than the parsing requires, so | |||
7378 | // those are opted out of the common argument checks. | |||
7379 | // | |||
7380 | // We also bail on unknown and ignored attributes because those are handled | |||
7381 | // as part of the target-specific handling logic. | |||
7382 | if (AL.getKind() == ParsedAttr::UnknownAttribute) | |||
7383 | return false; | |||
7384 | // Check whether the attribute requires specific language extensions to be | |||
7385 | // enabled. | |||
7386 | if (!AL.diagnoseLangOpts(S)) | |||
7387 | return true; | |||
7388 | // Check whether the attribute appertains to the given subject. | |||
7389 | if (!AL.diagnoseAppertainsTo(S, D)) | |||
7390 | return true; | |||
7391 | if (AL.hasCustomParsing()) | |||
7392 | return false; | |||
7393 | ||||
7394 | if (AL.getMinArgs() == AL.getMaxArgs()) { | |||
7395 | // If there are no optional arguments, then checking for the argument count | |||
7396 | // is trivial. | |||
7397 | if (!AL.checkExactlyNumArgs(S, AL.getMinArgs())) | |||
7398 | return true; | |||
7399 | } else { | |||
7400 | // There are optional arguments, so checking is slightly more involved. | |||
7401 | if (AL.getMinArgs() && !AL.checkAtLeastNumArgs(S, AL.getMinArgs())) | |||
7402 | return true; | |||
7403 | else if (!AL.hasVariadicArg() && AL.getMaxArgs() && | |||
7404 | !AL.checkAtMostNumArgs(S, AL.getMaxArgs())) | |||
7405 | return true; | |||
7406 | } | |||
7407 | ||||
7408 | if (S.CheckAttrTarget(AL)) | |||
7409 | return true; | |||
7410 | ||||
7411 | return false; | |||
7412 | } | |||
7413 | ||||
7414 | static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7415 | if (D->isInvalidDecl()) | |||
7416 | return; | |||
7417 | ||||
7418 | // Check if there is only one access qualifier. | |||
7419 | if (D->hasAttr<OpenCLAccessAttr>()) { | |||
7420 | if (D->getAttr<OpenCLAccessAttr>()->getSemanticSpelling() == | |||
7421 | AL.getSemanticSpelling()) { | |||
7422 | S.Diag(AL.getLoc(), diag::warn_duplicate_declspec) | |||
7423 | << AL.getAttrName()->getName() << AL.getRange(); | |||
7424 | } else { | |||
7425 | S.Diag(AL.getLoc(), diag::err_opencl_multiple_access_qualifiers) | |||
7426 | << D->getSourceRange(); | |||
7427 | D->setInvalidDecl(true); | |||
7428 | return; | |||
7429 | } | |||
7430 | } | |||
7431 | ||||
7432 | // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that an | |||
7433 | // image object can be read and written. | |||
7434 | // OpenCL v2.0 s6.13.6 - A kernel cannot read from and write to the same pipe | |||
7435 | // object. Using the read_write (or __read_write) qualifier with the pipe | |||
7436 | // qualifier is a compilation error. | |||
7437 | if (const auto *PDecl = dyn_cast<ParmVarDecl>(D)) { | |||
7438 | const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr(); | |||
7439 | if (AL.getAttrName()->getName().find("read_write") != StringRef::npos) { | |||
7440 | if ((!S.getLangOpts().OpenCLCPlusPlus && | |||
7441 | S.getLangOpts().OpenCLVersion < 200) || | |||
7442 | DeclTy->isPipeType()) { | |||
7443 | S.Diag(AL.getLoc(), diag::err_opencl_invalid_read_write) | |||
7444 | << AL << PDecl->getType() << DeclTy->isImageType(); | |||
7445 | D->setInvalidDecl(true); | |||
7446 | return; | |||
7447 | } | |||
7448 | } | |||
7449 | } | |||
7450 | ||||
7451 | D->addAttr(::new (S.Context) OpenCLAccessAttr(S.Context, AL)); | |||
7452 | } | |||
7453 | ||||
7454 | static void handleSYCLKernelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7455 | // The 'sycl_kernel' attribute applies only to function templates. | |||
7456 | const auto *FD = cast<FunctionDecl>(D); | |||
7457 | const FunctionTemplateDecl *FT = FD->getDescribedFunctionTemplate(); | |||
7458 | assert(FT && "Function template is expected")((FT && "Function template is expected") ? static_cast <void> (0) : __assert_fail ("FT && \"Function template is expected\"" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 7458, __PRETTY_FUNCTION__)); | |||
7459 | ||||
7460 | // Function template must have at least two template parameters. | |||
7461 | const TemplateParameterList *TL = FT->getTemplateParameters(); | |||
7462 | if (TL->size() < 2) { | |||
7463 | S.Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_template_params); | |||
7464 | return; | |||
7465 | } | |||
7466 | ||||
7467 | // Template parameters must be typenames. | |||
7468 | for (unsigned I = 0; I < 2; ++I) { | |||
7469 | const NamedDecl *TParam = TL->getParam(I); | |||
7470 | if (isa<NonTypeTemplateParmDecl>(TParam)) { | |||
7471 | S.Diag(FT->getLocation(), | |||
7472 | diag::warn_sycl_kernel_invalid_template_param_type); | |||
7473 | return; | |||
7474 | } | |||
7475 | } | |||
7476 | ||||
7477 | // Function must have at least one argument. | |||
7478 | if (getFunctionOrMethodNumParams(D) != 1) { | |||
7479 | S.Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_function_params); | |||
7480 | return; | |||
7481 | } | |||
7482 | ||||
7483 | // Function must return void. | |||
7484 | QualType RetTy = getFunctionOrMethodResultType(D); | |||
7485 | if (!RetTy->isVoidType()) { | |||
7486 | S.Diag(FT->getLocation(), diag::warn_sycl_kernel_return_type); | |||
7487 | return; | |||
7488 | } | |||
7489 | ||||
7490 | handleSimpleAttribute<SYCLKernelAttr>(S, D, AL); | |||
7491 | } | |||
7492 | ||||
7493 | static void handleDestroyAttr(Sema &S, Decl *D, const ParsedAttr &A) { | |||
7494 | if (!cast<VarDecl>(D)->hasGlobalStorage()) { | |||
7495 | S.Diag(D->getLocation(), diag::err_destroy_attr_on_non_static_var) | |||
7496 | << (A.getKind() == ParsedAttr::AT_AlwaysDestroy); | |||
7497 | return; | |||
7498 | } | |||
7499 | ||||
7500 | if (A.getKind() == ParsedAttr::AT_AlwaysDestroy) | |||
7501 | handleSimpleAttributeWithExclusions<AlwaysDestroyAttr, NoDestroyAttr>(S, D, A); | |||
7502 | else | |||
7503 | handleSimpleAttributeWithExclusions<NoDestroyAttr, AlwaysDestroyAttr>(S, D, A); | |||
7504 | } | |||
7505 | ||||
7506 | static void handleUninitializedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7507 | assert(cast<VarDecl>(D)->getStorageDuration() == SD_Automatic &&((cast<VarDecl>(D)->getStorageDuration() == SD_Automatic && "uninitialized is only valid on automatic duration variables" ) ? static_cast<void> (0) : __assert_fail ("cast<VarDecl>(D)->getStorageDuration() == SD_Automatic && \"uninitialized is only valid on automatic duration variables\"" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 7508, __PRETTY_FUNCTION__)) | |||
7508 | "uninitialized is only valid on automatic duration variables")((cast<VarDecl>(D)->getStorageDuration() == SD_Automatic && "uninitialized is only valid on automatic duration variables" ) ? static_cast<void> (0) : __assert_fail ("cast<VarDecl>(D)->getStorageDuration() == SD_Automatic && \"uninitialized is only valid on automatic duration variables\"" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 7508, __PRETTY_FUNCTION__)); | |||
7509 | D->addAttr(::new (S.Context) UninitializedAttr(S.Context, AL)); | |||
7510 | } | |||
7511 | ||||
7512 | static bool tryMakeVariablePseudoStrong(Sema &S, VarDecl *VD, | |||
7513 | bool DiagnoseFailure) { | |||
7514 | QualType Ty = VD->getType(); | |||
7515 | if (!Ty->isObjCRetainableType()) { | |||
7516 | if (DiagnoseFailure) { | |||
7517 | S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained) | |||
7518 | << 0; | |||
7519 | } | |||
7520 | return false; | |||
7521 | } | |||
7522 | ||||
7523 | Qualifiers::ObjCLifetime LifetimeQual = Ty.getQualifiers().getObjCLifetime(); | |||
7524 | ||||
7525 | // Sema::inferObjCARCLifetime must run after processing decl attributes | |||
7526 | // (because __block lowers to an attribute), so if the lifetime hasn't been | |||
7527 | // explicitly specified, infer it locally now. | |||
7528 | if (LifetimeQual == Qualifiers::OCL_None) | |||
7529 | LifetimeQual = Ty->getObjCARCImplicitLifetime(); | |||
7530 | ||||
7531 | // The attributes only really makes sense for __strong variables; ignore any | |||
7532 | // attempts to annotate a parameter with any other lifetime qualifier. | |||
7533 | if (LifetimeQual != Qualifiers::OCL_Strong) { | |||
7534 | if (DiagnoseFailure) { | |||
7535 | S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained) | |||
7536 | << 1; | |||
7537 | } | |||
7538 | return false; | |||
7539 | } | |||
7540 | ||||
7541 | // Tampering with the type of a VarDecl here is a bit of a hack, but we need | |||
7542 | // to ensure that the variable is 'const' so that we can error on | |||
7543 | // modification, which can otherwise over-release. | |||
7544 | VD->setType(Ty.withConst()); | |||
7545 | VD->setARCPseudoStrong(true); | |||
7546 | return true; | |||
7547 | } | |||
7548 | ||||
7549 | static void handleObjCExternallyRetainedAttr(Sema &S, Decl *D, | |||
7550 | const ParsedAttr &AL) { | |||
7551 | if (auto *VD = dyn_cast<VarDecl>(D)) { | |||
7552 | assert(!isa<ParmVarDecl>(VD) && "should be diagnosed automatically")((!isa<ParmVarDecl>(VD) && "should be diagnosed automatically" ) ? static_cast<void> (0) : __assert_fail ("!isa<ParmVarDecl>(VD) && \"should be diagnosed automatically\"" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 7552, __PRETTY_FUNCTION__)); | |||
7553 | if (!VD->hasLocalStorage()) { | |||
7554 | S.Diag(D->getBeginLoc(), diag::warn_ignored_objc_externally_retained) | |||
7555 | << 0; | |||
7556 | return; | |||
7557 | } | |||
7558 | ||||
7559 | if (!tryMakeVariablePseudoStrong(S, VD, /*DiagnoseFailure=*/true)) | |||
7560 | return; | |||
7561 | ||||
7562 | handleSimpleAttribute<ObjCExternallyRetainedAttr>(S, D, AL); | |||
7563 | return; | |||
7564 | } | |||
7565 | ||||
7566 | // If D is a function-like declaration (method, block, or function), then we | |||
7567 | // make every parameter psuedo-strong. | |||
7568 | unsigned NumParams = | |||
7569 | hasFunctionProto(D) ? getFunctionOrMethodNumParams(D) : 0; | |||
7570 | for (unsigned I = 0; I != NumParams; ++I) { | |||
7571 | auto *PVD = const_cast<ParmVarDecl *>(getFunctionOrMethodParam(D, I)); | |||
7572 | QualType Ty = PVD->getType(); | |||
7573 | ||||
7574 | // If a user wrote a parameter with __strong explicitly, then assume they | |||
7575 | // want "real" strong semantics for that parameter. This works because if | |||
7576 | // the parameter was written with __strong, then the strong qualifier will | |||
7577 | // be non-local. | |||
7578 | if (Ty.getLocalUnqualifiedType().getQualifiers().getObjCLifetime() == | |||
7579 | Qualifiers::OCL_Strong) | |||
7580 | continue; | |||
7581 | ||||
7582 | tryMakeVariablePseudoStrong(S, PVD, /*DiagnoseFailure=*/false); | |||
7583 | } | |||
7584 | handleSimpleAttribute<ObjCExternallyRetainedAttr>(S, D, AL); | |||
7585 | } | |||
7586 | ||||
7587 | static void handleMIGServerRoutineAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7588 | // Check that the return type is a `typedef int kern_return_t` or a typedef | |||
7589 | // around it, because otherwise MIG convention checks make no sense. | |||
7590 | // BlockDecl doesn't store a return type, so it's annoying to check, | |||
7591 | // so let's skip it for now. | |||
7592 | if (!isa<BlockDecl>(D)) { | |||
7593 | QualType T = getFunctionOrMethodResultType(D); | |||
7594 | bool IsKernReturnT = false; | |||
7595 | while (const auto *TT = T->getAs<TypedefType>()) { | |||
7596 | IsKernReturnT = (TT->getDecl()->getName() == "kern_return_t"); | |||
7597 | T = TT->desugar(); | |||
7598 | } | |||
7599 | if (!IsKernReturnT || T.getCanonicalType() != S.getASTContext().IntTy) { | |||
7600 | S.Diag(D->getBeginLoc(), | |||
7601 | diag::warn_mig_server_routine_does_not_return_kern_return_t); | |||
7602 | return; | |||
7603 | } | |||
7604 | } | |||
7605 | ||||
7606 | handleSimpleAttribute<MIGServerRoutineAttr>(S, D, AL); | |||
7607 | } | |||
7608 | ||||
7609 | static void handleMSAllocatorAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7610 | // Warn if the return type is not a pointer or reference type. | |||
7611 | if (auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
7612 | QualType RetTy = FD->getReturnType(); | |||
7613 | if (!RetTy->isPointerType() && !RetTy->isReferenceType()) { | |||
7614 | S.Diag(AL.getLoc(), diag::warn_declspec_allocator_nonpointer) | |||
7615 | << AL.getRange() << RetTy; | |||
7616 | return; | |||
7617 | } | |||
7618 | } | |||
7619 | ||||
7620 | handleSimpleAttribute<MSAllocatorAttr>(S, D, AL); | |||
7621 | } | |||
7622 | ||||
7623 | static void handleAcquireHandleAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7624 | if (AL.isUsedAsTypeAttr()) | |||
7625 | return; | |||
7626 | // Warn if the parameter is definitely not an output parameter. | |||
7627 | if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) { | |||
7628 | if (PVD->getType()->isIntegerType()) { | |||
7629 | S.Diag(AL.getLoc(), diag::err_attribute_output_parameter) | |||
7630 | << AL.getRange(); | |||
7631 | return; | |||
7632 | } | |||
7633 | } | |||
7634 | StringRef Argument; | |||
7635 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument)) | |||
7636 | return; | |||
7637 | D->addAttr(AcquireHandleAttr::Create(S.Context, Argument, AL)); | |||
7638 | } | |||
7639 | ||||
7640 | template<typename Attr> | |||
7641 | static void handleHandleAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7642 | StringRef Argument; | |||
7643 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument)) | |||
7644 | return; | |||
7645 | D->addAttr(Attr::Create(S.Context, Argument, AL)); | |||
7646 | } | |||
7647 | ||||
7648 | static void handleCFGuardAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7649 | // The guard attribute takes a single identifier argument. | |||
7650 | ||||
7651 | if (!AL.isArgIdent(0)) { | |||
7652 | S.Diag(AL.getLoc(), diag::err_attribute_argument_type) | |||
7653 | << AL << AANT_ArgumentIdentifier; | |||
7654 | return; | |||
7655 | } | |||
7656 | ||||
7657 | CFGuardAttr::GuardArg Arg; | |||
7658 | IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; | |||
7659 | if (!CFGuardAttr::ConvertStrToGuardArg(II->getName(), Arg)) { | |||
7660 | S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II; | |||
7661 | return; | |||
7662 | } | |||
7663 | ||||
7664 | D->addAttr(::new (S.Context) CFGuardAttr(S.Context, AL, Arg)); | |||
7665 | } | |||
7666 | ||||
7667 | ||||
7668 | template <typename AttrTy> | |||
7669 | static const AttrTy *findEnforceTCBAttrByName(Decl *D, StringRef Name) { | |||
7670 | auto Attrs = D->specific_attrs<AttrTy>(); | |||
7671 | auto I = llvm::find_if(Attrs, | |||
7672 | [Name](const AttrTy *A) { | |||
7673 | return A->getTCBName() == Name; | |||
7674 | }); | |||
7675 | return I == Attrs.end() ? nullptr : *I; | |||
7676 | } | |||
7677 | ||||
7678 | template <typename AttrTy, typename ConflictingAttrTy> | |||
7679 | static void handleEnforceTCBAttr(Sema &S, Decl *D, const ParsedAttr &AL) { | |||
7680 | StringRef Argument; | |||
7681 | if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument)) | |||
7682 | return; | |||
7683 | ||||
7684 | // A function cannot be have both regular and leaf membership in the same TCB. | |||
7685 | if (const ConflictingAttrTy *ConflictingAttr = | |||
7686 | findEnforceTCBAttrByName<ConflictingAttrTy>(D, Argument)) { | |||
7687 | // We could attach a note to the other attribute but in this case | |||
7688 | // there's no need given how the two are very close to each other. | |||
7689 | S.Diag(AL.getLoc(), diag::err_tcb_conflicting_attributes) | |||
7690 | << AL.getAttrName()->getName() << ConflictingAttr->getAttrName()->getName() | |||
7691 | << Argument; | |||
7692 | ||||
7693 | // Error recovery: drop the non-leaf attribute so that to suppress | |||
7694 | // all future warnings caused by erroneous attributes. The leaf attribute | |||
7695 | // needs to be kept because it can only suppresses warnings, not cause them. | |||
7696 | D->dropAttr<EnforceTCBAttr>(); | |||
7697 | return; | |||
7698 | } | |||
7699 | ||||
7700 | D->addAttr(AttrTy::Create(S.Context, Argument, AL)); | |||
7701 | } | |||
7702 | ||||
7703 | template <typename AttrTy, typename ConflictingAttrTy> | |||
7704 | static AttrTy *mergeEnforceTCBAttrImpl(Sema &S, Decl *D, const AttrTy &AL) { | |||
7705 | // Check if the new redeclaration has different leaf-ness in the same TCB. | |||
7706 | StringRef TCBName = AL.getTCBName(); | |||
7707 | if (const ConflictingAttrTy *ConflictingAttr = | |||
7708 | findEnforceTCBAttrByName<ConflictingAttrTy>(D, TCBName)) { | |||
7709 | S.Diag(ConflictingAttr->getLoc(), diag::err_tcb_conflicting_attributes) | |||
7710 | << ConflictingAttr->getAttrName()->getName() | |||
7711 | << AL.getAttrName()->getName() << TCBName; | |||
7712 | ||||
7713 | // Add a note so that the user could easily find the conflicting attribute. | |||
7714 | S.Diag(AL.getLoc(), diag::note_conflicting_attribute); | |||
7715 | ||||
7716 | // More error recovery. | |||
7717 | D->dropAttr<EnforceTCBAttr>(); | |||
7718 | return nullptr; | |||
7719 | } | |||
7720 | ||||
7721 | ASTContext &Context = S.getASTContext(); | |||
7722 | return ::new(Context) AttrTy(Context, AL, AL.getTCBName()); | |||
7723 | } | |||
7724 | ||||
7725 | EnforceTCBAttr *Sema::mergeEnforceTCBAttr(Decl *D, const EnforceTCBAttr &AL) { | |||
7726 | return mergeEnforceTCBAttrImpl<EnforceTCBAttr, EnforceTCBLeafAttr>( | |||
7727 | *this, D, AL); | |||
7728 | } | |||
7729 | ||||
7730 | EnforceTCBLeafAttr *Sema::mergeEnforceTCBLeafAttr( | |||
7731 | Decl *D, const EnforceTCBLeafAttr &AL) { | |||
7732 | return mergeEnforceTCBAttrImpl<EnforceTCBLeafAttr, EnforceTCBAttr>( | |||
7733 | *this, D, AL); | |||
7734 | } | |||
7735 | ||||
7736 | //===----------------------------------------------------------------------===// | |||
7737 | // Top Level Sema Entry Points | |||
7738 | //===----------------------------------------------------------------------===// | |||
7739 | ||||
7740 | /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if | |||
7741 | /// the attribute applies to decls. If the attribute is a type attribute, just | |||
7742 | /// silently ignore it if a GNU attribute. | |||
7743 | static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, | |||
7744 | const ParsedAttr &AL, | |||
7745 | bool IncludeCXX11Attributes) { | |||
7746 | if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute) | |||
7747 | return; | |||
7748 | ||||
7749 | // Ignore C++11 attributes on declarator chunks: they appertain to the type | |||
7750 | // instead. | |||
7751 | if (AL.isCXX11Attribute() && !IncludeCXX11Attributes) | |||
7752 | return; | |||
7753 | ||||
7754 | // Unknown attributes are automatically warned on. Target-specific attributes | |||
7755 | // which do not apply to the current target architecture are treated as | |||
7756 | // though they were unknown attributes. | |||
7757 | if (AL.getKind() == ParsedAttr::UnknownAttribute || | |||
7758 | !AL.existsInTarget(S.Context.getTargetInfo())) { | |||
7759 | S.Diag(AL.getLoc(), | |||
7760 | AL.isDeclspecAttribute() | |||
7761 | ? (unsigned)diag::warn_unhandled_ms_attribute_ignored | |||
7762 | : (unsigned)diag::warn_unknown_attribute_ignored) | |||
7763 | << AL << AL.getRange(); | |||
7764 | return; | |||
7765 | } | |||
7766 | ||||
7767 | if (handleCommonAttributeFeatures(S, D, AL)) | |||
7768 | return; | |||
7769 | ||||
7770 | switch (AL.getKind()) { | |||
7771 | default: | |||
7772 | if (AL.getInfo().handleDeclAttribute(S, D, AL) != ParsedAttrInfo::NotHandled) | |||
7773 | break; | |||
7774 | if (!AL.isStmtAttr()) { | |||
7775 | // Type attributes are handled elsewhere; silently move on. | |||
7776 | assert(AL.isTypeAttr() && "Non-type attribute not handled")((AL.isTypeAttr() && "Non-type attribute not handled" ) ? static_cast<void> (0) : __assert_fail ("AL.isTypeAttr() && \"Non-type attribute not handled\"" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 7776, __PRETTY_FUNCTION__)); | |||
7777 | break; | |||
7778 | } | |||
7779 | S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl) | |||
7780 | << AL << D->getLocation(); | |||
7781 | break; | |||
7782 | case ParsedAttr::AT_Interrupt: | |||
7783 | handleInterruptAttr(S, D, AL); | |||
7784 | break; | |||
7785 | case ParsedAttr::AT_X86ForceAlignArgPointer: | |||
7786 | handleX86ForceAlignArgPointerAttr(S, D, AL); | |||
7787 | break; | |||
7788 | case ParsedAttr::AT_DLLExport: | |||
7789 | case ParsedAttr::AT_DLLImport: | |||
7790 | handleDLLAttr(S, D, AL); | |||
7791 | break; | |||
7792 | case ParsedAttr::AT_Mips16: | |||
7793 | handleSimpleAttributeWithExclusions<Mips16Attr, MicroMipsAttr, | |||
7794 | MipsInterruptAttr>(S, D, AL); | |||
7795 | break; | |||
7796 | case ParsedAttr::AT_MicroMips: | |||
7797 | handleSimpleAttributeWithExclusions<MicroMipsAttr, Mips16Attr>(S, D, AL); | |||
7798 | break; | |||
7799 | case ParsedAttr::AT_MipsLongCall: | |||
7800 | handleSimpleAttributeWithExclusions<MipsLongCallAttr, MipsShortCallAttr>( | |||
7801 | S, D, AL); | |||
7802 | break; | |||
7803 | case ParsedAttr::AT_MipsShortCall: | |||
7804 | handleSimpleAttributeWithExclusions<MipsShortCallAttr, MipsLongCallAttr>( | |||
7805 | S, D, AL); | |||
7806 | break; | |||
7807 | case ParsedAttr::AT_AMDGPUFlatWorkGroupSize: | |||
7808 | handleAMDGPUFlatWorkGroupSizeAttr(S, D, AL); | |||
7809 | break; | |||
7810 | case ParsedAttr::AT_AMDGPUWavesPerEU: | |||
7811 | handleAMDGPUWavesPerEUAttr(S, D, AL); | |||
7812 | break; | |||
7813 | case ParsedAttr::AT_AMDGPUNumSGPR: | |||
7814 | handleAMDGPUNumSGPRAttr(S, D, AL); | |||
7815 | break; | |||
7816 | case ParsedAttr::AT_AMDGPUNumVGPR: | |||
7817 | handleAMDGPUNumVGPRAttr(S, D, AL); | |||
7818 | break; | |||
7819 | case ParsedAttr::AT_AVRSignal: | |||
7820 | handleAVRSignalAttr(S, D, AL); | |||
7821 | break; | |||
7822 | case ParsedAttr::AT_BPFPreserveAccessIndex: | |||
7823 | handleBPFPreserveAccessIndexAttr(S, D, AL); | |||
7824 | break; | |||
7825 | case ParsedAttr::AT_WebAssemblyExportName: | |||
7826 | handleWebAssemblyExportNameAttr(S, D, AL); | |||
7827 | break; | |||
7828 | case ParsedAttr::AT_WebAssemblyImportModule: | |||
7829 | handleWebAssemblyImportModuleAttr(S, D, AL); | |||
7830 | break; | |||
7831 | case ParsedAttr::AT_WebAssemblyImportName: | |||
7832 | handleWebAssemblyImportNameAttr(S, D, AL); | |||
7833 | break; | |||
7834 | case ParsedAttr::AT_IBOutlet: | |||
7835 | handleIBOutlet(S, D, AL); | |||
7836 | break; | |||
7837 | case ParsedAttr::AT_IBOutletCollection: | |||
7838 | handleIBOutletCollection(S, D, AL); | |||
7839 | break; | |||
7840 | case ParsedAttr::AT_IFunc: | |||
7841 | handleIFuncAttr(S, D, AL); | |||
7842 | break; | |||
7843 | case ParsedAttr::AT_Alias: | |||
7844 | handleAliasAttr(S, D, AL); | |||
7845 | break; | |||
7846 | case ParsedAttr::AT_Aligned: | |||
7847 | handleAlignedAttr(S, D, AL); | |||
7848 | break; | |||
7849 | case ParsedAttr::AT_AlignValue: | |||
7850 | handleAlignValueAttr(S, D, AL); | |||
7851 | break; | |||
7852 | case ParsedAttr::AT_AllocSize: | |||
7853 | handleAllocSizeAttr(S, D, AL); | |||
7854 | break; | |||
7855 | case ParsedAttr::AT_AlwaysInline: | |||
7856 | handleAlwaysInlineAttr(S, D, AL); | |||
7857 | break; | |||
7858 | case ParsedAttr::AT_AnalyzerNoReturn: | |||
7859 | handleAnalyzerNoReturnAttr(S, D, AL); | |||
7860 | break; | |||
7861 | case ParsedAttr::AT_TLSModel: | |||
7862 | handleTLSModelAttr(S, D, AL); | |||
7863 | break; | |||
7864 | case ParsedAttr::AT_Annotate: | |||
7865 | handleAnnotateAttr(S, D, AL); | |||
7866 | break; | |||
7867 | case ParsedAttr::AT_Availability: | |||
7868 | handleAvailabilityAttr(S, D, AL); | |||
7869 | break; | |||
7870 | case ParsedAttr::AT_CarriesDependency: | |||
7871 | handleDependencyAttr(S, scope, D, AL); | |||
7872 | break; | |||
7873 | case ParsedAttr::AT_CPUDispatch: | |||
7874 | case ParsedAttr::AT_CPUSpecific: | |||
7875 | handleCPUSpecificAttr(S, D, AL); | |||
7876 | break; | |||
7877 | case ParsedAttr::AT_Common: | |||
7878 | handleCommonAttr(S, D, AL); | |||
7879 | break; | |||
7880 | case ParsedAttr::AT_CUDAConstant: | |||
7881 | handleConstantAttr(S, D, AL); | |||
7882 | break; | |||
7883 | case ParsedAttr::AT_PassObjectSize: | |||
7884 | handlePassObjectSizeAttr(S, D, AL); | |||
7885 | break; | |||
7886 | case ParsedAttr::AT_Constructor: | |||
7887 | handleConstructorAttr(S, D, AL); | |||
7888 | break; | |||
7889 | case ParsedAttr::AT_Deprecated: | |||
7890 | handleDeprecatedAttr(S, D, AL); | |||
7891 | break; | |||
7892 | case ParsedAttr::AT_Destructor: | |||
7893 | handleDestructorAttr(S, D, AL); | |||
7894 | break; | |||
7895 | case ParsedAttr::AT_EnableIf: | |||
7896 | handleEnableIfAttr(S, D, AL); | |||
7897 | break; | |||
7898 | case ParsedAttr::AT_DiagnoseIf: | |||
7899 | handleDiagnoseIfAttr(S, D, AL); | |||
7900 | break; | |||
7901 | case ParsedAttr::AT_NoBuiltin: | |||
7902 | handleNoBuiltinAttr(S, D, AL); | |||
7903 | break; | |||
7904 | case ParsedAttr::AT_ExtVectorType: | |||
7905 | handleExtVectorTypeAttr(S, D, AL); | |||
7906 | break; | |||
7907 | case ParsedAttr::AT_ExternalSourceSymbol: | |||
7908 | handleExternalSourceSymbolAttr(S, D, AL); | |||
7909 | break; | |||
7910 | case ParsedAttr::AT_MinSize: | |||
7911 | handleMinSizeAttr(S, D, AL); | |||
7912 | break; | |||
7913 | case ParsedAttr::AT_OptimizeNone: | |||
7914 | handleOptimizeNoneAttr(S, D, AL); | |||
7915 | break; | |||
7916 | case ParsedAttr::AT_EnumExtensibility: | |||
7917 | handleEnumExtensibilityAttr(S, D, AL); | |||
7918 | break; | |||
7919 | case ParsedAttr::AT_SYCLKernel: | |||
7920 | handleSYCLKernelAttr(S, D, AL); | |||
7921 | break; | |||
7922 | case ParsedAttr::AT_Format: | |||
7923 | handleFormatAttr(S, D, AL); | |||
7924 | break; | |||
7925 | case ParsedAttr::AT_FormatArg: | |||
7926 | handleFormatArgAttr(S, D, AL); | |||
7927 | break; | |||
7928 | case ParsedAttr::AT_Callback: | |||
7929 | handleCallbackAttr(S, D, AL); | |||
7930 | break; | |||
7931 | case ParsedAttr::AT_CalledOnce: | |||
7932 | handleCalledOnceAttr(S, D, AL); | |||
7933 | break; | |||
7934 | case ParsedAttr::AT_CUDAGlobal: | |||
7935 | handleGlobalAttr(S, D, AL); | |||
7936 | break; | |||
7937 | case ParsedAttr::AT_CUDADevice: | |||
7938 | handleDeviceAttr(S, D, AL); | |||
7939 | break; | |||
7940 | case ParsedAttr::AT_CUDAHost: | |||
7941 | handleSimpleAttributeWithExclusions<CUDAHostAttr, CUDAGlobalAttr>(S, D, AL); | |||
7942 | break; | |||
7943 | case ParsedAttr::AT_HIPManaged: | |||
7944 | handleManagedAttr(S, D, AL); | |||
7945 | break; | |||
7946 | case ParsedAttr::AT_CUDADeviceBuiltinSurfaceType: | |||
7947 | handleSimpleAttributeWithExclusions<CUDADeviceBuiltinSurfaceTypeAttr, | |||
7948 | CUDADeviceBuiltinTextureTypeAttr>(S, D, | |||
7949 | AL); | |||
7950 | break; | |||
7951 | case ParsedAttr::AT_CUDADeviceBuiltinTextureType: | |||
7952 | handleSimpleAttributeWithExclusions<CUDADeviceBuiltinTextureTypeAttr, | |||
7953 | CUDADeviceBuiltinSurfaceTypeAttr>(S, D, | |||
7954 | AL); | |||
7955 | break; | |||
7956 | case ParsedAttr::AT_GNUInline: | |||
7957 | handleGNUInlineAttr(S, D, AL); | |||
7958 | break; | |||
7959 | case ParsedAttr::AT_CUDALaunchBounds: | |||
7960 | handleLaunchBoundsAttr(S, D, AL); | |||
7961 | break; | |||
7962 | case ParsedAttr::AT_Restrict: | |||
7963 | handleRestrictAttr(S, D, AL); | |||
7964 | break; | |||
7965 | case ParsedAttr::AT_Mode: | |||
7966 | handleModeAttr(S, D, AL); | |||
7967 | break; | |||
7968 | case ParsedAttr::AT_NonNull: | |||
7969 | if (auto *PVD = dyn_cast<ParmVarDecl>(D)) | |||
7970 | handleNonNullAttrParameter(S, PVD, AL); | |||
7971 | else | |||
7972 | handleNonNullAttr(S, D, AL); | |||
7973 | break; | |||
7974 | case ParsedAttr::AT_ReturnsNonNull: | |||
7975 | handleReturnsNonNullAttr(S, D, AL); | |||
7976 | break; | |||
7977 | case ParsedAttr::AT_NoEscape: | |||
7978 | handleNoEscapeAttr(S, D, AL); | |||
7979 | break; | |||
7980 | case ParsedAttr::AT_AssumeAligned: | |||
7981 | handleAssumeAlignedAttr(S, D, AL); | |||
7982 | break; | |||
7983 | case ParsedAttr::AT_AllocAlign: | |||
7984 | handleAllocAlignAttr(S, D, AL); | |||
7985 | break; | |||
7986 | case ParsedAttr::AT_Ownership: | |||
7987 | handleOwnershipAttr(S, D, AL); | |||
7988 | break; | |||
7989 | case ParsedAttr::AT_Cold: | |||
7990 | handleSimpleAttributeWithExclusions<ColdAttr, HotAttr>(S, D, AL); | |||
7991 | break; | |||
7992 | case ParsedAttr::AT_Hot: | |||
7993 | handleSimpleAttributeWithExclusions<HotAttr, ColdAttr>(S, D, AL); | |||
7994 | break; | |||
7995 | case ParsedAttr::AT_Naked: | |||
7996 | handleNakedAttr(S, D, AL); | |||
7997 | break; | |||
7998 | case ParsedAttr::AT_NoReturn: | |||
7999 | handleNoReturnAttr(S, D, AL); | |||
8000 | break; | |||
8001 | case ParsedAttr::AT_AnyX86NoCfCheck: | |||
8002 | handleNoCfCheckAttr(S, D, AL); | |||
8003 | break; | |||
8004 | case ParsedAttr::AT_Leaf: | |||
8005 | handleSimpleAttribute<LeafAttr>(S, D, AL); | |||
8006 | break; | |||
8007 | case ParsedAttr::AT_NoThrow: | |||
8008 | if (!AL.isUsedAsTypeAttr()) | |||
8009 | handleSimpleAttribute<NoThrowAttr>(S, D, AL); | |||
8010 | break; | |||
8011 | case ParsedAttr::AT_CUDAShared: | |||
8012 | handleSharedAttr(S, D, AL); | |||
8013 | break; | |||
8014 | case ParsedAttr::AT_VecReturn: | |||
8015 | handleVecReturnAttr(S, D, AL); | |||
8016 | break; | |||
8017 | case ParsedAttr::AT_ObjCOwnership: | |||
8018 | handleObjCOwnershipAttr(S, D, AL); | |||
8019 | break; | |||
8020 | case ParsedAttr::AT_ObjCPreciseLifetime: | |||
8021 | handleObjCPreciseLifetimeAttr(S, D, AL); | |||
8022 | break; | |||
8023 | case ParsedAttr::AT_ObjCReturnsInnerPointer: | |||
8024 | handleObjCReturnsInnerPointerAttr(S, D, AL); | |||
8025 | break; | |||
8026 | case ParsedAttr::AT_ObjCRequiresSuper: | |||
8027 | handleObjCRequiresSuperAttr(S, D, AL); | |||
8028 | break; | |||
8029 | case ParsedAttr::AT_ObjCBridge: | |||
8030 | handleObjCBridgeAttr(S, D, AL); | |||
8031 | break; | |||
8032 | case ParsedAttr::AT_ObjCBridgeMutable: | |||
8033 | handleObjCBridgeMutableAttr(S, D, AL); | |||
8034 | break; | |||
8035 | case ParsedAttr::AT_ObjCBridgeRelated: | |||
8036 | handleObjCBridgeRelatedAttr(S, D, AL); | |||
8037 | break; | |||
8038 | case ParsedAttr::AT_ObjCDesignatedInitializer: | |||
8039 | handleObjCDesignatedInitializer(S, D, AL); | |||
8040 | break; | |||
8041 | case ParsedAttr::AT_ObjCRuntimeName: | |||
8042 | handleObjCRuntimeName(S, D, AL); | |||
8043 | break; | |||
8044 | case ParsedAttr::AT_ObjCBoxable: | |||
8045 | handleObjCBoxable(S, D, AL); | |||
8046 | break; | |||
8047 | case ParsedAttr::AT_NSErrorDomain: | |||
8048 | handleNSErrorDomain(S, D, AL); | |||
8049 | break; | |||
8050 | case ParsedAttr::AT_CFAuditedTransfer: | |||
8051 | handleSimpleAttributeWithExclusions<CFAuditedTransferAttr, | |||
8052 | CFUnknownTransferAttr>(S, D, AL); | |||
8053 | break; | |||
8054 | case ParsedAttr::AT_CFUnknownTransfer: | |||
8055 | handleSimpleAttributeWithExclusions<CFUnknownTransferAttr, | |||
8056 | CFAuditedTransferAttr>(S, D, AL); | |||
8057 | break; | |||
8058 | case ParsedAttr::AT_CFConsumed: | |||
8059 | case ParsedAttr::AT_NSConsumed: | |||
8060 | case ParsedAttr::AT_OSConsumed: | |||
8061 | S.AddXConsumedAttr(D, AL, parsedAttrToRetainOwnershipKind(AL), | |||
8062 | /*IsTemplateInstantiation=*/false); | |||
8063 | break; | |||
8064 | case ParsedAttr::AT_OSReturnsRetainedOnZero: | |||
8065 | handleSimpleAttributeOrDiagnose<OSReturnsRetainedOnZeroAttr>( | |||
8066 | S, D, AL, isValidOSObjectOutParameter(D), | |||
8067 | diag::warn_ns_attribute_wrong_parameter_type, | |||
8068 | /*Extra Args=*/AL, /*pointer-to-OSObject-pointer*/ 3, AL.getRange()); | |||
8069 | break; | |||
8070 | case ParsedAttr::AT_OSReturnsRetainedOnNonZero: | |||
8071 | handleSimpleAttributeOrDiagnose<OSReturnsRetainedOnNonZeroAttr>( | |||
8072 | S, D, AL, isValidOSObjectOutParameter(D), | |||
8073 | diag::warn_ns_attribute_wrong_parameter_type, | |||
8074 | /*Extra Args=*/AL, /*pointer-to-OSObject-poointer*/ 3, AL.getRange()); | |||
8075 | break; | |||
8076 | case ParsedAttr::AT_NSReturnsAutoreleased: | |||
8077 | case ParsedAttr::AT_NSReturnsNotRetained: | |||
8078 | case ParsedAttr::AT_NSReturnsRetained: | |||
8079 | case ParsedAttr::AT_CFReturnsNotRetained: | |||
8080 | case ParsedAttr::AT_CFReturnsRetained: | |||
8081 | case ParsedAttr::AT_OSReturnsNotRetained: | |||
8082 | case ParsedAttr::AT_OSReturnsRetained: | |||
8083 | handleXReturnsXRetainedAttr(S, D, AL); | |||
8084 | break; | |||
8085 | case ParsedAttr::AT_WorkGroupSizeHint: | |||
8086 | handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, AL); | |||
8087 | break; | |||
8088 | case ParsedAttr::AT_ReqdWorkGroupSize: | |||
8089 | handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, AL); | |||
8090 | break; | |||
8091 | case ParsedAttr::AT_OpenCLIntelReqdSubGroupSize: | |||
8092 | handleSubGroupSize(S, D, AL); | |||
8093 | break; | |||
8094 | case ParsedAttr::AT_VecTypeHint: | |||
8095 | handleVecTypeHint(S, D, AL); | |||
8096 | break; | |||
8097 | case ParsedAttr::AT_InitPriority: | |||
8098 | if (S.Context.getTargetInfo().getTriple().isOSAIX()) | |||
8099 | llvm::report_fatal_error( | |||
8100 | "'init_priority' attribute is not yet supported on AIX"); | |||
8101 | else | |||
8102 | handleInitPriorityAttr(S, D, AL); | |||
8103 | break; | |||
8104 | case ParsedAttr::AT_Packed: | |||
8105 | handlePackedAttr(S, D, AL); | |||
8106 | break; | |||
8107 | case ParsedAttr::AT_PreferredName: | |||
8108 | handlePreferredName(S, D, AL); | |||
8109 | break; | |||
8110 | case ParsedAttr::AT_Section: | |||
8111 | handleSectionAttr(S, D, AL); | |||
8112 | break; | |||
8113 | case ParsedAttr::AT_SpeculativeLoadHardening: | |||
8114 | handleSimpleAttributeWithExclusions<SpeculativeLoadHardeningAttr, | |||
8115 | NoSpeculativeLoadHardeningAttr>(S, D, | |||
8116 | AL); | |||
8117 | break; | |||
8118 | case ParsedAttr::AT_NoSpeculativeLoadHardening: | |||
8119 | handleSimpleAttributeWithExclusions<NoSpeculativeLoadHardeningAttr, | |||
8120 | SpeculativeLoadHardeningAttr>(S, D, AL); | |||
8121 | break; | |||
8122 | case ParsedAttr::AT_CodeSeg: | |||
8123 | handleCodeSegAttr(S, D, AL); | |||
8124 | break; | |||
8125 | case ParsedAttr::AT_Target: | |||
8126 | handleTargetAttr(S, D, AL); | |||
8127 | break; | |||
8128 | case ParsedAttr::AT_MinVectorWidth: | |||
8129 | handleMinVectorWidthAttr(S, D, AL); | |||
8130 | break; | |||
8131 | case ParsedAttr::AT_Unavailable: | |||
8132 | handleAttrWithMessage<UnavailableAttr>(S, D, AL); | |||
8133 | break; | |||
8134 | case ParsedAttr::AT_Assumption: | |||
8135 | handleAssumumptionAttr(S, D, AL); | |||
8136 | break; | |||
8137 | case ParsedAttr::AT_ObjCDirect: | |||
8138 | handleObjCDirectAttr(S, D, AL); | |||
8139 | break; | |||
8140 | case ParsedAttr::AT_ObjCNonRuntimeProtocol: | |||
8141 | handleObjCNonRuntimeProtocolAttr(S, D, AL); | |||
8142 | break; | |||
8143 | case ParsedAttr::AT_ObjCDirectMembers: | |||
8144 | handleObjCDirectMembersAttr(S, D, AL); | |||
8145 | handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL); | |||
8146 | break; | |||
8147 | case ParsedAttr::AT_ObjCExplicitProtocolImpl: | |||
8148 | handleObjCSuppresProtocolAttr(S, D, AL); | |||
8149 | break; | |||
8150 | case ParsedAttr::AT_Unused: | |||
8151 | handleUnusedAttr(S, D, AL); | |||
8152 | break; | |||
8153 | case ParsedAttr::AT_NotTailCalled: | |||
8154 | handleSimpleAttributeWithExclusions<NotTailCalledAttr, AlwaysInlineAttr>( | |||
8155 | S, D, AL); | |||
8156 | break; | |||
8157 | case ParsedAttr::AT_DisableTailCalls: | |||
8158 | handleSimpleAttributeWithExclusions<DisableTailCallsAttr, NakedAttr>(S, D, | |||
8159 | AL); | |||
8160 | break; | |||
8161 | case ParsedAttr::AT_NoMerge: | |||
8162 | handleSimpleAttribute<NoMergeAttr>(S, D, AL); | |||
8163 | break; | |||
8164 | case ParsedAttr::AT_Visibility: | |||
8165 | handleVisibilityAttr(S, D, AL, false); | |||
8166 | break; | |||
8167 | case ParsedAttr::AT_TypeVisibility: | |||
8168 | handleVisibilityAttr(S, D, AL, true); | |||
8169 | break; | |||
8170 | case ParsedAttr::AT_WarnUnusedResult: | |||
8171 | handleWarnUnusedResult(S, D, AL); | |||
8172 | break; | |||
8173 | case ParsedAttr::AT_WeakRef: | |||
8174 | handleWeakRefAttr(S, D, AL); | |||
8175 | break; | |||
8176 | case ParsedAttr::AT_WeakImport: | |||
8177 | handleWeakImportAttr(S, D, AL); | |||
8178 | break; | |||
8179 | case ParsedAttr::AT_TransparentUnion: | |||
8180 | handleTransparentUnionAttr(S, D, AL); | |||
8181 | break; | |||
8182 | case ParsedAttr::AT_ObjCMethodFamily: | |||
8183 | handleObjCMethodFamilyAttr(S, D, AL); | |||
8184 | break; | |||
8185 | case ParsedAttr::AT_ObjCNSObject: | |||
8186 | handleObjCNSObject(S, D, AL); | |||
8187 | break; | |||
8188 | case ParsedAttr::AT_ObjCIndependentClass: | |||
8189 | handleObjCIndependentClass(S, D, AL); | |||
8190 | break; | |||
8191 | case ParsedAttr::AT_Blocks: | |||
8192 | handleBlocksAttr(S, D, AL); | |||
8193 | break; | |||
8194 | case ParsedAttr::AT_Sentinel: | |||
8195 | handleSentinelAttr(S, D, AL); | |||
8196 | break; | |||
8197 | case ParsedAttr::AT_Cleanup: | |||
8198 | handleCleanupAttr(S, D, AL); | |||
8199 | break; | |||
8200 | case ParsedAttr::AT_NoDebug: | |||
8201 | handleNoDebugAttr(S, D, AL); | |||
8202 | break; | |||
8203 | case ParsedAttr::AT_CmseNSEntry: | |||
8204 | handleCmseNSEntryAttr(S, D, AL); | |||
8205 | break; | |||
8206 | case ParsedAttr::AT_StdCall: | |||
8207 | case ParsedAttr::AT_CDecl: | |||
8208 | case ParsedAttr::AT_FastCall: | |||
8209 | case ParsedAttr::AT_ThisCall: | |||
8210 | case ParsedAttr::AT_Pascal: | |||
8211 | case ParsedAttr::AT_RegCall: | |||
8212 | case ParsedAttr::AT_SwiftCall: | |||
8213 | case ParsedAttr::AT_VectorCall: | |||
8214 | case ParsedAttr::AT_MSABI: | |||
8215 | case ParsedAttr::AT_SysVABI: | |||
8216 | case ParsedAttr::AT_Pcs: | |||
8217 | case ParsedAttr::AT_IntelOclBicc: | |||
8218 | case ParsedAttr::AT_PreserveMost: | |||
8219 | case ParsedAttr::AT_PreserveAll: | |||
8220 | case ParsedAttr::AT_AArch64VectorPcs: | |||
8221 | handleCallConvAttr(S, D, AL); | |||
8222 | break; | |||
8223 | case ParsedAttr::AT_Suppress: | |||
8224 | handleSuppressAttr(S, D, AL); | |||
8225 | break; | |||
8226 | case ParsedAttr::AT_Owner: | |||
8227 | case ParsedAttr::AT_Pointer: | |||
8228 | handleLifetimeCategoryAttr(S, D, AL); | |||
8229 | break; | |||
8230 | case ParsedAttr::AT_OpenCLAccess: | |||
8231 | handleOpenCLAccessAttr(S, D, AL); | |||
8232 | break; | |||
8233 | case ParsedAttr::AT_OpenCLNoSVM: | |||
8234 | handleOpenCLNoSVMAttr(S, D, AL); | |||
8235 | break; | |||
8236 | case ParsedAttr::AT_SwiftContext: | |||
8237 | S.AddParameterABIAttr(D, AL, ParameterABI::SwiftContext); | |||
8238 | break; | |||
8239 | case ParsedAttr::AT_SwiftErrorResult: | |||
8240 | S.AddParameterABIAttr(D, AL, ParameterABI::SwiftErrorResult); | |||
8241 | break; | |||
8242 | case ParsedAttr::AT_SwiftIndirectResult: | |||
8243 | S.AddParameterABIAttr(D, AL, ParameterABI::SwiftIndirectResult); | |||
8244 | break; | |||
8245 | case ParsedAttr::AT_InternalLinkage: | |||
8246 | handleInternalLinkageAttr(S, D, AL); | |||
8247 | break; | |||
8248 | ||||
8249 | // Microsoft attributes: | |||
8250 | case ParsedAttr::AT_LayoutVersion: | |||
8251 | handleLayoutVersion(S, D, AL); | |||
8252 | break; | |||
8253 | case ParsedAttr::AT_Uuid: | |||
8254 | handleUuidAttr(S, D, AL); | |||
8255 | break; | |||
8256 | case ParsedAttr::AT_MSInheritance: | |||
8257 | handleMSInheritanceAttr(S, D, AL); | |||
8258 | break; | |||
8259 | case ParsedAttr::AT_Thread: | |||
8260 | handleDeclspecThreadAttr(S, D, AL); | |||
8261 | break; | |||
8262 | ||||
8263 | case ParsedAttr::AT_AbiTag: | |||
8264 | handleAbiTagAttr(S, D, AL); | |||
8265 | break; | |||
8266 | case ParsedAttr::AT_CFGuard: | |||
8267 | handleCFGuardAttr(S, D, AL); | |||
8268 | break; | |||
8269 | ||||
8270 | // Thread safety attributes: | |||
8271 | case ParsedAttr::AT_AssertExclusiveLock: | |||
8272 | handleAssertExclusiveLockAttr(S, D, AL); | |||
8273 | break; | |||
8274 | case ParsedAttr::AT_AssertSharedLock: | |||
8275 | handleAssertSharedLockAttr(S, D, AL); | |||
8276 | break; | |||
8277 | case ParsedAttr::AT_PtGuardedVar: | |||
8278 | handlePtGuardedVarAttr(S, D, AL); | |||
8279 | break; | |||
8280 | case ParsedAttr::AT_NoSanitize: | |||
8281 | handleNoSanitizeAttr(S, D, AL); | |||
8282 | break; | |||
8283 | case ParsedAttr::AT_NoSanitizeSpecific: | |||
8284 | handleNoSanitizeSpecificAttr(S, D, AL); | |||
8285 | break; | |||
8286 | case ParsedAttr::AT_GuardedBy: | |||
8287 | handleGuardedByAttr(S, D, AL); | |||
8288 | break; | |||
8289 | case ParsedAttr::AT_PtGuardedBy: | |||
8290 | handlePtGuardedByAttr(S, D, AL); | |||
8291 | break; | |||
8292 | case ParsedAttr::AT_ExclusiveTrylockFunction: | |||
8293 | handleExclusiveTrylockFunctionAttr(S, D, AL); | |||
8294 | break; | |||
8295 | case ParsedAttr::AT_LockReturned: | |||
8296 | handleLockReturnedAttr(S, D, AL); | |||
8297 | break; | |||
8298 | case ParsedAttr::AT_LocksExcluded: | |||
8299 | handleLocksExcludedAttr(S, D, AL); | |||
8300 | break; | |||
8301 | case ParsedAttr::AT_SharedTrylockFunction: | |||
8302 | handleSharedTrylockFunctionAttr(S, D, AL); | |||
8303 | break; | |||
8304 | case ParsedAttr::AT_AcquiredBefore: | |||
8305 | handleAcquiredBeforeAttr(S, D, AL); | |||
8306 | break; | |||
8307 | case ParsedAttr::AT_AcquiredAfter: | |||
8308 | handleAcquiredAfterAttr(S, D, AL); | |||
8309 | break; | |||
8310 | ||||
8311 | // Capability analysis attributes. | |||
8312 | case ParsedAttr::AT_Capability: | |||
8313 | case ParsedAttr::AT_Lockable: | |||
8314 | handleCapabilityAttr(S, D, AL); | |||
8315 | break; | |||
8316 | case ParsedAttr::AT_RequiresCapability: | |||
8317 | handleRequiresCapabilityAttr(S, D, AL); | |||
8318 | break; | |||
8319 | ||||
8320 | case ParsedAttr::AT_AssertCapability: | |||
8321 | handleAssertCapabilityAttr(S, D, AL); | |||
8322 | break; | |||
8323 | case ParsedAttr::AT_AcquireCapability: | |||
8324 | handleAcquireCapabilityAttr(S, D, AL); | |||
8325 | break; | |||
8326 | case ParsedAttr::AT_ReleaseCapability: | |||
8327 | handleReleaseCapabilityAttr(S, D, AL); | |||
8328 | break; | |||
8329 | case ParsedAttr::AT_TryAcquireCapability: | |||
8330 | handleTryAcquireCapabilityAttr(S, D, AL); | |||
8331 | break; | |||
8332 | ||||
8333 | // Consumed analysis attributes. | |||
8334 | case ParsedAttr::AT_Consumable: | |||
8335 | handleConsumableAttr(S, D, AL); | |||
8336 | break; | |||
8337 | case ParsedAttr::AT_CallableWhen: | |||
8338 | handleCallableWhenAttr(S, D, AL); | |||
8339 | break; | |||
8340 | case ParsedAttr::AT_ParamTypestate: | |||
8341 | handleParamTypestateAttr(S, D, AL); | |||
8342 | break; | |||
8343 | case ParsedAttr::AT_ReturnTypestate: | |||
8344 | handleReturnTypestateAttr(S, D, AL); | |||
8345 | break; | |||
8346 | case ParsedAttr::AT_SetTypestate: | |||
8347 | handleSetTypestateAttr(S, D, AL); | |||
8348 | break; | |||
8349 | case ParsedAttr::AT_TestTypestate: | |||
8350 | handleTestTypestateAttr(S, D, AL); | |||
8351 | break; | |||
8352 | ||||
8353 | // Type safety attributes. | |||
8354 | case ParsedAttr::AT_ArgumentWithTypeTag: | |||
8355 | handleArgumentWithTypeTagAttr(S, D, AL); | |||
8356 | break; | |||
8357 | case ParsedAttr::AT_TypeTagForDatatype: | |||
8358 | handleTypeTagForDatatypeAttr(S, D, AL); | |||
8359 | break; | |||
8360 | ||||
8361 | // Swift attributes. | |||
8362 | case ParsedAttr::AT_SwiftAsyncName: | |||
8363 | handleSwiftAsyncName(S, D, AL); | |||
8364 | break; | |||
8365 | case ParsedAttr::AT_SwiftAttr: | |||
8366 | handleSwiftAttrAttr(S, D, AL); | |||
8367 | break; | |||
8368 | case ParsedAttr::AT_SwiftBridge: | |||
8369 | handleSwiftBridge(S, D, AL); | |||
8370 | break; | |||
8371 | case ParsedAttr::AT_SwiftBridgedTypedef: | |||
8372 | handleSimpleAttribute<SwiftBridgedTypedefAttr>(S, D, AL); | |||
8373 | break; | |||
8374 | case ParsedAttr::AT_SwiftError: | |||
8375 | handleSwiftError(S, D, AL); | |||
8376 | break; | |||
8377 | case ParsedAttr::AT_SwiftName: | |||
8378 | handleSwiftName(S, D, AL); | |||
8379 | break; | |||
8380 | case ParsedAttr::AT_SwiftNewType: | |||
8381 | handleSwiftNewType(S, D, AL); | |||
8382 | break; | |||
8383 | case ParsedAttr::AT_SwiftObjCMembers: | |||
8384 | handleSimpleAttribute<SwiftObjCMembersAttr>(S, D, AL); | |||
8385 | break; | |||
8386 | case ParsedAttr::AT_SwiftPrivate: | |||
8387 | handleSimpleAttribute<SwiftPrivateAttr>(S, D, AL); | |||
8388 | break; | |||
8389 | case ParsedAttr::AT_SwiftAsync: | |||
8390 | handleSwiftAsyncAttr(S, D, AL); | |||
8391 | break; | |||
8392 | case ParsedAttr::AT_SwiftAsyncError: | |||
8393 | handleSwiftAsyncError(S, D, AL); | |||
8394 | break; | |||
8395 | ||||
8396 | // XRay attributes. | |||
8397 | case ParsedAttr::AT_XRayLogArgs: | |||
8398 | handleXRayLogArgsAttr(S, D, AL); | |||
8399 | break; | |||
8400 | ||||
8401 | case ParsedAttr::AT_PatchableFunctionEntry: | |||
8402 | handlePatchableFunctionEntryAttr(S, D, AL); | |||
8403 | break; | |||
8404 | ||||
8405 | case ParsedAttr::AT_AlwaysDestroy: | |||
8406 | case ParsedAttr::AT_NoDestroy: | |||
8407 | handleDestroyAttr(S, D, AL); | |||
8408 | break; | |||
8409 | ||||
8410 | case ParsedAttr::AT_Uninitialized: | |||
8411 | handleUninitializedAttr(S, D, AL); | |||
8412 | break; | |||
8413 | ||||
8414 | case ParsedAttr::AT_LoaderUninitialized: | |||
8415 | handleSimpleAttribute<LoaderUninitializedAttr>(S, D, AL); | |||
8416 | break; | |||
8417 | ||||
8418 | case ParsedAttr::AT_ObjCExternallyRetained: | |||
8419 | handleObjCExternallyRetainedAttr(S, D, AL); | |||
8420 | break; | |||
8421 | ||||
8422 | case ParsedAttr::AT_MIGServerRoutine: | |||
8423 | handleMIGServerRoutineAttr(S, D, AL); | |||
8424 | break; | |||
8425 | ||||
8426 | case ParsedAttr::AT_MSAllocator: | |||
8427 | handleMSAllocatorAttr(S, D, AL); | |||
8428 | break; | |||
8429 | ||||
8430 | case ParsedAttr::AT_ArmBuiltinAlias: | |||
8431 | handleArmBuiltinAliasAttr(S, D, AL); | |||
8432 | break; | |||
8433 | ||||
8434 | case ParsedAttr::AT_AcquireHandle: | |||
8435 | handleAcquireHandleAttr(S, D, AL); | |||
8436 | break; | |||
8437 | ||||
8438 | case ParsedAttr::AT_ReleaseHandle: | |||
8439 | handleHandleAttr<ReleaseHandleAttr>(S, D, AL); | |||
8440 | break; | |||
8441 | ||||
8442 | case ParsedAttr::AT_UseHandle: | |||
8443 | handleHandleAttr<UseHandleAttr>(S, D, AL); | |||
8444 | break; | |||
8445 | ||||
8446 | case ParsedAttr::AT_EnforceTCB: | |||
8447 | handleEnforceTCBAttr<EnforceTCBAttr, EnforceTCBLeafAttr>(S, D, AL); | |||
8448 | break; | |||
8449 | ||||
8450 | case ParsedAttr::AT_EnforceTCBLeaf: | |||
8451 | handleEnforceTCBAttr<EnforceTCBLeafAttr, EnforceTCBAttr>(S, D, AL); | |||
8452 | break; | |||
8453 | } | |||
8454 | } | |||
8455 | ||||
8456 | /// ProcessDeclAttributeList - Apply all the decl attributes in the specified | |||
8457 | /// attribute list to the specified decl, ignoring any type attributes. | |||
8458 | void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, | |||
8459 | const ParsedAttributesView &AttrList, | |||
8460 | bool IncludeCXX11Attributes) { | |||
8461 | if (AttrList.empty()) | |||
8462 | return; | |||
8463 | ||||
8464 | for (const ParsedAttr &AL : AttrList) | |||
8465 | ProcessDeclAttribute(*this, S, D, AL, IncludeCXX11Attributes); | |||
8466 | ||||
8467 | // FIXME: We should be able to handle these cases in TableGen. | |||
8468 | // GCC accepts | |||
8469 | // static int a9 __attribute__((weakref)); | |||
8470 | // but that looks really pointless. We reject it. | |||
8471 | if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) { | |||
8472 | Diag(AttrList.begin()->getLoc(), diag::err_attribute_weakref_without_alias) | |||
8473 | << cast<NamedDecl>(D); | |||
8474 | D->dropAttr<WeakRefAttr>(); | |||
8475 | return; | |||
8476 | } | |||
8477 | ||||
8478 | // FIXME: We should be able to handle this in TableGen as well. It would be | |||
8479 | // good to have a way to specify "these attributes must appear as a group", | |||
8480 | // for these. Additionally, it would be good to have a way to specify "these | |||
8481 | // attribute must never appear as a group" for attributes like cold and hot. | |||
8482 | if (!D->hasAttr<OpenCLKernelAttr>()) { | |||
8483 | // These attributes cannot be applied to a non-kernel function. | |||
8484 | if (const auto *A = D->getAttr<ReqdWorkGroupSizeAttr>()) { | |||
8485 | // FIXME: This emits a different error message than | |||
8486 | // diag::err_attribute_wrong_decl_type + ExpectedKernelFunction. | |||
8487 | Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A; | |||
8488 | D->setInvalidDecl(); | |||
8489 | } else if (const auto *A = D->getAttr<WorkGroupSizeHintAttr>()) { | |||
8490 | Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A; | |||
8491 | D->setInvalidDecl(); | |||
8492 | } else if (const auto *A = D->getAttr<VecTypeHintAttr>()) { | |||
8493 | Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A; | |||
8494 | D->setInvalidDecl(); | |||
8495 | } else if (const auto *A = D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>()) { | |||
8496 | Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A; | |||
8497 | D->setInvalidDecl(); | |||
8498 | } else if (!D->hasAttr<CUDAGlobalAttr>()) { | |||
8499 | if (const auto *A = D->getAttr<AMDGPUFlatWorkGroupSizeAttr>()) { | |||
8500 | Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) | |||
8501 | << A << ExpectedKernelFunction; | |||
8502 | D->setInvalidDecl(); | |||
8503 | } else if (const auto *A = D->getAttr<AMDGPUWavesPerEUAttr>()) { | |||
8504 | Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) | |||
8505 | << A << ExpectedKernelFunction; | |||
8506 | D->setInvalidDecl(); | |||
8507 | } else if (const auto *A = D->getAttr<AMDGPUNumSGPRAttr>()) { | |||
8508 | Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) | |||
8509 | << A << ExpectedKernelFunction; | |||
8510 | D->setInvalidDecl(); | |||
8511 | } else if (const auto *A = D->getAttr<AMDGPUNumVGPRAttr>()) { | |||
8512 | Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) | |||
8513 | << A << ExpectedKernelFunction; | |||
8514 | D->setInvalidDecl(); | |||
8515 | } | |||
8516 | } | |||
8517 | } | |||
8518 | ||||
8519 | // Do this check after processing D's attributes because the attribute | |||
8520 | // objc_method_family can change whether the given method is in the init | |||
8521 | // family, and it can be applied after objc_designated_initializer. This is a | |||
8522 | // bit of a hack, but we need it to be compatible with versions of clang that | |||
8523 | // processed the attribute list in the wrong order. | |||
8524 | if (D->hasAttr<ObjCDesignatedInitializerAttr>() && | |||
8525 | cast<ObjCMethodDecl>(D)->getMethodFamily() != OMF_init) { | |||
8526 | Diag(D->getLocation(), diag::err_designated_init_attr_non_init); | |||
8527 | D->dropAttr<ObjCDesignatedInitializerAttr>(); | |||
8528 | } | |||
8529 | } | |||
8530 | ||||
8531 | // Helper for delayed processing TransparentUnion or BPFPreserveAccessIndexAttr | |||
8532 | // attribute. | |||
8533 | void Sema::ProcessDeclAttributeDelayed(Decl *D, | |||
8534 | const ParsedAttributesView &AttrList) { | |||
8535 | for (const ParsedAttr &AL : AttrList) | |||
8536 | if (AL.getKind() == ParsedAttr::AT_TransparentUnion) { | |||
8537 | handleTransparentUnionAttr(*this, D, AL); | |||
8538 | break; | |||
8539 | } | |||
8540 | ||||
8541 | // For BPFPreserveAccessIndexAttr, we want to populate the attributes | |||
8542 | // to fields and inner records as well. | |||
8543 | if (D && D->hasAttr<BPFPreserveAccessIndexAttr>()) | |||
8544 | handleBPFPreserveAIRecord(*this, cast<RecordDecl>(D)); | |||
8545 | } | |||
8546 | ||||
8547 | // Annotation attributes are the only attributes allowed after an access | |||
8548 | // specifier. | |||
8549 | bool Sema::ProcessAccessDeclAttributeList( | |||
8550 | AccessSpecDecl *ASDecl, const ParsedAttributesView &AttrList) { | |||
8551 | for (const ParsedAttr &AL : AttrList) { | |||
8552 | if (AL.getKind() == ParsedAttr::AT_Annotate) { | |||
8553 | ProcessDeclAttribute(*this, nullptr, ASDecl, AL, AL.isCXX11Attribute()); | |||
8554 | } else { | |||
8555 | Diag(AL.getLoc(), diag::err_only_annotate_after_access_spec); | |||
8556 | return true; | |||
8557 | } | |||
8558 | } | |||
8559 | return false; | |||
8560 | } | |||
8561 | ||||
8562 | /// checkUnusedDeclAttributes - Check a list of attributes to see if it | |||
8563 | /// contains any decl attributes that we should warn about. | |||
8564 | static void checkUnusedDeclAttributes(Sema &S, const ParsedAttributesView &A) { | |||
8565 | for (const ParsedAttr &AL : A) { | |||
8566 | // Only warn if the attribute is an unignored, non-type attribute. | |||
8567 | if (AL.isUsedAsTypeAttr() || AL.isInvalid()) | |||
8568 | continue; | |||
8569 | if (AL.getKind() == ParsedAttr::IgnoredAttribute) | |||
8570 | continue; | |||
8571 | ||||
8572 | if (AL.getKind() == ParsedAttr::UnknownAttribute) { | |||
8573 | S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) | |||
8574 | << AL << AL.getRange(); | |||
8575 | } else { | |||
8576 | S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl) << AL | |||
8577 | << AL.getRange(); | |||
8578 | } | |||
8579 | } | |||
8580 | } | |||
8581 | ||||
8582 | /// checkUnusedDeclAttributes - Given a declarator which is not being | |||
8583 | /// used to build a declaration, complain about any decl attributes | |||
8584 | /// which might be lying around on it. | |||
8585 | void Sema::checkUnusedDeclAttributes(Declarator &D) { | |||
8586 | ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes()); | |||
8587 | ::checkUnusedDeclAttributes(*this, D.getAttributes()); | |||
8588 | for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) | |||
8589 | ::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs()); | |||
8590 | } | |||
8591 | ||||
8592 | /// DeclClonePragmaWeak - clone existing decl (maybe definition), | |||
8593 | /// \#pragma weak needs a non-definition decl and source may not have one. | |||
8594 | NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, | |||
8595 | SourceLocation Loc) { | |||
8596 | assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND))((isa<FunctionDecl>(ND) || isa<VarDecl>(ND)) ? static_cast <void> (0) : __assert_fail ("isa<FunctionDecl>(ND) || isa<VarDecl>(ND)" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 8596, __PRETTY_FUNCTION__)); | |||
8597 | NamedDecl *NewD = nullptr; | |||
8598 | if (auto *FD = dyn_cast<FunctionDecl>(ND)) { | |||
8599 | FunctionDecl *NewFD; | |||
8600 | // FIXME: Missing call to CheckFunctionDeclaration(). | |||
8601 | // FIXME: Mangling? | |||
8602 | // FIXME: Is the qualifier info correct? | |||
8603 | // FIXME: Is the DeclContext correct? | |||
8604 | NewFD = FunctionDecl::Create( | |||
8605 | FD->getASTContext(), FD->getDeclContext(), Loc, Loc, | |||
8606 | DeclarationName(II), FD->getType(), FD->getTypeSourceInfo(), SC_None, | |||
8607 | false /*isInlineSpecified*/, FD->hasPrototype(), | |||
8608 | ConstexprSpecKind::Unspecified, FD->getTrailingRequiresClause()); | |||
8609 | NewD = NewFD; | |||
8610 | ||||
8611 | if (FD->getQualifier()) | |||
8612 | NewFD->setQualifierInfo(FD->getQualifierLoc()); | |||
8613 | ||||
8614 | // Fake up parameter variables; they are declared as if this were | |||
8615 | // a typedef. | |||
8616 | QualType FDTy = FD->getType(); | |||
8617 | if (const auto *FT = FDTy->getAs<FunctionProtoType>()) { | |||
8618 | SmallVector<ParmVarDecl*, 16> Params; | |||
8619 | for (const auto &AI : FT->param_types()) { | |||
8620 | ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, AI); | |||
8621 | Param->setScopeInfo(0, Params.size()); | |||
8622 | Params.push_back(Param); | |||
8623 | } | |||
8624 | NewFD->setParams(Params); | |||
8625 | } | |||
8626 | } else if (auto *VD = dyn_cast<VarDecl>(ND)) { | |||
8627 | NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(), | |||
8628 | VD->getInnerLocStart(), VD->getLocation(), II, | |||
8629 | VD->getType(), VD->getTypeSourceInfo(), | |||
8630 | VD->getStorageClass()); | |||
8631 | if (VD->getQualifier()) | |||
8632 | cast<VarDecl>(NewD)->setQualifierInfo(VD->getQualifierLoc()); | |||
8633 | } | |||
8634 | return NewD; | |||
8635 | } | |||
8636 | ||||
8637 | /// DeclApplyPragmaWeak - A declaration (maybe definition) needs \#pragma weak | |||
8638 | /// applied to it, possibly with an alias. | |||
8639 | void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) { | |||
8640 | if (W.getUsed()) return; // only do this once | |||
8641 | W.setUsed(true); | |||
8642 | if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...)) | |||
8643 | IdentifierInfo *NDId = ND->getIdentifier(); | |||
8644 | NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation()); | |||
8645 | NewD->addAttr( | |||
8646 | AliasAttr::CreateImplicit(Context, NDId->getName(), W.getLocation())); | |||
8647 | NewD->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation(), | |||
8648 | AttributeCommonInfo::AS_Pragma)); | |||
8649 | WeakTopLevelDecl.push_back(NewD); | |||
8650 | // FIXME: "hideous" code from Sema::LazilyCreateBuiltin | |||
8651 | // to insert Decl at TU scope, sorry. | |||
8652 | DeclContext *SavedContext = CurContext; | |||
8653 | CurContext = Context.getTranslationUnitDecl(); | |||
8654 | NewD->setDeclContext(CurContext); | |||
8655 | NewD->setLexicalDeclContext(CurContext); | |||
8656 | PushOnScopeChains(NewD, S); | |||
8657 | CurContext = SavedContext; | |||
8658 | } else { // just add weak to existing | |||
8659 | ND->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation(), | |||
8660 | AttributeCommonInfo::AS_Pragma)); | |||
8661 | } | |||
8662 | } | |||
8663 | ||||
8664 | void Sema::ProcessPragmaWeak(Scope *S, Decl *D) { | |||
8665 | // It's valid to "forward-declare" #pragma weak, in which case we | |||
8666 | // have to do this. | |||
8667 | LoadExternalWeakUndeclaredIdentifiers(); | |||
8668 | if (!WeakUndeclaredIdentifiers.empty()) { | |||
8669 | NamedDecl *ND = nullptr; | |||
8670 | if (auto *VD = dyn_cast<VarDecl>(D)) | |||
8671 | if (VD->isExternC()) | |||
8672 | ND = VD; | |||
8673 | if (auto *FD = dyn_cast<FunctionDecl>(D)) | |||
8674 | if (FD->isExternC()) | |||
8675 | ND = FD; | |||
8676 | if (ND) { | |||
8677 | if (IdentifierInfo *Id = ND->getIdentifier()) { | |||
8678 | auto I = WeakUndeclaredIdentifiers.find(Id); | |||
8679 | if (I != WeakUndeclaredIdentifiers.end()) { | |||
8680 | WeakInfo W = I->second; | |||
8681 | DeclApplyPragmaWeak(S, ND, W); | |||
8682 | WeakUndeclaredIdentifiers[Id] = W; | |||
8683 | } | |||
8684 | } | |||
8685 | } | |||
8686 | } | |||
8687 | } | |||
8688 | ||||
8689 | /// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in | |||
8690 | /// it, apply them to D. This is a bit tricky because PD can have attributes | |||
8691 | /// specified in many different places, and we need to find and apply them all. | |||
8692 | void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { | |||
8693 | // Apply decl attributes from the DeclSpec if present. | |||
8694 | if (!PD.getDeclSpec().getAttributes().empty()) | |||
8695 | ProcessDeclAttributeList(S, D, PD.getDeclSpec().getAttributes()); | |||
8696 | ||||
8697 | // Walk the declarator structure, applying decl attributes that were in a type | |||
8698 | // position to the decl itself. This handles cases like: | |||
8699 | // int *__attr__(x)** D; | |||
8700 | // when X is a decl attribute. | |||
8701 | for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) | |||
8702 | ProcessDeclAttributeList(S, D, PD.getTypeObject(i).getAttrs(), | |||
8703 | /*IncludeCXX11Attributes=*/false); | |||
8704 | ||||
8705 | // Finally, apply any attributes on the decl itself. | |||
8706 | ProcessDeclAttributeList(S, D, PD.getAttributes()); | |||
8707 | ||||
8708 | // Apply additional attributes specified by '#pragma clang attribute'. | |||
8709 | AddPragmaAttributes(S, D); | |||
8710 | } | |||
8711 | ||||
8712 | /// Is the given declaration allowed to use a forbidden type? | |||
8713 | /// If so, it'll still be annotated with an attribute that makes it | |||
8714 | /// illegal to actually use. | |||
8715 | static bool isForbiddenTypeAllowed(Sema &S, Decl *D, | |||
8716 | const DelayedDiagnostic &diag, | |||
8717 | UnavailableAttr::ImplicitReason &reason) { | |||
8718 | // Private ivars are always okay. Unfortunately, people don't | |||
8719 | // always properly make their ivars private, even in system headers. | |||
8720 | // Plus we need to make fields okay, too. | |||
8721 | if (!isa<FieldDecl>(D) && !isa<ObjCPropertyDecl>(D) && | |||
8722 | !isa<FunctionDecl>(D)) | |||
8723 | return false; | |||
8724 | ||||
8725 | // Silently accept unsupported uses of __weak in both user and system | |||
8726 | // declarations when it's been disabled, for ease of integration with | |||
8727 | // -fno-objc-arc files. We do have to take some care against attempts | |||
8728 | // to define such things; for now, we've only done that for ivars | |||
8729 | // and properties. | |||
8730 | if ((isa<ObjCIvarDecl>(D) || isa<ObjCPropertyDecl>(D))) { | |||
8731 | if (diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_disabled || | |||
8732 | diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_no_runtime) { | |||
8733 | reason = UnavailableAttr::IR_ForbiddenWeak; | |||
8734 | return true; | |||
8735 | } | |||
8736 | } | |||
8737 | ||||
8738 | // Allow all sorts of things in system headers. | |||
8739 | if (S.Context.getSourceManager().isInSystemHeader(D->getLocation())) { | |||
8740 | // Currently, all the failures dealt with this way are due to ARC | |||
8741 | // restrictions. | |||
8742 | reason = UnavailableAttr::IR_ARCForbiddenType; | |||
8743 | return true; | |||
8744 | } | |||
8745 | ||||
8746 | return false; | |||
8747 | } | |||
8748 | ||||
8749 | /// Handle a delayed forbidden-type diagnostic. | |||
8750 | static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &DD, | |||
8751 | Decl *D) { | |||
8752 | auto Reason = UnavailableAttr::IR_None; | |||
8753 | if (D && isForbiddenTypeAllowed(S, D, DD, Reason)) { | |||
8754 | assert(Reason && "didn't set reason?")((Reason && "didn't set reason?") ? static_cast<void > (0) : __assert_fail ("Reason && \"didn't set reason?\"" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 8754, __PRETTY_FUNCTION__)); | |||
8755 | D->addAttr(UnavailableAttr::CreateImplicit(S.Context, "", Reason, DD.Loc)); | |||
8756 | return; | |||
8757 | } | |||
8758 | if (S.getLangOpts().ObjCAutoRefCount) | |||
8759 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { | |||
8760 | // FIXME: we may want to suppress diagnostics for all | |||
8761 | // kind of forbidden type messages on unavailable functions. | |||
8762 | if (FD->hasAttr<UnavailableAttr>() && | |||
8763 | DD.getForbiddenTypeDiagnostic() == | |||
8764 | diag::err_arc_array_param_no_ownership) { | |||
8765 | DD.Triggered = true; | |||
8766 | return; | |||
8767 | } | |||
8768 | } | |||
8769 | ||||
8770 | S.Diag(DD.Loc, DD.getForbiddenTypeDiagnostic()) | |||
8771 | << DD.getForbiddenTypeOperand() << DD.getForbiddenTypeArgument(); | |||
8772 | DD.Triggered = true; | |||
8773 | } | |||
8774 | ||||
8775 | ||||
8776 | void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) { | |||
8777 | assert(DelayedDiagnostics.getCurrentPool())((DelayedDiagnostics.getCurrentPool()) ? static_cast<void> (0) : __assert_fail ("DelayedDiagnostics.getCurrentPool()", "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 8777, __PRETTY_FUNCTION__)); | |||
8778 | DelayedDiagnosticPool &poppedPool = *DelayedDiagnostics.getCurrentPool(); | |||
8779 | DelayedDiagnostics.popWithoutEmitting(state); | |||
8780 | ||||
8781 | // When delaying diagnostics to run in the context of a parsed | |||
8782 | // declaration, we only want to actually emit anything if parsing | |||
8783 | // succeeds. | |||
8784 | if (!decl) return; | |||
8785 | ||||
8786 | // We emit all the active diagnostics in this pool or any of its | |||
8787 | // parents. In general, we'll get one pool for the decl spec | |||
8788 | // and a child pool for each declarator; in a decl group like: | |||
8789 | // deprecated_typedef foo, *bar, baz(); | |||
8790 | // only the declarator pops will be passed decls. This is correct; | |||
8791 | // we really do need to consider delayed diagnostics from the decl spec | |||
8792 | // for each of the different declarations. | |||
8793 | const DelayedDiagnosticPool *pool = &poppedPool; | |||
8794 | do { | |||
8795 | bool AnyAccessFailures = false; | |||
8796 | for (DelayedDiagnosticPool::pool_iterator | |||
8797 | i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) { | |||
8798 | // This const_cast is a bit lame. Really, Triggered should be mutable. | |||
8799 | DelayedDiagnostic &diag = const_cast<DelayedDiagnostic&>(*i); | |||
8800 | if (diag.Triggered) | |||
8801 | continue; | |||
8802 | ||||
8803 | switch (diag.Kind) { | |||
8804 | case DelayedDiagnostic::Availability: | |||
8805 | // Don't bother giving deprecation/unavailable diagnostics if | |||
8806 | // the decl is invalid. | |||
8807 | if (!decl->isInvalidDecl()) | |||
8808 | handleDelayedAvailabilityCheck(diag, decl); | |||
8809 | break; | |||
8810 | ||||
8811 | case DelayedDiagnostic::Access: | |||
8812 | // Only produce one access control diagnostic for a structured binding | |||
8813 | // declaration: we don't need to tell the user that all the fields are | |||
8814 | // inaccessible one at a time. | |||
8815 | if (AnyAccessFailures && isa<DecompositionDecl>(decl)) | |||
8816 | continue; | |||
8817 | HandleDelayedAccessCheck(diag, decl); | |||
8818 | if (diag.Triggered) | |||
8819 | AnyAccessFailures = true; | |||
8820 | break; | |||
8821 | ||||
8822 | case DelayedDiagnostic::ForbiddenType: | |||
8823 | handleDelayedForbiddenType(*this, diag, decl); | |||
8824 | break; | |||
8825 | } | |||
8826 | } | |||
8827 | } while ((pool = pool->getParent())); | |||
8828 | } | |||
8829 | ||||
8830 | /// Given a set of delayed diagnostics, re-emit them as if they had | |||
8831 | /// been delayed in the current context instead of in the given pool. | |||
8832 | /// Essentially, this just moves them to the current pool. | |||
8833 | void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) { | |||
8834 | DelayedDiagnosticPool *curPool = DelayedDiagnostics.getCurrentPool(); | |||
8835 | assert(curPool && "re-emitting in undelayed context not supported")((curPool && "re-emitting in undelayed context not supported" ) ? static_cast<void> (0) : __assert_fail ("curPool && \"re-emitting in undelayed context not supported\"" , "/build/llvm-toolchain-snapshot-13~++20210311111132+403da6a69abc/clang/lib/Sema/SemaDeclAttr.cpp" , 8835, __PRETTY_FUNCTION__)); | |||
8836 | curPool->steal(pool); | |||
8837 | } |