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