xref: /minix3/external/bsd/llvm/dist/clang/lib/Sema/SemaDeclAttr.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc //  This file implements decl-related attribute processing.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc 
14f4a2713aSLionel Sambuc #include "clang/Sema/SemaInternal.h"
15f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h"
16f4a2713aSLionel Sambuc #include "clang/AST/CXXInheritance.h"
17f4a2713aSLionel Sambuc #include "clang/AST/DeclCXX.h"
18f4a2713aSLionel Sambuc #include "clang/AST/DeclObjC.h"
19f4a2713aSLionel Sambuc #include "clang/AST/DeclTemplate.h"
20f4a2713aSLionel Sambuc #include "clang/AST/Expr.h"
21*0a6a1f1dSLionel Sambuc #include "clang/AST/ExprCXX.h"
22f4a2713aSLionel Sambuc #include "clang/AST/Mangle.h"
23f4a2713aSLionel Sambuc #include "clang/Basic/CharInfo.h"
24f4a2713aSLionel Sambuc #include "clang/Basic/SourceManager.h"
25f4a2713aSLionel Sambuc #include "clang/Basic/TargetInfo.h"
26f4a2713aSLionel Sambuc #include "clang/Lex/Preprocessor.h"
27f4a2713aSLionel Sambuc #include "clang/Sema/DeclSpec.h"
28f4a2713aSLionel Sambuc #include "clang/Sema/DelayedDiagnostic.h"
29f4a2713aSLionel Sambuc #include "clang/Sema/Lookup.h"
30f4a2713aSLionel Sambuc #include "clang/Sema/Scope.h"
31f4a2713aSLionel Sambuc #include "llvm/ADT/StringExtras.h"
32*0a6a1f1dSLionel Sambuc #include "llvm/Support/MathExtras.h"
33f4a2713aSLionel Sambuc using namespace clang;
34f4a2713aSLionel Sambuc using namespace sema;
35f4a2713aSLionel Sambuc 
36*0a6a1f1dSLionel Sambuc namespace AttributeLangSupport {
37*0a6a1f1dSLionel Sambuc   enum LANG {
38*0a6a1f1dSLionel Sambuc     C,
39*0a6a1f1dSLionel Sambuc     Cpp,
40*0a6a1f1dSLionel Sambuc     ObjC
41f4a2713aSLionel Sambuc   };
42*0a6a1f1dSLionel Sambuc }
43f4a2713aSLionel Sambuc 
44f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
45f4a2713aSLionel Sambuc //  Helper functions
46f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
47f4a2713aSLionel Sambuc 
48f4a2713aSLionel Sambuc /// isFunctionOrMethod - Return true if the given decl has function
49f4a2713aSLionel Sambuc /// type (function or function-typed variable) or an Objective-C
50f4a2713aSLionel Sambuc /// method.
isFunctionOrMethod(const Decl * D)51f4a2713aSLionel Sambuc static bool isFunctionOrMethod(const Decl *D) {
52*0a6a1f1dSLionel Sambuc   return (D->getFunctionType() != nullptr) || isa<ObjCMethodDecl>(D);
53f4a2713aSLionel Sambuc }
54f4a2713aSLionel Sambuc 
55f4a2713aSLionel Sambuc /// Return true if the given decl has a declarator that should have
56f4a2713aSLionel Sambuc /// been processed by Sema::GetTypeForDeclarator.
hasDeclarator(const Decl * D)57f4a2713aSLionel Sambuc static bool hasDeclarator(const Decl *D) {
58f4a2713aSLionel Sambuc   // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl.
59f4a2713aSLionel Sambuc   return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) || isa<TypedefNameDecl>(D) ||
60f4a2713aSLionel Sambuc          isa<ObjCPropertyDecl>(D);
61f4a2713aSLionel Sambuc }
62f4a2713aSLionel Sambuc 
63f4a2713aSLionel Sambuc /// hasFunctionProto - Return true if the given decl has a argument
64f4a2713aSLionel Sambuc /// information. This decl should have already passed
65f4a2713aSLionel Sambuc /// isFunctionOrMethod or isFunctionOrMethodOrBlock.
hasFunctionProto(const Decl * D)66f4a2713aSLionel Sambuc static bool hasFunctionProto(const Decl *D) {
67*0a6a1f1dSLionel Sambuc   if (const FunctionType *FnTy = D->getFunctionType())
68f4a2713aSLionel Sambuc     return isa<FunctionProtoType>(FnTy);
69*0a6a1f1dSLionel Sambuc   return isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D);
70f4a2713aSLionel Sambuc }
71f4a2713aSLionel Sambuc 
72*0a6a1f1dSLionel Sambuc /// getFunctionOrMethodNumParams - Return number of function or method
73*0a6a1f1dSLionel Sambuc /// parameters. It is an error to call this on a K&R function (use
74f4a2713aSLionel Sambuc /// hasFunctionProto first).
getFunctionOrMethodNumParams(const Decl * D)75*0a6a1f1dSLionel Sambuc static unsigned getFunctionOrMethodNumParams(const Decl *D) {
76*0a6a1f1dSLionel Sambuc   if (const FunctionType *FnTy = D->getFunctionType())
77*0a6a1f1dSLionel Sambuc     return cast<FunctionProtoType>(FnTy)->getNumParams();
78f4a2713aSLionel Sambuc   if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
79f4a2713aSLionel Sambuc     return BD->getNumParams();
80f4a2713aSLionel Sambuc   return cast<ObjCMethodDecl>(D)->param_size();
81f4a2713aSLionel Sambuc }
82f4a2713aSLionel Sambuc 
getFunctionOrMethodParamType(const Decl * D,unsigned Idx)83*0a6a1f1dSLionel Sambuc static QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
84*0a6a1f1dSLionel Sambuc   if (const FunctionType *FnTy = D->getFunctionType())
85*0a6a1f1dSLionel Sambuc     return cast<FunctionProtoType>(FnTy)->getParamType(Idx);
86f4a2713aSLionel Sambuc   if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
87f4a2713aSLionel Sambuc     return BD->getParamDecl(Idx)->getType();
88f4a2713aSLionel Sambuc 
89*0a6a1f1dSLionel Sambuc   return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType();
90*0a6a1f1dSLionel Sambuc }
91*0a6a1f1dSLionel Sambuc 
getFunctionOrMethodParamRange(const Decl * D,unsigned Idx)92*0a6a1f1dSLionel Sambuc static SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) {
93*0a6a1f1dSLionel Sambuc   if (const auto *FD = dyn_cast<FunctionDecl>(D))
94*0a6a1f1dSLionel Sambuc     return FD->getParamDecl(Idx)->getSourceRange();
95*0a6a1f1dSLionel Sambuc   if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
96*0a6a1f1dSLionel Sambuc     return MD->parameters()[Idx]->getSourceRange();
97*0a6a1f1dSLionel Sambuc   if (const auto *BD = dyn_cast<BlockDecl>(D))
98*0a6a1f1dSLionel Sambuc     return BD->getParamDecl(Idx)->getSourceRange();
99*0a6a1f1dSLionel Sambuc   return SourceRange();
100f4a2713aSLionel Sambuc }
101f4a2713aSLionel Sambuc 
getFunctionOrMethodResultType(const Decl * D)102f4a2713aSLionel Sambuc static QualType getFunctionOrMethodResultType(const Decl *D) {
103*0a6a1f1dSLionel Sambuc   if (const FunctionType *FnTy = D->getFunctionType())
104*0a6a1f1dSLionel Sambuc     return cast<FunctionType>(FnTy)->getReturnType();
105*0a6a1f1dSLionel Sambuc   return cast<ObjCMethodDecl>(D)->getReturnType();
106*0a6a1f1dSLionel Sambuc }
107*0a6a1f1dSLionel Sambuc 
getFunctionOrMethodResultSourceRange(const Decl * D)108*0a6a1f1dSLionel Sambuc static SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) {
109*0a6a1f1dSLionel Sambuc   if (const auto *FD = dyn_cast<FunctionDecl>(D))
110*0a6a1f1dSLionel Sambuc     return FD->getReturnTypeSourceRange();
111*0a6a1f1dSLionel Sambuc   if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
112*0a6a1f1dSLionel Sambuc     return MD->getReturnTypeSourceRange();
113*0a6a1f1dSLionel Sambuc   return SourceRange();
114f4a2713aSLionel Sambuc }
115f4a2713aSLionel Sambuc 
isFunctionOrMethodVariadic(const Decl * D)116f4a2713aSLionel Sambuc static bool isFunctionOrMethodVariadic(const Decl *D) {
117*0a6a1f1dSLionel Sambuc   if (const FunctionType *FnTy = D->getFunctionType()) {
118f4a2713aSLionel Sambuc     const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy);
119f4a2713aSLionel Sambuc     return proto->isVariadic();
120f4a2713aSLionel Sambuc   }
121*0a6a1f1dSLionel Sambuc   if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
122*0a6a1f1dSLionel Sambuc     return BD->isVariadic();
123*0a6a1f1dSLionel Sambuc 
124*0a6a1f1dSLionel Sambuc   return cast<ObjCMethodDecl>(D)->isVariadic();
125f4a2713aSLionel Sambuc }
126f4a2713aSLionel Sambuc 
isInstanceMethod(const Decl * D)127f4a2713aSLionel Sambuc static bool isInstanceMethod(const Decl *D) {
128f4a2713aSLionel Sambuc   if (const CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D))
129f4a2713aSLionel Sambuc     return MethodDecl->isInstance();
130f4a2713aSLionel Sambuc   return false;
131f4a2713aSLionel Sambuc }
132f4a2713aSLionel Sambuc 
isNSStringType(QualType T,ASTContext & Ctx)133f4a2713aSLionel Sambuc static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
134f4a2713aSLionel Sambuc   const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
135f4a2713aSLionel Sambuc   if (!PT)
136f4a2713aSLionel Sambuc     return false;
137f4a2713aSLionel Sambuc 
138f4a2713aSLionel Sambuc   ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface();
139f4a2713aSLionel Sambuc   if (!Cls)
140f4a2713aSLionel Sambuc     return false;
141f4a2713aSLionel Sambuc 
142f4a2713aSLionel Sambuc   IdentifierInfo* ClsName = Cls->getIdentifier();
143f4a2713aSLionel Sambuc 
144f4a2713aSLionel Sambuc   // FIXME: Should we walk the chain of classes?
145f4a2713aSLionel Sambuc   return ClsName == &Ctx.Idents.get("NSString") ||
146f4a2713aSLionel Sambuc          ClsName == &Ctx.Idents.get("NSMutableString");
147f4a2713aSLionel Sambuc }
148f4a2713aSLionel Sambuc 
isCFStringType(QualType T,ASTContext & Ctx)149f4a2713aSLionel Sambuc static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
150f4a2713aSLionel Sambuc   const PointerType *PT = T->getAs<PointerType>();
151f4a2713aSLionel Sambuc   if (!PT)
152f4a2713aSLionel Sambuc     return false;
153f4a2713aSLionel Sambuc 
154f4a2713aSLionel Sambuc   const RecordType *RT = PT->getPointeeType()->getAs<RecordType>();
155f4a2713aSLionel Sambuc   if (!RT)
156f4a2713aSLionel Sambuc     return false;
157f4a2713aSLionel Sambuc 
158f4a2713aSLionel Sambuc   const RecordDecl *RD = RT->getDecl();
159f4a2713aSLionel Sambuc   if (RD->getTagKind() != TTK_Struct)
160f4a2713aSLionel Sambuc     return false;
161f4a2713aSLionel Sambuc 
162f4a2713aSLionel Sambuc   return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
163f4a2713aSLionel Sambuc }
164f4a2713aSLionel Sambuc 
getNumAttributeArgs(const AttributeList & Attr)165f4a2713aSLionel Sambuc static unsigned getNumAttributeArgs(const AttributeList &Attr) {
166f4a2713aSLionel Sambuc   // FIXME: Include the type in the argument list.
167f4a2713aSLionel Sambuc   return Attr.getNumArgs() + Attr.hasParsedType();
168f4a2713aSLionel Sambuc }
169f4a2713aSLionel Sambuc 
170*0a6a1f1dSLionel Sambuc template <typename Compare>
checkAttributeNumArgsImpl(Sema & S,const AttributeList & Attr,unsigned Num,unsigned Diag,Compare Comp)171*0a6a1f1dSLionel Sambuc static bool checkAttributeNumArgsImpl(Sema &S, const AttributeList &Attr,
172*0a6a1f1dSLionel Sambuc                                       unsigned Num, unsigned Diag,
173*0a6a1f1dSLionel Sambuc                                       Compare Comp) {
174*0a6a1f1dSLionel Sambuc   if (Comp(getNumAttributeArgs(Attr), Num)) {
175*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), Diag) << Attr.getName() << Num;
176f4a2713aSLionel Sambuc     return false;
177f4a2713aSLionel Sambuc   }
178f4a2713aSLionel Sambuc 
179f4a2713aSLionel Sambuc   return true;
180f4a2713aSLionel Sambuc }
181f4a2713aSLionel Sambuc 
182*0a6a1f1dSLionel Sambuc /// \brief Check if the attribute has exactly as many args as Num. May
183*0a6a1f1dSLionel Sambuc /// output an error.
checkAttributeNumArgs(Sema & S,const AttributeList & Attr,unsigned Num)184*0a6a1f1dSLionel Sambuc static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr,
185*0a6a1f1dSLionel Sambuc                                   unsigned Num) {
186*0a6a1f1dSLionel Sambuc   return checkAttributeNumArgsImpl(S, Attr, Num,
187*0a6a1f1dSLionel Sambuc                                    diag::err_attribute_wrong_number_arguments,
188*0a6a1f1dSLionel Sambuc                                    std::not_equal_to<unsigned>());
189*0a6a1f1dSLionel Sambuc }
190f4a2713aSLionel Sambuc 
191f4a2713aSLionel Sambuc /// \brief Check if the attribute has at least as many args as Num. May
192f4a2713aSLionel Sambuc /// output an error.
checkAttributeAtLeastNumArgs(Sema & S,const AttributeList & Attr,unsigned Num)193f4a2713aSLionel Sambuc static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr,
194f4a2713aSLionel Sambuc                                          unsigned Num) {
195*0a6a1f1dSLionel Sambuc   return checkAttributeNumArgsImpl(S, Attr, Num,
196*0a6a1f1dSLionel Sambuc                                    diag::err_attribute_too_few_arguments,
197*0a6a1f1dSLionel Sambuc                                    std::less<unsigned>());
198*0a6a1f1dSLionel Sambuc }
199*0a6a1f1dSLionel Sambuc 
200*0a6a1f1dSLionel Sambuc /// \brief Check if the attribute has at most as many args as Num. May
201*0a6a1f1dSLionel Sambuc /// output an error.
checkAttributeAtMostNumArgs(Sema & S,const AttributeList & Attr,unsigned Num)202*0a6a1f1dSLionel Sambuc static bool checkAttributeAtMostNumArgs(Sema &S, const AttributeList &Attr,
203*0a6a1f1dSLionel Sambuc                                          unsigned Num) {
204*0a6a1f1dSLionel Sambuc   return checkAttributeNumArgsImpl(S, Attr, Num,
205*0a6a1f1dSLionel Sambuc                                    diag::err_attribute_too_many_arguments,
206*0a6a1f1dSLionel Sambuc                                    std::greater<unsigned>());
207*0a6a1f1dSLionel Sambuc }
208*0a6a1f1dSLionel Sambuc 
209*0a6a1f1dSLionel Sambuc /// \brief If Expr is a valid integer constant, get the value of the integer
210*0a6a1f1dSLionel Sambuc /// expression and return success or failure. May output an error.
checkUInt32Argument(Sema & S,const AttributeList & Attr,const Expr * Expr,uint32_t & Val,unsigned Idx=UINT_MAX)211*0a6a1f1dSLionel Sambuc static bool checkUInt32Argument(Sema &S, const AttributeList &Attr,
212*0a6a1f1dSLionel Sambuc                                 const Expr *Expr, uint32_t &Val,
213*0a6a1f1dSLionel Sambuc                                 unsigned Idx = UINT_MAX) {
214*0a6a1f1dSLionel Sambuc   llvm::APSInt I(32);
215*0a6a1f1dSLionel Sambuc   if (Expr->isTypeDependent() || Expr->isValueDependent() ||
216*0a6a1f1dSLionel Sambuc       !Expr->isIntegerConstantExpr(I, S.Context)) {
217*0a6a1f1dSLionel Sambuc     if (Idx != UINT_MAX)
218*0a6a1f1dSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
219*0a6a1f1dSLionel Sambuc         << Attr.getName() << Idx << AANT_ArgumentIntegerConstant
220*0a6a1f1dSLionel Sambuc         << Expr->getSourceRange();
221*0a6a1f1dSLionel Sambuc     else
222*0a6a1f1dSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
223*0a6a1f1dSLionel Sambuc         << Attr.getName() << AANT_ArgumentIntegerConstant
224*0a6a1f1dSLionel Sambuc         << Expr->getSourceRange();
225f4a2713aSLionel Sambuc     return false;
226f4a2713aSLionel Sambuc   }
227f4a2713aSLionel Sambuc 
228*0a6a1f1dSLionel Sambuc   if (!I.isIntN(32)) {
229*0a6a1f1dSLionel Sambuc     S.Diag(Expr->getExprLoc(), diag::err_ice_too_large)
230*0a6a1f1dSLionel Sambuc         << I.toString(10, false) << 32 << /* Unsigned */ 1;
231*0a6a1f1dSLionel Sambuc     return false;
232*0a6a1f1dSLionel Sambuc   }
233*0a6a1f1dSLionel Sambuc 
234*0a6a1f1dSLionel Sambuc   Val = (uint32_t)I.getZExtValue();
235f4a2713aSLionel Sambuc   return true;
236f4a2713aSLionel Sambuc }
237f4a2713aSLionel Sambuc 
238*0a6a1f1dSLionel Sambuc /// \brief Diagnose mutually exclusive attributes when present on a given
239*0a6a1f1dSLionel Sambuc /// declaration. Returns true if diagnosed.
240*0a6a1f1dSLionel Sambuc template <typename AttrTy>
checkAttrMutualExclusion(Sema & S,Decl * D,const AttributeList & Attr)241*0a6a1f1dSLionel Sambuc static bool checkAttrMutualExclusion(Sema &S, Decl *D,
242*0a6a1f1dSLionel Sambuc                                      const AttributeList &Attr) {
243*0a6a1f1dSLionel Sambuc   if (AttrTy *A = D->getAttr<AttrTy>()) {
244*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
245*0a6a1f1dSLionel Sambuc       << Attr.getName() << A;
246*0a6a1f1dSLionel Sambuc     return true;
247*0a6a1f1dSLionel Sambuc   }
248*0a6a1f1dSLionel Sambuc   return false;
249*0a6a1f1dSLionel Sambuc }
250*0a6a1f1dSLionel Sambuc 
251*0a6a1f1dSLionel Sambuc /// \brief Check if IdxExpr is a valid parameter index for a function or
252f4a2713aSLionel Sambuc /// instance method D.  May output an error.
253f4a2713aSLionel Sambuc ///
254f4a2713aSLionel Sambuc /// \returns true if IdxExpr is a valid index.
checkFunctionOrMethodParameterIndex(Sema & S,const Decl * D,const AttributeList & Attr,unsigned AttrArgNum,const Expr * IdxExpr,uint64_t & Idx)255*0a6a1f1dSLionel Sambuc static bool checkFunctionOrMethodParameterIndex(Sema &S, const Decl *D,
256*0a6a1f1dSLionel Sambuc                                                 const AttributeList &Attr,
257f4a2713aSLionel Sambuc                                                 unsigned AttrArgNum,
258f4a2713aSLionel Sambuc                                                 const Expr *IdxExpr,
259*0a6a1f1dSLionel Sambuc                                                 uint64_t &Idx) {
260f4a2713aSLionel Sambuc   assert(isFunctionOrMethod(D));
261f4a2713aSLionel Sambuc 
262f4a2713aSLionel Sambuc   // In C++ the implicit 'this' function parameter also counts.
263f4a2713aSLionel Sambuc   // Parameters are counted from one.
264f4a2713aSLionel Sambuc   bool HP = hasFunctionProto(D);
265f4a2713aSLionel Sambuc   bool HasImplicitThisParam = isInstanceMethod(D);
266f4a2713aSLionel Sambuc   bool IV = HP && isFunctionOrMethodVariadic(D);
267*0a6a1f1dSLionel Sambuc   unsigned NumParams =
268*0a6a1f1dSLionel Sambuc       (HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam;
269f4a2713aSLionel Sambuc 
270f4a2713aSLionel Sambuc   llvm::APSInt IdxInt;
271f4a2713aSLionel Sambuc   if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
272f4a2713aSLionel Sambuc       !IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) {
273*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
274*0a6a1f1dSLionel Sambuc       << Attr.getName() << AttrArgNum << AANT_ArgumentIntegerConstant
275*0a6a1f1dSLionel Sambuc       << IdxExpr->getSourceRange();
276f4a2713aSLionel Sambuc     return false;
277f4a2713aSLionel Sambuc   }
278f4a2713aSLionel Sambuc 
279f4a2713aSLionel Sambuc   Idx = IdxInt.getLimitedValue();
280*0a6a1f1dSLionel Sambuc   if (Idx < 1 || (!IV && Idx > NumParams)) {
281*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
282*0a6a1f1dSLionel Sambuc       << Attr.getName() << AttrArgNum << IdxExpr->getSourceRange();
283f4a2713aSLionel Sambuc     return false;
284f4a2713aSLionel Sambuc   }
285f4a2713aSLionel Sambuc   Idx--; // Convert to zero-based.
286f4a2713aSLionel Sambuc   if (HasImplicitThisParam) {
287f4a2713aSLionel Sambuc     if (Idx == 0) {
288*0a6a1f1dSLionel Sambuc       S.Diag(Attr.getLoc(),
289f4a2713aSLionel Sambuc              diag::err_attribute_invalid_implicit_this_argument)
290*0a6a1f1dSLionel Sambuc         << Attr.getName() << IdxExpr->getSourceRange();
291f4a2713aSLionel Sambuc       return false;
292f4a2713aSLionel Sambuc     }
293f4a2713aSLionel Sambuc     --Idx;
294f4a2713aSLionel Sambuc   }
295f4a2713aSLionel Sambuc 
296f4a2713aSLionel Sambuc   return true;
297f4a2713aSLionel Sambuc }
298f4a2713aSLionel Sambuc 
299f4a2713aSLionel Sambuc /// \brief Check if the argument \p ArgNum of \p Attr is a ASCII string literal.
300f4a2713aSLionel Sambuc /// If not emit an error and return false. If the argument is an identifier it
301f4a2713aSLionel Sambuc /// will emit an error with a fixit hint and treat it as if it was a string
302f4a2713aSLionel Sambuc /// literal.
checkStringLiteralArgumentAttr(const AttributeList & Attr,unsigned ArgNum,StringRef & Str,SourceLocation * ArgLocation)303f4a2713aSLionel Sambuc bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr,
304f4a2713aSLionel Sambuc                                           unsigned ArgNum, StringRef &Str,
305f4a2713aSLionel Sambuc                                           SourceLocation *ArgLocation) {
306f4a2713aSLionel Sambuc   // Look for identifiers. If we have one emit a hint to fix it to a literal.
307f4a2713aSLionel Sambuc   if (Attr.isArgIdent(ArgNum)) {
308f4a2713aSLionel Sambuc     IdentifierLoc *Loc = Attr.getArgAsIdent(ArgNum);
309f4a2713aSLionel Sambuc     Diag(Loc->Loc, diag::err_attribute_argument_type)
310f4a2713aSLionel Sambuc         << Attr.getName() << AANT_ArgumentString
311f4a2713aSLionel Sambuc         << FixItHint::CreateInsertion(Loc->Loc, "\"")
312f4a2713aSLionel Sambuc         << FixItHint::CreateInsertion(PP.getLocForEndOfToken(Loc->Loc), "\"");
313f4a2713aSLionel Sambuc     Str = Loc->Ident->getName();
314f4a2713aSLionel Sambuc     if (ArgLocation)
315f4a2713aSLionel Sambuc       *ArgLocation = Loc->Loc;
316f4a2713aSLionel Sambuc     return true;
317f4a2713aSLionel Sambuc   }
318f4a2713aSLionel Sambuc 
319f4a2713aSLionel Sambuc   // Now check for an actual string literal.
320f4a2713aSLionel Sambuc   Expr *ArgExpr = Attr.getArgAsExpr(ArgNum);
321f4a2713aSLionel Sambuc   StringLiteral *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts());
322f4a2713aSLionel Sambuc   if (ArgLocation)
323f4a2713aSLionel Sambuc     *ArgLocation = ArgExpr->getLocStart();
324f4a2713aSLionel Sambuc 
325f4a2713aSLionel Sambuc   if (!Literal || !Literal->isAscii()) {
326f4a2713aSLionel Sambuc     Diag(ArgExpr->getLocStart(), diag::err_attribute_argument_type)
327f4a2713aSLionel Sambuc         << Attr.getName() << AANT_ArgumentString;
328f4a2713aSLionel Sambuc     return false;
329f4a2713aSLionel Sambuc   }
330f4a2713aSLionel Sambuc 
331f4a2713aSLionel Sambuc   Str = Literal->getString();
332f4a2713aSLionel Sambuc   return true;
333f4a2713aSLionel Sambuc }
334f4a2713aSLionel Sambuc 
335*0a6a1f1dSLionel Sambuc /// \brief Applies the given attribute to the Decl without performing any
336*0a6a1f1dSLionel Sambuc /// additional semantic checking.
337*0a6a1f1dSLionel Sambuc template <typename AttrType>
handleSimpleAttribute(Sema & S,Decl * D,const AttributeList & Attr)338*0a6a1f1dSLionel Sambuc static void handleSimpleAttribute(Sema &S, Decl *D,
339*0a6a1f1dSLionel Sambuc                                   const AttributeList &Attr) {
340*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context) AttrType(Attr.getRange(), S.Context,
341*0a6a1f1dSLionel Sambuc                                         Attr.getAttributeSpellingListIndex()));
342f4a2713aSLionel Sambuc }
343f4a2713aSLionel Sambuc 
344f4a2713aSLionel Sambuc /// \brief Check if the passed-in expression is of type int or bool.
isIntOrBool(Expr * Exp)345f4a2713aSLionel Sambuc static bool isIntOrBool(Expr *Exp) {
346f4a2713aSLionel Sambuc   QualType QT = Exp->getType();
347f4a2713aSLionel Sambuc   return QT->isBooleanType() || QT->isIntegerType();
348f4a2713aSLionel Sambuc }
349f4a2713aSLionel Sambuc 
350f4a2713aSLionel Sambuc 
351f4a2713aSLionel Sambuc // Check to see if the type is a smart pointer of some kind.  We assume
352f4a2713aSLionel Sambuc // it's a smart pointer if it defines both operator-> and operator*.
threadSafetyCheckIsSmartPointer(Sema & S,const RecordType * RT)353f4a2713aSLionel Sambuc static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) {
354f4a2713aSLionel Sambuc   DeclContextLookupConstResult Res1 = RT->getDecl()->lookup(
355f4a2713aSLionel Sambuc     S.Context.DeclarationNames.getCXXOperatorName(OO_Star));
356f4a2713aSLionel Sambuc   if (Res1.empty())
357f4a2713aSLionel Sambuc     return false;
358f4a2713aSLionel Sambuc 
359f4a2713aSLionel Sambuc   DeclContextLookupConstResult Res2 = RT->getDecl()->lookup(
360f4a2713aSLionel Sambuc     S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow));
361f4a2713aSLionel Sambuc   if (Res2.empty())
362f4a2713aSLionel Sambuc     return false;
363f4a2713aSLionel Sambuc 
364f4a2713aSLionel Sambuc   return true;
365f4a2713aSLionel Sambuc }
366f4a2713aSLionel Sambuc 
367f4a2713aSLionel Sambuc /// \brief Check if passed in Decl is a pointer type.
368f4a2713aSLionel Sambuc /// Note that this function may produce an error message.
369f4a2713aSLionel Sambuc /// \return true if the Decl is a pointer type; false otherwise
threadSafetyCheckIsPointer(Sema & S,const Decl * D,const AttributeList & Attr)370f4a2713aSLionel Sambuc static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D,
371f4a2713aSLionel Sambuc                                        const AttributeList &Attr) {
372*0a6a1f1dSLionel Sambuc   const ValueDecl *vd = cast<ValueDecl>(D);
373f4a2713aSLionel Sambuc   QualType QT = vd->getType();
374f4a2713aSLionel Sambuc   if (QT->isAnyPointerType())
375f4a2713aSLionel Sambuc     return true;
376f4a2713aSLionel Sambuc 
377f4a2713aSLionel Sambuc   if (const RecordType *RT = QT->getAs<RecordType>()) {
378f4a2713aSLionel Sambuc     // If it's an incomplete type, it could be a smart pointer; skip it.
379f4a2713aSLionel Sambuc     // (We don't want to force template instantiation if we can avoid it,
380f4a2713aSLionel Sambuc     // since that would alter the order in which templates are instantiated.)
381f4a2713aSLionel Sambuc     if (RT->isIncompleteType())
382f4a2713aSLionel Sambuc       return true;
383f4a2713aSLionel Sambuc 
384f4a2713aSLionel Sambuc     if (threadSafetyCheckIsSmartPointer(S, RT))
385f4a2713aSLionel Sambuc       return true;
386f4a2713aSLionel Sambuc   }
387f4a2713aSLionel Sambuc 
388f4a2713aSLionel Sambuc   S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_pointer)
389*0a6a1f1dSLionel Sambuc     << Attr.getName() << QT;
390f4a2713aSLionel Sambuc   return false;
391f4a2713aSLionel Sambuc }
392f4a2713aSLionel Sambuc 
393f4a2713aSLionel Sambuc /// \brief Checks that the passed in QualType either is of RecordType or points
394f4a2713aSLionel Sambuc /// to RecordType. Returns the relevant RecordType, null if it does not exit.
getRecordType(QualType QT)395f4a2713aSLionel Sambuc static const RecordType *getRecordType(QualType QT) {
396f4a2713aSLionel Sambuc   if (const RecordType *RT = QT->getAs<RecordType>())
397f4a2713aSLionel Sambuc     return RT;
398f4a2713aSLionel Sambuc 
399f4a2713aSLionel Sambuc   // Now check if we point to record type.
400f4a2713aSLionel Sambuc   if (const PointerType *PT = QT->getAs<PointerType>())
401f4a2713aSLionel Sambuc     return PT->getPointeeType()->getAs<RecordType>();
402f4a2713aSLionel Sambuc 
403*0a6a1f1dSLionel Sambuc   return nullptr;
404f4a2713aSLionel Sambuc }
405f4a2713aSLionel Sambuc 
checkRecordTypeForCapability(Sema & S,QualType Ty)406*0a6a1f1dSLionel Sambuc static bool checkRecordTypeForCapability(Sema &S, QualType Ty) {
407*0a6a1f1dSLionel Sambuc   const RecordType *RT = getRecordType(Ty);
408f4a2713aSLionel Sambuc 
409*0a6a1f1dSLionel Sambuc   if (!RT)
410*0a6a1f1dSLionel Sambuc     return false;
411*0a6a1f1dSLionel Sambuc 
412*0a6a1f1dSLionel Sambuc   // Don't check for the capability if the class hasn't been defined yet.
413*0a6a1f1dSLionel Sambuc   if (RT->isIncompleteType())
414f4a2713aSLionel Sambuc     return true;
415*0a6a1f1dSLionel Sambuc 
416*0a6a1f1dSLionel Sambuc   // Allow smart pointers to be used as capability objects.
417*0a6a1f1dSLionel Sambuc   // FIXME -- Check the type that the smart pointer points to.
418*0a6a1f1dSLionel Sambuc   if (threadSafetyCheckIsSmartPointer(S, RT))
419*0a6a1f1dSLionel Sambuc     return true;
420*0a6a1f1dSLionel Sambuc 
421*0a6a1f1dSLionel Sambuc   // Check if the record itself has a capability.
422*0a6a1f1dSLionel Sambuc   RecordDecl *RD = RT->getDecl();
423*0a6a1f1dSLionel Sambuc   if (RD->hasAttr<CapabilityAttr>())
424*0a6a1f1dSLionel Sambuc     return true;
425*0a6a1f1dSLionel Sambuc 
426*0a6a1f1dSLionel Sambuc   // Else check if any base classes have a capability.
427*0a6a1f1dSLionel Sambuc   if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
428*0a6a1f1dSLionel Sambuc     CXXBasePaths BPaths(false, false);
429*0a6a1f1dSLionel Sambuc     if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &P,
430*0a6a1f1dSLionel Sambuc       void *) {
431*0a6a1f1dSLionel Sambuc       return BS->getType()->getAs<RecordType>()
432*0a6a1f1dSLionel Sambuc         ->getDecl()->hasAttr<CapabilityAttr>();
433*0a6a1f1dSLionel Sambuc     }, nullptr, BPaths))
434*0a6a1f1dSLionel Sambuc       return true;
435*0a6a1f1dSLionel Sambuc   }
436f4a2713aSLionel Sambuc   return false;
437f4a2713aSLionel Sambuc }
438f4a2713aSLionel Sambuc 
checkTypedefTypeForCapability(QualType Ty)439*0a6a1f1dSLionel Sambuc static bool checkTypedefTypeForCapability(QualType Ty) {
440*0a6a1f1dSLionel Sambuc   const auto *TD = Ty->getAs<TypedefType>();
441*0a6a1f1dSLionel Sambuc   if (!TD)
442*0a6a1f1dSLionel Sambuc     return false;
443f4a2713aSLionel Sambuc 
444*0a6a1f1dSLionel Sambuc   TypedefNameDecl *TN = TD->getDecl();
445*0a6a1f1dSLionel Sambuc   if (!TN)
446*0a6a1f1dSLionel Sambuc     return false;
447f4a2713aSLionel Sambuc 
448*0a6a1f1dSLionel Sambuc   return TN->hasAttr<CapabilityAttr>();
449f4a2713aSLionel Sambuc }
450f4a2713aSLionel Sambuc 
typeHasCapability(Sema & S,QualType Ty)451*0a6a1f1dSLionel Sambuc static bool typeHasCapability(Sema &S, QualType Ty) {
452*0a6a1f1dSLionel Sambuc   if (checkTypedefTypeForCapability(Ty))
453*0a6a1f1dSLionel Sambuc     return true;
454f4a2713aSLionel Sambuc 
455*0a6a1f1dSLionel Sambuc   if (checkRecordTypeForCapability(S, Ty))
456*0a6a1f1dSLionel Sambuc     return true;
457f4a2713aSLionel Sambuc 
458*0a6a1f1dSLionel Sambuc   return false;
459f4a2713aSLionel Sambuc }
460f4a2713aSLionel Sambuc 
isCapabilityExpr(Sema & S,const Expr * Ex)461*0a6a1f1dSLionel Sambuc static bool isCapabilityExpr(Sema &S, const Expr *Ex) {
462*0a6a1f1dSLionel Sambuc   // Capability expressions are simple expressions involving the boolean logic
463*0a6a1f1dSLionel Sambuc   // operators &&, || or !, a simple DeclRefExpr, CastExpr or a ParenExpr. Once
464*0a6a1f1dSLionel Sambuc   // a DeclRefExpr is found, its type should be checked to determine whether it
465*0a6a1f1dSLionel Sambuc   // is a capability or not.
466*0a6a1f1dSLionel Sambuc 
467*0a6a1f1dSLionel Sambuc   if (const auto *E = dyn_cast<DeclRefExpr>(Ex))
468*0a6a1f1dSLionel Sambuc     return typeHasCapability(S, E->getType());
469*0a6a1f1dSLionel Sambuc   else if (const auto *E = dyn_cast<CastExpr>(Ex))
470*0a6a1f1dSLionel Sambuc     return isCapabilityExpr(S, E->getSubExpr());
471*0a6a1f1dSLionel Sambuc   else if (const auto *E = dyn_cast<ParenExpr>(Ex))
472*0a6a1f1dSLionel Sambuc     return isCapabilityExpr(S, E->getSubExpr());
473*0a6a1f1dSLionel Sambuc   else if (const auto *E = dyn_cast<UnaryOperator>(Ex)) {
474*0a6a1f1dSLionel Sambuc     if (E->getOpcode() == UO_LNot)
475*0a6a1f1dSLionel Sambuc       return isCapabilityExpr(S, E->getSubExpr());
476*0a6a1f1dSLionel Sambuc     return false;
477*0a6a1f1dSLionel Sambuc   } else if (const auto *E = dyn_cast<BinaryOperator>(Ex)) {
478*0a6a1f1dSLionel Sambuc     if (E->getOpcode() == BO_LAnd || E->getOpcode() == BO_LOr)
479*0a6a1f1dSLionel Sambuc       return isCapabilityExpr(S, E->getLHS()) &&
480*0a6a1f1dSLionel Sambuc              isCapabilityExpr(S, E->getRHS());
481*0a6a1f1dSLionel Sambuc     return false;
482f4a2713aSLionel Sambuc   }
483f4a2713aSLionel Sambuc 
484*0a6a1f1dSLionel Sambuc   return false;
485*0a6a1f1dSLionel Sambuc }
486*0a6a1f1dSLionel Sambuc 
487*0a6a1f1dSLionel Sambuc /// \brief Checks that all attribute arguments, starting from Sidx, resolve to
488*0a6a1f1dSLionel Sambuc /// a capability object.
489f4a2713aSLionel Sambuc /// \param Sidx The attribute argument index to start checking with.
490f4a2713aSLionel Sambuc /// \param ParamIdxOk Whether an argument can be indexing into a function
491f4a2713aSLionel Sambuc /// parameter list.
checkAttrArgsAreCapabilityObjs(Sema & S,Decl * D,const AttributeList & Attr,SmallVectorImpl<Expr * > & Args,int Sidx=0,bool ParamIdxOk=false)492*0a6a1f1dSLionel Sambuc static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
493f4a2713aSLionel Sambuc                                            const AttributeList &Attr,
494f4a2713aSLionel Sambuc                                            SmallVectorImpl<Expr *> &Args,
495f4a2713aSLionel Sambuc                                            int Sidx = 0,
496f4a2713aSLionel Sambuc                                            bool ParamIdxOk = false) {
497f4a2713aSLionel Sambuc   for (unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) {
498f4a2713aSLionel Sambuc     Expr *ArgExp = Attr.getArgAsExpr(Idx);
499f4a2713aSLionel Sambuc 
500f4a2713aSLionel Sambuc     if (ArgExp->isTypeDependent()) {
501f4a2713aSLionel Sambuc       // FIXME -- need to check this again on template instantiation
502f4a2713aSLionel Sambuc       Args.push_back(ArgExp);
503f4a2713aSLionel Sambuc       continue;
504f4a2713aSLionel Sambuc     }
505f4a2713aSLionel Sambuc 
506f4a2713aSLionel Sambuc     if (StringLiteral *StrLit = dyn_cast<StringLiteral>(ArgExp)) {
507f4a2713aSLionel Sambuc       if (StrLit->getLength() == 0 ||
508f4a2713aSLionel Sambuc           (StrLit->isAscii() && StrLit->getString() == StringRef("*"))) {
509f4a2713aSLionel Sambuc         // Pass empty strings to the analyzer without warnings.
510f4a2713aSLionel Sambuc         // Treat "*" as the universal lock.
511f4a2713aSLionel Sambuc         Args.push_back(ArgExp);
512f4a2713aSLionel Sambuc         continue;
513f4a2713aSLionel Sambuc       }
514f4a2713aSLionel Sambuc 
515f4a2713aSLionel Sambuc       // We allow constant strings to be used as a placeholder for expressions
516f4a2713aSLionel Sambuc       // that are not valid C++ syntax, but warn that they are ignored.
517f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_thread_attribute_ignored) <<
518f4a2713aSLionel Sambuc         Attr.getName();
519f4a2713aSLionel Sambuc       Args.push_back(ArgExp);
520f4a2713aSLionel Sambuc       continue;
521f4a2713aSLionel Sambuc     }
522f4a2713aSLionel Sambuc 
523f4a2713aSLionel Sambuc     QualType ArgTy = ArgExp->getType();
524f4a2713aSLionel Sambuc 
525f4a2713aSLionel Sambuc     // A pointer to member expression of the form  &MyClass::mu is treated
526f4a2713aSLionel Sambuc     // specially -- we need to look at the type of the member.
527f4a2713aSLionel Sambuc     if (UnaryOperator *UOp = dyn_cast<UnaryOperator>(ArgExp))
528f4a2713aSLionel Sambuc       if (UOp->getOpcode() == UO_AddrOf)
529f4a2713aSLionel Sambuc         if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(UOp->getSubExpr()))
530f4a2713aSLionel Sambuc           if (DRE->getDecl()->isCXXInstanceMember())
531f4a2713aSLionel Sambuc             ArgTy = DRE->getDecl()->getType();
532f4a2713aSLionel Sambuc 
533*0a6a1f1dSLionel Sambuc     // First see if we can just cast to record type, or pointer to record type.
534f4a2713aSLionel Sambuc     const RecordType *RT = getRecordType(ArgTy);
535f4a2713aSLionel Sambuc 
536f4a2713aSLionel Sambuc     // Now check if we index into a record type function param.
537f4a2713aSLionel Sambuc     if(!RT && ParamIdxOk) {
538f4a2713aSLionel Sambuc       FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
539f4a2713aSLionel Sambuc       IntegerLiteral *IL = dyn_cast<IntegerLiteral>(ArgExp);
540f4a2713aSLionel Sambuc       if(FD && IL) {
541f4a2713aSLionel Sambuc         unsigned int NumParams = FD->getNumParams();
542f4a2713aSLionel Sambuc         llvm::APInt ArgValue = IL->getValue();
543f4a2713aSLionel Sambuc         uint64_t ParamIdxFromOne = ArgValue.getZExtValue();
544f4a2713aSLionel Sambuc         uint64_t ParamIdxFromZero = ParamIdxFromOne - 1;
545f4a2713aSLionel Sambuc         if(!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) {
546f4a2713aSLionel Sambuc           S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_range)
547f4a2713aSLionel Sambuc             << Attr.getName() << Idx + 1 << NumParams;
548f4a2713aSLionel Sambuc           continue;
549f4a2713aSLionel Sambuc         }
550f4a2713aSLionel Sambuc         ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType();
551f4a2713aSLionel Sambuc       }
552f4a2713aSLionel Sambuc     }
553f4a2713aSLionel Sambuc 
554*0a6a1f1dSLionel Sambuc     // If the type does not have a capability, see if the components of the
555*0a6a1f1dSLionel Sambuc     // expression have capabilities. This allows for writing C code where the
556*0a6a1f1dSLionel Sambuc     // capability may be on the type, and the expression is a capability
557*0a6a1f1dSLionel Sambuc     // boolean logic expression. Eg) requires_capability(A || B && !C)
558*0a6a1f1dSLionel Sambuc     if (!typeHasCapability(S, ArgTy) && !isCapabilityExpr(S, ArgExp))
559*0a6a1f1dSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
560*0a6a1f1dSLionel Sambuc           << Attr.getName() << ArgTy;
561f4a2713aSLionel Sambuc 
562f4a2713aSLionel Sambuc     Args.push_back(ArgExp);
563f4a2713aSLionel Sambuc   }
564f4a2713aSLionel Sambuc }
565f4a2713aSLionel Sambuc 
566f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
567f4a2713aSLionel Sambuc // Attribute Implementations
568f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
569f4a2713aSLionel Sambuc 
handlePtGuardedVarAttr(Sema & S,Decl * D,const AttributeList & Attr)570f4a2713aSLionel Sambuc static void handlePtGuardedVarAttr(Sema &S, Decl *D,
571f4a2713aSLionel Sambuc                                    const AttributeList &Attr) {
572f4a2713aSLionel Sambuc   if (!threadSafetyCheckIsPointer(S, D, Attr))
573f4a2713aSLionel Sambuc     return;
574f4a2713aSLionel Sambuc 
575f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
576f4a2713aSLionel Sambuc              PtGuardedVarAttr(Attr.getRange(), S.Context,
577f4a2713aSLionel Sambuc                               Attr.getAttributeSpellingListIndex()));
578f4a2713aSLionel Sambuc }
579f4a2713aSLionel Sambuc 
checkGuardedByAttrCommon(Sema & S,Decl * D,const AttributeList & Attr,Expr * & Arg)580f4a2713aSLionel Sambuc static bool checkGuardedByAttrCommon(Sema &S, Decl *D,
581f4a2713aSLionel Sambuc                                      const AttributeList &Attr,
582f4a2713aSLionel Sambuc                                      Expr* &Arg) {
583f4a2713aSLionel Sambuc   SmallVector<Expr*, 1> Args;
584f4a2713aSLionel Sambuc   // check that all arguments are lockable objects
585*0a6a1f1dSLionel Sambuc   checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
586f4a2713aSLionel Sambuc   unsigned Size = Args.size();
587f4a2713aSLionel Sambuc   if (Size != 1)
588f4a2713aSLionel Sambuc     return false;
589f4a2713aSLionel Sambuc 
590f4a2713aSLionel Sambuc   Arg = Args[0];
591f4a2713aSLionel Sambuc 
592f4a2713aSLionel Sambuc   return true;
593f4a2713aSLionel Sambuc }
594f4a2713aSLionel Sambuc 
handleGuardedByAttr(Sema & S,Decl * D,const AttributeList & Attr)595f4a2713aSLionel Sambuc static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr) {
596*0a6a1f1dSLionel Sambuc   Expr *Arg = nullptr;
597f4a2713aSLionel Sambuc   if (!checkGuardedByAttrCommon(S, D, Attr, Arg))
598f4a2713aSLionel Sambuc     return;
599f4a2713aSLionel Sambuc 
600*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg,
601*0a6a1f1dSLionel Sambuc                                         Attr.getAttributeSpellingListIndex()));
602f4a2713aSLionel Sambuc }
603f4a2713aSLionel Sambuc 
handlePtGuardedByAttr(Sema & S,Decl * D,const AttributeList & Attr)604f4a2713aSLionel Sambuc static void handlePtGuardedByAttr(Sema &S, Decl *D,
605f4a2713aSLionel Sambuc                                   const AttributeList &Attr) {
606*0a6a1f1dSLionel Sambuc   Expr *Arg = nullptr;
607f4a2713aSLionel Sambuc   if (!checkGuardedByAttrCommon(S, D, Attr, Arg))
608f4a2713aSLionel Sambuc     return;
609f4a2713aSLionel Sambuc 
610f4a2713aSLionel Sambuc   if (!threadSafetyCheckIsPointer(S, D, Attr))
611f4a2713aSLionel Sambuc     return;
612f4a2713aSLionel Sambuc 
613f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(),
614*0a6a1f1dSLionel Sambuc                                                S.Context, Arg,
615f4a2713aSLionel Sambuc                                         Attr.getAttributeSpellingListIndex()));
616f4a2713aSLionel Sambuc }
617f4a2713aSLionel Sambuc 
checkAcquireOrderAttrCommon(Sema & S,Decl * D,const AttributeList & Attr,SmallVectorImpl<Expr * > & Args)618f4a2713aSLionel Sambuc static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D,
619f4a2713aSLionel Sambuc                                         const AttributeList &Attr,
620f4a2713aSLionel Sambuc                                         SmallVectorImpl<Expr *> &Args) {
621f4a2713aSLionel Sambuc   if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
622f4a2713aSLionel Sambuc     return false;
623f4a2713aSLionel Sambuc 
624f4a2713aSLionel Sambuc   // Check that this attribute only applies to lockable types.
625*0a6a1f1dSLionel Sambuc   QualType QT = cast<ValueDecl>(D)->getType();
626f4a2713aSLionel Sambuc   if (!QT->isDependentType()) {
627f4a2713aSLionel Sambuc     const RecordType *RT = getRecordType(QT);
628*0a6a1f1dSLionel Sambuc     if (!RT || !RT->getDecl()->hasAttr<CapabilityAttr>()) {
629f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable)
630f4a2713aSLionel Sambuc         << Attr.getName();
631f4a2713aSLionel Sambuc       return false;
632f4a2713aSLionel Sambuc     }
633f4a2713aSLionel Sambuc   }
634f4a2713aSLionel Sambuc 
635f4a2713aSLionel Sambuc   // Check that all arguments are lockable objects.
636*0a6a1f1dSLionel Sambuc   checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
637f4a2713aSLionel Sambuc   if (Args.empty())
638f4a2713aSLionel Sambuc     return false;
639f4a2713aSLionel Sambuc 
640f4a2713aSLionel Sambuc   return true;
641f4a2713aSLionel Sambuc }
642f4a2713aSLionel Sambuc 
handleAcquiredAfterAttr(Sema & S,Decl * D,const AttributeList & Attr)643f4a2713aSLionel Sambuc static void handleAcquiredAfterAttr(Sema &S, Decl *D,
644f4a2713aSLionel Sambuc                                     const AttributeList &Attr) {
645f4a2713aSLionel Sambuc   SmallVector<Expr*, 1> Args;
646f4a2713aSLionel Sambuc   if (!checkAcquireOrderAttrCommon(S, D, Attr, Args))
647f4a2713aSLionel Sambuc     return;
648f4a2713aSLionel Sambuc 
649f4a2713aSLionel Sambuc   Expr **StartArg = &Args[0];
650f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
651f4a2713aSLionel Sambuc              AcquiredAfterAttr(Attr.getRange(), S.Context,
652f4a2713aSLionel Sambuc                                StartArg, Args.size(),
653f4a2713aSLionel Sambuc                                Attr.getAttributeSpellingListIndex()));
654f4a2713aSLionel Sambuc }
655f4a2713aSLionel Sambuc 
handleAcquiredBeforeAttr(Sema & S,Decl * D,const AttributeList & Attr)656f4a2713aSLionel Sambuc static void handleAcquiredBeforeAttr(Sema &S, Decl *D,
657f4a2713aSLionel Sambuc                                      const AttributeList &Attr) {
658f4a2713aSLionel Sambuc   SmallVector<Expr*, 1> Args;
659f4a2713aSLionel Sambuc   if (!checkAcquireOrderAttrCommon(S, D, Attr, Args))
660f4a2713aSLionel Sambuc     return;
661f4a2713aSLionel Sambuc 
662f4a2713aSLionel Sambuc   Expr **StartArg = &Args[0];
663f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
664f4a2713aSLionel Sambuc              AcquiredBeforeAttr(Attr.getRange(), S.Context,
665f4a2713aSLionel Sambuc                                 StartArg, Args.size(),
666f4a2713aSLionel Sambuc                                 Attr.getAttributeSpellingListIndex()));
667f4a2713aSLionel Sambuc }
668f4a2713aSLionel Sambuc 
checkLockFunAttrCommon(Sema & S,Decl * D,const AttributeList & Attr,SmallVectorImpl<Expr * > & Args)669f4a2713aSLionel Sambuc static bool checkLockFunAttrCommon(Sema &S, Decl *D,
670f4a2713aSLionel Sambuc                                    const AttributeList &Attr,
671f4a2713aSLionel Sambuc                                    SmallVectorImpl<Expr *> &Args) {
672f4a2713aSLionel Sambuc   // zero or more arguments ok
673f4a2713aSLionel Sambuc   // check that all arguments are lockable objects
674*0a6a1f1dSLionel Sambuc   checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true);
675f4a2713aSLionel Sambuc 
676f4a2713aSLionel Sambuc   return true;
677f4a2713aSLionel Sambuc }
678f4a2713aSLionel Sambuc 
handleAssertSharedLockAttr(Sema & S,Decl * D,const AttributeList & Attr)679f4a2713aSLionel Sambuc static void handleAssertSharedLockAttr(Sema &S, Decl *D,
680f4a2713aSLionel Sambuc                                        const AttributeList &Attr) {
681f4a2713aSLionel Sambuc   SmallVector<Expr*, 1> Args;
682f4a2713aSLionel Sambuc   if (!checkLockFunAttrCommon(S, D, Attr, Args))
683f4a2713aSLionel Sambuc     return;
684f4a2713aSLionel Sambuc 
685f4a2713aSLionel Sambuc   unsigned Size = Args.size();
686*0a6a1f1dSLionel Sambuc   Expr **StartArg = Size == 0 ? nullptr : &Args[0];
687f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
688f4a2713aSLionel Sambuc              AssertSharedLockAttr(Attr.getRange(), S.Context, StartArg, Size,
689f4a2713aSLionel Sambuc                                   Attr.getAttributeSpellingListIndex()));
690f4a2713aSLionel Sambuc }
691f4a2713aSLionel Sambuc 
handleAssertExclusiveLockAttr(Sema & S,Decl * D,const AttributeList & Attr)692f4a2713aSLionel Sambuc static void handleAssertExclusiveLockAttr(Sema &S, Decl *D,
693f4a2713aSLionel Sambuc                                           const AttributeList &Attr) {
694f4a2713aSLionel Sambuc   SmallVector<Expr*, 1> Args;
695f4a2713aSLionel Sambuc   if (!checkLockFunAttrCommon(S, D, Attr, Args))
696f4a2713aSLionel Sambuc     return;
697f4a2713aSLionel Sambuc 
698f4a2713aSLionel Sambuc   unsigned Size = Args.size();
699*0a6a1f1dSLionel Sambuc   Expr **StartArg = Size == 0 ? nullptr : &Args[0];
700f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
701f4a2713aSLionel Sambuc              AssertExclusiveLockAttr(Attr.getRange(), S.Context,
702f4a2713aSLionel Sambuc                                      StartArg, Size,
703f4a2713aSLionel Sambuc                                      Attr.getAttributeSpellingListIndex()));
704f4a2713aSLionel Sambuc }
705f4a2713aSLionel Sambuc 
706f4a2713aSLionel Sambuc 
checkTryLockFunAttrCommon(Sema & S,Decl * D,const AttributeList & Attr,SmallVectorImpl<Expr * > & Args)707f4a2713aSLionel Sambuc static bool checkTryLockFunAttrCommon(Sema &S, Decl *D,
708f4a2713aSLionel Sambuc                                       const AttributeList &Attr,
709f4a2713aSLionel Sambuc                                       SmallVectorImpl<Expr *> &Args) {
710f4a2713aSLionel Sambuc   if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
711f4a2713aSLionel Sambuc     return false;
712f4a2713aSLionel Sambuc 
713f4a2713aSLionel Sambuc   if (!isIntOrBool(Attr.getArgAsExpr(0))) {
714f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
715f4a2713aSLionel Sambuc       << Attr.getName() << 1 << AANT_ArgumentIntOrBool;
716f4a2713aSLionel Sambuc     return false;
717f4a2713aSLionel Sambuc   }
718f4a2713aSLionel Sambuc 
719f4a2713aSLionel Sambuc   // check that all arguments are lockable objects
720*0a6a1f1dSLionel Sambuc   checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 1);
721f4a2713aSLionel Sambuc 
722f4a2713aSLionel Sambuc   return true;
723f4a2713aSLionel Sambuc }
724f4a2713aSLionel Sambuc 
handleSharedTrylockFunctionAttr(Sema & S,Decl * D,const AttributeList & Attr)725f4a2713aSLionel Sambuc static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D,
726f4a2713aSLionel Sambuc                                             const AttributeList &Attr) {
727f4a2713aSLionel Sambuc   SmallVector<Expr*, 2> Args;
728f4a2713aSLionel Sambuc   if (!checkTryLockFunAttrCommon(S, D, Attr, Args))
729f4a2713aSLionel Sambuc     return;
730f4a2713aSLionel Sambuc 
731f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
732f4a2713aSLionel Sambuc              SharedTrylockFunctionAttr(Attr.getRange(), S.Context,
733f4a2713aSLionel Sambuc                                        Attr.getArgAsExpr(0),
734f4a2713aSLionel Sambuc                                        Args.data(), Args.size(),
735f4a2713aSLionel Sambuc                                        Attr.getAttributeSpellingListIndex()));
736f4a2713aSLionel Sambuc }
737f4a2713aSLionel Sambuc 
handleExclusiveTrylockFunctionAttr(Sema & S,Decl * D,const AttributeList & Attr)738f4a2713aSLionel Sambuc static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D,
739f4a2713aSLionel Sambuc                                                const AttributeList &Attr) {
740f4a2713aSLionel Sambuc   SmallVector<Expr*, 2> Args;
741f4a2713aSLionel Sambuc   if (!checkTryLockFunAttrCommon(S, D, Attr, Args))
742f4a2713aSLionel Sambuc     return;
743f4a2713aSLionel Sambuc 
744*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(
745*0a6a1f1dSLionel Sambuc       Attr.getRange(), S.Context, Attr.getArgAsExpr(0), Args.data(),
746*0a6a1f1dSLionel Sambuc       Args.size(), Attr.getAttributeSpellingListIndex()));
747f4a2713aSLionel Sambuc }
748f4a2713aSLionel Sambuc 
handleLockReturnedAttr(Sema & S,Decl * D,const AttributeList & Attr)749f4a2713aSLionel Sambuc static void handleLockReturnedAttr(Sema &S, Decl *D,
750f4a2713aSLionel Sambuc                                    const AttributeList &Attr) {
751f4a2713aSLionel Sambuc   // check that the argument is lockable object
752f4a2713aSLionel Sambuc   SmallVector<Expr*, 1> Args;
753*0a6a1f1dSLionel Sambuc   checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
754f4a2713aSLionel Sambuc   unsigned Size = Args.size();
755f4a2713aSLionel Sambuc   if (Size == 0)
756f4a2713aSLionel Sambuc     return;
757f4a2713aSLionel Sambuc 
758f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
759f4a2713aSLionel Sambuc              LockReturnedAttr(Attr.getRange(), S.Context, Args[0],
760f4a2713aSLionel Sambuc                               Attr.getAttributeSpellingListIndex()));
761f4a2713aSLionel Sambuc }
762f4a2713aSLionel Sambuc 
handleLocksExcludedAttr(Sema & S,Decl * D,const AttributeList & Attr)763f4a2713aSLionel Sambuc static void handleLocksExcludedAttr(Sema &S, Decl *D,
764f4a2713aSLionel Sambuc                                     const AttributeList &Attr) {
765f4a2713aSLionel Sambuc   if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
766f4a2713aSLionel Sambuc     return;
767f4a2713aSLionel Sambuc 
768f4a2713aSLionel Sambuc   // check that all arguments are lockable objects
769f4a2713aSLionel Sambuc   SmallVector<Expr*, 1> Args;
770*0a6a1f1dSLionel Sambuc   checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
771f4a2713aSLionel Sambuc   unsigned Size = Args.size();
772f4a2713aSLionel Sambuc   if (Size == 0)
773f4a2713aSLionel Sambuc     return;
774f4a2713aSLionel Sambuc   Expr **StartArg = &Args[0];
775f4a2713aSLionel Sambuc 
776f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
777f4a2713aSLionel Sambuc              LocksExcludedAttr(Attr.getRange(), S.Context, StartArg, Size,
778f4a2713aSLionel Sambuc                                Attr.getAttributeSpellingListIndex()));
779f4a2713aSLionel Sambuc }
780f4a2713aSLionel Sambuc 
handleEnableIfAttr(Sema & S,Decl * D,const AttributeList & Attr)781*0a6a1f1dSLionel Sambuc static void handleEnableIfAttr(Sema &S, Decl *D, const AttributeList &Attr) {
782*0a6a1f1dSLionel Sambuc   Expr *Cond = Attr.getArgAsExpr(0);
783*0a6a1f1dSLionel Sambuc   if (!Cond->isTypeDependent()) {
784*0a6a1f1dSLionel Sambuc     ExprResult Converted = S.PerformContextuallyConvertToBool(Cond);
785*0a6a1f1dSLionel Sambuc     if (Converted.isInvalid())
786*0a6a1f1dSLionel Sambuc       return;
787*0a6a1f1dSLionel Sambuc     Cond = Converted.get();
788*0a6a1f1dSLionel Sambuc   }
789*0a6a1f1dSLionel Sambuc 
790*0a6a1f1dSLionel Sambuc   StringRef Msg;
791*0a6a1f1dSLionel Sambuc   if (!S.checkStringLiteralArgumentAttr(Attr, 1, Msg))
792*0a6a1f1dSLionel Sambuc     return;
793*0a6a1f1dSLionel Sambuc 
794*0a6a1f1dSLionel Sambuc   SmallVector<PartialDiagnosticAt, 8> Diags;
795*0a6a1f1dSLionel Sambuc   if (!Cond->isValueDependent() &&
796*0a6a1f1dSLionel Sambuc       !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D),
797*0a6a1f1dSLionel Sambuc                                                 Diags)) {
798*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_enable_if_never_constant_expr);
799*0a6a1f1dSLionel Sambuc     for (int I = 0, N = Diags.size(); I != N; ++I)
800*0a6a1f1dSLionel Sambuc       S.Diag(Diags[I].first, Diags[I].second);
801*0a6a1f1dSLionel Sambuc     return;
802*0a6a1f1dSLionel Sambuc   }
803*0a6a1f1dSLionel Sambuc 
804*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context)
805*0a6a1f1dSLionel Sambuc              EnableIfAttr(Attr.getRange(), S.Context, Cond, Msg,
806*0a6a1f1dSLionel Sambuc                           Attr.getAttributeSpellingListIndex()));
807*0a6a1f1dSLionel Sambuc }
808*0a6a1f1dSLionel Sambuc 
handleConsumableAttr(Sema & S,Decl * D,const AttributeList & Attr)809f4a2713aSLionel Sambuc static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
810f4a2713aSLionel Sambuc   ConsumableAttr::ConsumedState DefaultState;
811f4a2713aSLionel Sambuc 
812f4a2713aSLionel Sambuc   if (Attr.isArgIdent(0)) {
813f4a2713aSLionel Sambuc     IdentifierLoc *IL = Attr.getArgAsIdent(0);
814f4a2713aSLionel Sambuc     if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(),
815f4a2713aSLionel Sambuc                                                    DefaultState)) {
816f4a2713aSLionel Sambuc       S.Diag(IL->Loc, diag::warn_attribute_type_not_supported)
817f4a2713aSLionel Sambuc         << Attr.getName() << IL->Ident;
818f4a2713aSLionel Sambuc       return;
819f4a2713aSLionel Sambuc     }
820f4a2713aSLionel Sambuc   } else {
821f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
822f4a2713aSLionel Sambuc         << Attr.getName() << AANT_ArgumentIdentifier;
823f4a2713aSLionel Sambuc     return;
824f4a2713aSLionel Sambuc   }
825f4a2713aSLionel Sambuc 
826f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
827f4a2713aSLionel Sambuc              ConsumableAttr(Attr.getRange(), S.Context, DefaultState,
828f4a2713aSLionel Sambuc                             Attr.getAttributeSpellingListIndex()));
829f4a2713aSLionel Sambuc }
830f4a2713aSLionel Sambuc 
831*0a6a1f1dSLionel Sambuc 
checkForConsumableClass(Sema & S,const CXXMethodDecl * MD,const AttributeList & Attr)832f4a2713aSLionel Sambuc static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD,
833f4a2713aSLionel Sambuc                                         const AttributeList &Attr) {
834f4a2713aSLionel Sambuc   ASTContext &CurrContext = S.getASTContext();
835f4a2713aSLionel Sambuc   QualType ThisType = MD->getThisType(CurrContext)->getPointeeType();
836f4a2713aSLionel Sambuc 
837f4a2713aSLionel Sambuc   if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) {
838f4a2713aSLionel Sambuc     if (!RD->hasAttr<ConsumableAttr>()) {
839f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_attr_on_unconsumable_class) <<
840f4a2713aSLionel Sambuc         RD->getNameAsString();
841f4a2713aSLionel Sambuc 
842f4a2713aSLionel Sambuc       return false;
843f4a2713aSLionel Sambuc     }
844f4a2713aSLionel Sambuc   }
845f4a2713aSLionel Sambuc 
846f4a2713aSLionel Sambuc   return true;
847f4a2713aSLionel Sambuc }
848f4a2713aSLionel Sambuc 
849f4a2713aSLionel Sambuc 
handleCallableWhenAttr(Sema & S,Decl * D,const AttributeList & Attr)850f4a2713aSLionel Sambuc static void handleCallableWhenAttr(Sema &S, Decl *D,
851f4a2713aSLionel Sambuc                                    const AttributeList &Attr) {
852f4a2713aSLionel Sambuc   if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
853f4a2713aSLionel Sambuc     return;
854f4a2713aSLionel Sambuc 
855f4a2713aSLionel Sambuc   if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
856f4a2713aSLionel Sambuc     return;
857f4a2713aSLionel Sambuc 
858f4a2713aSLionel Sambuc   SmallVector<CallableWhenAttr::ConsumedState, 3> States;
859f4a2713aSLionel Sambuc   for (unsigned ArgIndex = 0; ArgIndex < Attr.getNumArgs(); ++ArgIndex) {
860f4a2713aSLionel Sambuc     CallableWhenAttr::ConsumedState CallableState;
861f4a2713aSLionel Sambuc 
862f4a2713aSLionel Sambuc     StringRef StateString;
863f4a2713aSLionel Sambuc     SourceLocation Loc;
864*0a6a1f1dSLionel Sambuc     if (Attr.isArgIdent(ArgIndex)) {
865*0a6a1f1dSLionel Sambuc       IdentifierLoc *Ident = Attr.getArgAsIdent(ArgIndex);
866*0a6a1f1dSLionel Sambuc       StateString = Ident->Ident->getName();
867*0a6a1f1dSLionel Sambuc       Loc = Ident->Loc;
868*0a6a1f1dSLionel Sambuc     } else {
869f4a2713aSLionel Sambuc       if (!S.checkStringLiteralArgumentAttr(Attr, ArgIndex, StateString, &Loc))
870f4a2713aSLionel Sambuc         return;
871*0a6a1f1dSLionel Sambuc     }
872f4a2713aSLionel Sambuc 
873f4a2713aSLionel Sambuc     if (!CallableWhenAttr::ConvertStrToConsumedState(StateString,
874f4a2713aSLionel Sambuc                                                      CallableState)) {
875f4a2713aSLionel Sambuc       S.Diag(Loc, diag::warn_attribute_type_not_supported)
876f4a2713aSLionel Sambuc         << Attr.getName() << StateString;
877f4a2713aSLionel Sambuc       return;
878f4a2713aSLionel Sambuc     }
879f4a2713aSLionel Sambuc 
880f4a2713aSLionel Sambuc     States.push_back(CallableState);
881f4a2713aSLionel Sambuc   }
882f4a2713aSLionel Sambuc 
883f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
884f4a2713aSLionel Sambuc              CallableWhenAttr(Attr.getRange(), S.Context, States.data(),
885f4a2713aSLionel Sambuc                States.size(), Attr.getAttributeSpellingListIndex()));
886f4a2713aSLionel Sambuc }
887f4a2713aSLionel Sambuc 
888f4a2713aSLionel Sambuc 
handleParamTypestateAttr(Sema & S,Decl * D,const AttributeList & Attr)889f4a2713aSLionel Sambuc static void handleParamTypestateAttr(Sema &S, Decl *D,
890f4a2713aSLionel Sambuc                                     const AttributeList &Attr) {
891f4a2713aSLionel Sambuc   ParamTypestateAttr::ConsumedState ParamState;
892f4a2713aSLionel Sambuc 
893f4a2713aSLionel Sambuc   if (Attr.isArgIdent(0)) {
894f4a2713aSLionel Sambuc     IdentifierLoc *Ident = Attr.getArgAsIdent(0);
895f4a2713aSLionel Sambuc     StringRef StateString = Ident->Ident->getName();
896f4a2713aSLionel Sambuc 
897f4a2713aSLionel Sambuc     if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString,
898f4a2713aSLionel Sambuc                                                        ParamState)) {
899f4a2713aSLionel Sambuc       S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
900f4a2713aSLionel Sambuc         << Attr.getName() << StateString;
901f4a2713aSLionel Sambuc       return;
902f4a2713aSLionel Sambuc     }
903f4a2713aSLionel Sambuc   } else {
904f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
905f4a2713aSLionel Sambuc       Attr.getName() << AANT_ArgumentIdentifier;
906f4a2713aSLionel Sambuc     return;
907f4a2713aSLionel Sambuc   }
908f4a2713aSLionel Sambuc 
909f4a2713aSLionel Sambuc   // FIXME: This check is currently being done in the analysis.  It can be
910f4a2713aSLionel Sambuc   //        enabled here only after the parser propagates attributes at
911f4a2713aSLionel Sambuc   //        template specialization definition, not declaration.
912f4a2713aSLionel Sambuc   //QualType ReturnType = cast<ParmVarDecl>(D)->getType();
913f4a2713aSLionel Sambuc   //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
914f4a2713aSLionel Sambuc   //
915f4a2713aSLionel Sambuc   //if (!RD || !RD->hasAttr<ConsumableAttr>()) {
916f4a2713aSLionel Sambuc   //    S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
917f4a2713aSLionel Sambuc   //      ReturnType.getAsString();
918f4a2713aSLionel Sambuc   //    return;
919f4a2713aSLionel Sambuc   //}
920f4a2713aSLionel Sambuc 
921f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
922f4a2713aSLionel Sambuc              ParamTypestateAttr(Attr.getRange(), S.Context, ParamState,
923f4a2713aSLionel Sambuc                                 Attr.getAttributeSpellingListIndex()));
924f4a2713aSLionel Sambuc }
925f4a2713aSLionel Sambuc 
926f4a2713aSLionel Sambuc 
handleReturnTypestateAttr(Sema & S,Decl * D,const AttributeList & Attr)927f4a2713aSLionel Sambuc static void handleReturnTypestateAttr(Sema &S, Decl *D,
928f4a2713aSLionel Sambuc                                       const AttributeList &Attr) {
929f4a2713aSLionel Sambuc   ReturnTypestateAttr::ConsumedState ReturnState;
930f4a2713aSLionel Sambuc 
931f4a2713aSLionel Sambuc   if (Attr.isArgIdent(0)) {
932f4a2713aSLionel Sambuc     IdentifierLoc *IL = Attr.getArgAsIdent(0);
933f4a2713aSLionel Sambuc     if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(),
934f4a2713aSLionel Sambuc                                                         ReturnState)) {
935f4a2713aSLionel Sambuc       S.Diag(IL->Loc, diag::warn_attribute_type_not_supported)
936f4a2713aSLionel Sambuc         << Attr.getName() << IL->Ident;
937f4a2713aSLionel Sambuc       return;
938f4a2713aSLionel Sambuc     }
939f4a2713aSLionel Sambuc   } else {
940f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
941f4a2713aSLionel Sambuc       Attr.getName() << AANT_ArgumentIdentifier;
942f4a2713aSLionel Sambuc     return;
943f4a2713aSLionel Sambuc   }
944f4a2713aSLionel Sambuc 
945f4a2713aSLionel Sambuc   // FIXME: This check is currently being done in the analysis.  It can be
946f4a2713aSLionel Sambuc   //        enabled here only after the parser propagates attributes at
947f4a2713aSLionel Sambuc   //        template specialization definition, not declaration.
948f4a2713aSLionel Sambuc   //QualType ReturnType;
949f4a2713aSLionel Sambuc   //
950f4a2713aSLionel Sambuc   //if (const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D)) {
951f4a2713aSLionel Sambuc   //  ReturnType = Param->getType();
952f4a2713aSLionel Sambuc   //
953f4a2713aSLionel Sambuc   //} else if (const CXXConstructorDecl *Constructor =
954f4a2713aSLionel Sambuc   //             dyn_cast<CXXConstructorDecl>(D)) {
955f4a2713aSLionel Sambuc   //  ReturnType = Constructor->getThisType(S.getASTContext())->getPointeeType();
956f4a2713aSLionel Sambuc   //
957f4a2713aSLionel Sambuc   //} else {
958f4a2713aSLionel Sambuc   //
959f4a2713aSLionel Sambuc   //  ReturnType = cast<FunctionDecl>(D)->getCallResultType();
960f4a2713aSLionel Sambuc   //}
961f4a2713aSLionel Sambuc   //
962f4a2713aSLionel Sambuc   //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
963f4a2713aSLionel Sambuc   //
964f4a2713aSLionel Sambuc   //if (!RD || !RD->hasAttr<ConsumableAttr>()) {
965f4a2713aSLionel Sambuc   //    S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
966f4a2713aSLionel Sambuc   //      ReturnType.getAsString();
967f4a2713aSLionel Sambuc   //    return;
968f4a2713aSLionel Sambuc   //}
969f4a2713aSLionel Sambuc 
970f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
971f4a2713aSLionel Sambuc              ReturnTypestateAttr(Attr.getRange(), S.Context, ReturnState,
972f4a2713aSLionel Sambuc                                  Attr.getAttributeSpellingListIndex()));
973f4a2713aSLionel Sambuc }
974f4a2713aSLionel Sambuc 
975f4a2713aSLionel Sambuc 
handleSetTypestateAttr(Sema & S,Decl * D,const AttributeList & Attr)976f4a2713aSLionel Sambuc static void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
977f4a2713aSLionel Sambuc   if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
978f4a2713aSLionel Sambuc     return;
979f4a2713aSLionel Sambuc 
980f4a2713aSLionel Sambuc   SetTypestateAttr::ConsumedState NewState;
981f4a2713aSLionel Sambuc   if (Attr.isArgIdent(0)) {
982f4a2713aSLionel Sambuc     IdentifierLoc *Ident = Attr.getArgAsIdent(0);
983f4a2713aSLionel Sambuc     StringRef Param = Ident->Ident->getName();
984f4a2713aSLionel Sambuc     if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) {
985f4a2713aSLionel Sambuc       S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
986f4a2713aSLionel Sambuc         << Attr.getName() << Param;
987f4a2713aSLionel Sambuc       return;
988f4a2713aSLionel Sambuc     }
989f4a2713aSLionel Sambuc   } else {
990f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
991f4a2713aSLionel Sambuc       Attr.getName() << AANT_ArgumentIdentifier;
992f4a2713aSLionel Sambuc     return;
993f4a2713aSLionel Sambuc   }
994f4a2713aSLionel Sambuc 
995f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
996f4a2713aSLionel Sambuc              SetTypestateAttr(Attr.getRange(), S.Context, NewState,
997f4a2713aSLionel Sambuc                               Attr.getAttributeSpellingListIndex()));
998f4a2713aSLionel Sambuc }
999f4a2713aSLionel Sambuc 
handleTestTypestateAttr(Sema & S,Decl * D,const AttributeList & Attr)1000f4a2713aSLionel Sambuc static void handleTestTypestateAttr(Sema &S, Decl *D,
1001f4a2713aSLionel Sambuc                                     const AttributeList &Attr) {
1002f4a2713aSLionel Sambuc   if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
1003f4a2713aSLionel Sambuc     return;
1004f4a2713aSLionel Sambuc 
1005f4a2713aSLionel Sambuc   TestTypestateAttr::ConsumedState TestState;
1006f4a2713aSLionel Sambuc   if (Attr.isArgIdent(0)) {
1007f4a2713aSLionel Sambuc     IdentifierLoc *Ident = Attr.getArgAsIdent(0);
1008f4a2713aSLionel Sambuc     StringRef Param = Ident->Ident->getName();
1009f4a2713aSLionel Sambuc     if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) {
1010f4a2713aSLionel Sambuc       S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
1011f4a2713aSLionel Sambuc         << Attr.getName() << Param;
1012f4a2713aSLionel Sambuc       return;
1013f4a2713aSLionel Sambuc     }
1014f4a2713aSLionel Sambuc   } else {
1015f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
1016f4a2713aSLionel Sambuc       Attr.getName() << AANT_ArgumentIdentifier;
1017f4a2713aSLionel Sambuc     return;
1018f4a2713aSLionel Sambuc   }
1019f4a2713aSLionel Sambuc 
1020f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
1021f4a2713aSLionel Sambuc              TestTypestateAttr(Attr.getRange(), S.Context, TestState,
1022f4a2713aSLionel Sambuc                                 Attr.getAttributeSpellingListIndex()));
1023f4a2713aSLionel Sambuc }
1024f4a2713aSLionel Sambuc 
handleExtVectorTypeAttr(Sema & S,Scope * scope,Decl * D,const AttributeList & Attr)1025f4a2713aSLionel Sambuc static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D,
1026f4a2713aSLionel Sambuc                                     const AttributeList &Attr) {
1027f4a2713aSLionel Sambuc   // Remember this typedef decl, we will need it later for diagnostics.
1028*0a6a1f1dSLionel Sambuc   S.ExtVectorDecls.push_back(cast<TypedefNameDecl>(D));
1029f4a2713aSLionel Sambuc }
1030f4a2713aSLionel Sambuc 
handlePackedAttr(Sema & S,Decl * D,const AttributeList & Attr)1031f4a2713aSLionel Sambuc static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
1032f4a2713aSLionel Sambuc   if (TagDecl *TD = dyn_cast<TagDecl>(D))
1033*0a6a1f1dSLionel Sambuc     TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context,
1034*0a6a1f1dSLionel Sambuc                                         Attr.getAttributeSpellingListIndex()));
1035f4a2713aSLionel Sambuc   else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
1036f4a2713aSLionel Sambuc     // If the alignment is less than or equal to 8 bits, the packed attribute
1037f4a2713aSLionel Sambuc     // has no effect.
1038f4a2713aSLionel Sambuc     if (!FD->getType()->isDependentType() &&
1039f4a2713aSLionel Sambuc         !FD->getType()->isIncompleteType() &&
1040f4a2713aSLionel Sambuc         S.Context.getTypeAlign(FD->getType()) <= 8)
1041f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
1042f4a2713aSLionel Sambuc         << Attr.getName() << FD->getType();
1043f4a2713aSLionel Sambuc     else
1044f4a2713aSLionel Sambuc       FD->addAttr(::new (S.Context)
1045f4a2713aSLionel Sambuc                   PackedAttr(Attr.getRange(), S.Context,
1046f4a2713aSLionel Sambuc                              Attr.getAttributeSpellingListIndex()));
1047f4a2713aSLionel Sambuc   } else
1048f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
1049f4a2713aSLionel Sambuc }
1050f4a2713aSLionel Sambuc 
checkIBOutletCommon(Sema & S,Decl * D,const AttributeList & Attr)1051f4a2713aSLionel Sambuc static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) {
1052f4a2713aSLionel Sambuc   // The IBOutlet/IBOutletCollection attributes only apply to instance
1053f4a2713aSLionel Sambuc   // variables or properties of Objective-C classes.  The outlet must also
1054f4a2713aSLionel Sambuc   // have an object reference type.
1055f4a2713aSLionel Sambuc   if (const ObjCIvarDecl *VD = dyn_cast<ObjCIvarDecl>(D)) {
1056f4a2713aSLionel Sambuc     if (!VD->getType()->getAs<ObjCObjectPointerType>()) {
1057f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type)
1058f4a2713aSLionel Sambuc         << Attr.getName() << VD->getType() << 0;
1059f4a2713aSLionel Sambuc       return false;
1060f4a2713aSLionel Sambuc     }
1061f4a2713aSLionel Sambuc   }
1062f4a2713aSLionel Sambuc   else if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) {
1063f4a2713aSLionel Sambuc     if (!PD->getType()->getAs<ObjCObjectPointerType>()) {
1064f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type)
1065f4a2713aSLionel Sambuc         << Attr.getName() << PD->getType() << 1;
1066f4a2713aSLionel Sambuc       return false;
1067f4a2713aSLionel Sambuc     }
1068f4a2713aSLionel Sambuc   }
1069f4a2713aSLionel Sambuc   else {
1070f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName();
1071f4a2713aSLionel Sambuc     return false;
1072f4a2713aSLionel Sambuc   }
1073f4a2713aSLionel Sambuc 
1074f4a2713aSLionel Sambuc   return true;
1075f4a2713aSLionel Sambuc }
1076f4a2713aSLionel Sambuc 
handleIBOutlet(Sema & S,Decl * D,const AttributeList & Attr)1077f4a2713aSLionel Sambuc static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) {
1078f4a2713aSLionel Sambuc   if (!checkIBOutletCommon(S, D, Attr))
1079f4a2713aSLionel Sambuc     return;
1080f4a2713aSLionel Sambuc 
1081f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
1082f4a2713aSLionel Sambuc              IBOutletAttr(Attr.getRange(), S.Context,
1083f4a2713aSLionel Sambuc                           Attr.getAttributeSpellingListIndex()));
1084f4a2713aSLionel Sambuc }
1085f4a2713aSLionel Sambuc 
handleIBOutletCollection(Sema & S,Decl * D,const AttributeList & Attr)1086f4a2713aSLionel Sambuc static void handleIBOutletCollection(Sema &S, Decl *D,
1087f4a2713aSLionel Sambuc                                      const AttributeList &Attr) {
1088f4a2713aSLionel Sambuc 
1089f4a2713aSLionel Sambuc   // The iboutletcollection attribute can have zero or one arguments.
1090f4a2713aSLionel Sambuc   if (Attr.getNumArgs() > 1) {
1091f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
1092f4a2713aSLionel Sambuc       << Attr.getName() << 1;
1093f4a2713aSLionel Sambuc     return;
1094f4a2713aSLionel Sambuc   }
1095f4a2713aSLionel Sambuc 
1096f4a2713aSLionel Sambuc   if (!checkIBOutletCommon(S, D, Attr))
1097f4a2713aSLionel Sambuc     return;
1098f4a2713aSLionel Sambuc 
1099f4a2713aSLionel Sambuc   ParsedType PT;
1100f4a2713aSLionel Sambuc 
1101f4a2713aSLionel Sambuc   if (Attr.hasParsedType())
1102f4a2713aSLionel Sambuc     PT = Attr.getTypeArg();
1103f4a2713aSLionel Sambuc   else {
1104f4a2713aSLionel Sambuc     PT = S.getTypeName(S.Context.Idents.get("NSObject"), Attr.getLoc(),
1105f4a2713aSLionel Sambuc                        S.getScopeForContext(D->getDeclContext()->getParent()));
1106f4a2713aSLionel Sambuc     if (!PT) {
1107f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << "NSObject";
1108f4a2713aSLionel Sambuc       return;
1109f4a2713aSLionel Sambuc     }
1110f4a2713aSLionel Sambuc   }
1111f4a2713aSLionel Sambuc 
1112*0a6a1f1dSLionel Sambuc   TypeSourceInfo *QTLoc = nullptr;
1113f4a2713aSLionel Sambuc   QualType QT = S.GetTypeFromParser(PT, &QTLoc);
1114f4a2713aSLionel Sambuc   if (!QTLoc)
1115f4a2713aSLionel Sambuc     QTLoc = S.Context.getTrivialTypeSourceInfo(QT, Attr.getLoc());
1116f4a2713aSLionel Sambuc 
1117f4a2713aSLionel Sambuc   // Diagnose use of non-object type in iboutletcollection attribute.
1118f4a2713aSLionel Sambuc   // FIXME. Gnu attribute extension ignores use of builtin types in
1119f4a2713aSLionel Sambuc   // attributes. So, __attribute__((iboutletcollection(char))) will be
1120f4a2713aSLionel Sambuc   // treated as __attribute__((iboutletcollection())).
1121f4a2713aSLionel Sambuc   if (!QT->isObjCIdType() && !QT->isObjCObjectType()) {
1122f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(),
1123f4a2713aSLionel Sambuc            QT->isBuiltinType() ? diag::err_iboutletcollection_builtintype
1124f4a2713aSLionel Sambuc                                : diag::err_iboutletcollection_type) << QT;
1125f4a2713aSLionel Sambuc     return;
1126f4a2713aSLionel Sambuc   }
1127f4a2713aSLionel Sambuc 
1128f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
1129f4a2713aSLionel Sambuc              IBOutletCollectionAttr(Attr.getRange(), S.Context, QTLoc,
1130f4a2713aSLionel Sambuc                                     Attr.getAttributeSpellingListIndex()));
1131f4a2713aSLionel Sambuc }
1132f4a2713aSLionel Sambuc 
isValidPointerAttrType(QualType T,bool RefOkay)1133*0a6a1f1dSLionel Sambuc bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) {
1134*0a6a1f1dSLionel Sambuc   if (RefOkay) {
1135*0a6a1f1dSLionel Sambuc     if (T->isReferenceType())
1136*0a6a1f1dSLionel Sambuc       return true;
1137*0a6a1f1dSLionel Sambuc   } else {
1138*0a6a1f1dSLionel Sambuc     T = T.getNonReferenceType();
1139*0a6a1f1dSLionel Sambuc   }
1140*0a6a1f1dSLionel Sambuc 
1141*0a6a1f1dSLionel Sambuc   // The nonnull attribute, and other similar attributes, can be applied to a
1142*0a6a1f1dSLionel Sambuc   // transparent union that contains a pointer type.
1143*0a6a1f1dSLionel Sambuc   if (const RecordType *UT = T->getAsUnionType()) {
1144f4a2713aSLionel Sambuc     if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) {
1145f4a2713aSLionel Sambuc       RecordDecl *UD = UT->getDecl();
1146*0a6a1f1dSLionel Sambuc       for (const auto *I : UD->fields()) {
1147*0a6a1f1dSLionel Sambuc         QualType QT = I->getType();
1148*0a6a1f1dSLionel Sambuc         if (QT->isAnyPointerType() || QT->isBlockPointerType())
1149*0a6a1f1dSLionel Sambuc           return true;
1150f4a2713aSLionel Sambuc       }
1151f4a2713aSLionel Sambuc     }
1152f4a2713aSLionel Sambuc   }
1153f4a2713aSLionel Sambuc 
1154*0a6a1f1dSLionel Sambuc   return T->isAnyPointerType() || T->isBlockPointerType();
1155f4a2713aSLionel Sambuc }
1156f4a2713aSLionel Sambuc 
attrNonNullArgCheck(Sema & S,QualType T,const AttributeList & Attr,SourceRange AttrParmRange,SourceRange TypeRange,bool isReturnValue=false)1157*0a6a1f1dSLionel Sambuc static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &Attr,
1158*0a6a1f1dSLionel Sambuc                                 SourceRange AttrParmRange,
1159*0a6a1f1dSLionel Sambuc                                 SourceRange TypeRange,
1160*0a6a1f1dSLionel Sambuc                                 bool isReturnValue = false) {
1161*0a6a1f1dSLionel Sambuc   if (!S.isValidPointerAttrType(T)) {
1162*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), isReturnValue
1163*0a6a1f1dSLionel Sambuc                               ? diag::warn_attribute_return_pointers_only
1164*0a6a1f1dSLionel Sambuc                               : diag::warn_attribute_pointers_only)
1165*0a6a1f1dSLionel Sambuc         << Attr.getName() << AttrParmRange << TypeRange;
1166*0a6a1f1dSLionel Sambuc     return false;
1167f4a2713aSLionel Sambuc   }
1168*0a6a1f1dSLionel Sambuc   return true;
1169f4a2713aSLionel Sambuc }
1170f4a2713aSLionel Sambuc 
handleNonNullAttr(Sema & S,Decl * D,const AttributeList & Attr)1171f4a2713aSLionel Sambuc static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
1172f4a2713aSLionel Sambuc   SmallVector<unsigned, 8> NonNullArgs;
1173*0a6a1f1dSLionel Sambuc   for (unsigned I = 0; I < Attr.getNumArgs(); ++I) {
1174*0a6a1f1dSLionel Sambuc     Expr *Ex = Attr.getArgAsExpr(I);
1175f4a2713aSLionel Sambuc     uint64_t Idx;
1176*0a6a1f1dSLionel Sambuc     if (!checkFunctionOrMethodParameterIndex(S, D, Attr, I + 1, Ex, Idx))
1177f4a2713aSLionel Sambuc       return;
1178f4a2713aSLionel Sambuc 
1179f4a2713aSLionel Sambuc     // Is the function argument a pointer type?
1180*0a6a1f1dSLionel Sambuc     if (Idx < getFunctionOrMethodNumParams(D) &&
1181*0a6a1f1dSLionel Sambuc         !attrNonNullArgCheck(S, getFunctionOrMethodParamType(D, Idx), Attr,
1182*0a6a1f1dSLionel Sambuc                              Ex->getSourceRange(),
1183*0a6a1f1dSLionel Sambuc                              getFunctionOrMethodParamRange(D, Idx)))
1184f4a2713aSLionel Sambuc       continue;
1185f4a2713aSLionel Sambuc 
1186f4a2713aSLionel Sambuc     NonNullArgs.push_back(Idx);
1187f4a2713aSLionel Sambuc   }
1188f4a2713aSLionel Sambuc 
1189f4a2713aSLionel Sambuc   // If no arguments were specified to __attribute__((nonnull)) then all pointer
1190*0a6a1f1dSLionel Sambuc   // arguments have a nonnull attribute; warn if there aren't any. Skip this
1191*0a6a1f1dSLionel Sambuc   // check if the attribute came from a macro expansion or a template
1192*0a6a1f1dSLionel Sambuc   // instantiation.
1193*0a6a1f1dSLionel Sambuc   if (NonNullArgs.empty() && Attr.getLoc().isFileID() &&
1194*0a6a1f1dSLionel Sambuc       S.ActiveTemplateInstantiations.empty()) {
1195*0a6a1f1dSLionel Sambuc     bool AnyPointers = isFunctionOrMethodVariadic(D);
1196*0a6a1f1dSLionel Sambuc     for (unsigned I = 0, E = getFunctionOrMethodNumParams(D);
1197*0a6a1f1dSLionel Sambuc          I != E && !AnyPointers; ++I) {
1198*0a6a1f1dSLionel Sambuc       QualType T = getFunctionOrMethodParamType(D, I);
1199*0a6a1f1dSLionel Sambuc       if (T->isDependentType() || S.isValidPointerAttrType(T))
1200*0a6a1f1dSLionel Sambuc         AnyPointers = true;
1201f4a2713aSLionel Sambuc     }
1202f4a2713aSLionel Sambuc 
1203*0a6a1f1dSLionel Sambuc     if (!AnyPointers)
1204f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers);
1205*0a6a1f1dSLionel Sambuc   }
1206*0a6a1f1dSLionel Sambuc 
1207*0a6a1f1dSLionel Sambuc   unsigned *Start = NonNullArgs.data();
1208*0a6a1f1dSLionel Sambuc   unsigned Size = NonNullArgs.size();
1209*0a6a1f1dSLionel Sambuc   llvm::array_pod_sort(Start, Start + Size);
1210*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context)
1211*0a6a1f1dSLionel Sambuc              NonNullAttr(Attr.getRange(), S.Context, Start, Size,
1212*0a6a1f1dSLionel Sambuc                          Attr.getAttributeSpellingListIndex()));
1213*0a6a1f1dSLionel Sambuc }
1214*0a6a1f1dSLionel Sambuc 
handleNonNullAttrParameter(Sema & S,ParmVarDecl * D,const AttributeList & Attr)1215*0a6a1f1dSLionel Sambuc static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D,
1216*0a6a1f1dSLionel Sambuc                                        const AttributeList &Attr) {
1217*0a6a1f1dSLionel Sambuc   if (Attr.getNumArgs() > 0) {
1218*0a6a1f1dSLionel Sambuc     if (D->getFunctionType()) {
1219*0a6a1f1dSLionel Sambuc       handleNonNullAttr(S, D, Attr);
1220*0a6a1f1dSLionel Sambuc     } else {
1221*0a6a1f1dSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_parm_no_args)
1222*0a6a1f1dSLionel Sambuc         << D->getSourceRange();
1223*0a6a1f1dSLionel Sambuc     }
1224*0a6a1f1dSLionel Sambuc     return;
1225*0a6a1f1dSLionel Sambuc   }
1226*0a6a1f1dSLionel Sambuc 
1227*0a6a1f1dSLionel Sambuc   // Is the argument a pointer type?
1228*0a6a1f1dSLionel Sambuc   if (!attrNonNullArgCheck(S, D->getType(), Attr, SourceRange(),
1229*0a6a1f1dSLionel Sambuc                            D->getSourceRange()))
1230*0a6a1f1dSLionel Sambuc     return;
1231*0a6a1f1dSLionel Sambuc 
1232*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context)
1233*0a6a1f1dSLionel Sambuc              NonNullAttr(Attr.getRange(), S.Context, nullptr, 0,
1234*0a6a1f1dSLionel Sambuc                          Attr.getAttributeSpellingListIndex()));
1235*0a6a1f1dSLionel Sambuc }
1236*0a6a1f1dSLionel Sambuc 
handleReturnsNonNullAttr(Sema & S,Decl * D,const AttributeList & Attr)1237*0a6a1f1dSLionel Sambuc static void handleReturnsNonNullAttr(Sema &S, Decl *D,
1238*0a6a1f1dSLionel Sambuc                                      const AttributeList &Attr) {
1239*0a6a1f1dSLionel Sambuc   QualType ResultType = getFunctionOrMethodResultType(D);
1240*0a6a1f1dSLionel Sambuc   SourceRange SR = getFunctionOrMethodResultSourceRange(D);
1241*0a6a1f1dSLionel Sambuc   if (!attrNonNullArgCheck(S, ResultType, Attr, SourceRange(), SR,
1242*0a6a1f1dSLionel Sambuc                            /* isReturnValue */ true))
1243*0a6a1f1dSLionel Sambuc     return;
1244*0a6a1f1dSLionel Sambuc 
1245*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context)
1246*0a6a1f1dSLionel Sambuc             ReturnsNonNullAttr(Attr.getRange(), S.Context,
1247*0a6a1f1dSLionel Sambuc                                Attr.getAttributeSpellingListIndex()));
1248*0a6a1f1dSLionel Sambuc }
1249*0a6a1f1dSLionel Sambuc 
handleAssumeAlignedAttr(Sema & S,Decl * D,const AttributeList & Attr)1250*0a6a1f1dSLionel Sambuc static void handleAssumeAlignedAttr(Sema &S, Decl *D,
1251*0a6a1f1dSLionel Sambuc                                     const AttributeList &Attr) {
1252*0a6a1f1dSLionel Sambuc   Expr *E = Attr.getArgAsExpr(0),
1253*0a6a1f1dSLionel Sambuc        *OE = Attr.getNumArgs() > 1 ? Attr.getArgAsExpr(1) : nullptr;
1254*0a6a1f1dSLionel Sambuc   S.AddAssumeAlignedAttr(Attr.getRange(), D, E, OE,
1255*0a6a1f1dSLionel Sambuc                          Attr.getAttributeSpellingListIndex());
1256*0a6a1f1dSLionel Sambuc }
1257*0a6a1f1dSLionel Sambuc 
AddAssumeAlignedAttr(SourceRange AttrRange,Decl * D,Expr * E,Expr * OE,unsigned SpellingListIndex)1258*0a6a1f1dSLionel Sambuc void Sema::AddAssumeAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
1259*0a6a1f1dSLionel Sambuc                                 Expr *OE, unsigned SpellingListIndex) {
1260*0a6a1f1dSLionel Sambuc   QualType ResultType = getFunctionOrMethodResultType(D);
1261*0a6a1f1dSLionel Sambuc   SourceRange SR = getFunctionOrMethodResultSourceRange(D);
1262*0a6a1f1dSLionel Sambuc 
1263*0a6a1f1dSLionel Sambuc   AssumeAlignedAttr TmpAttr(AttrRange, Context, E, OE, SpellingListIndex);
1264*0a6a1f1dSLionel Sambuc   SourceLocation AttrLoc = AttrRange.getBegin();
1265*0a6a1f1dSLionel Sambuc 
1266*0a6a1f1dSLionel Sambuc   if (!isValidPointerAttrType(ResultType, /* RefOkay */ true)) {
1267*0a6a1f1dSLionel Sambuc     Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only)
1268*0a6a1f1dSLionel Sambuc       << &TmpAttr << AttrRange << SR;
1269*0a6a1f1dSLionel Sambuc     return;
1270*0a6a1f1dSLionel Sambuc   }
1271*0a6a1f1dSLionel Sambuc 
1272*0a6a1f1dSLionel Sambuc   if (!E->isValueDependent()) {
1273*0a6a1f1dSLionel Sambuc     llvm::APSInt I(64);
1274*0a6a1f1dSLionel Sambuc     if (!E->isIntegerConstantExpr(I, Context)) {
1275*0a6a1f1dSLionel Sambuc       if (OE)
1276*0a6a1f1dSLionel Sambuc         Diag(AttrLoc, diag::err_attribute_argument_n_type)
1277*0a6a1f1dSLionel Sambuc           << &TmpAttr << 1 << AANT_ArgumentIntegerConstant
1278*0a6a1f1dSLionel Sambuc           << E->getSourceRange();
1279*0a6a1f1dSLionel Sambuc       else
1280*0a6a1f1dSLionel Sambuc         Diag(AttrLoc, diag::err_attribute_argument_type)
1281*0a6a1f1dSLionel Sambuc           << &TmpAttr << AANT_ArgumentIntegerConstant
1282*0a6a1f1dSLionel Sambuc           << E->getSourceRange();
1283*0a6a1f1dSLionel Sambuc       return;
1284*0a6a1f1dSLionel Sambuc     }
1285*0a6a1f1dSLionel Sambuc 
1286*0a6a1f1dSLionel Sambuc     if (!I.isPowerOf2()) {
1287*0a6a1f1dSLionel Sambuc       Diag(AttrLoc, diag::err_alignment_not_power_of_two)
1288*0a6a1f1dSLionel Sambuc         << E->getSourceRange();
1289f4a2713aSLionel Sambuc       return;
1290f4a2713aSLionel Sambuc     }
1291f4a2713aSLionel Sambuc   }
1292f4a2713aSLionel Sambuc 
1293*0a6a1f1dSLionel Sambuc   if (OE) {
1294*0a6a1f1dSLionel Sambuc     if (!OE->isValueDependent()) {
1295*0a6a1f1dSLionel Sambuc       llvm::APSInt I(64);
1296*0a6a1f1dSLionel Sambuc       if (!OE->isIntegerConstantExpr(I, Context)) {
1297*0a6a1f1dSLionel Sambuc         Diag(AttrLoc, diag::err_attribute_argument_n_type)
1298*0a6a1f1dSLionel Sambuc           << &TmpAttr << 2 << AANT_ArgumentIntegerConstant
1299*0a6a1f1dSLionel Sambuc           << OE->getSourceRange();
1300*0a6a1f1dSLionel Sambuc         return;
1301*0a6a1f1dSLionel Sambuc       }
1302*0a6a1f1dSLionel Sambuc     }
1303f4a2713aSLionel Sambuc   }
1304f4a2713aSLionel Sambuc 
1305*0a6a1f1dSLionel Sambuc   D->addAttr(::new (Context)
1306*0a6a1f1dSLionel Sambuc             AssumeAlignedAttr(AttrRange, Context, E, OE, SpellingListIndex));
1307f4a2713aSLionel Sambuc }
1308f4a2713aSLionel Sambuc 
handleOwnershipAttr(Sema & S,Decl * D,const AttributeList & AL)1309f4a2713aSLionel Sambuc static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
1310f4a2713aSLionel Sambuc   // This attribute must be applied to a function declaration. The first
1311f4a2713aSLionel Sambuc   // argument to the attribute must be an identifier, the name of the resource,
1312f4a2713aSLionel Sambuc   // for example: malloc. The following arguments must be argument indexes, the
1313f4a2713aSLionel Sambuc   // arguments must be of integer type for Returns, otherwise of pointer type.
1314f4a2713aSLionel Sambuc   // The difference between Holds and Takes is that a pointer may still be used
1315f4a2713aSLionel Sambuc   // after being held. free() should be __attribute((ownership_takes)), whereas
1316f4a2713aSLionel Sambuc   // a list append function may well be __attribute((ownership_holds)).
1317f4a2713aSLionel Sambuc 
1318f4a2713aSLionel Sambuc   if (!AL.isArgIdent(0)) {
1319f4a2713aSLionel Sambuc     S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
1320f4a2713aSLionel Sambuc       << AL.getName() << 1 << AANT_ArgumentIdentifier;
1321f4a2713aSLionel Sambuc     return;
1322f4a2713aSLionel Sambuc   }
1323f4a2713aSLionel Sambuc 
1324*0a6a1f1dSLionel Sambuc   // Figure out our Kind.
1325*0a6a1f1dSLionel Sambuc   OwnershipAttr::OwnershipKind K =
1326*0a6a1f1dSLionel Sambuc       OwnershipAttr(AL.getLoc(), S.Context, nullptr, nullptr, 0,
1327*0a6a1f1dSLionel Sambuc                     AL.getAttributeSpellingListIndex()).getOwnKind();
1328f4a2713aSLionel Sambuc 
1329*0a6a1f1dSLionel Sambuc   // Check arguments.
1330*0a6a1f1dSLionel Sambuc   switch (K) {
1331*0a6a1f1dSLionel Sambuc   case OwnershipAttr::Takes:
1332*0a6a1f1dSLionel Sambuc   case OwnershipAttr::Holds:
1333*0a6a1f1dSLionel Sambuc     if (AL.getNumArgs() < 2) {
1334*0a6a1f1dSLionel Sambuc       S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments)
1335*0a6a1f1dSLionel Sambuc         << AL.getName() << 2;
1336*0a6a1f1dSLionel Sambuc       return;
1337*0a6a1f1dSLionel Sambuc     }
1338*0a6a1f1dSLionel Sambuc     break;
1339*0a6a1f1dSLionel Sambuc   case OwnershipAttr::Returns:
1340f4a2713aSLionel Sambuc     if (AL.getNumArgs() > 2) {
1341*0a6a1f1dSLionel Sambuc       S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments)
1342*0a6a1f1dSLionel Sambuc         << AL.getName() << 1;
1343f4a2713aSLionel Sambuc       return;
1344f4a2713aSLionel Sambuc     }
1345f4a2713aSLionel Sambuc     break;
1346f4a2713aSLionel Sambuc   }
1347f4a2713aSLionel Sambuc 
1348*0a6a1f1dSLionel Sambuc   IdentifierInfo *Module = AL.getArgAsIdent(0)->Ident;
1349f4a2713aSLionel Sambuc 
1350f4a2713aSLionel Sambuc   // Normalize the argument, __foo__ becomes foo.
1351*0a6a1f1dSLionel Sambuc   StringRef ModuleName = Module->getName();
1352*0a6a1f1dSLionel Sambuc   if (ModuleName.startswith("__") && ModuleName.endswith("__") &&
1353*0a6a1f1dSLionel Sambuc       ModuleName.size() > 4) {
1354*0a6a1f1dSLionel Sambuc     ModuleName = ModuleName.drop_front(2).drop_back(2);
1355*0a6a1f1dSLionel Sambuc     Module = &S.PP.getIdentifierTable().get(ModuleName);
1356*0a6a1f1dSLionel Sambuc   }
1357f4a2713aSLionel Sambuc 
1358f4a2713aSLionel Sambuc   SmallVector<unsigned, 8> OwnershipArgs;
1359f4a2713aSLionel Sambuc   for (unsigned i = 1; i < AL.getNumArgs(); ++i) {
1360f4a2713aSLionel Sambuc     Expr *Ex = AL.getArgAsExpr(i);
1361f4a2713aSLionel Sambuc     uint64_t Idx;
1362*0a6a1f1dSLionel Sambuc     if (!checkFunctionOrMethodParameterIndex(S, D, AL, i, Ex, Idx))
1363f4a2713aSLionel Sambuc       return;
1364f4a2713aSLionel Sambuc 
1365f4a2713aSLionel Sambuc     // Is the function argument a pointer type?
1366*0a6a1f1dSLionel Sambuc     QualType T = getFunctionOrMethodParamType(D, Idx);
1367f4a2713aSLionel Sambuc     int Err = -1;  // No error
1368f4a2713aSLionel Sambuc     switch (K) {
1369f4a2713aSLionel Sambuc       case OwnershipAttr::Takes:
1370f4a2713aSLionel Sambuc       case OwnershipAttr::Holds:
1371f4a2713aSLionel Sambuc         if (!T->isAnyPointerType() && !T->isBlockPointerType())
1372f4a2713aSLionel Sambuc           Err = 0;
1373f4a2713aSLionel Sambuc         break;
1374f4a2713aSLionel Sambuc       case OwnershipAttr::Returns:
1375f4a2713aSLionel Sambuc         if (!T->isIntegerType())
1376f4a2713aSLionel Sambuc           Err = 1;
1377f4a2713aSLionel Sambuc         break;
1378f4a2713aSLionel Sambuc     }
1379f4a2713aSLionel Sambuc     if (-1 != Err) {
1380f4a2713aSLionel Sambuc       S.Diag(AL.getLoc(), diag::err_ownership_type) << AL.getName() << Err
1381f4a2713aSLionel Sambuc         << Ex->getSourceRange();
1382f4a2713aSLionel Sambuc       return;
1383f4a2713aSLionel Sambuc     }
1384f4a2713aSLionel Sambuc 
1385f4a2713aSLionel Sambuc     // Check we don't have a conflict with another ownership attribute.
1386*0a6a1f1dSLionel Sambuc     for (const auto *I : D->specific_attrs<OwnershipAttr>()) {
1387*0a6a1f1dSLionel Sambuc       // Cannot have two ownership attributes of different kinds for the same
1388*0a6a1f1dSLionel Sambuc       // index.
1389*0a6a1f1dSLionel Sambuc       if (I->getOwnKind() != K && I->args_end() !=
1390*0a6a1f1dSLionel Sambuc           std::find(I->args_begin(), I->args_end(), Idx)) {
1391f4a2713aSLionel Sambuc         S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
1392*0a6a1f1dSLionel Sambuc           << AL.getName() << I;
1393f4a2713aSLionel Sambuc         return;
1394*0a6a1f1dSLionel Sambuc       } else if (K == OwnershipAttr::Returns &&
1395*0a6a1f1dSLionel Sambuc                  I->getOwnKind() == OwnershipAttr::Returns) {
1396*0a6a1f1dSLionel Sambuc         // A returns attribute conflicts with any other returns attribute using
1397*0a6a1f1dSLionel Sambuc         // a different index. Note, diagnostic reporting is 1-based, but stored
1398*0a6a1f1dSLionel Sambuc         // argument indexes are 0-based.
1399*0a6a1f1dSLionel Sambuc         if (std::find(I->args_begin(), I->args_end(), Idx) == I->args_end()) {
1400*0a6a1f1dSLionel Sambuc           S.Diag(I->getLocation(), diag::err_ownership_returns_index_mismatch)
1401*0a6a1f1dSLionel Sambuc               << *(I->args_begin()) + 1;
1402*0a6a1f1dSLionel Sambuc           if (I->args_size())
1403*0a6a1f1dSLionel Sambuc             S.Diag(AL.getLoc(), diag::note_ownership_returns_index_mismatch)
1404*0a6a1f1dSLionel Sambuc                 << (unsigned)Idx + 1 << Ex->getSourceRange();
1405*0a6a1f1dSLionel Sambuc           return;
1406*0a6a1f1dSLionel Sambuc         }
1407f4a2713aSLionel Sambuc       }
1408f4a2713aSLionel Sambuc     }
1409f4a2713aSLionel Sambuc     OwnershipArgs.push_back(Idx);
1410f4a2713aSLionel Sambuc   }
1411f4a2713aSLionel Sambuc 
1412f4a2713aSLionel Sambuc   unsigned* start = OwnershipArgs.data();
1413f4a2713aSLionel Sambuc   unsigned size = OwnershipArgs.size();
1414f4a2713aSLionel Sambuc   llvm::array_pod_sort(start, start + size);
1415f4a2713aSLionel Sambuc 
1416f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
1417*0a6a1f1dSLionel Sambuc              OwnershipAttr(AL.getLoc(), S.Context, Module, start, size,
1418f4a2713aSLionel Sambuc                            AL.getAttributeSpellingListIndex()));
1419f4a2713aSLionel Sambuc }
1420f4a2713aSLionel Sambuc 
handleWeakRefAttr(Sema & S,Decl * D,const AttributeList & Attr)1421f4a2713aSLionel Sambuc static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
1422f4a2713aSLionel Sambuc   // Check the attribute arguments.
1423f4a2713aSLionel Sambuc   if (Attr.getNumArgs() > 1) {
1424f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
1425f4a2713aSLionel Sambuc       << Attr.getName() << 1;
1426f4a2713aSLionel Sambuc     return;
1427f4a2713aSLionel Sambuc   }
1428f4a2713aSLionel Sambuc 
1429f4a2713aSLionel Sambuc   NamedDecl *nd = cast<NamedDecl>(D);
1430f4a2713aSLionel Sambuc 
1431f4a2713aSLionel Sambuc   // gcc rejects
1432f4a2713aSLionel Sambuc   // class c {
1433f4a2713aSLionel Sambuc   //   static int a __attribute__((weakref ("v2")));
1434f4a2713aSLionel Sambuc   //   static int b() __attribute__((weakref ("f3")));
1435f4a2713aSLionel Sambuc   // };
1436f4a2713aSLionel Sambuc   // and ignores the attributes of
1437f4a2713aSLionel Sambuc   // void f(void) {
1438f4a2713aSLionel Sambuc   //   static int a __attribute__((weakref ("v2")));
1439f4a2713aSLionel Sambuc   // }
1440f4a2713aSLionel Sambuc   // we reject them
1441f4a2713aSLionel Sambuc   const DeclContext *Ctx = D->getDeclContext()->getRedeclContext();
1442f4a2713aSLionel Sambuc   if (!Ctx->isFileContext()) {
1443*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context)
1444*0a6a1f1dSLionel Sambuc       << nd;
1445f4a2713aSLionel Sambuc     return;
1446f4a2713aSLionel Sambuc   }
1447f4a2713aSLionel Sambuc 
1448f4a2713aSLionel Sambuc   // The GCC manual says
1449f4a2713aSLionel Sambuc   //
1450f4a2713aSLionel Sambuc   // At present, a declaration to which `weakref' is attached can only
1451f4a2713aSLionel Sambuc   // be `static'.
1452f4a2713aSLionel Sambuc   //
1453f4a2713aSLionel Sambuc   // It also says
1454f4a2713aSLionel Sambuc   //
1455f4a2713aSLionel Sambuc   // Without a TARGET,
1456f4a2713aSLionel Sambuc   // given as an argument to `weakref' or to `alias', `weakref' is
1457f4a2713aSLionel Sambuc   // equivalent to `weak'.
1458f4a2713aSLionel Sambuc   //
1459f4a2713aSLionel Sambuc   // gcc 4.4.1 will accept
1460f4a2713aSLionel Sambuc   // int a7 __attribute__((weakref));
1461f4a2713aSLionel Sambuc   // as
1462f4a2713aSLionel Sambuc   // int a7 __attribute__((weak));
1463f4a2713aSLionel Sambuc   // This looks like a bug in gcc. We reject that for now. We should revisit
1464f4a2713aSLionel Sambuc   // it if this behaviour is actually used.
1465f4a2713aSLionel Sambuc 
1466f4a2713aSLionel Sambuc   // GCC rejects
1467f4a2713aSLionel Sambuc   // static ((alias ("y"), weakref)).
1468f4a2713aSLionel Sambuc   // Should we? How to check that weakref is before or after alias?
1469f4a2713aSLionel Sambuc 
1470f4a2713aSLionel Sambuc   // FIXME: it would be good for us to keep the WeakRefAttr as-written instead
1471f4a2713aSLionel Sambuc   // of transforming it into an AliasAttr.  The WeakRefAttr never uses the
1472f4a2713aSLionel Sambuc   // StringRef parameter it was given anyway.
1473f4a2713aSLionel Sambuc   StringRef Str;
1474f4a2713aSLionel Sambuc   if (Attr.getNumArgs() && S.checkStringLiteralArgumentAttr(Attr, 0, Str))
1475f4a2713aSLionel Sambuc     // GCC will accept anything as the argument of weakref. Should we
1476f4a2713aSLionel Sambuc     // check for an existing decl?
1477f4a2713aSLionel Sambuc     D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str,
1478f4a2713aSLionel Sambuc                                         Attr.getAttributeSpellingListIndex()));
1479f4a2713aSLionel Sambuc 
1480f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
1481f4a2713aSLionel Sambuc              WeakRefAttr(Attr.getRange(), S.Context,
1482f4a2713aSLionel Sambuc                          Attr.getAttributeSpellingListIndex()));
1483f4a2713aSLionel Sambuc }
1484f4a2713aSLionel Sambuc 
handleAliasAttr(Sema & S,Decl * D,const AttributeList & Attr)1485f4a2713aSLionel Sambuc static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
1486f4a2713aSLionel Sambuc   StringRef Str;
1487f4a2713aSLionel Sambuc   if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str))
1488f4a2713aSLionel Sambuc     return;
1489f4a2713aSLionel Sambuc 
1490f4a2713aSLionel Sambuc   if (S.Context.getTargetInfo().getTriple().isOSDarwin()) {
1491f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin);
1492f4a2713aSLionel Sambuc     return;
1493f4a2713aSLionel Sambuc   }
1494f4a2713aSLionel Sambuc 
1495f4a2713aSLionel Sambuc   // FIXME: check if target symbol exists in current file
1496f4a2713aSLionel Sambuc 
1497f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str,
1498f4a2713aSLionel Sambuc                                          Attr.getAttributeSpellingListIndex()));
1499f4a2713aSLionel Sambuc }
1500f4a2713aSLionel Sambuc 
handleColdAttr(Sema & S,Decl * D,const AttributeList & Attr)1501f4a2713aSLionel Sambuc static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {
1502*0a6a1f1dSLionel Sambuc   if (checkAttrMutualExclusion<HotAttr>(S, D, Attr))
1503f4a2713aSLionel Sambuc     return;
1504f4a2713aSLionel Sambuc 
1505f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context,
1506f4a2713aSLionel Sambuc                                         Attr.getAttributeSpellingListIndex()));
1507f4a2713aSLionel Sambuc }
1508f4a2713aSLionel Sambuc 
handleHotAttr(Sema & S,Decl * D,const AttributeList & Attr)1509f4a2713aSLionel Sambuc static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) {
1510*0a6a1f1dSLionel Sambuc   if (checkAttrMutualExclusion<ColdAttr>(S, D, Attr))
1511f4a2713aSLionel Sambuc     return;
1512f4a2713aSLionel Sambuc 
1513f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context,
1514f4a2713aSLionel Sambuc                                        Attr.getAttributeSpellingListIndex()));
1515f4a2713aSLionel Sambuc }
1516f4a2713aSLionel Sambuc 
handleTLSModelAttr(Sema & S,Decl * D,const AttributeList & Attr)1517f4a2713aSLionel Sambuc static void handleTLSModelAttr(Sema &S, Decl *D,
1518f4a2713aSLionel Sambuc                                const AttributeList &Attr) {
1519f4a2713aSLionel Sambuc   StringRef Model;
1520f4a2713aSLionel Sambuc   SourceLocation LiteralLoc;
1521f4a2713aSLionel Sambuc   // Check that it is a string.
1522f4a2713aSLionel Sambuc   if (!S.checkStringLiteralArgumentAttr(Attr, 0, Model, &LiteralLoc))
1523f4a2713aSLionel Sambuc     return;
1524f4a2713aSLionel Sambuc 
1525f4a2713aSLionel Sambuc   // Check that the value.
1526f4a2713aSLionel Sambuc   if (Model != "global-dynamic" && Model != "local-dynamic"
1527f4a2713aSLionel Sambuc       && Model != "initial-exec" && Model != "local-exec") {
1528f4a2713aSLionel Sambuc     S.Diag(LiteralLoc, diag::err_attr_tlsmodel_arg);
1529f4a2713aSLionel Sambuc     return;
1530f4a2713aSLionel Sambuc   }
1531f4a2713aSLionel Sambuc 
1532f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
1533f4a2713aSLionel Sambuc              TLSModelAttr(Attr.getRange(), S.Context, Model,
1534f4a2713aSLionel Sambuc                           Attr.getAttributeSpellingListIndex()));
1535f4a2713aSLionel Sambuc }
1536f4a2713aSLionel Sambuc 
handleMallocAttr(Sema & S,Decl * D,const AttributeList & Attr)1537f4a2713aSLionel Sambuc static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) {
1538f4a2713aSLionel Sambuc   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
1539*0a6a1f1dSLionel Sambuc     QualType RetTy = FD->getReturnType();
1540f4a2713aSLionel Sambuc     if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
1541f4a2713aSLionel Sambuc       D->addAttr(::new (S.Context)
1542f4a2713aSLionel Sambuc                  MallocAttr(Attr.getRange(), S.Context,
1543f4a2713aSLionel Sambuc                             Attr.getAttributeSpellingListIndex()));
1544f4a2713aSLionel Sambuc       return;
1545f4a2713aSLionel Sambuc     }
1546f4a2713aSLionel Sambuc   }
1547f4a2713aSLionel Sambuc 
1548f4a2713aSLionel Sambuc   S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only);
1549f4a2713aSLionel Sambuc }
1550f4a2713aSLionel Sambuc 
handleCommonAttr(Sema & S,Decl * D,const AttributeList & Attr)1551f4a2713aSLionel Sambuc static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
1552f4a2713aSLionel Sambuc   if (S.LangOpts.CPlusPlus) {
1553*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
1554*0a6a1f1dSLionel Sambuc       << Attr.getName() << AttributeLangSupport::Cpp;
1555f4a2713aSLionel Sambuc     return;
1556f4a2713aSLionel Sambuc   }
1557f4a2713aSLionel Sambuc 
1558*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context) CommonAttr(Attr.getRange(), S.Context,
1559f4a2713aSLionel Sambuc                                         Attr.getAttributeSpellingListIndex()));
1560f4a2713aSLionel Sambuc }
1561f4a2713aSLionel Sambuc 
handleNoReturnAttr(Sema & S,Decl * D,const AttributeList & attr)1562f4a2713aSLionel Sambuc static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) {
1563f4a2713aSLionel Sambuc   if (hasDeclarator(D)) return;
1564f4a2713aSLionel Sambuc 
1565f4a2713aSLionel Sambuc   if (S.CheckNoReturnAttr(attr)) return;
1566f4a2713aSLionel Sambuc 
1567f4a2713aSLionel Sambuc   if (!isa<ObjCMethodDecl>(D)) {
1568f4a2713aSLionel Sambuc     S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
1569f4a2713aSLionel Sambuc       << attr.getName() << ExpectedFunctionOrMethod;
1570f4a2713aSLionel Sambuc     return;
1571f4a2713aSLionel Sambuc   }
1572f4a2713aSLionel Sambuc 
1573f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
1574f4a2713aSLionel Sambuc              NoReturnAttr(attr.getRange(), S.Context,
1575f4a2713aSLionel Sambuc                           attr.getAttributeSpellingListIndex()));
1576f4a2713aSLionel Sambuc }
1577f4a2713aSLionel Sambuc 
CheckNoReturnAttr(const AttributeList & attr)1578f4a2713aSLionel Sambuc bool Sema::CheckNoReturnAttr(const AttributeList &attr) {
1579f4a2713aSLionel Sambuc   if (!checkAttributeNumArgs(*this, attr, 0)) {
1580f4a2713aSLionel Sambuc     attr.setInvalid();
1581f4a2713aSLionel Sambuc     return true;
1582f4a2713aSLionel Sambuc   }
1583f4a2713aSLionel Sambuc 
1584f4a2713aSLionel Sambuc   return false;
1585f4a2713aSLionel Sambuc }
1586f4a2713aSLionel Sambuc 
handleAnalyzerNoReturnAttr(Sema & S,Decl * D,const AttributeList & Attr)1587f4a2713aSLionel Sambuc static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D,
1588f4a2713aSLionel Sambuc                                        const AttributeList &Attr) {
1589f4a2713aSLionel Sambuc 
1590f4a2713aSLionel Sambuc   // The checking path for 'noreturn' and 'analyzer_noreturn' are different
1591f4a2713aSLionel Sambuc   // because 'analyzer_noreturn' does not impact the type.
1592f4a2713aSLionel Sambuc   if (!isFunctionOrMethod(D) && !isa<BlockDecl>(D)) {
1593f4a2713aSLionel Sambuc     ValueDecl *VD = dyn_cast<ValueDecl>(D);
1594*0a6a1f1dSLionel Sambuc     if (!VD || (!VD->getType()->isBlockPointerType() &&
1595*0a6a1f1dSLionel Sambuc                 !VD->getType()->isFunctionPointerType())) {
1596f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(),
1597f4a2713aSLionel Sambuc              Attr.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type
1598f4a2713aSLionel Sambuc              : diag::warn_attribute_wrong_decl_type)
1599f4a2713aSLionel Sambuc         << Attr.getName() << ExpectedFunctionMethodOrBlock;
1600f4a2713aSLionel Sambuc       return;
1601f4a2713aSLionel Sambuc     }
1602f4a2713aSLionel Sambuc   }
1603f4a2713aSLionel Sambuc 
1604f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
1605f4a2713aSLionel Sambuc              AnalyzerNoReturnAttr(Attr.getRange(), S.Context,
1606f4a2713aSLionel Sambuc                                   Attr.getAttributeSpellingListIndex()));
1607f4a2713aSLionel Sambuc }
1608f4a2713aSLionel Sambuc 
1609f4a2713aSLionel Sambuc // PS3 PPU-specific.
handleVecReturnAttr(Sema & S,Decl * D,const AttributeList & Attr)1610f4a2713aSLionel Sambuc static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) {
1611f4a2713aSLionel Sambuc /*
1612f4a2713aSLionel Sambuc   Returning a Vector Class in Registers
1613f4a2713aSLionel Sambuc 
1614f4a2713aSLionel Sambuc   According to the PPU ABI specifications, a class with a single member of
1615f4a2713aSLionel Sambuc   vector type is returned in memory when used as the return value of a function.
1616f4a2713aSLionel Sambuc   This results in inefficient code when implementing vector classes. To return
1617f4a2713aSLionel Sambuc   the value in a single vector register, add the vecreturn attribute to the
1618f4a2713aSLionel Sambuc   class definition. This attribute is also applicable to struct types.
1619f4a2713aSLionel Sambuc 
1620f4a2713aSLionel Sambuc   Example:
1621f4a2713aSLionel Sambuc 
1622f4a2713aSLionel Sambuc   struct Vector
1623f4a2713aSLionel Sambuc   {
1624f4a2713aSLionel Sambuc     __vector float xyzw;
1625f4a2713aSLionel Sambuc   } __attribute__((vecreturn));
1626f4a2713aSLionel Sambuc 
1627f4a2713aSLionel Sambuc   Vector Add(Vector lhs, Vector rhs)
1628f4a2713aSLionel Sambuc   {
1629f4a2713aSLionel Sambuc     Vector result;
1630f4a2713aSLionel Sambuc     result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
1631f4a2713aSLionel Sambuc     return result; // This will be returned in a register
1632f4a2713aSLionel Sambuc   }
1633f4a2713aSLionel Sambuc */
1634*0a6a1f1dSLionel Sambuc   if (VecReturnAttr *A = D->getAttr<VecReturnAttr>()) {
1635*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << A;
1636f4a2713aSLionel Sambuc     return;
1637f4a2713aSLionel Sambuc   }
1638f4a2713aSLionel Sambuc 
1639f4a2713aSLionel Sambuc   RecordDecl *record = cast<RecordDecl>(D);
1640f4a2713aSLionel Sambuc   int count = 0;
1641f4a2713aSLionel Sambuc 
1642f4a2713aSLionel Sambuc   if (!isa<CXXRecordDecl>(record)) {
1643f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
1644f4a2713aSLionel Sambuc     return;
1645f4a2713aSLionel Sambuc   }
1646f4a2713aSLionel Sambuc 
1647f4a2713aSLionel Sambuc   if (!cast<CXXRecordDecl>(record)->isPOD()) {
1648f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_pod_record);
1649f4a2713aSLionel Sambuc     return;
1650f4a2713aSLionel Sambuc   }
1651f4a2713aSLionel Sambuc 
1652*0a6a1f1dSLionel Sambuc   for (const auto *I : record->fields()) {
1653*0a6a1f1dSLionel Sambuc     if ((count == 1) || !I->getType()->isVectorType()) {
1654f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
1655f4a2713aSLionel Sambuc       return;
1656f4a2713aSLionel Sambuc     }
1657f4a2713aSLionel Sambuc     count++;
1658f4a2713aSLionel Sambuc   }
1659f4a2713aSLionel Sambuc 
1660f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
1661f4a2713aSLionel Sambuc              VecReturnAttr(Attr.getRange(), S.Context,
1662f4a2713aSLionel Sambuc                            Attr.getAttributeSpellingListIndex()));
1663f4a2713aSLionel Sambuc }
1664f4a2713aSLionel Sambuc 
handleDependencyAttr(Sema & S,Scope * Scope,Decl * D,const AttributeList & Attr)1665f4a2713aSLionel Sambuc static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D,
1666f4a2713aSLionel Sambuc                                  const AttributeList &Attr) {
1667f4a2713aSLionel Sambuc   if (isa<ParmVarDecl>(D)) {
1668f4a2713aSLionel Sambuc     // [[carries_dependency]] can only be applied to a parameter if it is a
1669f4a2713aSLionel Sambuc     // parameter of a function declaration or lambda.
1670f4a2713aSLionel Sambuc     if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) {
1671f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(),
1672f4a2713aSLionel Sambuc              diag::err_carries_dependency_param_not_function_decl);
1673f4a2713aSLionel Sambuc       return;
1674f4a2713aSLionel Sambuc     }
1675f4a2713aSLionel Sambuc   }
1676f4a2713aSLionel Sambuc 
1677f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context) CarriesDependencyAttr(
1678f4a2713aSLionel Sambuc                                    Attr.getRange(), S.Context,
1679f4a2713aSLionel Sambuc                                    Attr.getAttributeSpellingListIndex()));
1680f4a2713aSLionel Sambuc }
1681f4a2713aSLionel Sambuc 
handleUsedAttr(Sema & S,Decl * D,const AttributeList & Attr)1682f4a2713aSLionel Sambuc static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
1683f4a2713aSLionel Sambuc   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
1684f4a2713aSLionel Sambuc     if (VD->hasLocalStorage()) {
1685*0a6a1f1dSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
1686f4a2713aSLionel Sambuc       return;
1687f4a2713aSLionel Sambuc     }
1688f4a2713aSLionel Sambuc   } else if (!isFunctionOrMethod(D)) {
1689f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
1690f4a2713aSLionel Sambuc       << Attr.getName() << ExpectedVariableOrFunction;
1691f4a2713aSLionel Sambuc     return;
1692f4a2713aSLionel Sambuc   }
1693f4a2713aSLionel Sambuc 
1694f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
1695f4a2713aSLionel Sambuc              UsedAttr(Attr.getRange(), S.Context,
1696f4a2713aSLionel Sambuc                       Attr.getAttributeSpellingListIndex()));
1697f4a2713aSLionel Sambuc }
1698f4a2713aSLionel Sambuc 
handleConstructorAttr(Sema & S,Decl * D,const AttributeList & Attr)1699f4a2713aSLionel Sambuc static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
1700*0a6a1f1dSLionel Sambuc   uint32_t priority = ConstructorAttr::DefaultPriority;
1701*0a6a1f1dSLionel Sambuc   if (Attr.getNumArgs() &&
1702*0a6a1f1dSLionel Sambuc       !checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), priority))
1703f4a2713aSLionel Sambuc     return;
1704f4a2713aSLionel Sambuc 
1705f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
1706f4a2713aSLionel Sambuc              ConstructorAttr(Attr.getRange(), S.Context, priority,
1707f4a2713aSLionel Sambuc                              Attr.getAttributeSpellingListIndex()));
1708f4a2713aSLionel Sambuc }
1709f4a2713aSLionel Sambuc 
handleDestructorAttr(Sema & S,Decl * D,const AttributeList & Attr)1710f4a2713aSLionel Sambuc static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
1711*0a6a1f1dSLionel Sambuc   uint32_t priority = DestructorAttr::DefaultPriority;
1712*0a6a1f1dSLionel Sambuc   if (Attr.getNumArgs() &&
1713*0a6a1f1dSLionel Sambuc       !checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), priority))
1714f4a2713aSLionel Sambuc     return;
1715f4a2713aSLionel Sambuc 
1716f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
1717f4a2713aSLionel Sambuc              DestructorAttr(Attr.getRange(), S.Context, priority,
1718f4a2713aSLionel Sambuc                             Attr.getAttributeSpellingListIndex()));
1719f4a2713aSLionel Sambuc }
1720f4a2713aSLionel Sambuc 
1721f4a2713aSLionel Sambuc template <typename AttrTy>
handleAttrWithMessage(Sema & S,Decl * D,const AttributeList & Attr)1722f4a2713aSLionel Sambuc static void handleAttrWithMessage(Sema &S, Decl *D,
1723f4a2713aSLionel Sambuc                                   const AttributeList &Attr) {
1724f4a2713aSLionel Sambuc   // Handle the case where the attribute has a text message.
1725f4a2713aSLionel Sambuc   StringRef Str;
1726*0a6a1f1dSLionel Sambuc   if (Attr.getNumArgs() == 1 && !S.checkStringLiteralArgumentAttr(Attr, 0, Str))
1727f4a2713aSLionel Sambuc     return;
1728f4a2713aSLionel Sambuc 
1729f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str,
1730f4a2713aSLionel Sambuc                                       Attr.getAttributeSpellingListIndex()));
1731f4a2713aSLionel Sambuc }
1732f4a2713aSLionel Sambuc 
handleObjCSuppresProtocolAttr(Sema & S,Decl * D,const AttributeList & Attr)1733*0a6a1f1dSLionel Sambuc static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D,
1734f4a2713aSLionel Sambuc                                           const AttributeList &Attr) {
1735*0a6a1f1dSLionel Sambuc   if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) {
1736*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_objc_attr_protocol_requires_definition)
1737*0a6a1f1dSLionel Sambuc       << Attr.getName() << Attr.getRange();
1738f4a2713aSLionel Sambuc     return;
1739f4a2713aSLionel Sambuc   }
1740f4a2713aSLionel Sambuc 
1741f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
1742*0a6a1f1dSLionel Sambuc           ObjCExplicitProtocolImplAttr(Attr.getRange(), S.Context,
1743f4a2713aSLionel Sambuc                                        Attr.getAttributeSpellingListIndex()));
1744f4a2713aSLionel Sambuc }
1745f4a2713aSLionel Sambuc 
checkAvailabilityAttr(Sema & S,SourceRange Range,IdentifierInfo * Platform,VersionTuple Introduced,VersionTuple Deprecated,VersionTuple Obsoleted)1746f4a2713aSLionel Sambuc static bool checkAvailabilityAttr(Sema &S, SourceRange Range,
1747f4a2713aSLionel Sambuc                                   IdentifierInfo *Platform,
1748f4a2713aSLionel Sambuc                                   VersionTuple Introduced,
1749f4a2713aSLionel Sambuc                                   VersionTuple Deprecated,
1750f4a2713aSLionel Sambuc                                   VersionTuple Obsoleted) {
1751f4a2713aSLionel Sambuc   StringRef PlatformName
1752f4a2713aSLionel Sambuc     = AvailabilityAttr::getPrettyPlatformName(Platform->getName());
1753f4a2713aSLionel Sambuc   if (PlatformName.empty())
1754f4a2713aSLionel Sambuc     PlatformName = Platform->getName();
1755f4a2713aSLionel Sambuc 
1756f4a2713aSLionel Sambuc   // Ensure that Introduced <= Deprecated <= Obsoleted (although not all
1757f4a2713aSLionel Sambuc   // of these steps are needed).
1758f4a2713aSLionel Sambuc   if (!Introduced.empty() && !Deprecated.empty() &&
1759f4a2713aSLionel Sambuc       !(Introduced <= Deprecated)) {
1760f4a2713aSLionel Sambuc     S.Diag(Range.getBegin(), diag::warn_availability_version_ordering)
1761f4a2713aSLionel Sambuc       << 1 << PlatformName << Deprecated.getAsString()
1762f4a2713aSLionel Sambuc       << 0 << Introduced.getAsString();
1763f4a2713aSLionel Sambuc     return true;
1764f4a2713aSLionel Sambuc   }
1765f4a2713aSLionel Sambuc 
1766f4a2713aSLionel Sambuc   if (!Introduced.empty() && !Obsoleted.empty() &&
1767f4a2713aSLionel Sambuc       !(Introduced <= Obsoleted)) {
1768f4a2713aSLionel Sambuc     S.Diag(Range.getBegin(), diag::warn_availability_version_ordering)
1769f4a2713aSLionel Sambuc       << 2 << PlatformName << Obsoleted.getAsString()
1770f4a2713aSLionel Sambuc       << 0 << Introduced.getAsString();
1771f4a2713aSLionel Sambuc     return true;
1772f4a2713aSLionel Sambuc   }
1773f4a2713aSLionel Sambuc 
1774f4a2713aSLionel Sambuc   if (!Deprecated.empty() && !Obsoleted.empty() &&
1775f4a2713aSLionel Sambuc       !(Deprecated <= Obsoleted)) {
1776f4a2713aSLionel Sambuc     S.Diag(Range.getBegin(), diag::warn_availability_version_ordering)
1777f4a2713aSLionel Sambuc       << 2 << PlatformName << Obsoleted.getAsString()
1778f4a2713aSLionel Sambuc       << 1 << Deprecated.getAsString();
1779f4a2713aSLionel Sambuc     return true;
1780f4a2713aSLionel Sambuc   }
1781f4a2713aSLionel Sambuc 
1782f4a2713aSLionel Sambuc   return false;
1783f4a2713aSLionel Sambuc }
1784f4a2713aSLionel Sambuc 
1785f4a2713aSLionel Sambuc /// \brief Check whether the two versions match.
1786f4a2713aSLionel Sambuc ///
1787f4a2713aSLionel Sambuc /// If either version tuple is empty, then they are assumed to match. If
1788f4a2713aSLionel Sambuc /// \p BeforeIsOkay is true, then \p X can be less than or equal to \p Y.
versionsMatch(const VersionTuple & X,const VersionTuple & Y,bool BeforeIsOkay)1789f4a2713aSLionel Sambuc static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y,
1790f4a2713aSLionel Sambuc                           bool BeforeIsOkay) {
1791f4a2713aSLionel Sambuc   if (X.empty() || Y.empty())
1792f4a2713aSLionel Sambuc     return true;
1793f4a2713aSLionel Sambuc 
1794f4a2713aSLionel Sambuc   if (X == Y)
1795f4a2713aSLionel Sambuc     return true;
1796f4a2713aSLionel Sambuc 
1797f4a2713aSLionel Sambuc   if (BeforeIsOkay && X < Y)
1798f4a2713aSLionel Sambuc     return true;
1799f4a2713aSLionel Sambuc 
1800f4a2713aSLionel Sambuc   return false;
1801f4a2713aSLionel Sambuc }
1802f4a2713aSLionel Sambuc 
mergeAvailabilityAttr(NamedDecl * D,SourceRange Range,IdentifierInfo * Platform,VersionTuple Introduced,VersionTuple Deprecated,VersionTuple Obsoleted,bool IsUnavailable,StringRef Message,bool Override,unsigned AttrSpellingListIndex)1803f4a2713aSLionel Sambuc AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
1804f4a2713aSLionel Sambuc                                               IdentifierInfo *Platform,
1805f4a2713aSLionel Sambuc                                               VersionTuple Introduced,
1806f4a2713aSLionel Sambuc                                               VersionTuple Deprecated,
1807f4a2713aSLionel Sambuc                                               VersionTuple Obsoleted,
1808f4a2713aSLionel Sambuc                                               bool IsUnavailable,
1809f4a2713aSLionel Sambuc                                               StringRef Message,
1810f4a2713aSLionel Sambuc                                               bool Override,
1811f4a2713aSLionel Sambuc                                               unsigned AttrSpellingListIndex) {
1812f4a2713aSLionel Sambuc   VersionTuple MergedIntroduced = Introduced;
1813f4a2713aSLionel Sambuc   VersionTuple MergedDeprecated = Deprecated;
1814f4a2713aSLionel Sambuc   VersionTuple MergedObsoleted = Obsoleted;
1815f4a2713aSLionel Sambuc   bool FoundAny = false;
1816f4a2713aSLionel Sambuc 
1817f4a2713aSLionel Sambuc   if (D->hasAttrs()) {
1818f4a2713aSLionel Sambuc     AttrVec &Attrs = D->getAttrs();
1819f4a2713aSLionel Sambuc     for (unsigned i = 0, e = Attrs.size(); i != e;) {
1820f4a2713aSLionel Sambuc       const AvailabilityAttr *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]);
1821f4a2713aSLionel Sambuc       if (!OldAA) {
1822f4a2713aSLionel Sambuc         ++i;
1823f4a2713aSLionel Sambuc         continue;
1824f4a2713aSLionel Sambuc       }
1825f4a2713aSLionel Sambuc 
1826f4a2713aSLionel Sambuc       IdentifierInfo *OldPlatform = OldAA->getPlatform();
1827f4a2713aSLionel Sambuc       if (OldPlatform != Platform) {
1828f4a2713aSLionel Sambuc         ++i;
1829f4a2713aSLionel Sambuc         continue;
1830f4a2713aSLionel Sambuc       }
1831f4a2713aSLionel Sambuc 
1832f4a2713aSLionel Sambuc       FoundAny = true;
1833f4a2713aSLionel Sambuc       VersionTuple OldIntroduced = OldAA->getIntroduced();
1834f4a2713aSLionel Sambuc       VersionTuple OldDeprecated = OldAA->getDeprecated();
1835f4a2713aSLionel Sambuc       VersionTuple OldObsoleted = OldAA->getObsoleted();
1836f4a2713aSLionel Sambuc       bool OldIsUnavailable = OldAA->getUnavailable();
1837f4a2713aSLionel Sambuc 
1838f4a2713aSLionel Sambuc       if (!versionsMatch(OldIntroduced, Introduced, Override) ||
1839f4a2713aSLionel Sambuc           !versionsMatch(Deprecated, OldDeprecated, Override) ||
1840f4a2713aSLionel Sambuc           !versionsMatch(Obsoleted, OldObsoleted, Override) ||
1841f4a2713aSLionel Sambuc           !(OldIsUnavailable == IsUnavailable ||
1842f4a2713aSLionel Sambuc             (Override && !OldIsUnavailable && IsUnavailable))) {
1843f4a2713aSLionel Sambuc         if (Override) {
1844f4a2713aSLionel Sambuc           int Which = -1;
1845f4a2713aSLionel Sambuc           VersionTuple FirstVersion;
1846f4a2713aSLionel Sambuc           VersionTuple SecondVersion;
1847f4a2713aSLionel Sambuc           if (!versionsMatch(OldIntroduced, Introduced, Override)) {
1848f4a2713aSLionel Sambuc             Which = 0;
1849f4a2713aSLionel Sambuc             FirstVersion = OldIntroduced;
1850f4a2713aSLionel Sambuc             SecondVersion = Introduced;
1851f4a2713aSLionel Sambuc           } else if (!versionsMatch(Deprecated, OldDeprecated, Override)) {
1852f4a2713aSLionel Sambuc             Which = 1;
1853f4a2713aSLionel Sambuc             FirstVersion = Deprecated;
1854f4a2713aSLionel Sambuc             SecondVersion = OldDeprecated;
1855f4a2713aSLionel Sambuc           } else if (!versionsMatch(Obsoleted, OldObsoleted, Override)) {
1856f4a2713aSLionel Sambuc             Which = 2;
1857f4a2713aSLionel Sambuc             FirstVersion = Obsoleted;
1858f4a2713aSLionel Sambuc             SecondVersion = OldObsoleted;
1859f4a2713aSLionel Sambuc           }
1860f4a2713aSLionel Sambuc 
1861f4a2713aSLionel Sambuc           if (Which == -1) {
1862f4a2713aSLionel Sambuc             Diag(OldAA->getLocation(),
1863f4a2713aSLionel Sambuc                  diag::warn_mismatched_availability_override_unavail)
1864f4a2713aSLionel Sambuc               << AvailabilityAttr::getPrettyPlatformName(Platform->getName());
1865f4a2713aSLionel Sambuc           } else {
1866f4a2713aSLionel Sambuc             Diag(OldAA->getLocation(),
1867f4a2713aSLionel Sambuc                  diag::warn_mismatched_availability_override)
1868f4a2713aSLionel Sambuc               << Which
1869f4a2713aSLionel Sambuc               << AvailabilityAttr::getPrettyPlatformName(Platform->getName())
1870f4a2713aSLionel Sambuc               << FirstVersion.getAsString() << SecondVersion.getAsString();
1871f4a2713aSLionel Sambuc           }
1872f4a2713aSLionel Sambuc           Diag(Range.getBegin(), diag::note_overridden_method);
1873f4a2713aSLionel Sambuc         } else {
1874f4a2713aSLionel Sambuc           Diag(OldAA->getLocation(), diag::warn_mismatched_availability);
1875f4a2713aSLionel Sambuc           Diag(Range.getBegin(), diag::note_previous_attribute);
1876f4a2713aSLionel Sambuc         }
1877f4a2713aSLionel Sambuc 
1878f4a2713aSLionel Sambuc         Attrs.erase(Attrs.begin() + i);
1879f4a2713aSLionel Sambuc         --e;
1880f4a2713aSLionel Sambuc         continue;
1881f4a2713aSLionel Sambuc       }
1882f4a2713aSLionel Sambuc 
1883f4a2713aSLionel Sambuc       VersionTuple MergedIntroduced2 = MergedIntroduced;
1884f4a2713aSLionel Sambuc       VersionTuple MergedDeprecated2 = MergedDeprecated;
1885f4a2713aSLionel Sambuc       VersionTuple MergedObsoleted2 = MergedObsoleted;
1886f4a2713aSLionel Sambuc 
1887f4a2713aSLionel Sambuc       if (MergedIntroduced2.empty())
1888f4a2713aSLionel Sambuc         MergedIntroduced2 = OldIntroduced;
1889f4a2713aSLionel Sambuc       if (MergedDeprecated2.empty())
1890f4a2713aSLionel Sambuc         MergedDeprecated2 = OldDeprecated;
1891f4a2713aSLionel Sambuc       if (MergedObsoleted2.empty())
1892f4a2713aSLionel Sambuc         MergedObsoleted2 = OldObsoleted;
1893f4a2713aSLionel Sambuc 
1894f4a2713aSLionel Sambuc       if (checkAvailabilityAttr(*this, OldAA->getRange(), Platform,
1895f4a2713aSLionel Sambuc                                 MergedIntroduced2, MergedDeprecated2,
1896f4a2713aSLionel Sambuc                                 MergedObsoleted2)) {
1897f4a2713aSLionel Sambuc         Attrs.erase(Attrs.begin() + i);
1898f4a2713aSLionel Sambuc         --e;
1899f4a2713aSLionel Sambuc         continue;
1900f4a2713aSLionel Sambuc       }
1901f4a2713aSLionel Sambuc 
1902f4a2713aSLionel Sambuc       MergedIntroduced = MergedIntroduced2;
1903f4a2713aSLionel Sambuc       MergedDeprecated = MergedDeprecated2;
1904f4a2713aSLionel Sambuc       MergedObsoleted = MergedObsoleted2;
1905f4a2713aSLionel Sambuc       ++i;
1906f4a2713aSLionel Sambuc     }
1907f4a2713aSLionel Sambuc   }
1908f4a2713aSLionel Sambuc 
1909f4a2713aSLionel Sambuc   if (FoundAny &&
1910f4a2713aSLionel Sambuc       MergedIntroduced == Introduced &&
1911f4a2713aSLionel Sambuc       MergedDeprecated == Deprecated &&
1912f4a2713aSLionel Sambuc       MergedObsoleted == Obsoleted)
1913*0a6a1f1dSLionel Sambuc     return nullptr;
1914f4a2713aSLionel Sambuc 
1915f4a2713aSLionel Sambuc   // Only create a new attribute if !Override, but we want to do
1916f4a2713aSLionel Sambuc   // the checking.
1917f4a2713aSLionel Sambuc   if (!checkAvailabilityAttr(*this, Range, Platform, MergedIntroduced,
1918f4a2713aSLionel Sambuc                              MergedDeprecated, MergedObsoleted) &&
1919f4a2713aSLionel Sambuc       !Override) {
1920f4a2713aSLionel Sambuc     return ::new (Context) AvailabilityAttr(Range, Context, Platform,
1921f4a2713aSLionel Sambuc                                             Introduced, Deprecated,
1922f4a2713aSLionel Sambuc                                             Obsoleted, IsUnavailable, Message,
1923f4a2713aSLionel Sambuc                                             AttrSpellingListIndex);
1924f4a2713aSLionel Sambuc   }
1925*0a6a1f1dSLionel Sambuc   return nullptr;
1926f4a2713aSLionel Sambuc }
1927f4a2713aSLionel Sambuc 
handleAvailabilityAttr(Sema & S,Decl * D,const AttributeList & Attr)1928f4a2713aSLionel Sambuc static void handleAvailabilityAttr(Sema &S, Decl *D,
1929f4a2713aSLionel Sambuc                                    const AttributeList &Attr) {
1930f4a2713aSLionel Sambuc   if (!checkAttributeNumArgs(S, Attr, 1))
1931f4a2713aSLionel Sambuc     return;
1932f4a2713aSLionel Sambuc   IdentifierLoc *Platform = Attr.getArgAsIdent(0);
1933f4a2713aSLionel Sambuc   unsigned Index = Attr.getAttributeSpellingListIndex();
1934f4a2713aSLionel Sambuc 
1935f4a2713aSLionel Sambuc   IdentifierInfo *II = Platform->Ident;
1936f4a2713aSLionel Sambuc   if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty())
1937f4a2713aSLionel Sambuc     S.Diag(Platform->Loc, diag::warn_availability_unknown_platform)
1938f4a2713aSLionel Sambuc       << Platform->Ident;
1939f4a2713aSLionel Sambuc 
1940f4a2713aSLionel Sambuc   NamedDecl *ND = dyn_cast<NamedDecl>(D);
1941f4a2713aSLionel Sambuc   if (!ND) {
1942f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
1943f4a2713aSLionel Sambuc     return;
1944f4a2713aSLionel Sambuc   }
1945f4a2713aSLionel Sambuc 
1946f4a2713aSLionel Sambuc   AvailabilityChange Introduced = Attr.getAvailabilityIntroduced();
1947f4a2713aSLionel Sambuc   AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated();
1948f4a2713aSLionel Sambuc   AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted();
1949f4a2713aSLionel Sambuc   bool IsUnavailable = Attr.getUnavailableLoc().isValid();
1950f4a2713aSLionel Sambuc   StringRef Str;
1951f4a2713aSLionel Sambuc   if (const StringLiteral *SE =
1952f4a2713aSLionel Sambuc           dyn_cast_or_null<StringLiteral>(Attr.getMessageExpr()))
1953f4a2713aSLionel Sambuc     Str = SE->getString();
1954f4a2713aSLionel Sambuc 
1955f4a2713aSLionel Sambuc   AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), II,
1956f4a2713aSLionel Sambuc                                                       Introduced.Version,
1957f4a2713aSLionel Sambuc                                                       Deprecated.Version,
1958f4a2713aSLionel Sambuc                                                       Obsoleted.Version,
1959f4a2713aSLionel Sambuc                                                       IsUnavailable, Str,
1960f4a2713aSLionel Sambuc                                                       /*Override=*/false,
1961f4a2713aSLionel Sambuc                                                       Index);
1962f4a2713aSLionel Sambuc   if (NewAttr)
1963f4a2713aSLionel Sambuc     D->addAttr(NewAttr);
1964f4a2713aSLionel Sambuc }
1965f4a2713aSLionel Sambuc 
1966f4a2713aSLionel Sambuc template <class T>
mergeVisibilityAttr(Sema & S,Decl * D,SourceRange range,typename T::VisibilityType value,unsigned attrSpellingListIndex)1967f4a2713aSLionel Sambuc static T *mergeVisibilityAttr(Sema &S, Decl *D, SourceRange range,
1968f4a2713aSLionel Sambuc                               typename T::VisibilityType value,
1969f4a2713aSLionel Sambuc                               unsigned attrSpellingListIndex) {
1970f4a2713aSLionel Sambuc   T *existingAttr = D->getAttr<T>();
1971f4a2713aSLionel Sambuc   if (existingAttr) {
1972f4a2713aSLionel Sambuc     typename T::VisibilityType existingValue = existingAttr->getVisibility();
1973f4a2713aSLionel Sambuc     if (existingValue == value)
1974*0a6a1f1dSLionel Sambuc       return nullptr;
1975f4a2713aSLionel Sambuc     S.Diag(existingAttr->getLocation(), diag::err_mismatched_visibility);
1976f4a2713aSLionel Sambuc     S.Diag(range.getBegin(), diag::note_previous_attribute);
1977f4a2713aSLionel Sambuc     D->dropAttr<T>();
1978f4a2713aSLionel Sambuc   }
1979f4a2713aSLionel Sambuc   return ::new (S.Context) T(range, S.Context, value, attrSpellingListIndex);
1980f4a2713aSLionel Sambuc }
1981f4a2713aSLionel Sambuc 
mergeVisibilityAttr(Decl * D,SourceRange Range,VisibilityAttr::VisibilityType Vis,unsigned AttrSpellingListIndex)1982f4a2713aSLionel Sambuc VisibilityAttr *Sema::mergeVisibilityAttr(Decl *D, SourceRange Range,
1983f4a2713aSLionel Sambuc                                           VisibilityAttr::VisibilityType Vis,
1984f4a2713aSLionel Sambuc                                           unsigned AttrSpellingListIndex) {
1985f4a2713aSLionel Sambuc   return ::mergeVisibilityAttr<VisibilityAttr>(*this, D, Range, Vis,
1986f4a2713aSLionel Sambuc                                                AttrSpellingListIndex);
1987f4a2713aSLionel Sambuc }
1988f4a2713aSLionel Sambuc 
mergeTypeVisibilityAttr(Decl * D,SourceRange Range,TypeVisibilityAttr::VisibilityType Vis,unsigned AttrSpellingListIndex)1989f4a2713aSLionel Sambuc TypeVisibilityAttr *Sema::mergeTypeVisibilityAttr(Decl *D, SourceRange Range,
1990f4a2713aSLionel Sambuc                                       TypeVisibilityAttr::VisibilityType Vis,
1991f4a2713aSLionel Sambuc                                       unsigned AttrSpellingListIndex) {
1992f4a2713aSLionel Sambuc   return ::mergeVisibilityAttr<TypeVisibilityAttr>(*this, D, Range, Vis,
1993f4a2713aSLionel Sambuc                                                    AttrSpellingListIndex);
1994f4a2713aSLionel Sambuc }
1995f4a2713aSLionel Sambuc 
handleVisibilityAttr(Sema & S,Decl * D,const AttributeList & Attr,bool isTypeVisibility)1996f4a2713aSLionel Sambuc static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr,
1997f4a2713aSLionel Sambuc                                  bool isTypeVisibility) {
1998f4a2713aSLionel Sambuc   // Visibility attributes don't mean anything on a typedef.
1999f4a2713aSLionel Sambuc   if (isa<TypedefNameDecl>(D)) {
2000f4a2713aSLionel Sambuc     S.Diag(Attr.getRange().getBegin(), diag::warn_attribute_ignored)
2001f4a2713aSLionel Sambuc       << Attr.getName();
2002f4a2713aSLionel Sambuc     return;
2003f4a2713aSLionel Sambuc   }
2004f4a2713aSLionel Sambuc 
2005f4a2713aSLionel Sambuc   // 'type_visibility' can only go on a type or namespace.
2006f4a2713aSLionel Sambuc   if (isTypeVisibility &&
2007f4a2713aSLionel Sambuc       !(isa<TagDecl>(D) ||
2008f4a2713aSLionel Sambuc         isa<ObjCInterfaceDecl>(D) ||
2009f4a2713aSLionel Sambuc         isa<NamespaceDecl>(D))) {
2010f4a2713aSLionel Sambuc     S.Diag(Attr.getRange().getBegin(), diag::err_attribute_wrong_decl_type)
2011f4a2713aSLionel Sambuc       << Attr.getName() << ExpectedTypeOrNamespace;
2012f4a2713aSLionel Sambuc     return;
2013f4a2713aSLionel Sambuc   }
2014f4a2713aSLionel Sambuc 
2015f4a2713aSLionel Sambuc   // Check that the argument is a string literal.
2016f4a2713aSLionel Sambuc   StringRef TypeStr;
2017f4a2713aSLionel Sambuc   SourceLocation LiteralLoc;
2018f4a2713aSLionel Sambuc   if (!S.checkStringLiteralArgumentAttr(Attr, 0, TypeStr, &LiteralLoc))
2019f4a2713aSLionel Sambuc     return;
2020f4a2713aSLionel Sambuc 
2021f4a2713aSLionel Sambuc   VisibilityAttr::VisibilityType type;
2022f4a2713aSLionel Sambuc   if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) {
2023f4a2713aSLionel Sambuc     S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported)
2024f4a2713aSLionel Sambuc       << Attr.getName() << TypeStr;
2025f4a2713aSLionel Sambuc     return;
2026f4a2713aSLionel Sambuc   }
2027f4a2713aSLionel Sambuc 
2028f4a2713aSLionel Sambuc   // Complain about attempts to use protected visibility on targets
2029f4a2713aSLionel Sambuc   // (like Darwin) that don't support it.
2030f4a2713aSLionel Sambuc   if (type == VisibilityAttr::Protected &&
2031f4a2713aSLionel Sambuc       !S.Context.getTargetInfo().hasProtectedVisibility()) {
2032f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility);
2033f4a2713aSLionel Sambuc     type = VisibilityAttr::Default;
2034f4a2713aSLionel Sambuc   }
2035f4a2713aSLionel Sambuc 
2036f4a2713aSLionel Sambuc   unsigned Index = Attr.getAttributeSpellingListIndex();
2037f4a2713aSLionel Sambuc   clang::Attr *newAttr;
2038f4a2713aSLionel Sambuc   if (isTypeVisibility) {
2039f4a2713aSLionel Sambuc     newAttr = S.mergeTypeVisibilityAttr(D, Attr.getRange(),
2040f4a2713aSLionel Sambuc                                     (TypeVisibilityAttr::VisibilityType) type,
2041f4a2713aSLionel Sambuc                                         Index);
2042f4a2713aSLionel Sambuc   } else {
2043f4a2713aSLionel Sambuc     newAttr = S.mergeVisibilityAttr(D, Attr.getRange(), type, Index);
2044f4a2713aSLionel Sambuc   }
2045f4a2713aSLionel Sambuc   if (newAttr)
2046f4a2713aSLionel Sambuc     D->addAttr(newAttr);
2047f4a2713aSLionel Sambuc }
2048f4a2713aSLionel Sambuc 
handleObjCMethodFamilyAttr(Sema & S,Decl * decl,const AttributeList & Attr)2049f4a2713aSLionel Sambuc static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,
2050f4a2713aSLionel Sambuc                                        const AttributeList &Attr) {
2051*0a6a1f1dSLionel Sambuc   ObjCMethodDecl *method = cast<ObjCMethodDecl>(decl);
2052f4a2713aSLionel Sambuc   if (!Attr.isArgIdent(0)) {
2053f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
2054f4a2713aSLionel Sambuc       << Attr.getName() << 1 << AANT_ArgumentIdentifier;
2055f4a2713aSLionel Sambuc     return;
2056f4a2713aSLionel Sambuc   }
2057f4a2713aSLionel Sambuc 
2058f4a2713aSLionel Sambuc   IdentifierLoc *IL = Attr.getArgAsIdent(0);
2059f4a2713aSLionel Sambuc   ObjCMethodFamilyAttr::FamilyKind F;
2060f4a2713aSLionel Sambuc   if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) {
2061f4a2713aSLionel Sambuc     S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << Attr.getName()
2062f4a2713aSLionel Sambuc       << IL->Ident;
2063f4a2713aSLionel Sambuc     return;
2064f4a2713aSLionel Sambuc   }
2065f4a2713aSLionel Sambuc 
2066f4a2713aSLionel Sambuc   if (F == ObjCMethodFamilyAttr::OMF_init &&
2067*0a6a1f1dSLionel Sambuc       !method->getReturnType()->isObjCObjectPointerType()) {
2068f4a2713aSLionel Sambuc     S.Diag(method->getLocation(), diag::err_init_method_bad_return_type)
2069*0a6a1f1dSLionel Sambuc         << method->getReturnType();
2070f4a2713aSLionel Sambuc     // Ignore the attribute.
2071f4a2713aSLionel Sambuc     return;
2072f4a2713aSLionel Sambuc   }
2073f4a2713aSLionel Sambuc 
2074f4a2713aSLionel Sambuc   method->addAttr(new (S.Context) ObjCMethodFamilyAttr(Attr.getRange(),
2075*0a6a1f1dSLionel Sambuc                                                        S.Context, F,
2076f4a2713aSLionel Sambuc                                         Attr.getAttributeSpellingListIndex()));
2077f4a2713aSLionel Sambuc }
2078f4a2713aSLionel Sambuc 
handleObjCNSObject(Sema & S,Decl * D,const AttributeList & Attr)2079f4a2713aSLionel Sambuc static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
2080f4a2713aSLionel Sambuc   if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
2081f4a2713aSLionel Sambuc     QualType T = TD->getUnderlyingType();
2082f4a2713aSLionel Sambuc     if (!T->isCARCBridgableType()) {
2083f4a2713aSLionel Sambuc       S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
2084f4a2713aSLionel Sambuc       return;
2085f4a2713aSLionel Sambuc     }
2086f4a2713aSLionel Sambuc   }
2087f4a2713aSLionel Sambuc   else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) {
2088f4a2713aSLionel Sambuc     QualType T = PD->getType();
2089f4a2713aSLionel Sambuc     if (!T->isCARCBridgableType()) {
2090f4a2713aSLionel Sambuc       S.Diag(PD->getLocation(), diag::err_nsobject_attribute);
2091f4a2713aSLionel Sambuc       return;
2092f4a2713aSLionel Sambuc     }
2093f4a2713aSLionel Sambuc   }
2094f4a2713aSLionel Sambuc   else {
2095f4a2713aSLionel Sambuc     // It is okay to include this attribute on properties, e.g.:
2096f4a2713aSLionel Sambuc     //
2097f4a2713aSLionel Sambuc     //  @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject));
2098f4a2713aSLionel Sambuc     //
2099f4a2713aSLionel Sambuc     // In this case it follows tradition and suppresses an error in the above
2100f4a2713aSLionel Sambuc     // case.
2101f4a2713aSLionel Sambuc     S.Diag(D->getLocation(), diag::warn_nsobject_attribute);
2102f4a2713aSLionel Sambuc   }
2103f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
2104f4a2713aSLionel Sambuc              ObjCNSObjectAttr(Attr.getRange(), S.Context,
2105f4a2713aSLionel Sambuc                               Attr.getAttributeSpellingListIndex()));
2106f4a2713aSLionel Sambuc }
2107f4a2713aSLionel Sambuc 
handleBlocksAttr(Sema & S,Decl * D,const AttributeList & Attr)2108f4a2713aSLionel Sambuc static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) {
2109f4a2713aSLionel Sambuc   if (!Attr.isArgIdent(0)) {
2110f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
2111f4a2713aSLionel Sambuc       << Attr.getName() << 1 << AANT_ArgumentIdentifier;
2112f4a2713aSLionel Sambuc     return;
2113f4a2713aSLionel Sambuc   }
2114f4a2713aSLionel Sambuc 
2115f4a2713aSLionel Sambuc   IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
2116f4a2713aSLionel Sambuc   BlocksAttr::BlockType type;
2117f4a2713aSLionel Sambuc   if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) {
2118f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
2119f4a2713aSLionel Sambuc       << Attr.getName() << II;
2120f4a2713aSLionel Sambuc     return;
2121f4a2713aSLionel Sambuc   }
2122f4a2713aSLionel Sambuc 
2123f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
2124f4a2713aSLionel Sambuc              BlocksAttr(Attr.getRange(), S.Context, type,
2125f4a2713aSLionel Sambuc                         Attr.getAttributeSpellingListIndex()));
2126f4a2713aSLionel Sambuc }
2127f4a2713aSLionel Sambuc 
handleSentinelAttr(Sema & S,Decl * D,const AttributeList & Attr)2128f4a2713aSLionel Sambuc static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {
2129*0a6a1f1dSLionel Sambuc   unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel;
2130f4a2713aSLionel Sambuc   if (Attr.getNumArgs() > 0) {
2131f4a2713aSLionel Sambuc     Expr *E = Attr.getArgAsExpr(0);
2132f4a2713aSLionel Sambuc     llvm::APSInt Idx(32);
2133f4a2713aSLionel Sambuc     if (E->isTypeDependent() || E->isValueDependent() ||
2134f4a2713aSLionel Sambuc         !E->isIntegerConstantExpr(Idx, S.Context)) {
2135f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
2136f4a2713aSLionel Sambuc         << Attr.getName() << 1 << AANT_ArgumentIntegerConstant
2137f4a2713aSLionel Sambuc         << E->getSourceRange();
2138f4a2713aSLionel Sambuc       return;
2139f4a2713aSLionel Sambuc     }
2140f4a2713aSLionel Sambuc 
2141f4a2713aSLionel Sambuc     if (Idx.isSigned() && Idx.isNegative()) {
2142f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero)
2143f4a2713aSLionel Sambuc         << E->getSourceRange();
2144f4a2713aSLionel Sambuc       return;
2145f4a2713aSLionel Sambuc     }
2146f4a2713aSLionel Sambuc 
2147f4a2713aSLionel Sambuc     sentinel = Idx.getZExtValue();
2148f4a2713aSLionel Sambuc   }
2149f4a2713aSLionel Sambuc 
2150*0a6a1f1dSLionel Sambuc   unsigned nullPos = (unsigned)SentinelAttr::DefaultNullPos;
2151f4a2713aSLionel Sambuc   if (Attr.getNumArgs() > 1) {
2152f4a2713aSLionel Sambuc     Expr *E = Attr.getArgAsExpr(1);
2153f4a2713aSLionel Sambuc     llvm::APSInt Idx(32);
2154f4a2713aSLionel Sambuc     if (E->isTypeDependent() || E->isValueDependent() ||
2155f4a2713aSLionel Sambuc         !E->isIntegerConstantExpr(Idx, S.Context)) {
2156f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
2157f4a2713aSLionel Sambuc         << Attr.getName() << 2 << AANT_ArgumentIntegerConstant
2158f4a2713aSLionel Sambuc         << E->getSourceRange();
2159f4a2713aSLionel Sambuc       return;
2160f4a2713aSLionel Sambuc     }
2161f4a2713aSLionel Sambuc     nullPos = Idx.getZExtValue();
2162f4a2713aSLionel Sambuc 
2163f4a2713aSLionel Sambuc     if ((Idx.isSigned() && Idx.isNegative()) || nullPos > 1) {
2164f4a2713aSLionel Sambuc       // FIXME: This error message could be improved, it would be nice
2165f4a2713aSLionel Sambuc       // to say what the bounds actually are.
2166f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
2167f4a2713aSLionel Sambuc         << E->getSourceRange();
2168f4a2713aSLionel Sambuc       return;
2169f4a2713aSLionel Sambuc     }
2170f4a2713aSLionel Sambuc   }
2171f4a2713aSLionel Sambuc 
2172f4a2713aSLionel Sambuc   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
2173f4a2713aSLionel Sambuc     const FunctionType *FT = FD->getType()->castAs<FunctionType>();
2174f4a2713aSLionel Sambuc     if (isa<FunctionNoProtoType>(FT)) {
2175f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_named_arguments);
2176f4a2713aSLionel Sambuc       return;
2177f4a2713aSLionel Sambuc     }
2178f4a2713aSLionel Sambuc 
2179f4a2713aSLionel Sambuc     if (!cast<FunctionProtoType>(FT)->isVariadic()) {
2180f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
2181f4a2713aSLionel Sambuc       return;
2182f4a2713aSLionel Sambuc     }
2183f4a2713aSLionel Sambuc   } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
2184f4a2713aSLionel Sambuc     if (!MD->isVariadic()) {
2185f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
2186f4a2713aSLionel Sambuc       return;
2187f4a2713aSLionel Sambuc     }
2188f4a2713aSLionel Sambuc   } else if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
2189f4a2713aSLionel Sambuc     if (!BD->isVariadic()) {
2190f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1;
2191f4a2713aSLionel Sambuc       return;
2192f4a2713aSLionel Sambuc     }
2193f4a2713aSLionel Sambuc   } else if (const VarDecl *V = dyn_cast<VarDecl>(D)) {
2194f4a2713aSLionel Sambuc     QualType Ty = V->getType();
2195f4a2713aSLionel Sambuc     if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
2196*0a6a1f1dSLionel Sambuc       const FunctionType *FT = Ty->isFunctionPointerType()
2197*0a6a1f1dSLionel Sambuc        ? D->getFunctionType()
2198f4a2713aSLionel Sambuc        : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
2199f4a2713aSLionel Sambuc       if (!cast<FunctionProtoType>(FT)->isVariadic()) {
2200f4a2713aSLionel Sambuc         int m = Ty->isFunctionPointerType() ? 0 : 1;
2201f4a2713aSLionel Sambuc         S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
2202f4a2713aSLionel Sambuc         return;
2203f4a2713aSLionel Sambuc       }
2204f4a2713aSLionel Sambuc     } else {
2205f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
2206f4a2713aSLionel Sambuc         << Attr.getName() << ExpectedFunctionMethodOrBlock;
2207f4a2713aSLionel Sambuc       return;
2208f4a2713aSLionel Sambuc     }
2209f4a2713aSLionel Sambuc   } else {
2210f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
2211f4a2713aSLionel Sambuc       << Attr.getName() << ExpectedFunctionMethodOrBlock;
2212f4a2713aSLionel Sambuc     return;
2213f4a2713aSLionel Sambuc   }
2214f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
2215f4a2713aSLionel Sambuc              SentinelAttr(Attr.getRange(), S.Context, sentinel, nullPos,
2216f4a2713aSLionel Sambuc                           Attr.getAttributeSpellingListIndex()));
2217f4a2713aSLionel Sambuc }
2218f4a2713aSLionel Sambuc 
handleWarnUnusedResult(Sema & S,Decl * D,const AttributeList & Attr)2219f4a2713aSLionel Sambuc static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) {
2220*0a6a1f1dSLionel Sambuc   if (D->getFunctionType() &&
2221*0a6a1f1dSLionel Sambuc       D->getFunctionType()->getReturnType()->isVoidType()) {
2222f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
2223f4a2713aSLionel Sambuc       << Attr.getName() << 0;
2224f4a2713aSLionel Sambuc     return;
2225f4a2713aSLionel Sambuc   }
2226f4a2713aSLionel Sambuc   if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
2227*0a6a1f1dSLionel Sambuc     if (MD->getReturnType()->isVoidType()) {
2228f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
2229f4a2713aSLionel Sambuc       << Attr.getName() << 1;
2230f4a2713aSLionel Sambuc       return;
2231f4a2713aSLionel Sambuc     }
2232f4a2713aSLionel Sambuc 
2233f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
2234f4a2713aSLionel Sambuc              WarnUnusedResultAttr(Attr.getRange(), S.Context,
2235f4a2713aSLionel Sambuc                                   Attr.getAttributeSpellingListIndex()));
2236f4a2713aSLionel Sambuc }
2237f4a2713aSLionel Sambuc 
handleWeakImportAttr(Sema & S,Decl * D,const AttributeList & Attr)2238f4a2713aSLionel Sambuc static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
2239f4a2713aSLionel Sambuc   // weak_import only applies to variable & function declarations.
2240f4a2713aSLionel Sambuc   bool isDef = false;
2241f4a2713aSLionel Sambuc   if (!D->canBeWeakImported(isDef)) {
2242f4a2713aSLionel Sambuc     if (isDef)
2243f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_attribute_invalid_on_definition)
2244f4a2713aSLionel Sambuc         << "weak_import";
2245f4a2713aSLionel Sambuc     else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) ||
2246f4a2713aSLionel Sambuc              (S.Context.getTargetInfo().getTriple().isOSDarwin() &&
2247f4a2713aSLionel Sambuc               (isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) {
2248f4a2713aSLionel Sambuc       // Nothing to warn about here.
2249f4a2713aSLionel Sambuc     } else
2250f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
2251f4a2713aSLionel Sambuc         << Attr.getName() << ExpectedVariableOrFunction;
2252f4a2713aSLionel Sambuc 
2253f4a2713aSLionel Sambuc     return;
2254f4a2713aSLionel Sambuc   }
2255f4a2713aSLionel Sambuc 
2256f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
2257f4a2713aSLionel Sambuc              WeakImportAttr(Attr.getRange(), S.Context,
2258f4a2713aSLionel Sambuc                             Attr.getAttributeSpellingListIndex()));
2259f4a2713aSLionel Sambuc }
2260f4a2713aSLionel Sambuc 
2261f4a2713aSLionel Sambuc // Handles reqd_work_group_size and work_group_size_hint.
2262*0a6a1f1dSLionel Sambuc template <typename WorkGroupAttr>
handleWorkGroupSize(Sema & S,Decl * D,const AttributeList & Attr)2263f4a2713aSLionel Sambuc static void handleWorkGroupSize(Sema &S, Decl *D,
2264f4a2713aSLionel Sambuc                                 const AttributeList &Attr) {
2265*0a6a1f1dSLionel Sambuc   uint32_t WGSize[3];
2266f4a2713aSLionel Sambuc   for (unsigned i = 0; i < 3; ++i) {
2267*0a6a1f1dSLionel Sambuc     const Expr *E = Attr.getArgAsExpr(i);
2268*0a6a1f1dSLionel Sambuc     if (!checkUInt32Argument(S, Attr, E, WGSize[i], i))
2269*0a6a1f1dSLionel Sambuc       return;
2270*0a6a1f1dSLionel Sambuc     if (WGSize[i] == 0) {
2271*0a6a1f1dSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero)
2272*0a6a1f1dSLionel Sambuc         << Attr.getName() << E->getSourceRange();
2273f4a2713aSLionel Sambuc       return;
2274f4a2713aSLionel Sambuc     }
2275f4a2713aSLionel Sambuc   }
2276f4a2713aSLionel Sambuc 
2277*0a6a1f1dSLionel Sambuc   WorkGroupAttr *Existing = D->getAttr<WorkGroupAttr>();
2278*0a6a1f1dSLionel Sambuc   if (Existing && !(Existing->getXDim() == WGSize[0] &&
2279*0a6a1f1dSLionel Sambuc                     Existing->getYDim() == WGSize[1] &&
2280*0a6a1f1dSLionel Sambuc                     Existing->getZDim() == WGSize[2]))
2281*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName();
2282f4a2713aSLionel Sambuc 
2283*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context) WorkGroupAttr(Attr.getRange(), S.Context,
2284f4a2713aSLionel Sambuc                                              WGSize[0], WGSize[1], WGSize[2],
2285f4a2713aSLionel Sambuc                                        Attr.getAttributeSpellingListIndex()));
2286f4a2713aSLionel Sambuc }
2287f4a2713aSLionel Sambuc 
handleVecTypeHint(Sema & S,Decl * D,const AttributeList & Attr)2288f4a2713aSLionel Sambuc static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) {
2289f4a2713aSLionel Sambuc   if (!Attr.hasParsedType()) {
2290f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
2291f4a2713aSLionel Sambuc       << Attr.getName() << 1;
2292f4a2713aSLionel Sambuc     return;
2293f4a2713aSLionel Sambuc   }
2294f4a2713aSLionel Sambuc 
2295*0a6a1f1dSLionel Sambuc   TypeSourceInfo *ParmTSI = nullptr;
2296f4a2713aSLionel Sambuc   QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg(), &ParmTSI);
2297f4a2713aSLionel Sambuc   assert(ParmTSI && "no type source info for attribute argument");
2298f4a2713aSLionel Sambuc 
2299f4a2713aSLionel Sambuc   if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() &&
2300f4a2713aSLionel Sambuc       (ParmType->isBooleanType() ||
2301f4a2713aSLionel Sambuc        !ParmType->isIntegralType(S.getASTContext()))) {
2302f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_vec_type_hint)
2303f4a2713aSLionel Sambuc         << ParmType;
2304f4a2713aSLionel Sambuc     return;
2305f4a2713aSLionel Sambuc   }
2306f4a2713aSLionel Sambuc 
2307*0a6a1f1dSLionel Sambuc   if (VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>()) {
2308f4a2713aSLionel Sambuc     if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) {
2309f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName();
2310f4a2713aSLionel Sambuc       return;
2311f4a2713aSLionel Sambuc     }
2312f4a2713aSLionel Sambuc   }
2313f4a2713aSLionel Sambuc 
2314f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context,
2315*0a6a1f1dSLionel Sambuc                                                ParmTSI,
2316*0a6a1f1dSLionel Sambuc                                         Attr.getAttributeSpellingListIndex()));
2317f4a2713aSLionel Sambuc }
2318f4a2713aSLionel Sambuc 
mergeSectionAttr(Decl * D,SourceRange Range,StringRef Name,unsigned AttrSpellingListIndex)2319f4a2713aSLionel Sambuc SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,
2320f4a2713aSLionel Sambuc                                     StringRef Name,
2321f4a2713aSLionel Sambuc                                     unsigned AttrSpellingListIndex) {
2322f4a2713aSLionel Sambuc   if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) {
2323f4a2713aSLionel Sambuc     if (ExistingAttr->getName() == Name)
2324*0a6a1f1dSLionel Sambuc       return nullptr;
2325f4a2713aSLionel Sambuc     Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section);
2326f4a2713aSLionel Sambuc     Diag(Range.getBegin(), diag::note_previous_attribute);
2327*0a6a1f1dSLionel Sambuc     return nullptr;
2328f4a2713aSLionel Sambuc   }
2329f4a2713aSLionel Sambuc   return ::new (Context) SectionAttr(Range, Context, Name,
2330f4a2713aSLionel Sambuc                                      AttrSpellingListIndex);
2331f4a2713aSLionel Sambuc }
2332f4a2713aSLionel Sambuc 
handleSectionAttr(Sema & S,Decl * D,const AttributeList & Attr)2333f4a2713aSLionel Sambuc static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) {
2334f4a2713aSLionel Sambuc   // Make sure that there is a string literal as the sections's single
2335f4a2713aSLionel Sambuc   // argument.
2336f4a2713aSLionel Sambuc   StringRef Str;
2337f4a2713aSLionel Sambuc   SourceLocation LiteralLoc;
2338f4a2713aSLionel Sambuc   if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc))
2339f4a2713aSLionel Sambuc     return;
2340f4a2713aSLionel Sambuc 
2341f4a2713aSLionel Sambuc   // If the target wants to validate the section specifier, make it happen.
2342f4a2713aSLionel Sambuc   std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(Str);
2343f4a2713aSLionel Sambuc   if (!Error.empty()) {
2344f4a2713aSLionel Sambuc     S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
2345f4a2713aSLionel Sambuc     << Error;
2346f4a2713aSLionel Sambuc     return;
2347f4a2713aSLionel Sambuc   }
2348f4a2713aSLionel Sambuc 
2349f4a2713aSLionel Sambuc   unsigned Index = Attr.getAttributeSpellingListIndex();
2350f4a2713aSLionel Sambuc   SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), Str, Index);
2351f4a2713aSLionel Sambuc   if (NewAttr)
2352f4a2713aSLionel Sambuc     D->addAttr(NewAttr);
2353f4a2713aSLionel Sambuc }
2354f4a2713aSLionel Sambuc 
2355f4a2713aSLionel Sambuc 
handleCleanupAttr(Sema & S,Decl * D,const AttributeList & Attr)2356f4a2713aSLionel Sambuc static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
2357*0a6a1f1dSLionel Sambuc   VarDecl *VD = cast<VarDecl>(D);
2358*0a6a1f1dSLionel Sambuc   if (!VD->hasLocalStorage()) {
2359f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
2360f4a2713aSLionel Sambuc     return;
2361f4a2713aSLionel Sambuc   }
2362f4a2713aSLionel Sambuc 
2363f4a2713aSLionel Sambuc   Expr *E = Attr.getArgAsExpr(0);
2364f4a2713aSLionel Sambuc   SourceLocation Loc = E->getExprLoc();
2365*0a6a1f1dSLionel Sambuc   FunctionDecl *FD = nullptr;
2366f4a2713aSLionel Sambuc   DeclarationNameInfo NI;
2367f4a2713aSLionel Sambuc 
2368f4a2713aSLionel Sambuc   // gcc only allows for simple identifiers. Since we support more than gcc, we
2369f4a2713aSLionel Sambuc   // will warn the user.
2370f4a2713aSLionel Sambuc   if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
2371f4a2713aSLionel Sambuc     if (DRE->hasQualifier())
2372f4a2713aSLionel Sambuc       S.Diag(Loc, diag::warn_cleanup_ext);
2373f4a2713aSLionel Sambuc     FD = dyn_cast<FunctionDecl>(DRE->getDecl());
2374f4a2713aSLionel Sambuc     NI = DRE->getNameInfo();
2375f4a2713aSLionel Sambuc     if (!FD) {
2376f4a2713aSLionel Sambuc       S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 1
2377f4a2713aSLionel Sambuc         << NI.getName();
2378f4a2713aSLionel Sambuc       return;
2379f4a2713aSLionel Sambuc     }
2380f4a2713aSLionel Sambuc   } else if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
2381f4a2713aSLionel Sambuc     if (ULE->hasExplicitTemplateArgs())
2382f4a2713aSLionel Sambuc       S.Diag(Loc, diag::warn_cleanup_ext);
2383f4a2713aSLionel Sambuc     FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true);
2384f4a2713aSLionel Sambuc     NI = ULE->getNameInfo();
2385f4a2713aSLionel Sambuc     if (!FD) {
2386f4a2713aSLionel Sambuc       S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2
2387f4a2713aSLionel Sambuc         << NI.getName();
2388f4a2713aSLionel Sambuc       if (ULE->getType() == S.Context.OverloadTy)
2389f4a2713aSLionel Sambuc         S.NoteAllOverloadCandidates(ULE);
2390f4a2713aSLionel Sambuc       return;
2391f4a2713aSLionel Sambuc     }
2392f4a2713aSLionel Sambuc   } else {
2393f4a2713aSLionel Sambuc     S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 0;
2394f4a2713aSLionel Sambuc     return;
2395f4a2713aSLionel Sambuc   }
2396f4a2713aSLionel Sambuc 
2397f4a2713aSLionel Sambuc   if (FD->getNumParams() != 1) {
2398f4a2713aSLionel Sambuc     S.Diag(Loc, diag::err_attribute_cleanup_func_must_take_one_arg)
2399f4a2713aSLionel Sambuc       << NI.getName();
2400f4a2713aSLionel Sambuc     return;
2401f4a2713aSLionel Sambuc   }
2402f4a2713aSLionel Sambuc 
2403f4a2713aSLionel Sambuc   // We're currently more strict than GCC about what function types we accept.
2404f4a2713aSLionel Sambuc   // If this ever proves to be a problem it should be easy to fix.
2405f4a2713aSLionel Sambuc   QualType Ty = S.Context.getPointerType(VD->getType());
2406f4a2713aSLionel Sambuc   QualType ParamTy = FD->getParamDecl(0)->getType();
2407f4a2713aSLionel Sambuc   if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(),
2408f4a2713aSLionel Sambuc                                    ParamTy, Ty) != Sema::Compatible) {
2409f4a2713aSLionel Sambuc     S.Diag(Loc, diag::err_attribute_cleanup_func_arg_incompatible_type)
2410f4a2713aSLionel Sambuc       << NI.getName() << ParamTy << Ty;
2411f4a2713aSLionel Sambuc     return;
2412f4a2713aSLionel Sambuc   }
2413f4a2713aSLionel Sambuc 
2414f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
2415f4a2713aSLionel Sambuc              CleanupAttr(Attr.getRange(), S.Context, FD,
2416f4a2713aSLionel Sambuc                          Attr.getAttributeSpellingListIndex()));
2417f4a2713aSLionel Sambuc }
2418f4a2713aSLionel Sambuc 
2419f4a2713aSLionel Sambuc /// Handle __attribute__((format_arg((idx)))) attribute based on
2420f4a2713aSLionel Sambuc /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
handleFormatArgAttr(Sema & S,Decl * D,const AttributeList & Attr)2421f4a2713aSLionel Sambuc static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
2422f4a2713aSLionel Sambuc   Expr *IdxExpr = Attr.getArgAsExpr(0);
2423*0a6a1f1dSLionel Sambuc   uint64_t Idx;
2424*0a6a1f1dSLionel Sambuc   if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 1, IdxExpr, Idx))
2425f4a2713aSLionel Sambuc     return;
2426f4a2713aSLionel Sambuc 
2427f4a2713aSLionel Sambuc   // make sure the format string is really a string
2428*0a6a1f1dSLionel Sambuc   QualType Ty = getFunctionOrMethodParamType(D, Idx);
2429f4a2713aSLionel Sambuc 
2430f4a2713aSLionel Sambuc   bool not_nsstring_type = !isNSStringType(Ty, S.Context);
2431f4a2713aSLionel Sambuc   if (not_nsstring_type &&
2432f4a2713aSLionel Sambuc       !isCFStringType(Ty, S.Context) &&
2433f4a2713aSLionel Sambuc       (!Ty->isPointerType() ||
2434f4a2713aSLionel Sambuc        !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
2435f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
2436f4a2713aSLionel Sambuc         << (not_nsstring_type ? "a string type" : "an NSString")
2437*0a6a1f1dSLionel Sambuc         << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0);
2438f4a2713aSLionel Sambuc     return;
2439f4a2713aSLionel Sambuc   }
2440f4a2713aSLionel Sambuc   Ty = getFunctionOrMethodResultType(D);
2441f4a2713aSLionel Sambuc   if (!isNSStringType(Ty, S.Context) &&
2442f4a2713aSLionel Sambuc       !isCFStringType(Ty, S.Context) &&
2443f4a2713aSLionel Sambuc       (!Ty->isPointerType() ||
2444f4a2713aSLionel Sambuc        !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
2445f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not)
2446f4a2713aSLionel Sambuc         << (not_nsstring_type ? "string type" : "NSString")
2447*0a6a1f1dSLionel Sambuc         << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0);
2448f4a2713aSLionel Sambuc     return;
2449f4a2713aSLionel Sambuc   }
2450f4a2713aSLionel Sambuc 
2451*0a6a1f1dSLionel Sambuc   // We cannot use the Idx returned from checkFunctionOrMethodParameterIndex
2452f4a2713aSLionel Sambuc   // because that has corrected for the implicit this parameter, and is zero-
2453f4a2713aSLionel Sambuc   // based.  The attribute expects what the user wrote explicitly.
2454f4a2713aSLionel Sambuc   llvm::APSInt Val;
2455f4a2713aSLionel Sambuc   IdxExpr->EvaluateAsInt(Val, S.Context);
2456f4a2713aSLionel Sambuc 
2457f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
2458f4a2713aSLionel Sambuc              FormatArgAttr(Attr.getRange(), S.Context, Val.getZExtValue(),
2459f4a2713aSLionel Sambuc                            Attr.getAttributeSpellingListIndex()));
2460f4a2713aSLionel Sambuc }
2461f4a2713aSLionel Sambuc 
2462f4a2713aSLionel Sambuc enum FormatAttrKind {
2463f4a2713aSLionel Sambuc   CFStringFormat,
2464f4a2713aSLionel Sambuc   NSStringFormat,
2465f4a2713aSLionel Sambuc   StrftimeFormat,
2466f4a2713aSLionel Sambuc   SupportedFormat,
2467f4a2713aSLionel Sambuc   IgnoredFormat,
2468f4a2713aSLionel Sambuc   InvalidFormat
2469f4a2713aSLionel Sambuc };
2470f4a2713aSLionel Sambuc 
2471f4a2713aSLionel Sambuc /// getFormatAttrKind - Map from format attribute names to supported format
2472f4a2713aSLionel Sambuc /// types.
getFormatAttrKind(StringRef Format)2473f4a2713aSLionel Sambuc static FormatAttrKind getFormatAttrKind(StringRef Format) {
2474f4a2713aSLionel Sambuc   return llvm::StringSwitch<FormatAttrKind>(Format)
2475f4a2713aSLionel Sambuc     // Check for formats that get handled specially.
2476f4a2713aSLionel Sambuc     .Case("NSString", NSStringFormat)
2477f4a2713aSLionel Sambuc     .Case("CFString", CFStringFormat)
2478f4a2713aSLionel Sambuc     .Case("strftime", StrftimeFormat)
2479f4a2713aSLionel Sambuc 
2480f4a2713aSLionel Sambuc     // Otherwise, check for supported formats.
2481f4a2713aSLionel Sambuc     .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat)
2482f4a2713aSLionel Sambuc     .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat)
2483f4a2713aSLionel Sambuc     .Case("kprintf", SupportedFormat) // OpenBSD.
2484f4a2713aSLionel Sambuc 
2485f4a2713aSLionel Sambuc     .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat)
2486f4a2713aSLionel Sambuc     .Default(InvalidFormat);
2487f4a2713aSLionel Sambuc }
2488f4a2713aSLionel Sambuc 
2489f4a2713aSLionel Sambuc /// Handle __attribute__((init_priority(priority))) attributes based on
2490f4a2713aSLionel Sambuc /// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html
handleInitPriorityAttr(Sema & S,Decl * D,const AttributeList & Attr)2491f4a2713aSLionel Sambuc static void handleInitPriorityAttr(Sema &S, Decl *D,
2492f4a2713aSLionel Sambuc                                    const AttributeList &Attr) {
2493f4a2713aSLionel Sambuc   if (!S.getLangOpts().CPlusPlus) {
2494f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
2495f4a2713aSLionel Sambuc     return;
2496f4a2713aSLionel Sambuc   }
2497f4a2713aSLionel Sambuc 
2498*0a6a1f1dSLionel Sambuc   if (S.getCurFunctionOrMethodDecl()) {
2499f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
2500f4a2713aSLionel Sambuc     Attr.setInvalid();
2501f4a2713aSLionel Sambuc     return;
2502f4a2713aSLionel Sambuc   }
2503*0a6a1f1dSLionel Sambuc   QualType T = cast<VarDecl>(D)->getType();
2504f4a2713aSLionel Sambuc   if (S.Context.getAsArrayType(T))
2505f4a2713aSLionel Sambuc     T = S.Context.getBaseElementType(T);
2506f4a2713aSLionel Sambuc   if (!T->getAs<RecordType>()) {
2507f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
2508f4a2713aSLionel Sambuc     Attr.setInvalid();
2509f4a2713aSLionel Sambuc     return;
2510f4a2713aSLionel Sambuc   }
2511f4a2713aSLionel Sambuc 
2512*0a6a1f1dSLionel Sambuc   Expr *E = Attr.getArgAsExpr(0);
2513*0a6a1f1dSLionel Sambuc   uint32_t prioritynum;
2514*0a6a1f1dSLionel Sambuc   if (!checkUInt32Argument(S, Attr, E, prioritynum)) {
2515f4a2713aSLionel Sambuc     Attr.setInvalid();
2516f4a2713aSLionel Sambuc     return;
2517f4a2713aSLionel Sambuc   }
2518*0a6a1f1dSLionel Sambuc 
2519f4a2713aSLionel Sambuc   if (prioritynum < 101 || prioritynum > 65535) {
2520f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range)
2521*0a6a1f1dSLionel Sambuc       << E->getSourceRange();
2522f4a2713aSLionel Sambuc     Attr.setInvalid();
2523f4a2713aSLionel Sambuc     return;
2524f4a2713aSLionel Sambuc   }
2525f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
2526f4a2713aSLionel Sambuc              InitPriorityAttr(Attr.getRange(), S.Context, prioritynum,
2527f4a2713aSLionel Sambuc                               Attr.getAttributeSpellingListIndex()));
2528f4a2713aSLionel Sambuc }
2529f4a2713aSLionel Sambuc 
mergeFormatAttr(Decl * D,SourceRange Range,IdentifierInfo * Format,int FormatIdx,int FirstArg,unsigned AttrSpellingListIndex)2530f4a2713aSLionel Sambuc FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range,
2531f4a2713aSLionel Sambuc                                   IdentifierInfo *Format, int FormatIdx,
2532f4a2713aSLionel Sambuc                                   int FirstArg,
2533f4a2713aSLionel Sambuc                                   unsigned AttrSpellingListIndex) {
2534f4a2713aSLionel Sambuc   // Check whether we already have an equivalent format attribute.
2535*0a6a1f1dSLionel Sambuc   for (auto *F : D->specific_attrs<FormatAttr>()) {
2536*0a6a1f1dSLionel Sambuc     if (F->getType() == Format &&
2537*0a6a1f1dSLionel Sambuc         F->getFormatIdx() == FormatIdx &&
2538*0a6a1f1dSLionel Sambuc         F->getFirstArg() == FirstArg) {
2539f4a2713aSLionel Sambuc       // If we don't have a valid location for this attribute, adopt the
2540f4a2713aSLionel Sambuc       // location.
2541*0a6a1f1dSLionel Sambuc       if (F->getLocation().isInvalid())
2542*0a6a1f1dSLionel Sambuc         F->setRange(Range);
2543*0a6a1f1dSLionel Sambuc       return nullptr;
2544f4a2713aSLionel Sambuc     }
2545f4a2713aSLionel Sambuc   }
2546f4a2713aSLionel Sambuc 
2547f4a2713aSLionel Sambuc   return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx,
2548f4a2713aSLionel Sambuc                                     FirstArg, AttrSpellingListIndex);
2549f4a2713aSLionel Sambuc }
2550f4a2713aSLionel Sambuc 
2551f4a2713aSLionel Sambuc /// Handle __attribute__((format(type,idx,firstarg))) attributes based on
2552f4a2713aSLionel Sambuc /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
handleFormatAttr(Sema & S,Decl * D,const AttributeList & Attr)2553f4a2713aSLionel Sambuc static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {
2554f4a2713aSLionel Sambuc   if (!Attr.isArgIdent(0)) {
2555f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
2556f4a2713aSLionel Sambuc       << Attr.getName() << 1 << AANT_ArgumentIdentifier;
2557f4a2713aSLionel Sambuc     return;
2558f4a2713aSLionel Sambuc   }
2559f4a2713aSLionel Sambuc 
2560f4a2713aSLionel Sambuc   // In C++ the implicit 'this' function parameter also counts, and they are
2561f4a2713aSLionel Sambuc   // counted from one.
2562f4a2713aSLionel Sambuc   bool HasImplicitThisParam = isInstanceMethod(D);
2563*0a6a1f1dSLionel Sambuc   unsigned NumArgs = getFunctionOrMethodNumParams(D) + HasImplicitThisParam;
2564f4a2713aSLionel Sambuc 
2565f4a2713aSLionel Sambuc   IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
2566f4a2713aSLionel Sambuc   StringRef Format = II->getName();
2567f4a2713aSLionel Sambuc 
2568f4a2713aSLionel Sambuc   // Normalize the argument, __foo__ becomes foo.
2569f4a2713aSLionel Sambuc   if (Format.startswith("__") && Format.endswith("__")) {
2570f4a2713aSLionel Sambuc     Format = Format.substr(2, Format.size() - 4);
2571f4a2713aSLionel Sambuc     // If we've modified the string name, we need a new identifier for it.
2572f4a2713aSLionel Sambuc     II = &S.Context.Idents.get(Format);
2573f4a2713aSLionel Sambuc   }
2574f4a2713aSLionel Sambuc 
2575f4a2713aSLionel Sambuc   // Check for supported formats.
2576f4a2713aSLionel Sambuc   FormatAttrKind Kind = getFormatAttrKind(Format);
2577f4a2713aSLionel Sambuc 
2578f4a2713aSLionel Sambuc   if (Kind == IgnoredFormat)
2579f4a2713aSLionel Sambuc     return;
2580f4a2713aSLionel Sambuc 
2581f4a2713aSLionel Sambuc   if (Kind == InvalidFormat) {
2582f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
2583*0a6a1f1dSLionel Sambuc       << Attr.getName() << II->getName();
2584f4a2713aSLionel Sambuc     return;
2585f4a2713aSLionel Sambuc   }
2586f4a2713aSLionel Sambuc 
2587f4a2713aSLionel Sambuc   // checks for the 2nd argument
2588f4a2713aSLionel Sambuc   Expr *IdxExpr = Attr.getArgAsExpr(1);
2589*0a6a1f1dSLionel Sambuc   uint32_t Idx;
2590*0a6a1f1dSLionel Sambuc   if (!checkUInt32Argument(S, Attr, IdxExpr, Idx, 2))
2591f4a2713aSLionel Sambuc     return;
2592f4a2713aSLionel Sambuc 
2593*0a6a1f1dSLionel Sambuc   if (Idx < 1 || Idx > NumArgs) {
2594f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
2595*0a6a1f1dSLionel Sambuc       << Attr.getName() << 2 << IdxExpr->getSourceRange();
2596f4a2713aSLionel Sambuc     return;
2597f4a2713aSLionel Sambuc   }
2598f4a2713aSLionel Sambuc 
2599f4a2713aSLionel Sambuc   // FIXME: Do we need to bounds check?
2600*0a6a1f1dSLionel Sambuc   unsigned ArgIdx = Idx - 1;
2601f4a2713aSLionel Sambuc 
2602f4a2713aSLionel Sambuc   if (HasImplicitThisParam) {
2603f4a2713aSLionel Sambuc     if (ArgIdx == 0) {
2604f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(),
2605f4a2713aSLionel Sambuc              diag::err_format_attribute_implicit_this_format_string)
2606f4a2713aSLionel Sambuc         << IdxExpr->getSourceRange();
2607f4a2713aSLionel Sambuc       return;
2608f4a2713aSLionel Sambuc     }
2609f4a2713aSLionel Sambuc     ArgIdx--;
2610f4a2713aSLionel Sambuc   }
2611f4a2713aSLionel Sambuc 
2612f4a2713aSLionel Sambuc   // make sure the format string is really a string
2613*0a6a1f1dSLionel Sambuc   QualType Ty = getFunctionOrMethodParamType(D, ArgIdx);
2614f4a2713aSLionel Sambuc 
2615f4a2713aSLionel Sambuc   if (Kind == CFStringFormat) {
2616f4a2713aSLionel Sambuc     if (!isCFStringType(Ty, S.Context)) {
2617f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
2618*0a6a1f1dSLionel Sambuc         << "a CFString" << IdxExpr->getSourceRange()
2619*0a6a1f1dSLionel Sambuc         << getFunctionOrMethodParamRange(D, ArgIdx);
2620f4a2713aSLionel Sambuc       return;
2621f4a2713aSLionel Sambuc     }
2622f4a2713aSLionel Sambuc   } else if (Kind == NSStringFormat) {
2623f4a2713aSLionel Sambuc     // FIXME: do we need to check if the type is NSString*?  What are the
2624f4a2713aSLionel Sambuc     // semantics?
2625f4a2713aSLionel Sambuc     if (!isNSStringType(Ty, S.Context)) {
2626f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
2627*0a6a1f1dSLionel Sambuc         << "an NSString" << IdxExpr->getSourceRange()
2628*0a6a1f1dSLionel Sambuc         << getFunctionOrMethodParamRange(D, ArgIdx);
2629f4a2713aSLionel Sambuc       return;
2630f4a2713aSLionel Sambuc     }
2631f4a2713aSLionel Sambuc   } else if (!Ty->isPointerType() ||
2632f4a2713aSLionel Sambuc              !Ty->getAs<PointerType>()->getPointeeType()->isCharType()) {
2633f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
2634*0a6a1f1dSLionel Sambuc       << "a string type" << IdxExpr->getSourceRange()
2635*0a6a1f1dSLionel Sambuc       << getFunctionOrMethodParamRange(D, ArgIdx);
2636f4a2713aSLionel Sambuc     return;
2637f4a2713aSLionel Sambuc   }
2638f4a2713aSLionel Sambuc 
2639f4a2713aSLionel Sambuc   // check the 3rd argument
2640f4a2713aSLionel Sambuc   Expr *FirstArgExpr = Attr.getArgAsExpr(2);
2641*0a6a1f1dSLionel Sambuc   uint32_t FirstArg;
2642*0a6a1f1dSLionel Sambuc   if (!checkUInt32Argument(S, Attr, FirstArgExpr, FirstArg, 3))
2643f4a2713aSLionel Sambuc     return;
2644f4a2713aSLionel Sambuc 
2645f4a2713aSLionel Sambuc   // check if the function is variadic if the 3rd argument non-zero
2646f4a2713aSLionel Sambuc   if (FirstArg != 0) {
2647f4a2713aSLionel Sambuc     if (isFunctionOrMethodVariadic(D)) {
2648f4a2713aSLionel Sambuc       ++NumArgs; // +1 for ...
2649f4a2713aSLionel Sambuc     } else {
2650f4a2713aSLionel Sambuc       S.Diag(D->getLocation(), diag::err_format_attribute_requires_variadic);
2651f4a2713aSLionel Sambuc       return;
2652f4a2713aSLionel Sambuc     }
2653f4a2713aSLionel Sambuc   }
2654f4a2713aSLionel Sambuc 
2655f4a2713aSLionel Sambuc   // strftime requires FirstArg to be 0 because it doesn't read from any
2656f4a2713aSLionel Sambuc   // variable the input is just the current time + the format string.
2657f4a2713aSLionel Sambuc   if (Kind == StrftimeFormat) {
2658f4a2713aSLionel Sambuc     if (FirstArg != 0) {
2659f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter)
2660f4a2713aSLionel Sambuc         << FirstArgExpr->getSourceRange();
2661f4a2713aSLionel Sambuc       return;
2662f4a2713aSLionel Sambuc     }
2663f4a2713aSLionel Sambuc   // if 0 it disables parameter checking (to use with e.g. va_list)
2664f4a2713aSLionel Sambuc   } else if (FirstArg != 0 && FirstArg != NumArgs) {
2665f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
2666*0a6a1f1dSLionel Sambuc       << Attr.getName() << 3 << FirstArgExpr->getSourceRange();
2667f4a2713aSLionel Sambuc     return;
2668f4a2713aSLionel Sambuc   }
2669f4a2713aSLionel Sambuc 
2670f4a2713aSLionel Sambuc   FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), II,
2671*0a6a1f1dSLionel Sambuc                                           Idx, FirstArg,
2672f4a2713aSLionel Sambuc                                           Attr.getAttributeSpellingListIndex());
2673f4a2713aSLionel Sambuc   if (NewAttr)
2674f4a2713aSLionel Sambuc     D->addAttr(NewAttr);
2675f4a2713aSLionel Sambuc }
2676f4a2713aSLionel Sambuc 
handleTransparentUnionAttr(Sema & S,Decl * D,const AttributeList & Attr)2677f4a2713aSLionel Sambuc static void handleTransparentUnionAttr(Sema &S, Decl *D,
2678f4a2713aSLionel Sambuc                                        const AttributeList &Attr) {
2679f4a2713aSLionel Sambuc   // Try to find the underlying union declaration.
2680*0a6a1f1dSLionel Sambuc   RecordDecl *RD = nullptr;
2681f4a2713aSLionel Sambuc   TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
2682f4a2713aSLionel Sambuc   if (TD && TD->getUnderlyingType()->isUnionType())
2683f4a2713aSLionel Sambuc     RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
2684f4a2713aSLionel Sambuc   else
2685f4a2713aSLionel Sambuc     RD = dyn_cast<RecordDecl>(D);
2686f4a2713aSLionel Sambuc 
2687f4a2713aSLionel Sambuc   if (!RD || !RD->isUnion()) {
2688f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
2689f4a2713aSLionel Sambuc       << Attr.getName() << ExpectedUnion;
2690f4a2713aSLionel Sambuc     return;
2691f4a2713aSLionel Sambuc   }
2692f4a2713aSLionel Sambuc 
2693f4a2713aSLionel Sambuc   if (!RD->isCompleteDefinition()) {
2694f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(),
2695f4a2713aSLionel Sambuc         diag::warn_transparent_union_attribute_not_definition);
2696f4a2713aSLionel Sambuc     return;
2697f4a2713aSLionel Sambuc   }
2698f4a2713aSLionel Sambuc 
2699f4a2713aSLionel Sambuc   RecordDecl::field_iterator Field = RD->field_begin(),
2700f4a2713aSLionel Sambuc                           FieldEnd = RD->field_end();
2701f4a2713aSLionel Sambuc   if (Field == FieldEnd) {
2702f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields);
2703f4a2713aSLionel Sambuc     return;
2704f4a2713aSLionel Sambuc   }
2705f4a2713aSLionel Sambuc 
2706f4a2713aSLionel Sambuc   FieldDecl *FirstField = *Field;
2707f4a2713aSLionel Sambuc   QualType FirstType = FirstField->getType();
2708f4a2713aSLionel Sambuc   if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) {
2709f4a2713aSLionel Sambuc     S.Diag(FirstField->getLocation(),
2710f4a2713aSLionel Sambuc            diag::warn_transparent_union_attribute_floating)
2711f4a2713aSLionel Sambuc       << FirstType->isVectorType() << FirstType;
2712f4a2713aSLionel Sambuc     return;
2713f4a2713aSLionel Sambuc   }
2714f4a2713aSLionel Sambuc 
2715f4a2713aSLionel Sambuc   uint64_t FirstSize = S.Context.getTypeSize(FirstType);
2716f4a2713aSLionel Sambuc   uint64_t FirstAlign = S.Context.getTypeAlign(FirstType);
2717f4a2713aSLionel Sambuc   for (; Field != FieldEnd; ++Field) {
2718f4a2713aSLionel Sambuc     QualType FieldType = Field->getType();
2719*0a6a1f1dSLionel Sambuc     // FIXME: this isn't fully correct; we also need to test whether the
2720*0a6a1f1dSLionel Sambuc     // members of the union would all have the same calling convention as the
2721*0a6a1f1dSLionel Sambuc     // first member of the union. Checking just the size and alignment isn't
2722*0a6a1f1dSLionel Sambuc     // sufficient (consider structs passed on the stack instead of in registers
2723*0a6a1f1dSLionel Sambuc     // as an example).
2724f4a2713aSLionel Sambuc     if (S.Context.getTypeSize(FieldType) != FirstSize ||
2725*0a6a1f1dSLionel Sambuc         S.Context.getTypeAlign(FieldType) > FirstAlign) {
2726f4a2713aSLionel Sambuc       // Warn if we drop the attribute.
2727f4a2713aSLionel Sambuc       bool isSize = S.Context.getTypeSize(FieldType) != FirstSize;
2728f4a2713aSLionel Sambuc       unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType)
2729f4a2713aSLionel Sambuc                                  : S.Context.getTypeAlign(FieldType);
2730f4a2713aSLionel Sambuc       S.Diag(Field->getLocation(),
2731f4a2713aSLionel Sambuc           diag::warn_transparent_union_attribute_field_size_align)
2732f4a2713aSLionel Sambuc         << isSize << Field->getDeclName() << FieldBits;
2733f4a2713aSLionel Sambuc       unsigned FirstBits = isSize? FirstSize : FirstAlign;
2734f4a2713aSLionel Sambuc       S.Diag(FirstField->getLocation(),
2735f4a2713aSLionel Sambuc              diag::note_transparent_union_first_field_size_align)
2736f4a2713aSLionel Sambuc         << isSize << FirstBits;
2737f4a2713aSLionel Sambuc       return;
2738f4a2713aSLionel Sambuc     }
2739f4a2713aSLionel Sambuc   }
2740f4a2713aSLionel Sambuc 
2741f4a2713aSLionel Sambuc   RD->addAttr(::new (S.Context)
2742f4a2713aSLionel Sambuc               TransparentUnionAttr(Attr.getRange(), S.Context,
2743f4a2713aSLionel Sambuc                                    Attr.getAttributeSpellingListIndex()));
2744f4a2713aSLionel Sambuc }
2745f4a2713aSLionel Sambuc 
handleAnnotateAttr(Sema & S,Decl * D,const AttributeList & Attr)2746f4a2713aSLionel Sambuc static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
2747f4a2713aSLionel Sambuc   // Make sure that there is a string literal as the annotation's single
2748f4a2713aSLionel Sambuc   // argument.
2749f4a2713aSLionel Sambuc   StringRef Str;
2750f4a2713aSLionel Sambuc   if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str))
2751f4a2713aSLionel Sambuc     return;
2752f4a2713aSLionel Sambuc 
2753f4a2713aSLionel Sambuc   // Don't duplicate annotations that are already set.
2754*0a6a1f1dSLionel Sambuc   for (const auto *I : D->specific_attrs<AnnotateAttr>()) {
2755*0a6a1f1dSLionel Sambuc     if (I->getAnnotation() == Str)
2756f4a2713aSLionel Sambuc       return;
2757f4a2713aSLionel Sambuc   }
2758f4a2713aSLionel Sambuc 
2759f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
2760f4a2713aSLionel Sambuc              AnnotateAttr(Attr.getRange(), S.Context, Str,
2761f4a2713aSLionel Sambuc                           Attr.getAttributeSpellingListIndex()));
2762f4a2713aSLionel Sambuc }
2763f4a2713aSLionel Sambuc 
handleAlignValueAttr(Sema & S,Decl * D,const AttributeList & Attr)2764*0a6a1f1dSLionel Sambuc static void handleAlignValueAttr(Sema &S, Decl *D,
2765*0a6a1f1dSLionel Sambuc                                  const AttributeList &Attr) {
2766*0a6a1f1dSLionel Sambuc   S.AddAlignValueAttr(Attr.getRange(), D, Attr.getArgAsExpr(0),
2767*0a6a1f1dSLionel Sambuc                       Attr.getAttributeSpellingListIndex());
2768*0a6a1f1dSLionel Sambuc }
2769*0a6a1f1dSLionel Sambuc 
AddAlignValueAttr(SourceRange AttrRange,Decl * D,Expr * E,unsigned SpellingListIndex)2770*0a6a1f1dSLionel Sambuc void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
2771*0a6a1f1dSLionel Sambuc                              unsigned SpellingListIndex) {
2772*0a6a1f1dSLionel Sambuc   AlignValueAttr TmpAttr(AttrRange, Context, E, SpellingListIndex);
2773*0a6a1f1dSLionel Sambuc   SourceLocation AttrLoc = AttrRange.getBegin();
2774*0a6a1f1dSLionel Sambuc 
2775*0a6a1f1dSLionel Sambuc   QualType T;
2776*0a6a1f1dSLionel Sambuc   if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
2777*0a6a1f1dSLionel Sambuc     T = TD->getUnderlyingType();
2778*0a6a1f1dSLionel Sambuc   else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
2779*0a6a1f1dSLionel Sambuc     T = VD->getType();
2780*0a6a1f1dSLionel Sambuc   else
2781*0a6a1f1dSLionel Sambuc     llvm_unreachable("Unknown decl type for align_value");
2782*0a6a1f1dSLionel Sambuc 
2783*0a6a1f1dSLionel Sambuc   if (!T->isDependentType() && !T->isAnyPointerType() &&
2784*0a6a1f1dSLionel Sambuc       !T->isReferenceType() && !T->isMemberPointerType()) {
2785*0a6a1f1dSLionel Sambuc     Diag(AttrLoc, diag::warn_attribute_pointer_or_reference_only)
2786*0a6a1f1dSLionel Sambuc       << &TmpAttr /*TmpAttr.getName()*/ << T << D->getSourceRange();
2787*0a6a1f1dSLionel Sambuc     return;
2788*0a6a1f1dSLionel Sambuc   }
2789*0a6a1f1dSLionel Sambuc 
2790*0a6a1f1dSLionel Sambuc   if (!E->isValueDependent()) {
2791*0a6a1f1dSLionel Sambuc     llvm::APSInt Alignment(32);
2792*0a6a1f1dSLionel Sambuc     ExprResult ICE
2793*0a6a1f1dSLionel Sambuc       = VerifyIntegerConstantExpression(E, &Alignment,
2794*0a6a1f1dSLionel Sambuc           diag::err_align_value_attribute_argument_not_int,
2795*0a6a1f1dSLionel Sambuc             /*AllowFold*/ false);
2796*0a6a1f1dSLionel Sambuc     if (ICE.isInvalid())
2797*0a6a1f1dSLionel Sambuc       return;
2798*0a6a1f1dSLionel Sambuc 
2799*0a6a1f1dSLionel Sambuc     if (!Alignment.isPowerOf2()) {
2800*0a6a1f1dSLionel Sambuc       Diag(AttrLoc, diag::err_alignment_not_power_of_two)
2801*0a6a1f1dSLionel Sambuc         << E->getSourceRange();
2802*0a6a1f1dSLionel Sambuc       return;
2803*0a6a1f1dSLionel Sambuc     }
2804*0a6a1f1dSLionel Sambuc 
2805*0a6a1f1dSLionel Sambuc     D->addAttr(::new (Context)
2806*0a6a1f1dSLionel Sambuc                AlignValueAttr(AttrRange, Context, ICE.get(),
2807*0a6a1f1dSLionel Sambuc                SpellingListIndex));
2808*0a6a1f1dSLionel Sambuc     return;
2809*0a6a1f1dSLionel Sambuc   }
2810*0a6a1f1dSLionel Sambuc 
2811*0a6a1f1dSLionel Sambuc   // Save dependent expressions in the AST to be instantiated.
2812*0a6a1f1dSLionel Sambuc   D->addAttr(::new (Context) AlignValueAttr(TmpAttr));
2813*0a6a1f1dSLionel Sambuc   return;
2814*0a6a1f1dSLionel Sambuc }
2815*0a6a1f1dSLionel Sambuc 
handleAlignedAttr(Sema & S,Decl * D,const AttributeList & Attr)2816f4a2713aSLionel Sambuc static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
2817f4a2713aSLionel Sambuc   // check the attribute arguments.
2818f4a2713aSLionel Sambuc   if (Attr.getNumArgs() > 1) {
2819f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
2820f4a2713aSLionel Sambuc       << Attr.getName() << 1;
2821f4a2713aSLionel Sambuc     return;
2822f4a2713aSLionel Sambuc   }
2823f4a2713aSLionel Sambuc 
2824f4a2713aSLionel Sambuc   if (Attr.getNumArgs() == 0) {
2825f4a2713aSLionel Sambuc     D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context,
2826*0a6a1f1dSLionel Sambuc                true, nullptr, Attr.getAttributeSpellingListIndex()));
2827f4a2713aSLionel Sambuc     return;
2828f4a2713aSLionel Sambuc   }
2829f4a2713aSLionel Sambuc 
2830f4a2713aSLionel Sambuc   Expr *E = Attr.getArgAsExpr(0);
2831f4a2713aSLionel Sambuc   if (Attr.isPackExpansion() && !E->containsUnexpandedParameterPack()) {
2832f4a2713aSLionel Sambuc     S.Diag(Attr.getEllipsisLoc(),
2833f4a2713aSLionel Sambuc            diag::err_pack_expansion_without_parameter_packs);
2834f4a2713aSLionel Sambuc     return;
2835f4a2713aSLionel Sambuc   }
2836f4a2713aSLionel Sambuc 
2837f4a2713aSLionel Sambuc   if (!Attr.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E))
2838f4a2713aSLionel Sambuc     return;
2839f4a2713aSLionel Sambuc 
2840f4a2713aSLionel Sambuc   S.AddAlignedAttr(Attr.getRange(), D, E, Attr.getAttributeSpellingListIndex(),
2841f4a2713aSLionel Sambuc                    Attr.isPackExpansion());
2842f4a2713aSLionel Sambuc }
2843f4a2713aSLionel Sambuc 
AddAlignedAttr(SourceRange AttrRange,Decl * D,Expr * E,unsigned SpellingListIndex,bool IsPackExpansion)2844f4a2713aSLionel Sambuc void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
2845f4a2713aSLionel Sambuc                           unsigned SpellingListIndex, bool IsPackExpansion) {
2846f4a2713aSLionel Sambuc   AlignedAttr TmpAttr(AttrRange, Context, true, E, SpellingListIndex);
2847f4a2713aSLionel Sambuc   SourceLocation AttrLoc = AttrRange.getBegin();
2848f4a2713aSLionel Sambuc 
2849f4a2713aSLionel Sambuc   // C++11 alignas(...) and C11 _Alignas(...) have additional requirements.
2850f4a2713aSLionel Sambuc   if (TmpAttr.isAlignas()) {
2851f4a2713aSLionel Sambuc     // C++11 [dcl.align]p1:
2852f4a2713aSLionel Sambuc     //   An alignment-specifier may be applied to a variable or to a class
2853f4a2713aSLionel Sambuc     //   data member, but it shall not be applied to a bit-field, a function
2854f4a2713aSLionel Sambuc     //   parameter, the formal parameter of a catch clause, or a variable
2855f4a2713aSLionel Sambuc     //   declared with the register storage class specifier. An
2856f4a2713aSLionel Sambuc     //   alignment-specifier may also be applied to the declaration of a class
2857f4a2713aSLionel Sambuc     //   or enumeration type.
2858f4a2713aSLionel Sambuc     // C11 6.7.5/2:
2859f4a2713aSLionel Sambuc     //   An alignment attribute shall not be specified in a declaration of
2860f4a2713aSLionel Sambuc     //   a typedef, or a bit-field, or a function, or a parameter, or an
2861f4a2713aSLionel Sambuc     //   object declared with the register storage-class specifier.
2862f4a2713aSLionel Sambuc     int DiagKind = -1;
2863f4a2713aSLionel Sambuc     if (isa<ParmVarDecl>(D)) {
2864f4a2713aSLionel Sambuc       DiagKind = 0;
2865f4a2713aSLionel Sambuc     } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
2866f4a2713aSLionel Sambuc       if (VD->getStorageClass() == SC_Register)
2867f4a2713aSLionel Sambuc         DiagKind = 1;
2868f4a2713aSLionel Sambuc       if (VD->isExceptionVariable())
2869f4a2713aSLionel Sambuc         DiagKind = 2;
2870f4a2713aSLionel Sambuc     } else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
2871f4a2713aSLionel Sambuc       if (FD->isBitField())
2872f4a2713aSLionel Sambuc         DiagKind = 3;
2873f4a2713aSLionel Sambuc     } else if (!isa<TagDecl>(D)) {
2874*0a6a1f1dSLionel Sambuc       Diag(AttrLoc, diag::err_attribute_wrong_decl_type) << &TmpAttr
2875f4a2713aSLionel Sambuc         << (TmpAttr.isC11() ? ExpectedVariableOrField
2876f4a2713aSLionel Sambuc                             : ExpectedVariableFieldOrTag);
2877f4a2713aSLionel Sambuc       return;
2878f4a2713aSLionel Sambuc     }
2879f4a2713aSLionel Sambuc     if (DiagKind != -1) {
2880f4a2713aSLionel Sambuc       Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type)
2881*0a6a1f1dSLionel Sambuc         << &TmpAttr << DiagKind;
2882f4a2713aSLionel Sambuc       return;
2883f4a2713aSLionel Sambuc     }
2884f4a2713aSLionel Sambuc   }
2885f4a2713aSLionel Sambuc 
2886f4a2713aSLionel Sambuc   if (E->isTypeDependent() || E->isValueDependent()) {
2887f4a2713aSLionel Sambuc     // Save dependent expressions in the AST to be instantiated.
2888f4a2713aSLionel Sambuc     AlignedAttr *AA = ::new (Context) AlignedAttr(TmpAttr);
2889f4a2713aSLionel Sambuc     AA->setPackExpansion(IsPackExpansion);
2890f4a2713aSLionel Sambuc     D->addAttr(AA);
2891f4a2713aSLionel Sambuc     return;
2892f4a2713aSLionel Sambuc   }
2893f4a2713aSLionel Sambuc 
2894f4a2713aSLionel Sambuc   // FIXME: Cache the number on the Attr object?
2895f4a2713aSLionel Sambuc   llvm::APSInt Alignment(32);
2896f4a2713aSLionel Sambuc   ExprResult ICE
2897f4a2713aSLionel Sambuc     = VerifyIntegerConstantExpression(E, &Alignment,
2898f4a2713aSLionel Sambuc         diag::err_aligned_attribute_argument_not_int,
2899f4a2713aSLionel Sambuc         /*AllowFold*/ false);
2900f4a2713aSLionel Sambuc   if (ICE.isInvalid())
2901f4a2713aSLionel Sambuc     return;
2902f4a2713aSLionel Sambuc 
2903f4a2713aSLionel Sambuc   // C++11 [dcl.align]p2:
2904f4a2713aSLionel Sambuc   //   -- if the constant expression evaluates to zero, the alignment
2905f4a2713aSLionel Sambuc   //      specifier shall have no effect
2906f4a2713aSLionel Sambuc   // C11 6.7.5p6:
2907f4a2713aSLionel Sambuc   //   An alignment specification of zero has no effect.
2908f4a2713aSLionel Sambuc   if (!(TmpAttr.isAlignas() && !Alignment) &&
2909f4a2713aSLionel Sambuc       !llvm::isPowerOf2_64(Alignment.getZExtValue())) {
2910*0a6a1f1dSLionel Sambuc     Diag(AttrLoc, diag::err_alignment_not_power_of_two)
2911f4a2713aSLionel Sambuc       << E->getSourceRange();
2912f4a2713aSLionel Sambuc     return;
2913f4a2713aSLionel Sambuc   }
2914f4a2713aSLionel Sambuc 
2915*0a6a1f1dSLionel Sambuc   // Alignment calculations can wrap around if it's greater than 2**28.
2916*0a6a1f1dSLionel Sambuc   unsigned MaxValidAlignment = TmpAttr.isDeclspec() ? 8192 : 268435456;
2917*0a6a1f1dSLionel Sambuc   if (Alignment.getZExtValue() > MaxValidAlignment) {
2918*0a6a1f1dSLionel Sambuc     Diag(AttrLoc, diag::err_attribute_aligned_too_great) << MaxValidAlignment
2919f4a2713aSLionel Sambuc                                                          << E->getSourceRange();
2920f4a2713aSLionel Sambuc     return;
2921f4a2713aSLionel Sambuc   }
2922f4a2713aSLionel Sambuc 
2923f4a2713aSLionel Sambuc   AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, true,
2924*0a6a1f1dSLionel Sambuc                                                 ICE.get(), SpellingListIndex);
2925f4a2713aSLionel Sambuc   AA->setPackExpansion(IsPackExpansion);
2926f4a2713aSLionel Sambuc   D->addAttr(AA);
2927f4a2713aSLionel Sambuc }
2928f4a2713aSLionel Sambuc 
AddAlignedAttr(SourceRange AttrRange,Decl * D,TypeSourceInfo * TS,unsigned SpellingListIndex,bool IsPackExpansion)2929f4a2713aSLionel Sambuc void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS,
2930f4a2713aSLionel Sambuc                           unsigned SpellingListIndex, bool IsPackExpansion) {
2931f4a2713aSLionel Sambuc   // FIXME: Cache the number on the Attr object if non-dependent?
2932f4a2713aSLionel Sambuc   // FIXME: Perform checking of type validity
2933f4a2713aSLionel Sambuc   AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, false, TS,
2934f4a2713aSLionel Sambuc                                                 SpellingListIndex);
2935f4a2713aSLionel Sambuc   AA->setPackExpansion(IsPackExpansion);
2936f4a2713aSLionel Sambuc   D->addAttr(AA);
2937f4a2713aSLionel Sambuc }
2938f4a2713aSLionel Sambuc 
CheckAlignasUnderalignment(Decl * D)2939f4a2713aSLionel Sambuc void Sema::CheckAlignasUnderalignment(Decl *D) {
2940f4a2713aSLionel Sambuc   assert(D->hasAttrs() && "no attributes on decl");
2941f4a2713aSLionel Sambuc 
2942f4a2713aSLionel Sambuc   QualType Ty;
2943f4a2713aSLionel Sambuc   if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
2944f4a2713aSLionel Sambuc     Ty = VD->getType();
2945f4a2713aSLionel Sambuc   else
2946f4a2713aSLionel Sambuc     Ty = Context.getTagDeclType(cast<TagDecl>(D));
2947f4a2713aSLionel Sambuc   if (Ty->isDependentType() || Ty->isIncompleteType())
2948f4a2713aSLionel Sambuc     return;
2949f4a2713aSLionel Sambuc 
2950f4a2713aSLionel Sambuc   // C++11 [dcl.align]p5, C11 6.7.5/4:
2951f4a2713aSLionel Sambuc   //   The combined effect of all alignment attributes in a declaration shall
2952f4a2713aSLionel Sambuc   //   not specify an alignment that is less strict than the alignment that
2953f4a2713aSLionel Sambuc   //   would otherwise be required for the entity being declared.
2954*0a6a1f1dSLionel Sambuc   AlignedAttr *AlignasAttr = nullptr;
2955f4a2713aSLionel Sambuc   unsigned Align = 0;
2956*0a6a1f1dSLionel Sambuc   for (auto *I : D->specific_attrs<AlignedAttr>()) {
2957f4a2713aSLionel Sambuc     if (I->isAlignmentDependent())
2958f4a2713aSLionel Sambuc       return;
2959f4a2713aSLionel Sambuc     if (I->isAlignas())
2960*0a6a1f1dSLionel Sambuc       AlignasAttr = I;
2961f4a2713aSLionel Sambuc     Align = std::max(Align, I->getAlignment(Context));
2962f4a2713aSLionel Sambuc   }
2963f4a2713aSLionel Sambuc 
2964f4a2713aSLionel Sambuc   if (AlignasAttr && Align) {
2965f4a2713aSLionel Sambuc     CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align);
2966f4a2713aSLionel Sambuc     CharUnits NaturalAlign = Context.getTypeAlignInChars(Ty);
2967f4a2713aSLionel Sambuc     if (NaturalAlign > RequestedAlign)
2968f4a2713aSLionel Sambuc       Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned)
2969f4a2713aSLionel Sambuc         << Ty << (unsigned)NaturalAlign.getQuantity();
2970f4a2713aSLionel Sambuc   }
2971f4a2713aSLionel Sambuc }
2972f4a2713aSLionel Sambuc 
checkMSInheritanceAttrOnDefinition(CXXRecordDecl * RD,SourceRange Range,bool BestCase,MSInheritanceAttr::Spelling SemanticSpelling)2973*0a6a1f1dSLionel Sambuc bool Sema::checkMSInheritanceAttrOnDefinition(
2974*0a6a1f1dSLionel Sambuc     CXXRecordDecl *RD, SourceRange Range, bool BestCase,
2975*0a6a1f1dSLionel Sambuc     MSInheritanceAttr::Spelling SemanticSpelling) {
2976*0a6a1f1dSLionel Sambuc   assert(RD->hasDefinition() && "RD has no definition!");
2977*0a6a1f1dSLionel Sambuc 
2978*0a6a1f1dSLionel Sambuc   // We may not have seen base specifiers or any virtual methods yet.  We will
2979*0a6a1f1dSLionel Sambuc   // have to wait until the record is defined to catch any mismatches.
2980*0a6a1f1dSLionel Sambuc   if (!RD->getDefinition()->isCompleteDefinition())
2981*0a6a1f1dSLionel Sambuc     return false;
2982*0a6a1f1dSLionel Sambuc 
2983*0a6a1f1dSLionel Sambuc   // The unspecified model never matches what a definition could need.
2984*0a6a1f1dSLionel Sambuc   if (SemanticSpelling == MSInheritanceAttr::Keyword_unspecified_inheritance)
2985*0a6a1f1dSLionel Sambuc     return false;
2986*0a6a1f1dSLionel Sambuc 
2987*0a6a1f1dSLionel Sambuc   if (BestCase) {
2988*0a6a1f1dSLionel Sambuc     if (RD->calculateInheritanceModel() == SemanticSpelling)
2989*0a6a1f1dSLionel Sambuc       return false;
2990*0a6a1f1dSLionel Sambuc   } else {
2991*0a6a1f1dSLionel Sambuc     if (RD->calculateInheritanceModel() <= SemanticSpelling)
2992*0a6a1f1dSLionel Sambuc       return false;
2993*0a6a1f1dSLionel Sambuc   }
2994*0a6a1f1dSLionel Sambuc 
2995*0a6a1f1dSLionel Sambuc   Diag(Range.getBegin(), diag::err_mismatched_ms_inheritance)
2996*0a6a1f1dSLionel Sambuc       << 0 /*definition*/;
2997*0a6a1f1dSLionel Sambuc   Diag(RD->getDefinition()->getLocation(), diag::note_defined_here)
2998*0a6a1f1dSLionel Sambuc       << RD->getNameAsString();
2999*0a6a1f1dSLionel Sambuc   return true;
3000*0a6a1f1dSLionel Sambuc }
3001*0a6a1f1dSLionel Sambuc 
3002f4a2713aSLionel Sambuc /// handleModeAttr - This attribute modifies the width of a decl with primitive
3003f4a2713aSLionel Sambuc /// type.
3004f4a2713aSLionel Sambuc ///
3005f4a2713aSLionel Sambuc /// Despite what would be logical, the mode attribute is a decl attribute, not a
3006f4a2713aSLionel Sambuc /// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
3007f4a2713aSLionel Sambuc /// HImode, not an intermediate pointer.
handleModeAttr(Sema & S,Decl * D,const AttributeList & Attr)3008f4a2713aSLionel Sambuc static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
3009f4a2713aSLionel Sambuc   // This attribute isn't documented, but glibc uses it.  It changes
3010f4a2713aSLionel Sambuc   // the width of an int or unsigned int to the specified size.
3011f4a2713aSLionel Sambuc   if (!Attr.isArgIdent(0)) {
3012f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
3013f4a2713aSLionel Sambuc       << AANT_ArgumentIdentifier;
3014f4a2713aSLionel Sambuc     return;
3015f4a2713aSLionel Sambuc   }
3016f4a2713aSLionel Sambuc 
3017f4a2713aSLionel Sambuc   IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident;
3018f4a2713aSLionel Sambuc   StringRef Str = Name->getName();
3019f4a2713aSLionel Sambuc 
3020f4a2713aSLionel Sambuc   // Normalize the attribute name, __foo__ becomes foo.
3021f4a2713aSLionel Sambuc   if (Str.startswith("__") && Str.endswith("__"))
3022f4a2713aSLionel Sambuc     Str = Str.substr(2, Str.size() - 4);
3023f4a2713aSLionel Sambuc 
3024f4a2713aSLionel Sambuc   unsigned DestWidth = 0;
3025f4a2713aSLionel Sambuc   bool IntegerMode = true;
3026f4a2713aSLionel Sambuc   bool ComplexMode = false;
3027f4a2713aSLionel Sambuc   switch (Str.size()) {
3028f4a2713aSLionel Sambuc   case 2:
3029f4a2713aSLionel Sambuc     switch (Str[0]) {
3030f4a2713aSLionel Sambuc     case 'Q': DestWidth = 8; break;
3031f4a2713aSLionel Sambuc     case 'H': DestWidth = 16; break;
3032f4a2713aSLionel Sambuc     case 'S': DestWidth = 32; break;
3033f4a2713aSLionel Sambuc     case 'D': DestWidth = 64; break;
3034f4a2713aSLionel Sambuc     case 'X': DestWidth = 96; break;
3035f4a2713aSLionel Sambuc     case 'T': DestWidth = 128; break;
3036f4a2713aSLionel Sambuc     }
3037f4a2713aSLionel Sambuc     if (Str[1] == 'F') {
3038f4a2713aSLionel Sambuc       IntegerMode = false;
3039f4a2713aSLionel Sambuc     } else if (Str[1] == 'C') {
3040f4a2713aSLionel Sambuc       IntegerMode = false;
3041f4a2713aSLionel Sambuc       ComplexMode = true;
3042f4a2713aSLionel Sambuc     } else if (Str[1] != 'I') {
3043f4a2713aSLionel Sambuc       DestWidth = 0;
3044f4a2713aSLionel Sambuc     }
3045f4a2713aSLionel Sambuc     break;
3046f4a2713aSLionel Sambuc   case 4:
3047f4a2713aSLionel Sambuc     // FIXME: glibc uses 'word' to define register_t; this is narrower than a
3048f4a2713aSLionel Sambuc     // pointer on PIC16 and other embedded platforms.
3049f4a2713aSLionel Sambuc     if (Str == "word")
3050f4a2713aSLionel Sambuc       DestWidth = S.Context.getTargetInfo().getPointerWidth(0);
3051f4a2713aSLionel Sambuc     else if (Str == "byte")
3052f4a2713aSLionel Sambuc       DestWidth = S.Context.getTargetInfo().getCharWidth();
3053f4a2713aSLionel Sambuc     break;
3054f4a2713aSLionel Sambuc   case 7:
3055f4a2713aSLionel Sambuc     if (Str == "pointer")
3056f4a2713aSLionel Sambuc       DestWidth = S.Context.getTargetInfo().getPointerWidth(0);
3057f4a2713aSLionel Sambuc     break;
3058f4a2713aSLionel Sambuc   case 11:
3059f4a2713aSLionel Sambuc     if (Str == "unwind_word")
3060f4a2713aSLionel Sambuc       DestWidth = S.Context.getTargetInfo().getUnwindWordWidth();
3061f4a2713aSLionel Sambuc     break;
3062f4a2713aSLionel Sambuc   }
3063f4a2713aSLionel Sambuc 
3064f4a2713aSLionel Sambuc   QualType OldTy;
3065f4a2713aSLionel Sambuc   if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
3066f4a2713aSLionel Sambuc     OldTy = TD->getUnderlyingType();
3067f4a2713aSLionel Sambuc   else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
3068f4a2713aSLionel Sambuc     OldTy = VD->getType();
3069f4a2713aSLionel Sambuc   else {
3070f4a2713aSLionel Sambuc     S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
3071*0a6a1f1dSLionel Sambuc       << Attr.getName() << Attr.getRange();
3072f4a2713aSLionel Sambuc     return;
3073f4a2713aSLionel Sambuc   }
3074f4a2713aSLionel Sambuc 
3075f4a2713aSLionel Sambuc   if (!OldTy->getAs<BuiltinType>() && !OldTy->isComplexType())
3076f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
3077f4a2713aSLionel Sambuc   else if (IntegerMode) {
3078f4a2713aSLionel Sambuc     if (!OldTy->isIntegralOrEnumerationType())
3079f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
3080f4a2713aSLionel Sambuc   } else if (ComplexMode) {
3081f4a2713aSLionel Sambuc     if (!OldTy->isComplexType())
3082f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
3083f4a2713aSLionel Sambuc   } else {
3084f4a2713aSLionel Sambuc     if (!OldTy->isFloatingType())
3085f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
3086f4a2713aSLionel Sambuc   }
3087f4a2713aSLionel Sambuc 
3088f4a2713aSLionel Sambuc   // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
3089f4a2713aSLionel Sambuc   // and friends, at least with glibc.
3090f4a2713aSLionel Sambuc   // FIXME: Make sure floating-point mappings are accurate
3091f4a2713aSLionel Sambuc   // FIXME: Support XF and TF types
3092f4a2713aSLionel Sambuc   if (!DestWidth) {
3093*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_machine_mode) << 0 /*Unknown*/ << Name;
3094f4a2713aSLionel Sambuc     return;
3095f4a2713aSLionel Sambuc   }
3096f4a2713aSLionel Sambuc 
3097f4a2713aSLionel Sambuc   QualType NewTy;
3098f4a2713aSLionel Sambuc 
3099f4a2713aSLionel Sambuc   if (IntegerMode)
3100f4a2713aSLionel Sambuc     NewTy = S.Context.getIntTypeForBitwidth(DestWidth,
3101f4a2713aSLionel Sambuc                                             OldTy->isSignedIntegerType());
3102f4a2713aSLionel Sambuc   else
3103f4a2713aSLionel Sambuc     NewTy = S.Context.getRealTypeForBitwidth(DestWidth);
3104f4a2713aSLionel Sambuc 
3105f4a2713aSLionel Sambuc   if (NewTy.isNull()) {
3106*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
3107f4a2713aSLionel Sambuc     return;
3108f4a2713aSLionel Sambuc   }
3109f4a2713aSLionel Sambuc 
3110f4a2713aSLionel Sambuc   if (ComplexMode) {
3111f4a2713aSLionel Sambuc     NewTy = S.Context.getComplexType(NewTy);
3112f4a2713aSLionel Sambuc   }
3113f4a2713aSLionel Sambuc 
3114f4a2713aSLionel Sambuc   // Install the new type.
3115f4a2713aSLionel Sambuc   if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
3116f4a2713aSLionel Sambuc     TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy);
3117f4a2713aSLionel Sambuc   else
3118f4a2713aSLionel Sambuc     cast<ValueDecl>(D)->setType(NewTy);
3119f4a2713aSLionel Sambuc 
3120f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
3121f4a2713aSLionel Sambuc              ModeAttr(Attr.getRange(), S.Context, Name,
3122f4a2713aSLionel Sambuc                       Attr.getAttributeSpellingListIndex()));
3123f4a2713aSLionel Sambuc }
3124f4a2713aSLionel Sambuc 
handleNoDebugAttr(Sema & S,Decl * D,const AttributeList & Attr)3125f4a2713aSLionel Sambuc static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {
3126f4a2713aSLionel Sambuc   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
3127f4a2713aSLionel Sambuc     if (!VD->hasGlobalStorage())
3128f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(),
3129f4a2713aSLionel Sambuc              diag::warn_attribute_requires_functions_or_static_globals)
3130f4a2713aSLionel Sambuc         << Attr.getName();
3131f4a2713aSLionel Sambuc   } else if (!isFunctionOrMethod(D)) {
3132f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(),
3133f4a2713aSLionel Sambuc            diag::warn_attribute_requires_functions_or_static_globals)
3134f4a2713aSLionel Sambuc       << Attr.getName();
3135f4a2713aSLionel Sambuc     return;
3136f4a2713aSLionel Sambuc   }
3137f4a2713aSLionel Sambuc 
3138f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
3139f4a2713aSLionel Sambuc              NoDebugAttr(Attr.getRange(), S.Context,
3140f4a2713aSLionel Sambuc                          Attr.getAttributeSpellingListIndex()));
3141f4a2713aSLionel Sambuc }
3142f4a2713aSLionel Sambuc 
mergeAlwaysInlineAttr(Decl * D,SourceRange Range,IdentifierInfo * Ident,unsigned AttrSpellingListIndex)3143*0a6a1f1dSLionel Sambuc AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
3144*0a6a1f1dSLionel Sambuc                                               IdentifierInfo *Ident,
3145*0a6a1f1dSLionel Sambuc                                               unsigned AttrSpellingListIndex) {
3146*0a6a1f1dSLionel Sambuc   if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) {
3147*0a6a1f1dSLionel Sambuc     Diag(Range.getBegin(), diag::warn_attribute_ignored) << Ident;
3148*0a6a1f1dSLionel Sambuc     Diag(Optnone->getLocation(), diag::note_conflicting_attribute);
3149*0a6a1f1dSLionel Sambuc     return nullptr;
3150f4a2713aSLionel Sambuc   }
3151f4a2713aSLionel Sambuc 
3152*0a6a1f1dSLionel Sambuc   if (D->hasAttr<AlwaysInlineAttr>())
3153*0a6a1f1dSLionel Sambuc     return nullptr;
3154*0a6a1f1dSLionel Sambuc 
3155*0a6a1f1dSLionel Sambuc   return ::new (Context) AlwaysInlineAttr(Range, Context,
3156*0a6a1f1dSLionel Sambuc                                           AttrSpellingListIndex);
3157f4a2713aSLionel Sambuc }
3158f4a2713aSLionel Sambuc 
mergeMinSizeAttr(Decl * D,SourceRange Range,unsigned AttrSpellingListIndex)3159*0a6a1f1dSLionel Sambuc MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, SourceRange Range,
3160*0a6a1f1dSLionel Sambuc                                     unsigned AttrSpellingListIndex) {
3161*0a6a1f1dSLionel Sambuc   if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) {
3162*0a6a1f1dSLionel Sambuc     Diag(Range.getBegin(), diag::warn_attribute_ignored) << "'minsize'";
3163*0a6a1f1dSLionel Sambuc     Diag(Optnone->getLocation(), diag::note_conflicting_attribute);
3164*0a6a1f1dSLionel Sambuc     return nullptr;
3165*0a6a1f1dSLionel Sambuc   }
3166*0a6a1f1dSLionel Sambuc 
3167*0a6a1f1dSLionel Sambuc   if (D->hasAttr<MinSizeAttr>())
3168*0a6a1f1dSLionel Sambuc     return nullptr;
3169*0a6a1f1dSLionel Sambuc 
3170*0a6a1f1dSLionel Sambuc   return ::new (Context) MinSizeAttr(Range, Context, AttrSpellingListIndex);
3171*0a6a1f1dSLionel Sambuc }
3172*0a6a1f1dSLionel Sambuc 
mergeOptimizeNoneAttr(Decl * D,SourceRange Range,unsigned AttrSpellingListIndex)3173*0a6a1f1dSLionel Sambuc OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
3174*0a6a1f1dSLionel Sambuc                                               unsigned AttrSpellingListIndex) {
3175*0a6a1f1dSLionel Sambuc   if (AlwaysInlineAttr *Inline = D->getAttr<AlwaysInlineAttr>()) {
3176*0a6a1f1dSLionel Sambuc     Diag(Inline->getLocation(), diag::warn_attribute_ignored) << Inline;
3177*0a6a1f1dSLionel Sambuc     Diag(Range.getBegin(), diag::note_conflicting_attribute);
3178*0a6a1f1dSLionel Sambuc     D->dropAttr<AlwaysInlineAttr>();
3179*0a6a1f1dSLionel Sambuc   }
3180*0a6a1f1dSLionel Sambuc   if (MinSizeAttr *MinSize = D->getAttr<MinSizeAttr>()) {
3181*0a6a1f1dSLionel Sambuc     Diag(MinSize->getLocation(), diag::warn_attribute_ignored) << MinSize;
3182*0a6a1f1dSLionel Sambuc     Diag(Range.getBegin(), diag::note_conflicting_attribute);
3183*0a6a1f1dSLionel Sambuc     D->dropAttr<MinSizeAttr>();
3184*0a6a1f1dSLionel Sambuc   }
3185*0a6a1f1dSLionel Sambuc 
3186*0a6a1f1dSLionel Sambuc   if (D->hasAttr<OptimizeNoneAttr>())
3187*0a6a1f1dSLionel Sambuc     return nullptr;
3188*0a6a1f1dSLionel Sambuc 
3189*0a6a1f1dSLionel Sambuc   return ::new (Context) OptimizeNoneAttr(Range, Context,
3190*0a6a1f1dSLionel Sambuc                                           AttrSpellingListIndex);
3191*0a6a1f1dSLionel Sambuc }
3192*0a6a1f1dSLionel Sambuc 
handleAlwaysInlineAttr(Sema & S,Decl * D,const AttributeList & Attr)3193*0a6a1f1dSLionel Sambuc static void handleAlwaysInlineAttr(Sema &S, Decl *D,
3194f4a2713aSLionel Sambuc                                    const AttributeList &Attr) {
3195*0a6a1f1dSLionel Sambuc   if (AlwaysInlineAttr *Inline = S.mergeAlwaysInlineAttr(
3196*0a6a1f1dSLionel Sambuc           D, Attr.getRange(), Attr.getName(),
3197*0a6a1f1dSLionel Sambuc           Attr.getAttributeSpellingListIndex()))
3198*0a6a1f1dSLionel Sambuc     D->addAttr(Inline);
3199f4a2713aSLionel Sambuc }
3200f4a2713aSLionel Sambuc 
handleMinSizeAttr(Sema & S,Decl * D,const AttributeList & Attr)3201*0a6a1f1dSLionel Sambuc static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
3202*0a6a1f1dSLionel Sambuc   if (MinSizeAttr *MinSize = S.mergeMinSizeAttr(
3203*0a6a1f1dSLionel Sambuc           D, Attr.getRange(), Attr.getAttributeSpellingListIndex()))
3204*0a6a1f1dSLionel Sambuc     D->addAttr(MinSize);
3205f4a2713aSLionel Sambuc }
3206f4a2713aSLionel Sambuc 
handleOptimizeNoneAttr(Sema & S,Decl * D,const AttributeList & Attr)3207*0a6a1f1dSLionel Sambuc static void handleOptimizeNoneAttr(Sema &S, Decl *D,
3208*0a6a1f1dSLionel Sambuc                                    const AttributeList &Attr) {
3209*0a6a1f1dSLionel Sambuc   if (OptimizeNoneAttr *Optnone = S.mergeOptimizeNoneAttr(
3210*0a6a1f1dSLionel Sambuc           D, Attr.getRange(), Attr.getAttributeSpellingListIndex()))
3211*0a6a1f1dSLionel Sambuc     D->addAttr(Optnone);
3212f4a2713aSLionel Sambuc }
3213f4a2713aSLionel Sambuc 
handleGlobalAttr(Sema & S,Decl * D,const AttributeList & Attr)3214f4a2713aSLionel Sambuc static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
3215f4a2713aSLionel Sambuc   FunctionDecl *FD = cast<FunctionDecl>(D);
3216*0a6a1f1dSLionel Sambuc   if (!FD->getReturnType()->isVoidType()) {
3217*0a6a1f1dSLionel Sambuc     SourceRange RTRange = FD->getReturnTypeSourceRange();
3218f4a2713aSLionel Sambuc     S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
3219f4a2713aSLionel Sambuc         << FD->getType()
3220*0a6a1f1dSLionel Sambuc         << (RTRange.isValid() ? FixItHint::CreateReplacement(RTRange, "void")
3221*0a6a1f1dSLionel Sambuc                               : FixItHint());
3222f4a2713aSLionel Sambuc     return;
3223f4a2713aSLionel Sambuc   }
3224f4a2713aSLionel Sambuc 
3225f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
3226f4a2713aSLionel Sambuc               CUDAGlobalAttr(Attr.getRange(), S.Context,
3227f4a2713aSLionel Sambuc                              Attr.getAttributeSpellingListIndex()));
3228f4a2713aSLionel Sambuc }
3229f4a2713aSLionel Sambuc 
handleGNUInlineAttr(Sema & S,Decl * D,const AttributeList & Attr)3230f4a2713aSLionel Sambuc static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
3231*0a6a1f1dSLionel Sambuc   FunctionDecl *Fn = cast<FunctionDecl>(D);
3232f4a2713aSLionel Sambuc   if (!Fn->isInlineSpecified()) {
3233f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
3234f4a2713aSLionel Sambuc     return;
3235f4a2713aSLionel Sambuc   }
3236f4a2713aSLionel Sambuc 
3237f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
3238f4a2713aSLionel Sambuc              GNUInlineAttr(Attr.getRange(), S.Context,
3239f4a2713aSLionel Sambuc                            Attr.getAttributeSpellingListIndex()));
3240f4a2713aSLionel Sambuc }
3241f4a2713aSLionel Sambuc 
handleCallConvAttr(Sema & S,Decl * D,const AttributeList & Attr)3242f4a2713aSLionel Sambuc static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
3243f4a2713aSLionel Sambuc   if (hasDeclarator(D)) return;
3244f4a2713aSLionel Sambuc 
3245f4a2713aSLionel Sambuc   const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
3246f4a2713aSLionel Sambuc   // Diagnostic is emitted elsewhere: here we store the (valid) Attr
3247f4a2713aSLionel Sambuc   // in the Decl node for syntactic reasoning, e.g., pretty-printing.
3248f4a2713aSLionel Sambuc   CallingConv CC;
3249f4a2713aSLionel Sambuc   if (S.CheckCallingConvAttr(Attr, CC, FD))
3250f4a2713aSLionel Sambuc     return;
3251f4a2713aSLionel Sambuc 
3252f4a2713aSLionel Sambuc   if (!isa<ObjCMethodDecl>(D)) {
3253f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
3254f4a2713aSLionel Sambuc       << Attr.getName() << ExpectedFunctionOrMethod;
3255f4a2713aSLionel Sambuc     return;
3256f4a2713aSLionel Sambuc   }
3257f4a2713aSLionel Sambuc 
3258f4a2713aSLionel Sambuc   switch (Attr.getKind()) {
3259f4a2713aSLionel Sambuc   case AttributeList::AT_FastCall:
3260f4a2713aSLionel Sambuc     D->addAttr(::new (S.Context)
3261f4a2713aSLionel Sambuc                FastCallAttr(Attr.getRange(), S.Context,
3262f4a2713aSLionel Sambuc                             Attr.getAttributeSpellingListIndex()));
3263f4a2713aSLionel Sambuc     return;
3264f4a2713aSLionel Sambuc   case AttributeList::AT_StdCall:
3265f4a2713aSLionel Sambuc     D->addAttr(::new (S.Context)
3266f4a2713aSLionel Sambuc                StdCallAttr(Attr.getRange(), S.Context,
3267f4a2713aSLionel Sambuc                            Attr.getAttributeSpellingListIndex()));
3268f4a2713aSLionel Sambuc     return;
3269f4a2713aSLionel Sambuc   case AttributeList::AT_ThisCall:
3270f4a2713aSLionel Sambuc     D->addAttr(::new (S.Context)
3271f4a2713aSLionel Sambuc                ThisCallAttr(Attr.getRange(), S.Context,
3272f4a2713aSLionel Sambuc                             Attr.getAttributeSpellingListIndex()));
3273f4a2713aSLionel Sambuc     return;
3274f4a2713aSLionel Sambuc   case AttributeList::AT_CDecl:
3275f4a2713aSLionel Sambuc     D->addAttr(::new (S.Context)
3276f4a2713aSLionel Sambuc                CDeclAttr(Attr.getRange(), S.Context,
3277f4a2713aSLionel Sambuc                          Attr.getAttributeSpellingListIndex()));
3278f4a2713aSLionel Sambuc     return;
3279f4a2713aSLionel Sambuc   case AttributeList::AT_Pascal:
3280f4a2713aSLionel Sambuc     D->addAttr(::new (S.Context)
3281f4a2713aSLionel Sambuc                PascalAttr(Attr.getRange(), S.Context,
3282f4a2713aSLionel Sambuc                           Attr.getAttributeSpellingListIndex()));
3283f4a2713aSLionel Sambuc     return;
3284*0a6a1f1dSLionel Sambuc   case AttributeList::AT_VectorCall:
3285*0a6a1f1dSLionel Sambuc     D->addAttr(::new (S.Context)
3286*0a6a1f1dSLionel Sambuc                VectorCallAttr(Attr.getRange(), S.Context,
3287*0a6a1f1dSLionel Sambuc                               Attr.getAttributeSpellingListIndex()));
3288*0a6a1f1dSLionel Sambuc     return;
3289f4a2713aSLionel Sambuc   case AttributeList::AT_MSABI:
3290f4a2713aSLionel Sambuc     D->addAttr(::new (S.Context)
3291f4a2713aSLionel Sambuc                MSABIAttr(Attr.getRange(), S.Context,
3292f4a2713aSLionel Sambuc                          Attr.getAttributeSpellingListIndex()));
3293f4a2713aSLionel Sambuc     return;
3294f4a2713aSLionel Sambuc   case AttributeList::AT_SysVABI:
3295f4a2713aSLionel Sambuc     D->addAttr(::new (S.Context)
3296f4a2713aSLionel Sambuc                SysVABIAttr(Attr.getRange(), S.Context,
3297f4a2713aSLionel Sambuc                            Attr.getAttributeSpellingListIndex()));
3298f4a2713aSLionel Sambuc     return;
3299f4a2713aSLionel Sambuc   case AttributeList::AT_Pcs: {
3300f4a2713aSLionel Sambuc     PcsAttr::PCSType PCS;
3301f4a2713aSLionel Sambuc     switch (CC) {
3302f4a2713aSLionel Sambuc     case CC_AAPCS:
3303f4a2713aSLionel Sambuc       PCS = PcsAttr::AAPCS;
3304f4a2713aSLionel Sambuc       break;
3305f4a2713aSLionel Sambuc     case CC_AAPCS_VFP:
3306f4a2713aSLionel Sambuc       PCS = PcsAttr::AAPCS_VFP;
3307f4a2713aSLionel Sambuc       break;
3308f4a2713aSLionel Sambuc     default:
3309f4a2713aSLionel Sambuc       llvm_unreachable("unexpected calling convention in pcs attribute");
3310f4a2713aSLionel Sambuc     }
3311f4a2713aSLionel Sambuc 
3312f4a2713aSLionel Sambuc     D->addAttr(::new (S.Context)
3313f4a2713aSLionel Sambuc                PcsAttr(Attr.getRange(), S.Context, PCS,
3314f4a2713aSLionel Sambuc                        Attr.getAttributeSpellingListIndex()));
3315f4a2713aSLionel Sambuc     return;
3316f4a2713aSLionel Sambuc   }
3317f4a2713aSLionel Sambuc   case AttributeList::AT_PnaclCall:
3318f4a2713aSLionel Sambuc     D->addAttr(::new (S.Context)
3319f4a2713aSLionel Sambuc                PnaclCallAttr(Attr.getRange(), S.Context,
3320f4a2713aSLionel Sambuc                              Attr.getAttributeSpellingListIndex()));
3321f4a2713aSLionel Sambuc     return;
3322f4a2713aSLionel Sambuc   case AttributeList::AT_IntelOclBicc:
3323f4a2713aSLionel Sambuc     D->addAttr(::new (S.Context)
3324f4a2713aSLionel Sambuc                IntelOclBiccAttr(Attr.getRange(), S.Context,
3325f4a2713aSLionel Sambuc                                 Attr.getAttributeSpellingListIndex()));
3326f4a2713aSLionel Sambuc     return;
3327f4a2713aSLionel Sambuc 
3328f4a2713aSLionel Sambuc   default:
3329f4a2713aSLionel Sambuc     llvm_unreachable("unexpected attribute kind");
3330f4a2713aSLionel Sambuc   }
3331f4a2713aSLionel Sambuc }
3332f4a2713aSLionel Sambuc 
CheckCallingConvAttr(const AttributeList & attr,CallingConv & CC,const FunctionDecl * FD)3333f4a2713aSLionel Sambuc bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
3334f4a2713aSLionel Sambuc                                 const FunctionDecl *FD) {
3335f4a2713aSLionel Sambuc   if (attr.isInvalid())
3336f4a2713aSLionel Sambuc     return true;
3337f4a2713aSLionel Sambuc 
3338f4a2713aSLionel Sambuc   unsigned ReqArgs = attr.getKind() == AttributeList::AT_Pcs ? 1 : 0;
3339f4a2713aSLionel Sambuc   if (!checkAttributeNumArgs(*this, attr, ReqArgs)) {
3340f4a2713aSLionel Sambuc     attr.setInvalid();
3341f4a2713aSLionel Sambuc     return true;
3342f4a2713aSLionel Sambuc   }
3343f4a2713aSLionel Sambuc 
3344*0a6a1f1dSLionel Sambuc   // TODO: diagnose uses of these conventions on the wrong target.
3345f4a2713aSLionel Sambuc   switch (attr.getKind()) {
3346f4a2713aSLionel Sambuc   case AttributeList::AT_CDecl: CC = CC_C; break;
3347f4a2713aSLionel Sambuc   case AttributeList::AT_FastCall: CC = CC_X86FastCall; break;
3348f4a2713aSLionel Sambuc   case AttributeList::AT_StdCall: CC = CC_X86StdCall; break;
3349f4a2713aSLionel Sambuc   case AttributeList::AT_ThisCall: CC = CC_X86ThisCall; break;
3350f4a2713aSLionel Sambuc   case AttributeList::AT_Pascal: CC = CC_X86Pascal; break;
3351*0a6a1f1dSLionel Sambuc   case AttributeList::AT_VectorCall: CC = CC_X86VectorCall; break;
3352f4a2713aSLionel Sambuc   case AttributeList::AT_MSABI:
3353f4a2713aSLionel Sambuc     CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C :
3354f4a2713aSLionel Sambuc                                                              CC_X86_64Win64;
3355f4a2713aSLionel Sambuc     break;
3356f4a2713aSLionel Sambuc   case AttributeList::AT_SysVABI:
3357f4a2713aSLionel Sambuc     CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV :
3358f4a2713aSLionel Sambuc                                                              CC_C;
3359f4a2713aSLionel Sambuc     break;
3360f4a2713aSLionel Sambuc   case AttributeList::AT_Pcs: {
3361f4a2713aSLionel Sambuc     StringRef StrRef;
3362f4a2713aSLionel Sambuc     if (!checkStringLiteralArgumentAttr(attr, 0, StrRef)) {
3363f4a2713aSLionel Sambuc       attr.setInvalid();
3364f4a2713aSLionel Sambuc       return true;
3365f4a2713aSLionel Sambuc     }
3366f4a2713aSLionel Sambuc     if (StrRef == "aapcs") {
3367f4a2713aSLionel Sambuc       CC = CC_AAPCS;
3368f4a2713aSLionel Sambuc       break;
3369f4a2713aSLionel Sambuc     } else if (StrRef == "aapcs-vfp") {
3370f4a2713aSLionel Sambuc       CC = CC_AAPCS_VFP;
3371f4a2713aSLionel Sambuc       break;
3372f4a2713aSLionel Sambuc     }
3373f4a2713aSLionel Sambuc 
3374f4a2713aSLionel Sambuc     attr.setInvalid();
3375f4a2713aSLionel Sambuc     Diag(attr.getLoc(), diag::err_invalid_pcs);
3376f4a2713aSLionel Sambuc     return true;
3377f4a2713aSLionel Sambuc   }
3378f4a2713aSLionel Sambuc   case AttributeList::AT_PnaclCall: CC = CC_PnaclCall; break;
3379f4a2713aSLionel Sambuc   case AttributeList::AT_IntelOclBicc: CC = CC_IntelOclBicc; break;
3380f4a2713aSLionel Sambuc   default: llvm_unreachable("unexpected attribute kind");
3381f4a2713aSLionel Sambuc   }
3382f4a2713aSLionel Sambuc 
3383f4a2713aSLionel Sambuc   const TargetInfo &TI = Context.getTargetInfo();
3384f4a2713aSLionel Sambuc   TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC);
3385f4a2713aSLionel Sambuc   if (A == TargetInfo::CCCR_Warning) {
3386f4a2713aSLionel Sambuc     Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName();
3387f4a2713aSLionel Sambuc 
3388f4a2713aSLionel Sambuc     TargetInfo::CallingConvMethodType MT = TargetInfo::CCMT_Unknown;
3389f4a2713aSLionel Sambuc     if (FD)
3390f4a2713aSLionel Sambuc       MT = FD->isCXXInstanceMember() ? TargetInfo::CCMT_Member :
3391f4a2713aSLionel Sambuc                                     TargetInfo::CCMT_NonMember;
3392f4a2713aSLionel Sambuc     CC = TI.getDefaultCallingConv(MT);
3393f4a2713aSLionel Sambuc   }
3394f4a2713aSLionel Sambuc 
3395f4a2713aSLionel Sambuc   return false;
3396f4a2713aSLionel Sambuc }
3397f4a2713aSLionel Sambuc 
3398f4a2713aSLionel Sambuc /// Checks a regparm attribute, returning true if it is ill-formed and
3399f4a2713aSLionel Sambuc /// otherwise setting numParams to the appropriate value.
CheckRegparmAttr(const AttributeList & Attr,unsigned & numParams)3400f4a2713aSLionel Sambuc bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) {
3401f4a2713aSLionel Sambuc   if (Attr.isInvalid())
3402f4a2713aSLionel Sambuc     return true;
3403f4a2713aSLionel Sambuc 
3404f4a2713aSLionel Sambuc   if (!checkAttributeNumArgs(*this, Attr, 1)) {
3405f4a2713aSLionel Sambuc     Attr.setInvalid();
3406f4a2713aSLionel Sambuc     return true;
3407f4a2713aSLionel Sambuc   }
3408f4a2713aSLionel Sambuc 
3409*0a6a1f1dSLionel Sambuc   uint32_t NP;
3410f4a2713aSLionel Sambuc   Expr *NumParamsExpr = Attr.getArgAsExpr(0);
3411*0a6a1f1dSLionel Sambuc   if (!checkUInt32Argument(*this, Attr, NumParamsExpr, NP)) {
3412f4a2713aSLionel Sambuc     Attr.setInvalid();
3413f4a2713aSLionel Sambuc     return true;
3414f4a2713aSLionel Sambuc   }
3415f4a2713aSLionel Sambuc 
3416f4a2713aSLionel Sambuc   if (Context.getTargetInfo().getRegParmMax() == 0) {
3417f4a2713aSLionel Sambuc     Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform)
3418f4a2713aSLionel Sambuc       << NumParamsExpr->getSourceRange();
3419f4a2713aSLionel Sambuc     Attr.setInvalid();
3420f4a2713aSLionel Sambuc     return true;
3421f4a2713aSLionel Sambuc   }
3422f4a2713aSLionel Sambuc 
3423*0a6a1f1dSLionel Sambuc   numParams = NP;
3424f4a2713aSLionel Sambuc   if (numParams > Context.getTargetInfo().getRegParmMax()) {
3425f4a2713aSLionel Sambuc     Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number)
3426f4a2713aSLionel Sambuc       << Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange();
3427f4a2713aSLionel Sambuc     Attr.setInvalid();
3428f4a2713aSLionel Sambuc     return true;
3429f4a2713aSLionel Sambuc   }
3430f4a2713aSLionel Sambuc 
3431f4a2713aSLionel Sambuc   return false;
3432f4a2713aSLionel Sambuc }
3433f4a2713aSLionel Sambuc 
handleLaunchBoundsAttr(Sema & S,Decl * D,const AttributeList & Attr)3434*0a6a1f1dSLionel Sambuc static void handleLaunchBoundsAttr(Sema &S, Decl *D,
3435*0a6a1f1dSLionel Sambuc                                    const AttributeList &Attr) {
3436*0a6a1f1dSLionel Sambuc   uint32_t MaxThreads, MinBlocks = 0;
3437*0a6a1f1dSLionel Sambuc   if (!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), MaxThreads, 1))
3438f4a2713aSLionel Sambuc     return;
3439*0a6a1f1dSLionel Sambuc   if (Attr.getNumArgs() > 1 && !checkUInt32Argument(S, Attr,
3440*0a6a1f1dSLionel Sambuc                                                     Attr.getArgAsExpr(1),
3441*0a6a1f1dSLionel Sambuc                                                     MinBlocks, 2))
3442f4a2713aSLionel Sambuc     return;
3443f4a2713aSLionel Sambuc 
3444f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
3445f4a2713aSLionel Sambuc               CUDALaunchBoundsAttr(Attr.getRange(), S.Context,
3446*0a6a1f1dSLionel Sambuc                                   MaxThreads, MinBlocks,
3447f4a2713aSLionel Sambuc                                   Attr.getAttributeSpellingListIndex()));
3448f4a2713aSLionel Sambuc }
3449f4a2713aSLionel Sambuc 
handleArgumentWithTypeTagAttr(Sema & S,Decl * D,const AttributeList & Attr)3450f4a2713aSLionel Sambuc static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
3451f4a2713aSLionel Sambuc                                           const AttributeList &Attr) {
3452f4a2713aSLionel Sambuc   if (!Attr.isArgIdent(0)) {
3453f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
3454f4a2713aSLionel Sambuc       << Attr.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier;
3455f4a2713aSLionel Sambuc     return;
3456f4a2713aSLionel Sambuc   }
3457f4a2713aSLionel Sambuc 
3458f4a2713aSLionel Sambuc   if (!checkAttributeNumArgs(S, Attr, 3))
3459f4a2713aSLionel Sambuc     return;
3460f4a2713aSLionel Sambuc 
3461f4a2713aSLionel Sambuc   IdentifierInfo *ArgumentKind = Attr.getArgAsIdent(0)->Ident;
3462f4a2713aSLionel Sambuc 
3463f4a2713aSLionel Sambuc   if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {
3464f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
3465f4a2713aSLionel Sambuc       << Attr.getName() << ExpectedFunctionOrMethod;
3466f4a2713aSLionel Sambuc     return;
3467f4a2713aSLionel Sambuc   }
3468f4a2713aSLionel Sambuc 
3469f4a2713aSLionel Sambuc   uint64_t ArgumentIdx;
3470*0a6a1f1dSLionel Sambuc   if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 2, Attr.getArgAsExpr(1),
3471*0a6a1f1dSLionel Sambuc                                            ArgumentIdx))
3472f4a2713aSLionel Sambuc     return;
3473f4a2713aSLionel Sambuc 
3474f4a2713aSLionel Sambuc   uint64_t TypeTagIdx;
3475*0a6a1f1dSLionel Sambuc   if (!checkFunctionOrMethodParameterIndex(S, D, Attr, 3, Attr.getArgAsExpr(2),
3476*0a6a1f1dSLionel Sambuc                                            TypeTagIdx))
3477f4a2713aSLionel Sambuc     return;
3478f4a2713aSLionel Sambuc 
3479*0a6a1f1dSLionel Sambuc   bool IsPointer = (Attr.getName()->getName() == "pointer_with_type_tag");
3480f4a2713aSLionel Sambuc   if (IsPointer) {
3481f4a2713aSLionel Sambuc     // Ensure that buffer has a pointer type.
3482*0a6a1f1dSLionel Sambuc     QualType BufferTy = getFunctionOrMethodParamType(D, ArgumentIdx);
3483f4a2713aSLionel Sambuc     if (!BufferTy->isPointerType()) {
3484f4a2713aSLionel Sambuc       S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only)
3485f4a2713aSLionel Sambuc         << Attr.getName();
3486f4a2713aSLionel Sambuc     }
3487f4a2713aSLionel Sambuc   }
3488f4a2713aSLionel Sambuc 
3489f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
3490f4a2713aSLionel Sambuc              ArgumentWithTypeTagAttr(Attr.getRange(), S.Context, ArgumentKind,
3491f4a2713aSLionel Sambuc                                      ArgumentIdx, TypeTagIdx, IsPointer,
3492f4a2713aSLionel Sambuc                                      Attr.getAttributeSpellingListIndex()));
3493f4a2713aSLionel Sambuc }
3494f4a2713aSLionel Sambuc 
handleTypeTagForDatatypeAttr(Sema & S,Decl * D,const AttributeList & Attr)3495f4a2713aSLionel Sambuc static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
3496f4a2713aSLionel Sambuc                                          const AttributeList &Attr) {
3497f4a2713aSLionel Sambuc   if (!Attr.isArgIdent(0)) {
3498f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
3499f4a2713aSLionel Sambuc       << Attr.getName() << 1 << AANT_ArgumentIdentifier;
3500f4a2713aSLionel Sambuc     return;
3501f4a2713aSLionel Sambuc   }
3502f4a2713aSLionel Sambuc 
3503f4a2713aSLionel Sambuc   if (!checkAttributeNumArgs(S, Attr, 1))
3504f4a2713aSLionel Sambuc     return;
3505f4a2713aSLionel Sambuc 
3506*0a6a1f1dSLionel Sambuc   if (!isa<VarDecl>(D)) {
3507*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
3508*0a6a1f1dSLionel Sambuc       << Attr.getName() << ExpectedVariable;
3509*0a6a1f1dSLionel Sambuc     return;
3510*0a6a1f1dSLionel Sambuc   }
3511*0a6a1f1dSLionel Sambuc 
3512f4a2713aSLionel Sambuc   IdentifierInfo *PointerKind = Attr.getArgAsIdent(0)->Ident;
3513*0a6a1f1dSLionel Sambuc   TypeSourceInfo *MatchingCTypeLoc = nullptr;
3514f4a2713aSLionel Sambuc   S.GetTypeFromParser(Attr.getMatchingCType(), &MatchingCTypeLoc);
3515f4a2713aSLionel Sambuc   assert(MatchingCTypeLoc && "no type source info for attribute argument");
3516f4a2713aSLionel Sambuc 
3517f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
3518f4a2713aSLionel Sambuc              TypeTagForDatatypeAttr(Attr.getRange(), S.Context, PointerKind,
3519f4a2713aSLionel Sambuc                                     MatchingCTypeLoc,
3520f4a2713aSLionel Sambuc                                     Attr.getLayoutCompatible(),
3521f4a2713aSLionel Sambuc                                     Attr.getMustBeNull(),
3522f4a2713aSLionel Sambuc                                     Attr.getAttributeSpellingListIndex()));
3523f4a2713aSLionel Sambuc }
3524f4a2713aSLionel Sambuc 
3525f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
3526f4a2713aSLionel Sambuc // Checker-specific attribute handlers.
3527f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
3528f4a2713aSLionel Sambuc 
isValidSubjectOfNSReturnsRetainedAttribute(QualType type)3529*0a6a1f1dSLionel Sambuc static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType type) {
3530*0a6a1f1dSLionel Sambuc   return type->isDependentType() ||
3531*0a6a1f1dSLionel Sambuc          type->isObjCRetainableType();
3532*0a6a1f1dSLionel Sambuc }
3533*0a6a1f1dSLionel Sambuc 
isValidSubjectOfNSAttribute(Sema & S,QualType type)3534f4a2713aSLionel Sambuc static bool isValidSubjectOfNSAttribute(Sema &S, QualType type) {
3535f4a2713aSLionel Sambuc   return type->isDependentType() ||
3536f4a2713aSLionel Sambuc          type->isObjCObjectPointerType() ||
3537f4a2713aSLionel Sambuc          S.Context.isObjCNSObjectType(type);
3538f4a2713aSLionel Sambuc }
isValidSubjectOfCFAttribute(Sema & S,QualType type)3539f4a2713aSLionel Sambuc static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) {
3540f4a2713aSLionel Sambuc   return type->isDependentType() ||
3541f4a2713aSLionel Sambuc          type->isPointerType() ||
3542f4a2713aSLionel Sambuc          isValidSubjectOfNSAttribute(S, type);
3543f4a2713aSLionel Sambuc }
3544f4a2713aSLionel Sambuc 
handleNSConsumedAttr(Sema & S,Decl * D,const AttributeList & Attr)3545f4a2713aSLionel Sambuc static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
3546*0a6a1f1dSLionel Sambuc   ParmVarDecl *param = cast<ParmVarDecl>(D);
3547f4a2713aSLionel Sambuc   bool typeOK, cf;
3548*0a6a1f1dSLionel Sambuc 
3549f4a2713aSLionel Sambuc   if (Attr.getKind() == AttributeList::AT_NSConsumed) {
3550f4a2713aSLionel Sambuc     typeOK = isValidSubjectOfNSAttribute(S, param->getType());
3551f4a2713aSLionel Sambuc     cf = false;
3552f4a2713aSLionel Sambuc   } else {
3553f4a2713aSLionel Sambuc     typeOK = isValidSubjectOfCFAttribute(S, param->getType());
3554f4a2713aSLionel Sambuc     cf = true;
3555f4a2713aSLionel Sambuc   }
3556f4a2713aSLionel Sambuc 
3557f4a2713aSLionel Sambuc   if (!typeOK) {
3558f4a2713aSLionel Sambuc     S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type)
3559f4a2713aSLionel Sambuc       << Attr.getRange() << Attr.getName() << cf;
3560f4a2713aSLionel Sambuc     return;
3561f4a2713aSLionel Sambuc   }
3562f4a2713aSLionel Sambuc 
3563f4a2713aSLionel Sambuc   if (cf)
3564f4a2713aSLionel Sambuc     param->addAttr(::new (S.Context)
3565f4a2713aSLionel Sambuc                    CFConsumedAttr(Attr.getRange(), S.Context,
3566f4a2713aSLionel Sambuc                                   Attr.getAttributeSpellingListIndex()));
3567f4a2713aSLionel Sambuc   else
3568f4a2713aSLionel Sambuc     param->addAttr(::new (S.Context)
3569f4a2713aSLionel Sambuc                    NSConsumedAttr(Attr.getRange(), S.Context,
3570f4a2713aSLionel Sambuc                                   Attr.getAttributeSpellingListIndex()));
3571f4a2713aSLionel Sambuc }
3572f4a2713aSLionel Sambuc 
handleNSReturnsRetainedAttr(Sema & S,Decl * D,const AttributeList & Attr)3573f4a2713aSLionel Sambuc static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,
3574f4a2713aSLionel Sambuc                                         const AttributeList &Attr) {
3575f4a2713aSLionel Sambuc 
3576f4a2713aSLionel Sambuc   QualType returnType;
3577f4a2713aSLionel Sambuc 
3578f4a2713aSLionel Sambuc   if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
3579*0a6a1f1dSLionel Sambuc     returnType = MD->getReturnType();
3580f4a2713aSLionel Sambuc   else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) &&
3581f4a2713aSLionel Sambuc            (Attr.getKind() == AttributeList::AT_NSReturnsRetained))
3582f4a2713aSLionel Sambuc     return; // ignore: was handled as a type attribute
3583f4a2713aSLionel Sambuc   else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
3584f4a2713aSLionel Sambuc     returnType = PD->getType();
3585f4a2713aSLionel Sambuc   else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
3586*0a6a1f1dSLionel Sambuc     returnType = FD->getReturnType();
3587f4a2713aSLionel Sambuc   else {
3588f4a2713aSLionel Sambuc     S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
3589f4a2713aSLionel Sambuc         << Attr.getRange() << Attr.getName()
3590f4a2713aSLionel Sambuc         << ExpectedFunctionOrMethod;
3591f4a2713aSLionel Sambuc     return;
3592f4a2713aSLionel Sambuc   }
3593f4a2713aSLionel Sambuc 
3594f4a2713aSLionel Sambuc   bool typeOK;
3595f4a2713aSLionel Sambuc   bool cf;
3596f4a2713aSLionel Sambuc   switch (Attr.getKind()) {
3597f4a2713aSLionel Sambuc   default: llvm_unreachable("invalid ownership attribute");
3598f4a2713aSLionel Sambuc   case AttributeList::AT_NSReturnsRetained:
3599*0a6a1f1dSLionel Sambuc     typeOK = isValidSubjectOfNSReturnsRetainedAttribute(returnType);
3600*0a6a1f1dSLionel Sambuc     cf = false;
3601*0a6a1f1dSLionel Sambuc     break;
3602*0a6a1f1dSLionel Sambuc 
3603*0a6a1f1dSLionel Sambuc   case AttributeList::AT_NSReturnsAutoreleased:
3604f4a2713aSLionel Sambuc   case AttributeList::AT_NSReturnsNotRetained:
3605f4a2713aSLionel Sambuc     typeOK = isValidSubjectOfNSAttribute(S, returnType);
3606f4a2713aSLionel Sambuc     cf = false;
3607f4a2713aSLionel Sambuc     break;
3608f4a2713aSLionel Sambuc 
3609f4a2713aSLionel Sambuc   case AttributeList::AT_CFReturnsRetained:
3610f4a2713aSLionel Sambuc   case AttributeList::AT_CFReturnsNotRetained:
3611f4a2713aSLionel Sambuc     typeOK = isValidSubjectOfCFAttribute(S, returnType);
3612f4a2713aSLionel Sambuc     cf = true;
3613f4a2713aSLionel Sambuc     break;
3614f4a2713aSLionel Sambuc   }
3615f4a2713aSLionel Sambuc 
3616f4a2713aSLionel Sambuc   if (!typeOK) {
3617f4a2713aSLionel Sambuc     S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
3618f4a2713aSLionel Sambuc       << Attr.getRange() << Attr.getName() << isa<ObjCMethodDecl>(D) << cf;
3619f4a2713aSLionel Sambuc     return;
3620f4a2713aSLionel Sambuc   }
3621f4a2713aSLionel Sambuc 
3622f4a2713aSLionel Sambuc   switch (Attr.getKind()) {
3623f4a2713aSLionel Sambuc     default:
3624f4a2713aSLionel Sambuc       llvm_unreachable("invalid ownership attribute");
3625f4a2713aSLionel Sambuc     case AttributeList::AT_NSReturnsAutoreleased:
3626*0a6a1f1dSLionel Sambuc       D->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(
3627*0a6a1f1dSLionel Sambuc           Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
3628f4a2713aSLionel Sambuc       return;
3629f4a2713aSLionel Sambuc     case AttributeList::AT_CFReturnsNotRetained:
3630*0a6a1f1dSLionel Sambuc       D->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(
3631*0a6a1f1dSLionel Sambuc           Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
3632f4a2713aSLionel Sambuc       return;
3633f4a2713aSLionel Sambuc     case AttributeList::AT_NSReturnsNotRetained:
3634*0a6a1f1dSLionel Sambuc       D->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(
3635*0a6a1f1dSLionel Sambuc           Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
3636f4a2713aSLionel Sambuc       return;
3637f4a2713aSLionel Sambuc     case AttributeList::AT_CFReturnsRetained:
3638*0a6a1f1dSLionel Sambuc       D->addAttr(::new (S.Context) CFReturnsRetainedAttr(
3639*0a6a1f1dSLionel Sambuc           Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
3640f4a2713aSLionel Sambuc       return;
3641f4a2713aSLionel Sambuc     case AttributeList::AT_NSReturnsRetained:
3642*0a6a1f1dSLionel Sambuc       D->addAttr(::new (S.Context) NSReturnsRetainedAttr(
3643*0a6a1f1dSLionel Sambuc           Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
3644f4a2713aSLionel Sambuc       return;
3645f4a2713aSLionel Sambuc   };
3646f4a2713aSLionel Sambuc }
3647f4a2713aSLionel Sambuc 
handleObjCReturnsInnerPointerAttr(Sema & S,Decl * D,const AttributeList & attr)3648f4a2713aSLionel Sambuc static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
3649f4a2713aSLionel Sambuc                                               const AttributeList &attr) {
3650f4a2713aSLionel Sambuc   const int EP_ObjCMethod = 1;
3651f4a2713aSLionel Sambuc   const int EP_ObjCProperty = 2;
3652f4a2713aSLionel Sambuc 
3653f4a2713aSLionel Sambuc   SourceLocation loc = attr.getLoc();
3654f4a2713aSLionel Sambuc   QualType resultType;
3655*0a6a1f1dSLionel Sambuc   if (isa<ObjCMethodDecl>(D))
3656*0a6a1f1dSLionel Sambuc     resultType = cast<ObjCMethodDecl>(D)->getReturnType();
3657f4a2713aSLionel Sambuc   else
3658*0a6a1f1dSLionel Sambuc     resultType = cast<ObjCPropertyDecl>(D)->getType();
3659f4a2713aSLionel Sambuc 
3660f4a2713aSLionel Sambuc   if (!resultType->isReferenceType() &&
3661f4a2713aSLionel Sambuc       (!resultType->isPointerType() || resultType->isObjCRetainableType())) {
3662f4a2713aSLionel Sambuc     S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
3663f4a2713aSLionel Sambuc       << SourceRange(loc)
3664*0a6a1f1dSLionel Sambuc     << attr.getName()
3665*0a6a1f1dSLionel Sambuc     << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty)
3666f4a2713aSLionel Sambuc     << /*non-retainable pointer*/ 2;
3667f4a2713aSLionel Sambuc 
3668f4a2713aSLionel Sambuc     // Drop the attribute.
3669f4a2713aSLionel Sambuc     return;
3670f4a2713aSLionel Sambuc   }
3671f4a2713aSLionel Sambuc 
3672*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context) ObjCReturnsInnerPointerAttr(
3673*0a6a1f1dSLionel Sambuc       attr.getRange(), S.Context, attr.getAttributeSpellingListIndex()));
3674f4a2713aSLionel Sambuc }
3675f4a2713aSLionel Sambuc 
handleObjCRequiresSuperAttr(Sema & S,Decl * D,const AttributeList & attr)3676f4a2713aSLionel Sambuc static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
3677f4a2713aSLionel Sambuc                                         const AttributeList &attr) {
3678*0a6a1f1dSLionel Sambuc   ObjCMethodDecl *method = cast<ObjCMethodDecl>(D);
3679f4a2713aSLionel Sambuc 
3680f4a2713aSLionel Sambuc   DeclContext *DC = method->getDeclContext();
3681f4a2713aSLionel Sambuc   if (const ObjCProtocolDecl *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
3682f4a2713aSLionel Sambuc     S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
3683f4a2713aSLionel Sambuc     << attr.getName() << 0;
3684f4a2713aSLionel Sambuc     S.Diag(PDecl->getLocation(), diag::note_protocol_decl);
3685f4a2713aSLionel Sambuc     return;
3686f4a2713aSLionel Sambuc   }
3687f4a2713aSLionel Sambuc   if (method->getMethodFamily() == OMF_dealloc) {
3688f4a2713aSLionel Sambuc     S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
3689f4a2713aSLionel Sambuc     << attr.getName() << 1;
3690f4a2713aSLionel Sambuc     return;
3691f4a2713aSLionel Sambuc   }
3692f4a2713aSLionel Sambuc 
3693f4a2713aSLionel Sambuc   method->addAttr(::new (S.Context)
3694f4a2713aSLionel Sambuc                   ObjCRequiresSuperAttr(attr.getRange(), S.Context,
3695f4a2713aSLionel Sambuc                                         attr.getAttributeSpellingListIndex()));
3696f4a2713aSLionel Sambuc }
3697f4a2713aSLionel Sambuc 
handleCFAuditedTransferAttr(Sema & S,Decl * D,const AttributeList & Attr)3698*0a6a1f1dSLionel Sambuc static void handleCFAuditedTransferAttr(Sema &S, Decl *D,
3699f4a2713aSLionel Sambuc                                         const AttributeList &Attr) {
3700*0a6a1f1dSLionel Sambuc   if (checkAttrMutualExclusion<CFUnknownTransferAttr>(S, D, Attr))
3701*0a6a1f1dSLionel Sambuc     return;
3702f4a2713aSLionel Sambuc 
3703f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
3704*0a6a1f1dSLionel Sambuc              CFAuditedTransferAttr(Attr.getRange(), S.Context,
3705*0a6a1f1dSLionel Sambuc                                    Attr.getAttributeSpellingListIndex()));
3706*0a6a1f1dSLionel Sambuc }
3707*0a6a1f1dSLionel Sambuc 
handleCFUnknownTransferAttr(Sema & S,Decl * D,const AttributeList & Attr)3708*0a6a1f1dSLionel Sambuc static void handleCFUnknownTransferAttr(Sema &S, Decl *D,
3709*0a6a1f1dSLionel Sambuc                                         const AttributeList &Attr) {
3710*0a6a1f1dSLionel Sambuc   if (checkAttrMutualExclusion<CFAuditedTransferAttr>(S, D, Attr))
3711*0a6a1f1dSLionel Sambuc     return;
3712*0a6a1f1dSLionel Sambuc 
3713*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context)
3714*0a6a1f1dSLionel Sambuc              CFUnknownTransferAttr(Attr.getRange(), S.Context,
3715f4a2713aSLionel Sambuc              Attr.getAttributeSpellingListIndex()));
3716f4a2713aSLionel Sambuc }
3717f4a2713aSLionel Sambuc 
handleObjCBridgeAttr(Sema & S,Scope * Sc,Decl * D,const AttributeList & Attr)3718f4a2713aSLionel Sambuc static void handleObjCBridgeAttr(Sema &S, Scope *Sc, Decl *D,
3719f4a2713aSLionel Sambuc                                 const AttributeList &Attr) {
3720*0a6a1f1dSLionel Sambuc   IdentifierLoc * Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
3721f4a2713aSLionel Sambuc 
3722f4a2713aSLionel Sambuc   if (!Parm) {
3723*0a6a1f1dSLionel Sambuc     S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
3724f4a2713aSLionel Sambuc     return;
3725f4a2713aSLionel Sambuc   }
3726f4a2713aSLionel Sambuc 
3727f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
3728*0a6a1f1dSLionel Sambuc              ObjCBridgeAttr(Attr.getRange(), S.Context, Parm->Ident,
3729*0a6a1f1dSLionel Sambuc                            Attr.getAttributeSpellingListIndex()));
3730*0a6a1f1dSLionel Sambuc }
3731*0a6a1f1dSLionel Sambuc 
handleObjCBridgeMutableAttr(Sema & S,Scope * Sc,Decl * D,const AttributeList & Attr)3732*0a6a1f1dSLionel Sambuc static void handleObjCBridgeMutableAttr(Sema &S, Scope *Sc, Decl *D,
3733*0a6a1f1dSLionel Sambuc                                         const AttributeList &Attr) {
3734*0a6a1f1dSLionel Sambuc   IdentifierLoc * Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : nullptr;
3735*0a6a1f1dSLionel Sambuc 
3736*0a6a1f1dSLionel Sambuc   if (!Parm) {
3737*0a6a1f1dSLionel Sambuc     S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
3738*0a6a1f1dSLionel Sambuc     return;
3739*0a6a1f1dSLionel Sambuc   }
3740*0a6a1f1dSLionel Sambuc 
3741*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context)
3742*0a6a1f1dSLionel Sambuc              ObjCBridgeMutableAttr(Attr.getRange(), S.Context, Parm->Ident,
3743*0a6a1f1dSLionel Sambuc                             Attr.getAttributeSpellingListIndex()));
3744*0a6a1f1dSLionel Sambuc }
3745*0a6a1f1dSLionel Sambuc 
handleObjCBridgeRelatedAttr(Sema & S,Scope * Sc,Decl * D,const AttributeList & Attr)3746*0a6a1f1dSLionel Sambuc static void handleObjCBridgeRelatedAttr(Sema &S, Scope *Sc, Decl *D,
3747*0a6a1f1dSLionel Sambuc                                  const AttributeList &Attr) {
3748*0a6a1f1dSLionel Sambuc   IdentifierInfo *RelatedClass =
3749*0a6a1f1dSLionel Sambuc     Attr.isArgIdent(0) ? Attr.getArgAsIdent(0)->Ident : nullptr;
3750*0a6a1f1dSLionel Sambuc   if (!RelatedClass) {
3751*0a6a1f1dSLionel Sambuc     S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
3752*0a6a1f1dSLionel Sambuc     return;
3753*0a6a1f1dSLionel Sambuc   }
3754*0a6a1f1dSLionel Sambuc   IdentifierInfo *ClassMethod =
3755*0a6a1f1dSLionel Sambuc     Attr.getArgAsIdent(1) ? Attr.getArgAsIdent(1)->Ident : nullptr;
3756*0a6a1f1dSLionel Sambuc   IdentifierInfo *InstanceMethod =
3757*0a6a1f1dSLionel Sambuc     Attr.getArgAsIdent(2) ? Attr.getArgAsIdent(2)->Ident : nullptr;
3758*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context)
3759*0a6a1f1dSLionel Sambuc              ObjCBridgeRelatedAttr(Attr.getRange(), S.Context, RelatedClass,
3760*0a6a1f1dSLionel Sambuc                                    ClassMethod, InstanceMethod,
3761*0a6a1f1dSLionel Sambuc                                    Attr.getAttributeSpellingListIndex()));
3762*0a6a1f1dSLionel Sambuc }
3763*0a6a1f1dSLionel Sambuc 
handleObjCDesignatedInitializer(Sema & S,Decl * D,const AttributeList & Attr)3764*0a6a1f1dSLionel Sambuc static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
3765*0a6a1f1dSLionel Sambuc                                             const AttributeList &Attr) {
3766*0a6a1f1dSLionel Sambuc   ObjCInterfaceDecl *IFace;
3767*0a6a1f1dSLionel Sambuc   if (ObjCCategoryDecl *CatDecl =
3768*0a6a1f1dSLionel Sambuc           dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
3769*0a6a1f1dSLionel Sambuc     IFace = CatDecl->getClassInterface();
3770*0a6a1f1dSLionel Sambuc   else
3771*0a6a1f1dSLionel Sambuc     IFace = cast<ObjCInterfaceDecl>(D->getDeclContext());
3772*0a6a1f1dSLionel Sambuc   IFace->setHasDesignatedInitializers();
3773*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context)
3774*0a6a1f1dSLionel Sambuc                   ObjCDesignatedInitializerAttr(Attr.getRange(), S.Context,
3775*0a6a1f1dSLionel Sambuc                                          Attr.getAttributeSpellingListIndex()));
3776*0a6a1f1dSLionel Sambuc }
3777*0a6a1f1dSLionel Sambuc 
handleObjCRuntimeName(Sema & S,Decl * D,const AttributeList & Attr)3778*0a6a1f1dSLionel Sambuc static void handleObjCRuntimeName(Sema &S, Decl *D,
3779*0a6a1f1dSLionel Sambuc                                   const AttributeList &Attr) {
3780*0a6a1f1dSLionel Sambuc   StringRef MetaDataName;
3781*0a6a1f1dSLionel Sambuc   if (!S.checkStringLiteralArgumentAttr(Attr, 0, MetaDataName))
3782*0a6a1f1dSLionel Sambuc     return;
3783*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context)
3784*0a6a1f1dSLionel Sambuc              ObjCRuntimeNameAttr(Attr.getRange(), S.Context,
3785*0a6a1f1dSLionel Sambuc                                  MetaDataName,
3786f4a2713aSLionel Sambuc                                  Attr.getAttributeSpellingListIndex()));
3787f4a2713aSLionel Sambuc }
3788f4a2713aSLionel Sambuc 
handleObjCOwnershipAttr(Sema & S,Decl * D,const AttributeList & Attr)3789f4a2713aSLionel Sambuc static void handleObjCOwnershipAttr(Sema &S, Decl *D,
3790f4a2713aSLionel Sambuc                                     const AttributeList &Attr) {
3791f4a2713aSLionel Sambuc   if (hasDeclarator(D)) return;
3792f4a2713aSLionel Sambuc 
3793f4a2713aSLionel Sambuc   S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
3794f4a2713aSLionel Sambuc     << Attr.getRange() << Attr.getName() << ExpectedVariable;
3795f4a2713aSLionel Sambuc }
3796f4a2713aSLionel Sambuc 
handleObjCPreciseLifetimeAttr(Sema & S,Decl * D,const AttributeList & Attr)3797f4a2713aSLionel Sambuc static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
3798f4a2713aSLionel Sambuc                                           const AttributeList &Attr) {
3799f4a2713aSLionel Sambuc   ValueDecl *vd = cast<ValueDecl>(D);
3800f4a2713aSLionel Sambuc   QualType type = vd->getType();
3801f4a2713aSLionel Sambuc 
3802f4a2713aSLionel Sambuc   if (!type->isDependentType() &&
3803f4a2713aSLionel Sambuc       !type->isObjCLifetimeType()) {
3804f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_objc_precise_lifetime_bad_type)
3805f4a2713aSLionel Sambuc       << type;
3806f4a2713aSLionel Sambuc     return;
3807f4a2713aSLionel Sambuc   }
3808f4a2713aSLionel Sambuc 
3809f4a2713aSLionel Sambuc   Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime();
3810f4a2713aSLionel Sambuc 
3811f4a2713aSLionel Sambuc   // If we have no lifetime yet, check the lifetime we're presumably
3812f4a2713aSLionel Sambuc   // going to infer.
3813f4a2713aSLionel Sambuc   if (lifetime == Qualifiers::OCL_None && !type->isDependentType())
3814f4a2713aSLionel Sambuc     lifetime = type->getObjCARCImplicitLifetime();
3815f4a2713aSLionel Sambuc 
3816f4a2713aSLionel Sambuc   switch (lifetime) {
3817f4a2713aSLionel Sambuc   case Qualifiers::OCL_None:
3818f4a2713aSLionel Sambuc     assert(type->isDependentType() &&
3819f4a2713aSLionel Sambuc            "didn't infer lifetime for non-dependent type?");
3820f4a2713aSLionel Sambuc     break;
3821f4a2713aSLionel Sambuc 
3822f4a2713aSLionel Sambuc   case Qualifiers::OCL_Weak:   // meaningful
3823f4a2713aSLionel Sambuc   case Qualifiers::OCL_Strong: // meaningful
3824f4a2713aSLionel Sambuc     break;
3825f4a2713aSLionel Sambuc 
3826f4a2713aSLionel Sambuc   case Qualifiers::OCL_ExplicitNone:
3827f4a2713aSLionel Sambuc   case Qualifiers::OCL_Autoreleasing:
3828f4a2713aSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_objc_precise_lifetime_meaningless)
3829f4a2713aSLionel Sambuc       << (lifetime == Qualifiers::OCL_Autoreleasing);
3830f4a2713aSLionel Sambuc     break;
3831f4a2713aSLionel Sambuc   }
3832f4a2713aSLionel Sambuc 
3833f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
3834f4a2713aSLionel Sambuc              ObjCPreciseLifetimeAttr(Attr.getRange(), S.Context,
3835f4a2713aSLionel Sambuc                                      Attr.getAttributeSpellingListIndex()));
3836f4a2713aSLionel Sambuc }
3837f4a2713aSLionel Sambuc 
3838f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
3839f4a2713aSLionel Sambuc // Microsoft specific attribute handlers.
3840f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
3841f4a2713aSLionel Sambuc 
handleUuidAttr(Sema & S,Decl * D,const AttributeList & Attr)3842*0a6a1f1dSLionel Sambuc static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
3843*0a6a1f1dSLionel Sambuc   if (!S.LangOpts.CPlusPlus) {
3844*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
3845*0a6a1f1dSLionel Sambuc       << Attr.getName() << AttributeLangSupport::C;
3846*0a6a1f1dSLionel Sambuc     return;
3847f4a2713aSLionel Sambuc   }
3848f4a2713aSLionel Sambuc 
3849*0a6a1f1dSLionel Sambuc   if (!isa<CXXRecordDecl>(D)) {
3850*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
3851*0a6a1f1dSLionel Sambuc       << Attr.getName() << ExpectedClass;
3852f4a2713aSLionel Sambuc     return;
3853*0a6a1f1dSLionel Sambuc   }
3854f4a2713aSLionel Sambuc 
3855f4a2713aSLionel Sambuc   StringRef StrRef;
3856f4a2713aSLionel Sambuc   SourceLocation LiteralLoc;
3857f4a2713aSLionel Sambuc   if (!S.checkStringLiteralArgumentAttr(Attr, 0, StrRef, &LiteralLoc))
3858f4a2713aSLionel Sambuc     return;
3859f4a2713aSLionel Sambuc 
3860f4a2713aSLionel Sambuc   // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or
3861f4a2713aSLionel Sambuc   // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}", normalize to the former.
3862f4a2713aSLionel Sambuc   if (StrRef.size() == 38 && StrRef.front() == '{' && StrRef.back() == '}')
3863f4a2713aSLionel Sambuc     StrRef = StrRef.drop_front().drop_back();
3864f4a2713aSLionel Sambuc 
3865f4a2713aSLionel Sambuc   // Validate GUID length.
3866f4a2713aSLionel Sambuc   if (StrRef.size() != 36) {
3867f4a2713aSLionel Sambuc     S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);
3868f4a2713aSLionel Sambuc     return;
3869f4a2713aSLionel Sambuc   }
3870f4a2713aSLionel Sambuc 
3871f4a2713aSLionel Sambuc   for (unsigned i = 0; i < 36; ++i) {
3872f4a2713aSLionel Sambuc     if (i == 8 || i == 13 || i == 18 || i == 23) {
3873f4a2713aSLionel Sambuc       if (StrRef[i] != '-') {
3874f4a2713aSLionel Sambuc         S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);
3875f4a2713aSLionel Sambuc         return;
3876f4a2713aSLionel Sambuc       }
3877f4a2713aSLionel Sambuc     } else if (!isHexDigit(StrRef[i])) {
3878f4a2713aSLionel Sambuc       S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);
3879f4a2713aSLionel Sambuc       return;
3880f4a2713aSLionel Sambuc     }
3881f4a2713aSLionel Sambuc   }
3882f4a2713aSLionel Sambuc 
3883f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context) UuidAttr(Attr.getRange(), S.Context, StrRef,
3884f4a2713aSLionel Sambuc                                         Attr.getAttributeSpellingListIndex()));
3885f4a2713aSLionel Sambuc }
3886f4a2713aSLionel Sambuc 
handleMSInheritanceAttr(Sema & S,Decl * D,const AttributeList & Attr)3887*0a6a1f1dSLionel Sambuc static void handleMSInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
3888*0a6a1f1dSLionel Sambuc   if (!S.LangOpts.CPlusPlus) {
3889*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
3890*0a6a1f1dSLionel Sambuc       << Attr.getName() << AttributeLangSupport::C;
3891f4a2713aSLionel Sambuc     return;
3892*0a6a1f1dSLionel Sambuc   }
3893*0a6a1f1dSLionel Sambuc   MSInheritanceAttr *IA = S.mergeMSInheritanceAttr(
3894*0a6a1f1dSLionel Sambuc       D, Attr.getRange(), /*BestCase=*/true,
3895*0a6a1f1dSLionel Sambuc       Attr.getAttributeSpellingListIndex(),
3896*0a6a1f1dSLionel Sambuc       (MSInheritanceAttr::Spelling)Attr.getSemanticSpelling());
3897*0a6a1f1dSLionel Sambuc   if (IA)
3898*0a6a1f1dSLionel Sambuc     D->addAttr(IA);
3899f4a2713aSLionel Sambuc }
3900f4a2713aSLionel Sambuc 
handleDeclspecThreadAttr(Sema & S,Decl * D,const AttributeList & Attr)3901*0a6a1f1dSLionel Sambuc static void handleDeclspecThreadAttr(Sema &S, Decl *D,
3902*0a6a1f1dSLionel Sambuc                                      const AttributeList &Attr) {
3903*0a6a1f1dSLionel Sambuc   VarDecl *VD = cast<VarDecl>(D);
3904*0a6a1f1dSLionel Sambuc   if (!S.Context.getTargetInfo().isTLSSupported()) {
3905*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_thread_unsupported);
3906f4a2713aSLionel Sambuc     return;
3907*0a6a1f1dSLionel Sambuc   }
3908*0a6a1f1dSLionel Sambuc   if (VD->getTSCSpec() != TSCS_unspecified) {
3909*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_declspec_thread_on_thread_variable);
3910*0a6a1f1dSLionel Sambuc     return;
3911*0a6a1f1dSLionel Sambuc   }
3912*0a6a1f1dSLionel Sambuc   if (VD->hasLocalStorage()) {
3913*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_thread_non_global) << "__declspec(thread)";
3914*0a6a1f1dSLionel Sambuc     return;
3915*0a6a1f1dSLionel Sambuc   }
3916*0a6a1f1dSLionel Sambuc   VD->addAttr(::new (S.Context) ThreadAttr(
3917*0a6a1f1dSLionel Sambuc       Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
3918f4a2713aSLionel Sambuc }
3919f4a2713aSLionel Sambuc 
handleARMInterruptAttr(Sema & S,Decl * D,const AttributeList & Attr)3920*0a6a1f1dSLionel Sambuc static void handleARMInterruptAttr(Sema &S, Decl *D,
3921*0a6a1f1dSLionel Sambuc                                    const AttributeList &Attr) {
3922*0a6a1f1dSLionel Sambuc   // Check the attribute arguments.
3923*0a6a1f1dSLionel Sambuc   if (Attr.getNumArgs() > 1) {
3924*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
3925*0a6a1f1dSLionel Sambuc       << Attr.getName() << 1;
3926f4a2713aSLionel Sambuc     return;
3927*0a6a1f1dSLionel Sambuc   }
3928*0a6a1f1dSLionel Sambuc 
3929*0a6a1f1dSLionel Sambuc   StringRef Str;
3930*0a6a1f1dSLionel Sambuc   SourceLocation ArgLoc;
3931*0a6a1f1dSLionel Sambuc 
3932*0a6a1f1dSLionel Sambuc   if (Attr.getNumArgs() == 0)
3933*0a6a1f1dSLionel Sambuc     Str = "";
3934*0a6a1f1dSLionel Sambuc   else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc))
3935*0a6a1f1dSLionel Sambuc     return;
3936*0a6a1f1dSLionel Sambuc 
3937*0a6a1f1dSLionel Sambuc   ARMInterruptAttr::InterruptType Kind;
3938*0a6a1f1dSLionel Sambuc   if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
3939*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
3940*0a6a1f1dSLionel Sambuc       << Attr.getName() << Str << ArgLoc;
3941*0a6a1f1dSLionel Sambuc     return;
3942*0a6a1f1dSLionel Sambuc   }
3943*0a6a1f1dSLionel Sambuc 
3944*0a6a1f1dSLionel Sambuc   unsigned Index = Attr.getAttributeSpellingListIndex();
3945f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
3946*0a6a1f1dSLionel Sambuc              ARMInterruptAttr(Attr.getLoc(), S.Context, Kind, Index));
3947*0a6a1f1dSLionel Sambuc }
3948*0a6a1f1dSLionel Sambuc 
handleMSP430InterruptAttr(Sema & S,Decl * D,const AttributeList & Attr)3949*0a6a1f1dSLionel Sambuc static void handleMSP430InterruptAttr(Sema &S, Decl *D,
3950*0a6a1f1dSLionel Sambuc                                       const AttributeList &Attr) {
3951*0a6a1f1dSLionel Sambuc   if (!checkAttributeNumArgs(S, Attr, 1))
3952*0a6a1f1dSLionel Sambuc     return;
3953*0a6a1f1dSLionel Sambuc 
3954*0a6a1f1dSLionel Sambuc   if (!Attr.isArgExpr(0)) {
3955*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
3956*0a6a1f1dSLionel Sambuc       << AANT_ArgumentIntegerConstant;
3957*0a6a1f1dSLionel Sambuc     return;
3958*0a6a1f1dSLionel Sambuc   }
3959*0a6a1f1dSLionel Sambuc 
3960*0a6a1f1dSLionel Sambuc   // FIXME: Check for decl - it should be void ()(void).
3961*0a6a1f1dSLionel Sambuc 
3962*0a6a1f1dSLionel Sambuc   Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
3963*0a6a1f1dSLionel Sambuc   llvm::APSInt NumParams(32);
3964*0a6a1f1dSLionel Sambuc   if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
3965*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
3966*0a6a1f1dSLionel Sambuc       << Attr.getName() << AANT_ArgumentIntegerConstant
3967*0a6a1f1dSLionel Sambuc       << NumParamsExpr->getSourceRange();
3968*0a6a1f1dSLionel Sambuc     return;
3969*0a6a1f1dSLionel Sambuc   }
3970*0a6a1f1dSLionel Sambuc 
3971*0a6a1f1dSLionel Sambuc   unsigned Num = NumParams.getLimitedValue(255);
3972*0a6a1f1dSLionel Sambuc   if ((Num & 1) || Num > 30) {
3973*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
3974*0a6a1f1dSLionel Sambuc       << Attr.getName() << (int)NumParams.getSExtValue()
3975*0a6a1f1dSLionel Sambuc       << NumParamsExpr->getSourceRange();
3976*0a6a1f1dSLionel Sambuc     return;
3977*0a6a1f1dSLionel Sambuc   }
3978*0a6a1f1dSLionel Sambuc 
3979*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context)
3980*0a6a1f1dSLionel Sambuc               MSP430InterruptAttr(Attr.getLoc(), S.Context, Num,
3981*0a6a1f1dSLionel Sambuc                                   Attr.getAttributeSpellingListIndex()));
3982*0a6a1f1dSLionel Sambuc   D->addAttr(UsedAttr::CreateImplicit(S.Context));
3983*0a6a1f1dSLionel Sambuc }
3984*0a6a1f1dSLionel Sambuc 
handleInterruptAttr(Sema & S,Decl * D,const AttributeList & Attr)3985*0a6a1f1dSLionel Sambuc static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
3986*0a6a1f1dSLionel Sambuc   // Dispatch the interrupt attribute based on the current target.
3987*0a6a1f1dSLionel Sambuc   if (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::msp430)
3988*0a6a1f1dSLionel Sambuc     handleMSP430InterruptAttr(S, D, Attr);
3989*0a6a1f1dSLionel Sambuc   else
3990*0a6a1f1dSLionel Sambuc     handleARMInterruptAttr(S, D, Attr);
3991*0a6a1f1dSLionel Sambuc }
3992*0a6a1f1dSLionel Sambuc 
handleAMDGPUNumVGPRAttr(Sema & S,Decl * D,const AttributeList & Attr)3993*0a6a1f1dSLionel Sambuc static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D,
3994*0a6a1f1dSLionel Sambuc                                     const AttributeList &Attr) {
3995*0a6a1f1dSLionel Sambuc   uint32_t NumRegs;
3996*0a6a1f1dSLionel Sambuc   Expr *NumRegsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
3997*0a6a1f1dSLionel Sambuc   if (!checkUInt32Argument(S, Attr, NumRegsExpr, NumRegs))
3998*0a6a1f1dSLionel Sambuc     return;
3999*0a6a1f1dSLionel Sambuc 
4000*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context)
4001*0a6a1f1dSLionel Sambuc              AMDGPUNumVGPRAttr(Attr.getLoc(), S.Context,
4002*0a6a1f1dSLionel Sambuc                                NumRegs,
4003f4a2713aSLionel Sambuc                                Attr.getAttributeSpellingListIndex()));
4004f4a2713aSLionel Sambuc }
4005f4a2713aSLionel Sambuc 
handleAMDGPUNumSGPRAttr(Sema & S,Decl * D,const AttributeList & Attr)4006*0a6a1f1dSLionel Sambuc static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D,
4007*0a6a1f1dSLionel Sambuc                                     const AttributeList &Attr) {
4008*0a6a1f1dSLionel Sambuc   uint32_t NumRegs;
4009*0a6a1f1dSLionel Sambuc   Expr *NumRegsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
4010*0a6a1f1dSLionel Sambuc   if (!checkUInt32Argument(S, Attr, NumRegsExpr, NumRegs))
4011f4a2713aSLionel Sambuc     return;
4012*0a6a1f1dSLionel Sambuc 
4013f4a2713aSLionel Sambuc   D->addAttr(::new (S.Context)
4014*0a6a1f1dSLionel Sambuc              AMDGPUNumSGPRAttr(Attr.getLoc(), S.Context,
4015*0a6a1f1dSLionel Sambuc                                NumRegs,
4016f4a2713aSLionel Sambuc                                Attr.getAttributeSpellingListIndex()));
4017f4a2713aSLionel Sambuc }
4018f4a2713aSLionel Sambuc 
handleX86ForceAlignArgPointerAttr(Sema & S,Decl * D,const AttributeList & Attr)4019*0a6a1f1dSLionel Sambuc static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D,
4020*0a6a1f1dSLionel Sambuc                                               const AttributeList& Attr) {
4021*0a6a1f1dSLionel Sambuc   // If we try to apply it to a function pointer, don't warn, but don't
4022*0a6a1f1dSLionel Sambuc   // do anything, either. It doesn't matter anyway, because there's nothing
4023*0a6a1f1dSLionel Sambuc   // special about calling a force_align_arg_pointer function.
4024*0a6a1f1dSLionel Sambuc   ValueDecl *VD = dyn_cast<ValueDecl>(D);
4025*0a6a1f1dSLionel Sambuc   if (VD && VD->getType()->isFunctionPointerType())
4026*0a6a1f1dSLionel Sambuc     return;
4027*0a6a1f1dSLionel Sambuc   // Also don't warn on function pointer typedefs.
4028*0a6a1f1dSLionel Sambuc   TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
4029*0a6a1f1dSLionel Sambuc   if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
4030*0a6a1f1dSLionel Sambuc     TD->getUnderlyingType()->isFunctionType()))
4031*0a6a1f1dSLionel Sambuc     return;
4032*0a6a1f1dSLionel Sambuc   // Attribute can only be applied to function types.
4033*0a6a1f1dSLionel Sambuc   if (!isa<FunctionDecl>(D)) {
4034*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
4035*0a6a1f1dSLionel Sambuc       << Attr.getName() << /* function */0;
4036*0a6a1f1dSLionel Sambuc     return;
4037*0a6a1f1dSLionel Sambuc   }
4038*0a6a1f1dSLionel Sambuc 
4039*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context)
4040*0a6a1f1dSLionel Sambuc               X86ForceAlignArgPointerAttr(Attr.getRange(), S.Context,
4041*0a6a1f1dSLionel Sambuc                                         Attr.getAttributeSpellingListIndex()));
4042*0a6a1f1dSLionel Sambuc }
4043*0a6a1f1dSLionel Sambuc 
mergeDLLImportAttr(Decl * D,SourceRange Range,unsigned AttrSpellingListIndex)4044*0a6a1f1dSLionel Sambuc DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
4045*0a6a1f1dSLionel Sambuc                                         unsigned AttrSpellingListIndex) {
4046*0a6a1f1dSLionel Sambuc   if (D->hasAttr<DLLExportAttr>()) {
4047*0a6a1f1dSLionel Sambuc     Diag(Range.getBegin(), diag::warn_attribute_ignored) << "'dllimport'";
4048*0a6a1f1dSLionel Sambuc     return nullptr;
4049*0a6a1f1dSLionel Sambuc   }
4050*0a6a1f1dSLionel Sambuc 
4051*0a6a1f1dSLionel Sambuc   if (D->hasAttr<DLLImportAttr>())
4052*0a6a1f1dSLionel Sambuc     return nullptr;
4053*0a6a1f1dSLionel Sambuc 
4054*0a6a1f1dSLionel Sambuc   return ::new (Context) DLLImportAttr(Range, Context, AttrSpellingListIndex);
4055*0a6a1f1dSLionel Sambuc }
4056*0a6a1f1dSLionel Sambuc 
mergeDLLExportAttr(Decl * D,SourceRange Range,unsigned AttrSpellingListIndex)4057*0a6a1f1dSLionel Sambuc DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range,
4058*0a6a1f1dSLionel Sambuc                                         unsigned AttrSpellingListIndex) {
4059*0a6a1f1dSLionel Sambuc   if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
4060*0a6a1f1dSLionel Sambuc     Diag(Import->getLocation(), diag::warn_attribute_ignored) << Import;
4061*0a6a1f1dSLionel Sambuc     D->dropAttr<DLLImportAttr>();
4062*0a6a1f1dSLionel Sambuc   }
4063*0a6a1f1dSLionel Sambuc 
4064*0a6a1f1dSLionel Sambuc   if (D->hasAttr<DLLExportAttr>())
4065*0a6a1f1dSLionel Sambuc     return nullptr;
4066*0a6a1f1dSLionel Sambuc 
4067*0a6a1f1dSLionel Sambuc   return ::new (Context) DLLExportAttr(Range, Context, AttrSpellingListIndex);
4068*0a6a1f1dSLionel Sambuc }
4069*0a6a1f1dSLionel Sambuc 
handleDLLAttr(Sema & S,Decl * D,const AttributeList & A)4070*0a6a1f1dSLionel Sambuc static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) {
4071*0a6a1f1dSLionel Sambuc   if (isa<ClassTemplatePartialSpecializationDecl>(D) &&
4072*0a6a1f1dSLionel Sambuc       S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
4073*0a6a1f1dSLionel Sambuc     S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored)
4074*0a6a1f1dSLionel Sambuc         << A.getName();
4075*0a6a1f1dSLionel Sambuc     return;
4076*0a6a1f1dSLionel Sambuc   }
4077*0a6a1f1dSLionel Sambuc 
4078*0a6a1f1dSLionel Sambuc   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
4079*0a6a1f1dSLionel Sambuc     if (FD->isInlined() && A.getKind() == AttributeList::AT_DLLImport &&
4080*0a6a1f1dSLionel Sambuc         !S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
4081*0a6a1f1dSLionel Sambuc       // MinGW doesn't allow dllimport on inline functions.
4082*0a6a1f1dSLionel Sambuc       S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline)
4083*0a6a1f1dSLionel Sambuc           << A.getName();
4084*0a6a1f1dSLionel Sambuc       return;
4085*0a6a1f1dSLionel Sambuc     }
4086*0a6a1f1dSLionel Sambuc   }
4087*0a6a1f1dSLionel Sambuc 
4088*0a6a1f1dSLionel Sambuc   unsigned Index = A.getAttributeSpellingListIndex();
4089*0a6a1f1dSLionel Sambuc   Attr *NewAttr = A.getKind() == AttributeList::AT_DLLExport
4090*0a6a1f1dSLionel Sambuc                       ? (Attr *)S.mergeDLLExportAttr(D, A.getRange(), Index)
4091*0a6a1f1dSLionel Sambuc                       : (Attr *)S.mergeDLLImportAttr(D, A.getRange(), Index);
4092*0a6a1f1dSLionel Sambuc   if (NewAttr)
4093*0a6a1f1dSLionel Sambuc     D->addAttr(NewAttr);
4094*0a6a1f1dSLionel Sambuc }
4095*0a6a1f1dSLionel Sambuc 
4096*0a6a1f1dSLionel Sambuc MSInheritanceAttr *
mergeMSInheritanceAttr(Decl * D,SourceRange Range,bool BestCase,unsigned AttrSpellingListIndex,MSInheritanceAttr::Spelling SemanticSpelling)4097*0a6a1f1dSLionel Sambuc Sema::mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase,
4098*0a6a1f1dSLionel Sambuc                              unsigned AttrSpellingListIndex,
4099*0a6a1f1dSLionel Sambuc                              MSInheritanceAttr::Spelling SemanticSpelling) {
4100*0a6a1f1dSLionel Sambuc   if (MSInheritanceAttr *IA = D->getAttr<MSInheritanceAttr>()) {
4101*0a6a1f1dSLionel Sambuc     if (IA->getSemanticSpelling() == SemanticSpelling)
4102*0a6a1f1dSLionel Sambuc       return nullptr;
4103*0a6a1f1dSLionel Sambuc     Diag(IA->getLocation(), diag::err_mismatched_ms_inheritance)
4104*0a6a1f1dSLionel Sambuc         << 1 /*previous declaration*/;
4105*0a6a1f1dSLionel Sambuc     Diag(Range.getBegin(), diag::note_previous_ms_inheritance);
4106*0a6a1f1dSLionel Sambuc     D->dropAttr<MSInheritanceAttr>();
4107*0a6a1f1dSLionel Sambuc   }
4108*0a6a1f1dSLionel Sambuc 
4109*0a6a1f1dSLionel Sambuc   CXXRecordDecl *RD = cast<CXXRecordDecl>(D);
4110*0a6a1f1dSLionel Sambuc   if (RD->hasDefinition()) {
4111*0a6a1f1dSLionel Sambuc     if (checkMSInheritanceAttrOnDefinition(RD, Range, BestCase,
4112*0a6a1f1dSLionel Sambuc                                            SemanticSpelling)) {
4113*0a6a1f1dSLionel Sambuc       return nullptr;
4114*0a6a1f1dSLionel Sambuc     }
4115*0a6a1f1dSLionel Sambuc   } else {
4116*0a6a1f1dSLionel Sambuc     if (isa<ClassTemplatePartialSpecializationDecl>(RD)) {
4117*0a6a1f1dSLionel Sambuc       Diag(Range.getBegin(), diag::warn_ignored_ms_inheritance)
4118*0a6a1f1dSLionel Sambuc           << 1 /*partial specialization*/;
4119*0a6a1f1dSLionel Sambuc       return nullptr;
4120*0a6a1f1dSLionel Sambuc     }
4121*0a6a1f1dSLionel Sambuc     if (RD->getDescribedClassTemplate()) {
4122*0a6a1f1dSLionel Sambuc       Diag(Range.getBegin(), diag::warn_ignored_ms_inheritance)
4123*0a6a1f1dSLionel Sambuc           << 0 /*primary template*/;
4124*0a6a1f1dSLionel Sambuc       return nullptr;
4125*0a6a1f1dSLionel Sambuc     }
4126*0a6a1f1dSLionel Sambuc   }
4127*0a6a1f1dSLionel Sambuc 
4128*0a6a1f1dSLionel Sambuc   return ::new (Context)
4129*0a6a1f1dSLionel Sambuc       MSInheritanceAttr(Range, Context, BestCase, AttrSpellingListIndex);
4130*0a6a1f1dSLionel Sambuc }
4131*0a6a1f1dSLionel Sambuc 
handleCapabilityAttr(Sema & S,Decl * D,const AttributeList & Attr)4132*0a6a1f1dSLionel Sambuc static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
4133*0a6a1f1dSLionel Sambuc   // The capability attributes take a single string parameter for the name of
4134*0a6a1f1dSLionel Sambuc   // the capability they represent. The lockable attribute does not take any
4135*0a6a1f1dSLionel Sambuc   // parameters. However, semantically, both attributes represent the same
4136*0a6a1f1dSLionel Sambuc   // concept, and so they use the same semantic attribute. Eventually, the
4137*0a6a1f1dSLionel Sambuc   // lockable attribute will be removed.
4138*0a6a1f1dSLionel Sambuc   //
4139*0a6a1f1dSLionel Sambuc   // For backward compatibility, any capability which has no specified string
4140*0a6a1f1dSLionel Sambuc   // literal will be considered a "mutex."
4141*0a6a1f1dSLionel Sambuc   StringRef N("mutex");
4142*0a6a1f1dSLionel Sambuc   SourceLocation LiteralLoc;
4143*0a6a1f1dSLionel Sambuc   if (Attr.getKind() == AttributeList::AT_Capability &&
4144*0a6a1f1dSLionel Sambuc       !S.checkStringLiteralArgumentAttr(Attr, 0, N, &LiteralLoc))
4145*0a6a1f1dSLionel Sambuc     return;
4146*0a6a1f1dSLionel Sambuc 
4147*0a6a1f1dSLionel Sambuc   // Currently, there are only two names allowed for a capability: role and
4148*0a6a1f1dSLionel Sambuc   // mutex (case insensitive). Diagnose other capability names.
4149*0a6a1f1dSLionel Sambuc   if (!N.equals_lower("mutex") && !N.equals_lower("role"))
4150*0a6a1f1dSLionel Sambuc     S.Diag(LiteralLoc, diag::warn_invalid_capability_name) << N;
4151*0a6a1f1dSLionel Sambuc 
4152*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context) CapabilityAttr(Attr.getRange(), S.Context, N,
4153*0a6a1f1dSLionel Sambuc                                         Attr.getAttributeSpellingListIndex()));
4154*0a6a1f1dSLionel Sambuc }
4155*0a6a1f1dSLionel Sambuc 
handleAssertCapabilityAttr(Sema & S,Decl * D,const AttributeList & Attr)4156*0a6a1f1dSLionel Sambuc static void handleAssertCapabilityAttr(Sema &S, Decl *D,
4157*0a6a1f1dSLionel Sambuc                                        const AttributeList &Attr) {
4158*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context) AssertCapabilityAttr(Attr.getRange(), S.Context,
4159*0a6a1f1dSLionel Sambuc                                                     Attr.getArgAsExpr(0),
4160*0a6a1f1dSLionel Sambuc                                         Attr.getAttributeSpellingListIndex()));
4161*0a6a1f1dSLionel Sambuc }
4162*0a6a1f1dSLionel Sambuc 
handleAcquireCapabilityAttr(Sema & S,Decl * D,const AttributeList & Attr)4163*0a6a1f1dSLionel Sambuc static void handleAcquireCapabilityAttr(Sema &S, Decl *D,
4164*0a6a1f1dSLionel Sambuc                                         const AttributeList &Attr) {
4165*0a6a1f1dSLionel Sambuc   SmallVector<Expr*, 1> Args;
4166*0a6a1f1dSLionel Sambuc   if (!checkLockFunAttrCommon(S, D, Attr, Args))
4167*0a6a1f1dSLionel Sambuc     return;
4168*0a6a1f1dSLionel Sambuc 
4169*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context) AcquireCapabilityAttr(Attr.getRange(),
4170*0a6a1f1dSLionel Sambuc                                                      S.Context,
4171*0a6a1f1dSLionel Sambuc                                                      Args.data(), Args.size(),
4172*0a6a1f1dSLionel Sambuc                                         Attr.getAttributeSpellingListIndex()));
4173*0a6a1f1dSLionel Sambuc }
4174*0a6a1f1dSLionel Sambuc 
handleTryAcquireCapabilityAttr(Sema & S,Decl * D,const AttributeList & Attr)4175*0a6a1f1dSLionel Sambuc static void handleTryAcquireCapabilityAttr(Sema &S, Decl *D,
4176*0a6a1f1dSLionel Sambuc                                            const AttributeList &Attr) {
4177*0a6a1f1dSLionel Sambuc   SmallVector<Expr*, 2> Args;
4178*0a6a1f1dSLionel Sambuc   if (!checkTryLockFunAttrCommon(S, D, Attr, Args))
4179*0a6a1f1dSLionel Sambuc     return;
4180*0a6a1f1dSLionel Sambuc 
4181*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context) TryAcquireCapabilityAttr(Attr.getRange(),
4182*0a6a1f1dSLionel Sambuc                                                         S.Context,
4183*0a6a1f1dSLionel Sambuc                                                         Attr.getArgAsExpr(0),
4184*0a6a1f1dSLionel Sambuc                                                         Args.data(),
4185*0a6a1f1dSLionel Sambuc                                                         Args.size(),
4186*0a6a1f1dSLionel Sambuc                                         Attr.getAttributeSpellingListIndex()));
4187*0a6a1f1dSLionel Sambuc }
4188*0a6a1f1dSLionel Sambuc 
handleReleaseCapabilityAttr(Sema & S,Decl * D,const AttributeList & Attr)4189*0a6a1f1dSLionel Sambuc static void handleReleaseCapabilityAttr(Sema &S, Decl *D,
4190*0a6a1f1dSLionel Sambuc                                         const AttributeList &Attr) {
4191*0a6a1f1dSLionel Sambuc   // Check that all arguments are lockable objects.
4192*0a6a1f1dSLionel Sambuc   SmallVector<Expr *, 1> Args;
4193*0a6a1f1dSLionel Sambuc   checkAttrArgsAreCapabilityObjs(S, D, Attr, Args, 0, true);
4194*0a6a1f1dSLionel Sambuc 
4195*0a6a1f1dSLionel Sambuc   D->addAttr(::new (S.Context) ReleaseCapabilityAttr(
4196*0a6a1f1dSLionel Sambuc       Attr.getRange(), S.Context, Args.data(), Args.size(),
4197*0a6a1f1dSLionel Sambuc       Attr.getAttributeSpellingListIndex()));
4198*0a6a1f1dSLionel Sambuc }
4199*0a6a1f1dSLionel Sambuc 
handleRequiresCapabilityAttr(Sema & S,Decl * D,const AttributeList & Attr)4200*0a6a1f1dSLionel Sambuc static void handleRequiresCapabilityAttr(Sema &S, Decl *D,
4201*0a6a1f1dSLionel Sambuc                                          const AttributeList &Attr) {
4202*0a6a1f1dSLionel Sambuc   if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
4203*0a6a1f1dSLionel Sambuc     return;
4204*0a6a1f1dSLionel Sambuc 
4205*0a6a1f1dSLionel Sambuc   // check that all arguments are lockable objects
4206*0a6a1f1dSLionel Sambuc   SmallVector<Expr*, 1> Args;
4207*0a6a1f1dSLionel Sambuc   checkAttrArgsAreCapabilityObjs(S, D, Attr, Args);
4208*0a6a1f1dSLionel Sambuc   if (Args.empty())
4209*0a6a1f1dSLionel Sambuc     return;
4210*0a6a1f1dSLionel Sambuc 
4211*0a6a1f1dSLionel Sambuc   RequiresCapabilityAttr *RCA = ::new (S.Context)
4212*0a6a1f1dSLionel Sambuc     RequiresCapabilityAttr(Attr.getRange(), S.Context, Args.data(),
4213*0a6a1f1dSLionel Sambuc                            Args.size(), Attr.getAttributeSpellingListIndex());
4214*0a6a1f1dSLionel Sambuc 
4215*0a6a1f1dSLionel Sambuc   D->addAttr(RCA);
4216*0a6a1f1dSLionel Sambuc }
4217*0a6a1f1dSLionel Sambuc 
handleDeprecatedAttr(Sema & S,Decl * D,const AttributeList & Attr)4218*0a6a1f1dSLionel Sambuc static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
4219*0a6a1f1dSLionel Sambuc   if (auto *NSD = dyn_cast<NamespaceDecl>(D)) {
4220*0a6a1f1dSLionel Sambuc     if (NSD->isAnonymousNamespace()) {
4221*0a6a1f1dSLionel Sambuc       S.Diag(Attr.getLoc(), diag::warn_deprecated_anonymous_namespace);
4222*0a6a1f1dSLionel Sambuc       // Do not want to attach the attribute to the namespace because that will
4223*0a6a1f1dSLionel Sambuc       // cause confusing diagnostic reports for uses of declarations within the
4224*0a6a1f1dSLionel Sambuc       // namespace.
4225*0a6a1f1dSLionel Sambuc       return;
4226*0a6a1f1dSLionel Sambuc     }
4227*0a6a1f1dSLionel Sambuc   }
4228*0a6a1f1dSLionel Sambuc   handleAttrWithMessage<DeprecatedAttr>(S, D, Attr);
4229*0a6a1f1dSLionel Sambuc }
4230*0a6a1f1dSLionel Sambuc 
4231f4a2713aSLionel Sambuc /// Handles semantic checking for features that are common to all attributes,
4232f4a2713aSLionel Sambuc /// such as checking whether a parameter was properly specified, or the correct
4233f4a2713aSLionel Sambuc /// number of arguments were passed, etc.
handleCommonAttributeFeatures(Sema & S,Scope * scope,Decl * D,const AttributeList & Attr)4234f4a2713aSLionel Sambuc static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D,
4235f4a2713aSLionel Sambuc                                           const AttributeList &Attr) {
4236f4a2713aSLionel Sambuc   // Several attributes carry different semantics than the parsing requires, so
4237f4a2713aSLionel Sambuc   // those are opted out of the common handling.
4238f4a2713aSLionel Sambuc   //
4239f4a2713aSLionel Sambuc   // We also bail on unknown and ignored attributes because those are handled
4240f4a2713aSLionel Sambuc   // as part of the target-specific handling logic.
4241f4a2713aSLionel Sambuc   if (Attr.hasCustomParsing() ||
4242*0a6a1f1dSLionel Sambuc       Attr.getKind() == AttributeList::UnknownAttribute)
4243f4a2713aSLionel Sambuc     return false;
4244f4a2713aSLionel Sambuc 
4245*0a6a1f1dSLionel Sambuc   // Check whether the attribute requires specific language extensions to be
4246*0a6a1f1dSLionel Sambuc   // enabled.
4247*0a6a1f1dSLionel Sambuc   if (!Attr.diagnoseLangOpts(S))
4248*0a6a1f1dSLionel Sambuc     return true;
4249*0a6a1f1dSLionel Sambuc 
4250*0a6a1f1dSLionel Sambuc   if (Attr.getMinArgs() == Attr.getMaxArgs()) {
4251f4a2713aSLionel Sambuc     // If there are no optional arguments, then checking for the argument count
4252f4a2713aSLionel Sambuc     // is trivial.
4253*0a6a1f1dSLionel Sambuc     if (!checkAttributeNumArgs(S, Attr, Attr.getMinArgs()))
4254f4a2713aSLionel Sambuc       return true;
4255*0a6a1f1dSLionel Sambuc   } else {
4256*0a6a1f1dSLionel Sambuc     // There are optional arguments, so checking is slightly more involved.
4257*0a6a1f1dSLionel Sambuc     if (Attr.getMinArgs() &&
4258*0a6a1f1dSLionel Sambuc         !checkAttributeAtLeastNumArgs(S, Attr, Attr.getMinArgs()))
4259*0a6a1f1dSLionel Sambuc       return true;
4260*0a6a1f1dSLionel Sambuc     else if (!Attr.hasVariadicArg() && Attr.getMaxArgs() &&
4261*0a6a1f1dSLionel Sambuc              !checkAttributeAtMostNumArgs(S, Attr, Attr.getMaxArgs()))
4262*0a6a1f1dSLionel Sambuc       return true;
4263*0a6a1f1dSLionel Sambuc   }
4264*0a6a1f1dSLionel Sambuc 
4265*0a6a1f1dSLionel Sambuc   // Check whether the attribute appertains to the given subject.
4266*0a6a1f1dSLionel Sambuc   if (!Attr.diagnoseAppertainsTo(S, D))
4267*0a6a1f1dSLionel Sambuc     return true;
4268*0a6a1f1dSLionel Sambuc 
4269f4a2713aSLionel Sambuc   return false;
4270f4a2713aSLionel Sambuc }
4271f4a2713aSLionel Sambuc 
4272f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
4273f4a2713aSLionel Sambuc // Top Level Sema Entry Points
4274f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
4275f4a2713aSLionel Sambuc 
4276f4a2713aSLionel Sambuc /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
4277f4a2713aSLionel Sambuc /// the attribute applies to decls.  If the attribute is a type attribute, just
4278f4a2713aSLionel Sambuc /// silently ignore it if a GNU attribute.
ProcessDeclAttribute(Sema & S,Scope * scope,Decl * D,const AttributeList & Attr,bool IncludeCXX11Attributes)4279f4a2713aSLionel Sambuc static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
4280f4a2713aSLionel Sambuc                                  const AttributeList &Attr,
4281f4a2713aSLionel Sambuc                                  bool IncludeCXX11Attributes) {
4282*0a6a1f1dSLionel Sambuc   if (Attr.isInvalid() || Attr.getKind() == AttributeList::IgnoredAttribute)
4283f4a2713aSLionel Sambuc     return;
4284f4a2713aSLionel Sambuc 
4285f4a2713aSLionel Sambuc   // Ignore C++11 attributes on declarator chunks: they appertain to the type
4286f4a2713aSLionel Sambuc   // instead.
4287f4a2713aSLionel Sambuc   if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes)
4288f4a2713aSLionel Sambuc     return;
4289f4a2713aSLionel Sambuc 
4290*0a6a1f1dSLionel Sambuc   // Unknown attributes are automatically warned on. Target-specific attributes
4291*0a6a1f1dSLionel Sambuc   // which do not apply to the current target architecture are treated as
4292*0a6a1f1dSLionel Sambuc   // though they were unknown attributes.
4293*0a6a1f1dSLionel Sambuc   if (Attr.getKind() == AttributeList::UnknownAttribute ||
4294*0a6a1f1dSLionel Sambuc       !Attr.existsInTarget(S.Context.getTargetInfo().getTriple())) {
4295*0a6a1f1dSLionel Sambuc     S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute()
4296*0a6a1f1dSLionel Sambuc                               ? diag::warn_unhandled_ms_attribute_ignored
4297*0a6a1f1dSLionel Sambuc                               : diag::warn_unknown_attribute_ignored)
4298*0a6a1f1dSLionel Sambuc         << Attr.getName();
4299*0a6a1f1dSLionel Sambuc     return;
4300*0a6a1f1dSLionel Sambuc   }
4301*0a6a1f1dSLionel Sambuc 
4302f4a2713aSLionel Sambuc   if (handleCommonAttributeFeatures(S, scope, D, Attr))
4303f4a2713aSLionel Sambuc     return;
4304f4a2713aSLionel Sambuc 
4305f4a2713aSLionel Sambuc   switch (Attr.getKind()) {
4306*0a6a1f1dSLionel Sambuc   default:
4307*0a6a1f1dSLionel Sambuc     // Type attributes are handled elsewhere; silently move on.
4308*0a6a1f1dSLionel Sambuc     assert(Attr.isTypeAttr() && "Non-type attribute not handled");
4309f4a2713aSLionel Sambuc     break;
4310*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Interrupt:
4311*0a6a1f1dSLionel Sambuc     handleInterruptAttr(S, D, Attr);
4312*0a6a1f1dSLionel Sambuc     break;
4313*0a6a1f1dSLionel Sambuc   case AttributeList::AT_X86ForceAlignArgPointer:
4314*0a6a1f1dSLionel Sambuc     handleX86ForceAlignArgPointerAttr(S, D, Attr);
4315*0a6a1f1dSLionel Sambuc     break;
4316*0a6a1f1dSLionel Sambuc   case AttributeList::AT_DLLExport:
4317*0a6a1f1dSLionel Sambuc   case AttributeList::AT_DLLImport:
4318*0a6a1f1dSLionel Sambuc     handleDLLAttr(S, D, Attr);
4319*0a6a1f1dSLionel Sambuc     break;
4320*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Mips16:
4321*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<Mips16Attr>(S, D, Attr);
4322*0a6a1f1dSLionel Sambuc     break;
4323*0a6a1f1dSLionel Sambuc   case AttributeList::AT_NoMips16:
4324*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<NoMips16Attr>(S, D, Attr);
4325*0a6a1f1dSLionel Sambuc     break;
4326*0a6a1f1dSLionel Sambuc   case AttributeList::AT_AMDGPUNumVGPR:
4327*0a6a1f1dSLionel Sambuc     handleAMDGPUNumVGPRAttr(S, D, Attr);
4328*0a6a1f1dSLionel Sambuc     break;
4329*0a6a1f1dSLionel Sambuc   case AttributeList::AT_AMDGPUNumSGPR:
4330*0a6a1f1dSLionel Sambuc     handleAMDGPUNumSGPRAttr(S, D, Attr);
4331*0a6a1f1dSLionel Sambuc     break;
4332*0a6a1f1dSLionel Sambuc   case AttributeList::AT_IBAction:
4333*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<IBActionAttr>(S, D, Attr);
4334*0a6a1f1dSLionel Sambuc     break;
4335*0a6a1f1dSLionel Sambuc   case AttributeList::AT_IBOutlet:
4336*0a6a1f1dSLionel Sambuc     handleIBOutlet(S, D, Attr);
4337*0a6a1f1dSLionel Sambuc     break;
4338*0a6a1f1dSLionel Sambuc   case AttributeList::AT_IBOutletCollection:
4339*0a6a1f1dSLionel Sambuc     handleIBOutletCollection(S, D, Attr);
4340*0a6a1f1dSLionel Sambuc     break;
4341*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Alias:
4342*0a6a1f1dSLionel Sambuc     handleAliasAttr(S, D, Attr);
4343*0a6a1f1dSLionel Sambuc     break;
4344*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Aligned:
4345*0a6a1f1dSLionel Sambuc     handleAlignedAttr(S, D, Attr);
4346*0a6a1f1dSLionel Sambuc     break;
4347*0a6a1f1dSLionel Sambuc   case AttributeList::AT_AlignValue:
4348*0a6a1f1dSLionel Sambuc     handleAlignValueAttr(S, D, Attr);
4349*0a6a1f1dSLionel Sambuc     break;
4350f4a2713aSLionel Sambuc   case AttributeList::AT_AlwaysInline:
4351*0a6a1f1dSLionel Sambuc     handleAlwaysInlineAttr(S, D, Attr);
4352*0a6a1f1dSLionel Sambuc     break;
4353f4a2713aSLionel Sambuc   case AttributeList::AT_AnalyzerNoReturn:
4354*0a6a1f1dSLionel Sambuc     handleAnalyzerNoReturnAttr(S, D, Attr);
4355*0a6a1f1dSLionel Sambuc     break;
4356*0a6a1f1dSLionel Sambuc   case AttributeList::AT_TLSModel:
4357*0a6a1f1dSLionel Sambuc     handleTLSModelAttr(S, D, Attr);
4358*0a6a1f1dSLionel Sambuc     break;
4359*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Annotate:
4360*0a6a1f1dSLionel Sambuc     handleAnnotateAttr(S, D, Attr);
4361*0a6a1f1dSLionel Sambuc     break;
4362*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Availability:
4363*0a6a1f1dSLionel Sambuc     handleAvailabilityAttr(S, D, Attr);
4364*0a6a1f1dSLionel Sambuc     break;
4365f4a2713aSLionel Sambuc   case AttributeList::AT_CarriesDependency:
4366f4a2713aSLionel Sambuc     handleDependencyAttr(S, scope, D, Attr);
4367f4a2713aSLionel Sambuc     break;
4368*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Common:
4369*0a6a1f1dSLionel Sambuc     handleCommonAttr(S, D, Attr);
4370*0a6a1f1dSLionel Sambuc     break;
4371*0a6a1f1dSLionel Sambuc   case AttributeList::AT_CUDAConstant:
4372*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<CUDAConstantAttr>(S, D, Attr);
4373*0a6a1f1dSLionel Sambuc     break;
4374*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Constructor:
4375*0a6a1f1dSLionel Sambuc     handleConstructorAttr(S, D, Attr);
4376*0a6a1f1dSLionel Sambuc     break;
4377f4a2713aSLionel Sambuc   case AttributeList::AT_CXX11NoReturn:
4378*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<CXX11NoReturnAttr>(S, D, Attr);
4379f4a2713aSLionel Sambuc     break;
4380f4a2713aSLionel Sambuc   case AttributeList::AT_Deprecated:
4381*0a6a1f1dSLionel Sambuc     handleDeprecatedAttr(S, D, Attr);
4382f4a2713aSLionel Sambuc     break;
4383*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Destructor:
4384*0a6a1f1dSLionel Sambuc     handleDestructorAttr(S, D, Attr);
4385*0a6a1f1dSLionel Sambuc     break;
4386*0a6a1f1dSLionel Sambuc   case AttributeList::AT_EnableIf:
4387*0a6a1f1dSLionel Sambuc     handleEnableIfAttr(S, D, Attr);
4388*0a6a1f1dSLionel Sambuc     break;
4389f4a2713aSLionel Sambuc   case AttributeList::AT_ExtVectorType:
4390f4a2713aSLionel Sambuc     handleExtVectorTypeAttr(S, scope, D, Attr);
4391f4a2713aSLionel Sambuc     break;
4392f4a2713aSLionel Sambuc   case AttributeList::AT_MinSize:
4393f4a2713aSLionel Sambuc     handleMinSizeAttr(S, D, Attr);
4394f4a2713aSLionel Sambuc     break;
4395*0a6a1f1dSLionel Sambuc   case AttributeList::AT_OptimizeNone:
4396*0a6a1f1dSLionel Sambuc     handleOptimizeNoneAttr(S, D, Attr);
4397*0a6a1f1dSLionel Sambuc     break;
4398*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Flatten:
4399*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<FlattenAttr>(S, D, Attr);
4400*0a6a1f1dSLionel Sambuc     break;
4401*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Format:
4402*0a6a1f1dSLionel Sambuc     handleFormatAttr(S, D, Attr);
4403*0a6a1f1dSLionel Sambuc     break;
4404*0a6a1f1dSLionel Sambuc   case AttributeList::AT_FormatArg:
4405*0a6a1f1dSLionel Sambuc     handleFormatArgAttr(S, D, Attr);
4406*0a6a1f1dSLionel Sambuc     break;
4407*0a6a1f1dSLionel Sambuc   case AttributeList::AT_CUDAGlobal:
4408*0a6a1f1dSLionel Sambuc     handleGlobalAttr(S, D, Attr);
4409*0a6a1f1dSLionel Sambuc     break;
4410*0a6a1f1dSLionel Sambuc   case AttributeList::AT_CUDADevice:
4411*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<CUDADeviceAttr>(S, D, Attr);
4412*0a6a1f1dSLionel Sambuc     break;
4413*0a6a1f1dSLionel Sambuc   case AttributeList::AT_CUDAHost:
4414*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<CUDAHostAttr>(S, D, Attr);
4415*0a6a1f1dSLionel Sambuc     break;
4416*0a6a1f1dSLionel Sambuc   case AttributeList::AT_GNUInline:
4417*0a6a1f1dSLionel Sambuc     handleGNUInlineAttr(S, D, Attr);
4418*0a6a1f1dSLionel Sambuc     break;
4419f4a2713aSLionel Sambuc   case AttributeList::AT_CUDALaunchBounds:
4420f4a2713aSLionel Sambuc     handleLaunchBoundsAttr(S, D, Attr);
4421f4a2713aSLionel Sambuc     break;
4422*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Malloc:
4423*0a6a1f1dSLionel Sambuc     handleMallocAttr(S, D, Attr);
4424*0a6a1f1dSLionel Sambuc     break;
4425*0a6a1f1dSLionel Sambuc   case AttributeList::AT_MayAlias:
4426*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<MayAliasAttr>(S, D, Attr);
4427*0a6a1f1dSLionel Sambuc     break;
4428*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Mode:
4429*0a6a1f1dSLionel Sambuc     handleModeAttr(S, D, Attr);
4430*0a6a1f1dSLionel Sambuc     break;
4431*0a6a1f1dSLionel Sambuc   case AttributeList::AT_NoCommon:
4432*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<NoCommonAttr>(S, D, Attr);
4433*0a6a1f1dSLionel Sambuc     break;
4434*0a6a1f1dSLionel Sambuc   case AttributeList::AT_NoSplitStack:
4435*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<NoSplitStackAttr>(S, D, Attr);
4436*0a6a1f1dSLionel Sambuc     break;
4437*0a6a1f1dSLionel Sambuc   case AttributeList::AT_NonNull:
4438*0a6a1f1dSLionel Sambuc     if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D))
4439*0a6a1f1dSLionel Sambuc       handleNonNullAttrParameter(S, PVD, Attr);
4440*0a6a1f1dSLionel Sambuc     else
4441*0a6a1f1dSLionel Sambuc       handleNonNullAttr(S, D, Attr);
4442*0a6a1f1dSLionel Sambuc     break;
4443*0a6a1f1dSLionel Sambuc   case AttributeList::AT_ReturnsNonNull:
4444*0a6a1f1dSLionel Sambuc     handleReturnsNonNullAttr(S, D, Attr);
4445*0a6a1f1dSLionel Sambuc     break;
4446*0a6a1f1dSLionel Sambuc   case AttributeList::AT_AssumeAligned:
4447*0a6a1f1dSLionel Sambuc     handleAssumeAlignedAttr(S, D, Attr);
4448*0a6a1f1dSLionel Sambuc     break;
4449*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Overloadable:
4450*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<OverloadableAttr>(S, D, Attr);
4451*0a6a1f1dSLionel Sambuc     break;
4452*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Ownership:
4453*0a6a1f1dSLionel Sambuc     handleOwnershipAttr(S, D, Attr);
4454*0a6a1f1dSLionel Sambuc     break;
4455*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Cold:
4456*0a6a1f1dSLionel Sambuc     handleColdAttr(S, D, Attr);
4457*0a6a1f1dSLionel Sambuc     break;
4458*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Hot:
4459*0a6a1f1dSLionel Sambuc     handleHotAttr(S, D, Attr);
4460*0a6a1f1dSLionel Sambuc     break;
4461*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Naked:
4462*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<NakedAttr>(S, D, Attr);
4463*0a6a1f1dSLionel Sambuc     break;
4464*0a6a1f1dSLionel Sambuc   case AttributeList::AT_NoReturn:
4465*0a6a1f1dSLionel Sambuc     handleNoReturnAttr(S, D, Attr);
4466*0a6a1f1dSLionel Sambuc     break;
4467*0a6a1f1dSLionel Sambuc   case AttributeList::AT_NoThrow:
4468*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<NoThrowAttr>(S, D, Attr);
4469*0a6a1f1dSLionel Sambuc     break;
4470*0a6a1f1dSLionel Sambuc   case AttributeList::AT_CUDAShared:
4471*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<CUDASharedAttr>(S, D, Attr);
4472*0a6a1f1dSLionel Sambuc     break;
4473*0a6a1f1dSLionel Sambuc   case AttributeList::AT_VecReturn:
4474*0a6a1f1dSLionel Sambuc     handleVecReturnAttr(S, D, Attr);
4475*0a6a1f1dSLionel Sambuc     break;
4476f4a2713aSLionel Sambuc 
4477f4a2713aSLionel Sambuc   case AttributeList::AT_ObjCOwnership:
4478*0a6a1f1dSLionel Sambuc     handleObjCOwnershipAttr(S, D, Attr);
4479*0a6a1f1dSLionel Sambuc     break;
4480f4a2713aSLionel Sambuc   case AttributeList::AT_ObjCPreciseLifetime:
4481*0a6a1f1dSLionel Sambuc     handleObjCPreciseLifetimeAttr(S, D, Attr);
4482*0a6a1f1dSLionel Sambuc     break;
4483f4a2713aSLionel Sambuc 
4484f4a2713aSLionel Sambuc   case AttributeList::AT_ObjCReturnsInnerPointer:
4485*0a6a1f1dSLionel Sambuc     handleObjCReturnsInnerPointerAttr(S, D, Attr);
4486*0a6a1f1dSLionel Sambuc     break;
4487f4a2713aSLionel Sambuc 
4488f4a2713aSLionel Sambuc   case AttributeList::AT_ObjCRequiresSuper:
4489*0a6a1f1dSLionel Sambuc     handleObjCRequiresSuperAttr(S, D, Attr);
4490*0a6a1f1dSLionel Sambuc     break;
4491f4a2713aSLionel Sambuc 
4492f4a2713aSLionel Sambuc   case AttributeList::AT_ObjCBridge:
4493*0a6a1f1dSLionel Sambuc     handleObjCBridgeAttr(S, scope, D, Attr);
4494*0a6a1f1dSLionel Sambuc     break;
4495*0a6a1f1dSLionel Sambuc 
4496*0a6a1f1dSLionel Sambuc   case AttributeList::AT_ObjCBridgeMutable:
4497*0a6a1f1dSLionel Sambuc     handleObjCBridgeMutableAttr(S, scope, D, Attr);
4498*0a6a1f1dSLionel Sambuc     break;
4499*0a6a1f1dSLionel Sambuc 
4500*0a6a1f1dSLionel Sambuc   case AttributeList::AT_ObjCBridgeRelated:
4501*0a6a1f1dSLionel Sambuc     handleObjCBridgeRelatedAttr(S, scope, D, Attr);
4502*0a6a1f1dSLionel Sambuc     break;
4503*0a6a1f1dSLionel Sambuc 
4504*0a6a1f1dSLionel Sambuc   case AttributeList::AT_ObjCDesignatedInitializer:
4505*0a6a1f1dSLionel Sambuc     handleObjCDesignatedInitializer(S, D, Attr);
4506*0a6a1f1dSLionel Sambuc     break;
4507*0a6a1f1dSLionel Sambuc 
4508*0a6a1f1dSLionel Sambuc   case AttributeList::AT_ObjCRuntimeName:
4509*0a6a1f1dSLionel Sambuc     handleObjCRuntimeName(S, D, Attr);
4510*0a6a1f1dSLionel Sambuc     break;
4511f4a2713aSLionel Sambuc 
4512f4a2713aSLionel Sambuc   case AttributeList::AT_CFAuditedTransfer:
4513*0a6a1f1dSLionel Sambuc     handleCFAuditedTransferAttr(S, D, Attr);
4514*0a6a1f1dSLionel Sambuc     break;
4515f4a2713aSLionel Sambuc   case AttributeList::AT_CFUnknownTransfer:
4516*0a6a1f1dSLionel Sambuc     handleCFUnknownTransferAttr(S, D, Attr);
4517*0a6a1f1dSLionel Sambuc     break;
4518f4a2713aSLionel Sambuc 
4519f4a2713aSLionel Sambuc   case AttributeList::AT_CFConsumed:
4520*0a6a1f1dSLionel Sambuc   case AttributeList::AT_NSConsumed:
4521*0a6a1f1dSLionel Sambuc     handleNSConsumedAttr(S, D, Attr);
4522*0a6a1f1dSLionel Sambuc     break;
4523f4a2713aSLionel Sambuc   case AttributeList::AT_NSConsumesSelf:
4524*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<NSConsumesSelfAttr>(S, D, Attr);
4525*0a6a1f1dSLionel Sambuc     break;
4526f4a2713aSLionel Sambuc 
4527f4a2713aSLionel Sambuc   case AttributeList::AT_NSReturnsAutoreleased:
4528f4a2713aSLionel Sambuc   case AttributeList::AT_NSReturnsNotRetained:
4529f4a2713aSLionel Sambuc   case AttributeList::AT_CFReturnsNotRetained:
4530f4a2713aSLionel Sambuc   case AttributeList::AT_NSReturnsRetained:
4531f4a2713aSLionel Sambuc   case AttributeList::AT_CFReturnsRetained:
4532*0a6a1f1dSLionel Sambuc     handleNSReturnsRetainedAttr(S, D, Attr);
4533*0a6a1f1dSLionel Sambuc     break;
4534f4a2713aSLionel Sambuc   case AttributeList::AT_WorkGroupSizeHint:
4535*0a6a1f1dSLionel Sambuc     handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, Attr);
4536*0a6a1f1dSLionel Sambuc     break;
4537f4a2713aSLionel Sambuc   case AttributeList::AT_ReqdWorkGroupSize:
4538*0a6a1f1dSLionel Sambuc     handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, Attr);
4539*0a6a1f1dSLionel Sambuc     break;
4540f4a2713aSLionel Sambuc   case AttributeList::AT_VecTypeHint:
4541*0a6a1f1dSLionel Sambuc     handleVecTypeHint(S, D, Attr);
4542*0a6a1f1dSLionel Sambuc     break;
4543f4a2713aSLionel Sambuc 
4544f4a2713aSLionel Sambuc   case AttributeList::AT_InitPriority:
4545*0a6a1f1dSLionel Sambuc     handleInitPriorityAttr(S, D, Attr);
4546*0a6a1f1dSLionel Sambuc     break;
4547f4a2713aSLionel Sambuc 
4548*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Packed:
4549*0a6a1f1dSLionel Sambuc     handlePackedAttr(S, D, Attr);
4550*0a6a1f1dSLionel Sambuc     break;
4551*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Section:
4552*0a6a1f1dSLionel Sambuc     handleSectionAttr(S, D, Attr);
4553*0a6a1f1dSLionel Sambuc     break;
4554f4a2713aSLionel Sambuc   case AttributeList::AT_Unavailable:
4555f4a2713aSLionel Sambuc     handleAttrWithMessage<UnavailableAttr>(S, D, Attr);
4556f4a2713aSLionel Sambuc     break;
4557f4a2713aSLionel Sambuc   case AttributeList::AT_ArcWeakrefUnavailable:
4558*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<ArcWeakrefUnavailableAttr>(S, D, Attr);
4559f4a2713aSLionel Sambuc     break;
4560f4a2713aSLionel Sambuc   case AttributeList::AT_ObjCRootClass:
4561*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<ObjCRootClassAttr>(S, D, Attr);
4562*0a6a1f1dSLionel Sambuc     break;
4563*0a6a1f1dSLionel Sambuc   case AttributeList::AT_ObjCExplicitProtocolImpl:
4564*0a6a1f1dSLionel Sambuc     handleObjCSuppresProtocolAttr(S, D, Attr);
4565f4a2713aSLionel Sambuc     break;
4566f4a2713aSLionel Sambuc   case AttributeList::AT_ObjCRequiresPropertyDefs:
4567*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<ObjCRequiresPropertyDefsAttr>(S, D, Attr);
4568f4a2713aSLionel Sambuc     break;
4569*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Unused:
4570*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<UnusedAttr>(S, D, Attr);
4571*0a6a1f1dSLionel Sambuc     break;
4572f4a2713aSLionel Sambuc   case AttributeList::AT_ReturnsTwice:
4573*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<ReturnsTwiceAttr>(S, D, Attr);
4574f4a2713aSLionel Sambuc     break;
4575*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Used:
4576*0a6a1f1dSLionel Sambuc     handleUsedAttr(S, D, Attr);
4577*0a6a1f1dSLionel Sambuc     break;
4578f4a2713aSLionel Sambuc   case AttributeList::AT_Visibility:
4579f4a2713aSLionel Sambuc     handleVisibilityAttr(S, D, Attr, false);
4580f4a2713aSLionel Sambuc     break;
4581f4a2713aSLionel Sambuc   case AttributeList::AT_TypeVisibility:
4582f4a2713aSLionel Sambuc     handleVisibilityAttr(S, D, Attr, true);
4583f4a2713aSLionel Sambuc     break;
4584f4a2713aSLionel Sambuc   case AttributeList::AT_WarnUnused:
4585*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<WarnUnusedAttr>(S, D, Attr);
4586f4a2713aSLionel Sambuc     break;
4587*0a6a1f1dSLionel Sambuc   case AttributeList::AT_WarnUnusedResult:
4588*0a6a1f1dSLionel Sambuc     handleWarnUnusedResult(S, D, Attr);
4589f4a2713aSLionel Sambuc     break;
4590*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Weak:
4591*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<WeakAttr>(S, D, Attr);
4592*0a6a1f1dSLionel Sambuc     break;
4593*0a6a1f1dSLionel Sambuc   case AttributeList::AT_WeakRef:
4594*0a6a1f1dSLionel Sambuc     handleWeakRefAttr(S, D, Attr);
4595*0a6a1f1dSLionel Sambuc     break;
4596*0a6a1f1dSLionel Sambuc   case AttributeList::AT_WeakImport:
4597*0a6a1f1dSLionel Sambuc     handleWeakImportAttr(S, D, Attr);
4598*0a6a1f1dSLionel Sambuc     break;
4599f4a2713aSLionel Sambuc   case AttributeList::AT_TransparentUnion:
4600f4a2713aSLionel Sambuc     handleTransparentUnionAttr(S, D, Attr);
4601f4a2713aSLionel Sambuc     break;
4602f4a2713aSLionel Sambuc   case AttributeList::AT_ObjCException:
4603*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<ObjCExceptionAttr>(S, D, Attr);
4604f4a2713aSLionel Sambuc     break;
4605f4a2713aSLionel Sambuc   case AttributeList::AT_ObjCMethodFamily:
4606f4a2713aSLionel Sambuc     handleObjCMethodFamilyAttr(S, D, Attr);
4607f4a2713aSLionel Sambuc     break;
4608*0a6a1f1dSLionel Sambuc   case AttributeList::AT_ObjCNSObject:
4609*0a6a1f1dSLionel Sambuc     handleObjCNSObject(S, D, Attr);
4610*0a6a1f1dSLionel Sambuc     break;
4611*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Blocks:
4612*0a6a1f1dSLionel Sambuc     handleBlocksAttr(S, D, Attr);
4613*0a6a1f1dSLionel Sambuc     break;
4614*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Sentinel:
4615*0a6a1f1dSLionel Sambuc     handleSentinelAttr(S, D, Attr);
4616*0a6a1f1dSLionel Sambuc     break;
4617*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Const:
4618*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<ConstAttr>(S, D, Attr);
4619*0a6a1f1dSLionel Sambuc     break;
4620*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Pure:
4621*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<PureAttr>(S, D, Attr);
4622*0a6a1f1dSLionel Sambuc     break;
4623*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Cleanup:
4624*0a6a1f1dSLionel Sambuc     handleCleanupAttr(S, D, Attr);
4625*0a6a1f1dSLionel Sambuc     break;
4626*0a6a1f1dSLionel Sambuc   case AttributeList::AT_NoDebug:
4627*0a6a1f1dSLionel Sambuc     handleNoDebugAttr(S, D, Attr);
4628*0a6a1f1dSLionel Sambuc     break;
4629*0a6a1f1dSLionel Sambuc   case AttributeList::AT_NoDuplicate:
4630*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<NoDuplicateAttr>(S, D, Attr);
4631*0a6a1f1dSLionel Sambuc     break;
4632*0a6a1f1dSLionel Sambuc   case AttributeList::AT_NoInline:
4633*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<NoInlineAttr>(S, D, Attr);
4634f4a2713aSLionel Sambuc     break;
4635f4a2713aSLionel Sambuc   case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg.
4636*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<NoInstrumentFunctionAttr>(S, D, Attr);
4637f4a2713aSLionel Sambuc     break;
4638f4a2713aSLionel Sambuc   case AttributeList::AT_StdCall:
4639f4a2713aSLionel Sambuc   case AttributeList::AT_CDecl:
4640f4a2713aSLionel Sambuc   case AttributeList::AT_FastCall:
4641f4a2713aSLionel Sambuc   case AttributeList::AT_ThisCall:
4642f4a2713aSLionel Sambuc   case AttributeList::AT_Pascal:
4643*0a6a1f1dSLionel Sambuc   case AttributeList::AT_VectorCall:
4644f4a2713aSLionel Sambuc   case AttributeList::AT_MSABI:
4645f4a2713aSLionel Sambuc   case AttributeList::AT_SysVABI:
4646f4a2713aSLionel Sambuc   case AttributeList::AT_Pcs:
4647f4a2713aSLionel Sambuc   case AttributeList::AT_PnaclCall:
4648f4a2713aSLionel Sambuc   case AttributeList::AT_IntelOclBicc:
4649f4a2713aSLionel Sambuc     handleCallConvAttr(S, D, Attr);
4650f4a2713aSLionel Sambuc     break;
4651f4a2713aSLionel Sambuc   case AttributeList::AT_OpenCLKernel:
4652*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<OpenCLKernelAttr>(S, D, Attr);
4653f4a2713aSLionel Sambuc     break;
4654f4a2713aSLionel Sambuc   case AttributeList::AT_OpenCLImageAccess:
4655*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<OpenCLImageAccessAttr>(S, D, Attr);
4656f4a2713aSLionel Sambuc     break;
4657f4a2713aSLionel Sambuc 
4658f4a2713aSLionel Sambuc   // Microsoft attributes:
4659f4a2713aSLionel Sambuc   case AttributeList::AT_MsStruct:
4660*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<MsStructAttr>(S, D, Attr);
4661f4a2713aSLionel Sambuc     break;
4662f4a2713aSLionel Sambuc   case AttributeList::AT_Uuid:
4663f4a2713aSLionel Sambuc     handleUuidAttr(S, D, Attr);
4664f4a2713aSLionel Sambuc     break;
4665*0a6a1f1dSLionel Sambuc   case AttributeList::AT_MSInheritance:
4666*0a6a1f1dSLionel Sambuc     handleMSInheritanceAttr(S, D, Attr);
4667f4a2713aSLionel Sambuc     break;
4668f4a2713aSLionel Sambuc   case AttributeList::AT_SelectAny:
4669*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<SelectAnyAttr>(S, D, Attr);
4670*0a6a1f1dSLionel Sambuc     break;
4671*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Thread:
4672*0a6a1f1dSLionel Sambuc     handleDeclspecThreadAttr(S, D, Attr);
4673f4a2713aSLionel Sambuc     break;
4674f4a2713aSLionel Sambuc 
4675f4a2713aSLionel Sambuc   // Thread safety attributes:
4676f4a2713aSLionel Sambuc   case AttributeList::AT_AssertExclusiveLock:
4677f4a2713aSLionel Sambuc     handleAssertExclusiveLockAttr(S, D, Attr);
4678f4a2713aSLionel Sambuc     break;
4679f4a2713aSLionel Sambuc   case AttributeList::AT_AssertSharedLock:
4680f4a2713aSLionel Sambuc     handleAssertSharedLockAttr(S, D, Attr);
4681f4a2713aSLionel Sambuc     break;
4682f4a2713aSLionel Sambuc   case AttributeList::AT_GuardedVar:
4683*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<GuardedVarAttr>(S, D, Attr);
4684f4a2713aSLionel Sambuc     break;
4685f4a2713aSLionel Sambuc   case AttributeList::AT_PtGuardedVar:
4686f4a2713aSLionel Sambuc     handlePtGuardedVarAttr(S, D, Attr);
4687f4a2713aSLionel Sambuc     break;
4688f4a2713aSLionel Sambuc   case AttributeList::AT_ScopedLockable:
4689*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<ScopedLockableAttr>(S, D, Attr);
4690f4a2713aSLionel Sambuc     break;
4691f4a2713aSLionel Sambuc   case AttributeList::AT_NoSanitizeAddress:
4692*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<NoSanitizeAddressAttr>(S, D, Attr);
4693f4a2713aSLionel Sambuc     break;
4694f4a2713aSLionel Sambuc   case AttributeList::AT_NoThreadSafetyAnalysis:
4695*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<NoThreadSafetyAnalysisAttr>(S, D, Attr);
4696f4a2713aSLionel Sambuc     break;
4697f4a2713aSLionel Sambuc   case AttributeList::AT_NoSanitizeThread:
4698*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<NoSanitizeThreadAttr>(S, D, Attr);
4699f4a2713aSLionel Sambuc     break;
4700f4a2713aSLionel Sambuc   case AttributeList::AT_NoSanitizeMemory:
4701*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<NoSanitizeMemoryAttr>(S, D, Attr);
4702f4a2713aSLionel Sambuc     break;
4703f4a2713aSLionel Sambuc   case AttributeList::AT_GuardedBy:
4704f4a2713aSLionel Sambuc     handleGuardedByAttr(S, D, Attr);
4705f4a2713aSLionel Sambuc     break;
4706f4a2713aSLionel Sambuc   case AttributeList::AT_PtGuardedBy:
4707f4a2713aSLionel Sambuc     handlePtGuardedByAttr(S, D, Attr);
4708f4a2713aSLionel Sambuc     break;
4709f4a2713aSLionel Sambuc   case AttributeList::AT_ExclusiveTrylockFunction:
4710f4a2713aSLionel Sambuc     handleExclusiveTrylockFunctionAttr(S, D, Attr);
4711f4a2713aSLionel Sambuc     break;
4712f4a2713aSLionel Sambuc   case AttributeList::AT_LockReturned:
4713f4a2713aSLionel Sambuc     handleLockReturnedAttr(S, D, Attr);
4714f4a2713aSLionel Sambuc     break;
4715f4a2713aSLionel Sambuc   case AttributeList::AT_LocksExcluded:
4716f4a2713aSLionel Sambuc     handleLocksExcludedAttr(S, D, Attr);
4717f4a2713aSLionel Sambuc     break;
4718f4a2713aSLionel Sambuc   case AttributeList::AT_SharedTrylockFunction:
4719f4a2713aSLionel Sambuc     handleSharedTrylockFunctionAttr(S, D, Attr);
4720f4a2713aSLionel Sambuc     break;
4721f4a2713aSLionel Sambuc   case AttributeList::AT_AcquiredBefore:
4722f4a2713aSLionel Sambuc     handleAcquiredBeforeAttr(S, D, Attr);
4723f4a2713aSLionel Sambuc     break;
4724f4a2713aSLionel Sambuc   case AttributeList::AT_AcquiredAfter:
4725f4a2713aSLionel Sambuc     handleAcquiredAfterAttr(S, D, Attr);
4726f4a2713aSLionel Sambuc     break;
4727f4a2713aSLionel Sambuc 
4728*0a6a1f1dSLionel Sambuc   // Capability analysis attributes.
4729*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Capability:
4730*0a6a1f1dSLionel Sambuc   case AttributeList::AT_Lockable:
4731*0a6a1f1dSLionel Sambuc     handleCapabilityAttr(S, D, Attr);
4732*0a6a1f1dSLionel Sambuc     break;
4733*0a6a1f1dSLionel Sambuc   case AttributeList::AT_RequiresCapability:
4734*0a6a1f1dSLionel Sambuc     handleRequiresCapabilityAttr(S, D, Attr);
4735*0a6a1f1dSLionel Sambuc     break;
4736*0a6a1f1dSLionel Sambuc 
4737*0a6a1f1dSLionel Sambuc   case AttributeList::AT_AssertCapability:
4738*0a6a1f1dSLionel Sambuc     handleAssertCapabilityAttr(S, D, Attr);
4739*0a6a1f1dSLionel Sambuc     break;
4740*0a6a1f1dSLionel Sambuc   case AttributeList::AT_AcquireCapability:
4741*0a6a1f1dSLionel Sambuc     handleAcquireCapabilityAttr(S, D, Attr);
4742*0a6a1f1dSLionel Sambuc     break;
4743*0a6a1f1dSLionel Sambuc   case AttributeList::AT_ReleaseCapability:
4744*0a6a1f1dSLionel Sambuc     handleReleaseCapabilityAttr(S, D, Attr);
4745*0a6a1f1dSLionel Sambuc     break;
4746*0a6a1f1dSLionel Sambuc   case AttributeList::AT_TryAcquireCapability:
4747*0a6a1f1dSLionel Sambuc     handleTryAcquireCapabilityAttr(S, D, Attr);
4748*0a6a1f1dSLionel Sambuc     break;
4749*0a6a1f1dSLionel Sambuc 
4750f4a2713aSLionel Sambuc   // Consumed analysis attributes.
4751f4a2713aSLionel Sambuc   case AttributeList::AT_Consumable:
4752f4a2713aSLionel Sambuc     handleConsumableAttr(S, D, Attr);
4753f4a2713aSLionel Sambuc     break;
4754*0a6a1f1dSLionel Sambuc   case AttributeList::AT_ConsumableAutoCast:
4755*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<ConsumableAutoCastAttr>(S, D, Attr);
4756*0a6a1f1dSLionel Sambuc     break;
4757*0a6a1f1dSLionel Sambuc   case AttributeList::AT_ConsumableSetOnRead:
4758*0a6a1f1dSLionel Sambuc     handleSimpleAttribute<ConsumableSetOnReadAttr>(S, D, Attr);
4759*0a6a1f1dSLionel Sambuc     break;
4760f4a2713aSLionel Sambuc   case AttributeList::AT_CallableWhen:
4761f4a2713aSLionel Sambuc     handleCallableWhenAttr(S, D, Attr);
4762f4a2713aSLionel Sambuc     break;
4763f4a2713aSLionel Sambuc   case AttributeList::AT_ParamTypestate:
4764f4a2713aSLionel Sambuc     handleParamTypestateAttr(S, D, Attr);
4765f4a2713aSLionel Sambuc     break;
4766f4a2713aSLionel Sambuc   case AttributeList::AT_ReturnTypestate:
4767f4a2713aSLionel Sambuc     handleReturnTypestateAttr(S, D, Attr);
4768f4a2713aSLionel Sambuc     break;
4769f4a2713aSLionel Sambuc   case AttributeList::AT_SetTypestate:
4770f4a2713aSLionel Sambuc     handleSetTypestateAttr(S, D, Attr);
4771f4a2713aSLionel Sambuc     break;
4772f4a2713aSLionel Sambuc   case AttributeList::AT_TestTypestate:
4773f4a2713aSLionel Sambuc     handleTestTypestateAttr(S, D, Attr);
4774f4a2713aSLionel Sambuc     break;
4775f4a2713aSLionel Sambuc 
4776f4a2713aSLionel Sambuc   // Type safety attributes.
4777f4a2713aSLionel Sambuc   case AttributeList::AT_ArgumentWithTypeTag:
4778f4a2713aSLionel Sambuc     handleArgumentWithTypeTagAttr(S, D, Attr);
4779f4a2713aSLionel Sambuc     break;
4780f4a2713aSLionel Sambuc   case AttributeList::AT_TypeTagForDatatype:
4781f4a2713aSLionel Sambuc     handleTypeTagForDatatypeAttr(S, D, Attr);
4782f4a2713aSLionel Sambuc     break;
4783f4a2713aSLionel Sambuc   }
4784f4a2713aSLionel Sambuc }
4785f4a2713aSLionel Sambuc 
4786f4a2713aSLionel Sambuc /// ProcessDeclAttributeList - Apply all the decl attributes in the specified
4787f4a2713aSLionel Sambuc /// attribute list to the specified decl, ignoring any type attributes.
ProcessDeclAttributeList(Scope * S,Decl * D,const AttributeList * AttrList,bool IncludeCXX11Attributes)4788f4a2713aSLionel Sambuc void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
4789f4a2713aSLionel Sambuc                                     const AttributeList *AttrList,
4790f4a2713aSLionel Sambuc                                     bool IncludeCXX11Attributes) {
4791f4a2713aSLionel Sambuc   for (const AttributeList* l = AttrList; l; l = l->getNext())
4792f4a2713aSLionel Sambuc     ProcessDeclAttribute(*this, S, D, *l, IncludeCXX11Attributes);
4793f4a2713aSLionel Sambuc 
4794*0a6a1f1dSLionel Sambuc   // FIXME: We should be able to handle these cases in TableGen.
4795f4a2713aSLionel Sambuc   // GCC accepts
4796f4a2713aSLionel Sambuc   // static int a9 __attribute__((weakref));
4797f4a2713aSLionel Sambuc   // but that looks really pointless. We reject it.
4798f4a2713aSLionel Sambuc   if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
4799*0a6a1f1dSLionel Sambuc     Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias)
4800*0a6a1f1dSLionel Sambuc       << cast<NamedDecl>(D);
4801f4a2713aSLionel Sambuc     D->dropAttr<WeakRefAttr>();
4802f4a2713aSLionel Sambuc     return;
4803f4a2713aSLionel Sambuc   }
4804*0a6a1f1dSLionel Sambuc 
4805*0a6a1f1dSLionel Sambuc   // FIXME: We should be able to handle this in TableGen as well. It would be
4806*0a6a1f1dSLionel Sambuc   // good to have a way to specify "these attributes must appear as a group",
4807*0a6a1f1dSLionel Sambuc   // for these. Additionally, it would be good to have a way to specify "these
4808*0a6a1f1dSLionel Sambuc   // attribute must never appear as a group" for attributes like cold and hot.
4809*0a6a1f1dSLionel Sambuc   if (!D->hasAttr<OpenCLKernelAttr>()) {
4810*0a6a1f1dSLionel Sambuc     // These attributes cannot be applied to a non-kernel function.
4811*0a6a1f1dSLionel Sambuc     if (Attr *A = D->getAttr<ReqdWorkGroupSizeAttr>()) {
4812*0a6a1f1dSLionel Sambuc       // FIXME: This emits a different error message than
4813*0a6a1f1dSLionel Sambuc       // diag::err_attribute_wrong_decl_type + ExpectedKernelFunction.
4814*0a6a1f1dSLionel Sambuc       Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
4815*0a6a1f1dSLionel Sambuc       D->setInvalidDecl();
4816*0a6a1f1dSLionel Sambuc     } else if (Attr *A = D->getAttr<WorkGroupSizeHintAttr>()) {
4817*0a6a1f1dSLionel Sambuc       Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
4818*0a6a1f1dSLionel Sambuc       D->setInvalidDecl();
4819*0a6a1f1dSLionel Sambuc     } else if (Attr *A = D->getAttr<VecTypeHintAttr>()) {
4820*0a6a1f1dSLionel Sambuc       Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
4821*0a6a1f1dSLionel Sambuc       D->setInvalidDecl();
4822*0a6a1f1dSLionel Sambuc     } else if (Attr *A = D->getAttr<AMDGPUNumVGPRAttr>()) {
4823*0a6a1f1dSLionel Sambuc       Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
4824*0a6a1f1dSLionel Sambuc         << A << ExpectedKernelFunction;
4825*0a6a1f1dSLionel Sambuc       D->setInvalidDecl();
4826*0a6a1f1dSLionel Sambuc     } else if (Attr *A = D->getAttr<AMDGPUNumSGPRAttr>()) {
4827*0a6a1f1dSLionel Sambuc       Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
4828*0a6a1f1dSLionel Sambuc         << A << ExpectedKernelFunction;
4829*0a6a1f1dSLionel Sambuc       D->setInvalidDecl();
4830*0a6a1f1dSLionel Sambuc     }
4831*0a6a1f1dSLionel Sambuc   }
4832f4a2713aSLionel Sambuc }
4833f4a2713aSLionel Sambuc 
4834f4a2713aSLionel Sambuc // Annotation attributes are the only attributes allowed after an access
4835f4a2713aSLionel Sambuc // specifier.
ProcessAccessDeclAttributeList(AccessSpecDecl * ASDecl,const AttributeList * AttrList)4836f4a2713aSLionel Sambuc bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
4837f4a2713aSLionel Sambuc                                           const AttributeList *AttrList) {
4838f4a2713aSLionel Sambuc   for (const AttributeList* l = AttrList; l; l = l->getNext()) {
4839f4a2713aSLionel Sambuc     if (l->getKind() == AttributeList::AT_Annotate) {
4840*0a6a1f1dSLionel Sambuc       ProcessDeclAttribute(*this, nullptr, ASDecl, *l, l->isCXX11Attribute());
4841f4a2713aSLionel Sambuc     } else {
4842f4a2713aSLionel Sambuc       Diag(l->getLoc(), diag::err_only_annotate_after_access_spec);
4843f4a2713aSLionel Sambuc       return true;
4844f4a2713aSLionel Sambuc     }
4845f4a2713aSLionel Sambuc   }
4846f4a2713aSLionel Sambuc 
4847f4a2713aSLionel Sambuc   return false;
4848f4a2713aSLionel Sambuc }
4849f4a2713aSLionel Sambuc 
4850f4a2713aSLionel Sambuc /// checkUnusedDeclAttributes - Check a list of attributes to see if it
4851f4a2713aSLionel Sambuc /// contains any decl attributes that we should warn about.
checkUnusedDeclAttributes(Sema & S,const AttributeList * A)4852f4a2713aSLionel Sambuc static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) {
4853f4a2713aSLionel Sambuc   for ( ; A; A = A->getNext()) {
4854f4a2713aSLionel Sambuc     // Only warn if the attribute is an unignored, non-type attribute.
4855f4a2713aSLionel Sambuc     if (A->isUsedAsTypeAttr() || A->isInvalid()) continue;
4856f4a2713aSLionel Sambuc     if (A->getKind() == AttributeList::IgnoredAttribute) continue;
4857f4a2713aSLionel Sambuc 
4858f4a2713aSLionel Sambuc     if (A->getKind() == AttributeList::UnknownAttribute) {
4859f4a2713aSLionel Sambuc       S.Diag(A->getLoc(), diag::warn_unknown_attribute_ignored)
4860f4a2713aSLionel Sambuc         << A->getName() << A->getRange();
4861f4a2713aSLionel Sambuc     } else {
4862f4a2713aSLionel Sambuc       S.Diag(A->getLoc(), diag::warn_attribute_not_on_decl)
4863f4a2713aSLionel Sambuc         << A->getName() << A->getRange();
4864f4a2713aSLionel Sambuc     }
4865f4a2713aSLionel Sambuc   }
4866f4a2713aSLionel Sambuc }
4867f4a2713aSLionel Sambuc 
4868f4a2713aSLionel Sambuc /// checkUnusedDeclAttributes - Given a declarator which is not being
4869f4a2713aSLionel Sambuc /// used to build a declaration, complain about any decl attributes
4870f4a2713aSLionel Sambuc /// which might be lying around on it.
checkUnusedDeclAttributes(Declarator & D)4871f4a2713aSLionel Sambuc void Sema::checkUnusedDeclAttributes(Declarator &D) {
4872f4a2713aSLionel Sambuc   ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes().getList());
4873f4a2713aSLionel Sambuc   ::checkUnusedDeclAttributes(*this, D.getAttributes());
4874f4a2713aSLionel Sambuc   for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)
4875f4a2713aSLionel Sambuc     ::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs());
4876f4a2713aSLionel Sambuc }
4877f4a2713aSLionel Sambuc 
4878f4a2713aSLionel Sambuc /// DeclClonePragmaWeak - clone existing decl (maybe definition),
4879f4a2713aSLionel Sambuc /// \#pragma weak needs a non-definition decl and source may not have one.
DeclClonePragmaWeak(NamedDecl * ND,IdentifierInfo * II,SourceLocation Loc)4880f4a2713aSLionel Sambuc NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
4881f4a2713aSLionel Sambuc                                       SourceLocation Loc) {
4882f4a2713aSLionel Sambuc   assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
4883*0a6a1f1dSLionel Sambuc   NamedDecl *NewD = nullptr;
4884f4a2713aSLionel Sambuc   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
4885f4a2713aSLionel Sambuc     FunctionDecl *NewFD;
4886f4a2713aSLionel Sambuc     // FIXME: Missing call to CheckFunctionDeclaration().
4887f4a2713aSLionel Sambuc     // FIXME: Mangling?
4888f4a2713aSLionel Sambuc     // FIXME: Is the qualifier info correct?
4889f4a2713aSLionel Sambuc     // FIXME: Is the DeclContext correct?
4890f4a2713aSLionel Sambuc     NewFD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(),
4891f4a2713aSLionel Sambuc                                  Loc, Loc, DeclarationName(II),
4892f4a2713aSLionel Sambuc                                  FD->getType(), FD->getTypeSourceInfo(),
4893f4a2713aSLionel Sambuc                                  SC_None, false/*isInlineSpecified*/,
4894f4a2713aSLionel Sambuc                                  FD->hasPrototype(),
4895f4a2713aSLionel Sambuc                                  false/*isConstexprSpecified*/);
4896f4a2713aSLionel Sambuc     NewD = NewFD;
4897f4a2713aSLionel Sambuc 
4898f4a2713aSLionel Sambuc     if (FD->getQualifier())
4899f4a2713aSLionel Sambuc       NewFD->setQualifierInfo(FD->getQualifierLoc());
4900f4a2713aSLionel Sambuc 
4901f4a2713aSLionel Sambuc     // Fake up parameter variables; they are declared as if this were
4902f4a2713aSLionel Sambuc     // a typedef.
4903f4a2713aSLionel Sambuc     QualType FDTy = FD->getType();
4904f4a2713aSLionel Sambuc     if (const FunctionProtoType *FT = FDTy->getAs<FunctionProtoType>()) {
4905f4a2713aSLionel Sambuc       SmallVector<ParmVarDecl*, 16> Params;
4906*0a6a1f1dSLionel Sambuc       for (const auto &AI : FT->param_types()) {
4907*0a6a1f1dSLionel Sambuc         ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, AI);
4908f4a2713aSLionel Sambuc         Param->setScopeInfo(0, Params.size());
4909f4a2713aSLionel Sambuc         Params.push_back(Param);
4910f4a2713aSLionel Sambuc       }
4911f4a2713aSLionel Sambuc       NewFD->setParams(Params);
4912f4a2713aSLionel Sambuc     }
4913f4a2713aSLionel Sambuc   } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) {
4914f4a2713aSLionel Sambuc     NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
4915f4a2713aSLionel Sambuc                            VD->getInnerLocStart(), VD->getLocation(), II,
4916f4a2713aSLionel Sambuc                            VD->getType(), VD->getTypeSourceInfo(),
4917f4a2713aSLionel Sambuc                            VD->getStorageClass());
4918f4a2713aSLionel Sambuc     if (VD->getQualifier()) {
4919f4a2713aSLionel Sambuc       VarDecl *NewVD = cast<VarDecl>(NewD);
4920f4a2713aSLionel Sambuc       NewVD->setQualifierInfo(VD->getQualifierLoc());
4921f4a2713aSLionel Sambuc     }
4922f4a2713aSLionel Sambuc   }
4923f4a2713aSLionel Sambuc   return NewD;
4924f4a2713aSLionel Sambuc }
4925f4a2713aSLionel Sambuc 
4926f4a2713aSLionel Sambuc /// DeclApplyPragmaWeak - A declaration (maybe definition) needs \#pragma weak
4927f4a2713aSLionel Sambuc /// applied to it, possibly with an alias.
DeclApplyPragmaWeak(Scope * S,NamedDecl * ND,WeakInfo & W)4928f4a2713aSLionel Sambuc void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
4929f4a2713aSLionel Sambuc   if (W.getUsed()) return; // only do this once
4930f4a2713aSLionel Sambuc   W.setUsed(true);
4931f4a2713aSLionel Sambuc   if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
4932f4a2713aSLionel Sambuc     IdentifierInfo *NDId = ND->getIdentifier();
4933f4a2713aSLionel Sambuc     NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation());
4934*0a6a1f1dSLionel Sambuc     NewD->addAttr(AliasAttr::CreateImplicit(Context, NDId->getName(),
4935*0a6a1f1dSLionel Sambuc                                             W.getLocation()));
4936*0a6a1f1dSLionel Sambuc     NewD->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation()));
4937f4a2713aSLionel Sambuc     WeakTopLevelDecl.push_back(NewD);
4938f4a2713aSLionel Sambuc     // FIXME: "hideous" code from Sema::LazilyCreateBuiltin
4939f4a2713aSLionel Sambuc     // to insert Decl at TU scope, sorry.
4940f4a2713aSLionel Sambuc     DeclContext *SavedContext = CurContext;
4941f4a2713aSLionel Sambuc     CurContext = Context.getTranslationUnitDecl();
4942*0a6a1f1dSLionel Sambuc     NewD->setDeclContext(CurContext);
4943*0a6a1f1dSLionel Sambuc     NewD->setLexicalDeclContext(CurContext);
4944f4a2713aSLionel Sambuc     PushOnScopeChains(NewD, S);
4945f4a2713aSLionel Sambuc     CurContext = SavedContext;
4946f4a2713aSLionel Sambuc   } else { // just add weak to existing
4947*0a6a1f1dSLionel Sambuc     ND->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation()));
4948f4a2713aSLionel Sambuc   }
4949f4a2713aSLionel Sambuc }
4950f4a2713aSLionel Sambuc 
ProcessPragmaWeak(Scope * S,Decl * D)4951f4a2713aSLionel Sambuc void Sema::ProcessPragmaWeak(Scope *S, Decl *D) {
4952f4a2713aSLionel Sambuc   // It's valid to "forward-declare" #pragma weak, in which case we
4953f4a2713aSLionel Sambuc   // have to do this.
4954f4a2713aSLionel Sambuc   LoadExternalWeakUndeclaredIdentifiers();
4955f4a2713aSLionel Sambuc   if (!WeakUndeclaredIdentifiers.empty()) {
4956*0a6a1f1dSLionel Sambuc     NamedDecl *ND = nullptr;
4957f4a2713aSLionel Sambuc     if (VarDecl *VD = dyn_cast<VarDecl>(D))
4958f4a2713aSLionel Sambuc       if (VD->isExternC())
4959f4a2713aSLionel Sambuc         ND = VD;
4960f4a2713aSLionel Sambuc     if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
4961f4a2713aSLionel Sambuc       if (FD->isExternC())
4962f4a2713aSLionel Sambuc         ND = FD;
4963f4a2713aSLionel Sambuc     if (ND) {
4964f4a2713aSLionel Sambuc       if (IdentifierInfo *Id = ND->getIdentifier()) {
4965f4a2713aSLionel Sambuc         llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I
4966f4a2713aSLionel Sambuc           = WeakUndeclaredIdentifiers.find(Id);
4967f4a2713aSLionel Sambuc         if (I != WeakUndeclaredIdentifiers.end()) {
4968f4a2713aSLionel Sambuc           WeakInfo W = I->second;
4969f4a2713aSLionel Sambuc           DeclApplyPragmaWeak(S, ND, W);
4970f4a2713aSLionel Sambuc           WeakUndeclaredIdentifiers[Id] = W;
4971f4a2713aSLionel Sambuc         }
4972f4a2713aSLionel Sambuc       }
4973f4a2713aSLionel Sambuc     }
4974f4a2713aSLionel Sambuc   }
4975f4a2713aSLionel Sambuc }
4976f4a2713aSLionel Sambuc 
4977f4a2713aSLionel Sambuc /// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
4978f4a2713aSLionel Sambuc /// it, apply them to D.  This is a bit tricky because PD can have attributes
4979f4a2713aSLionel Sambuc /// specified in many different places, and we need to find and apply them all.
ProcessDeclAttributes(Scope * S,Decl * D,const Declarator & PD)4980f4a2713aSLionel Sambuc void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
4981f4a2713aSLionel Sambuc   // Apply decl attributes from the DeclSpec if present.
4982f4a2713aSLionel Sambuc   if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList())
4983f4a2713aSLionel Sambuc     ProcessDeclAttributeList(S, D, Attrs);
4984f4a2713aSLionel Sambuc 
4985f4a2713aSLionel Sambuc   // Walk the declarator structure, applying decl attributes that were in a type
4986f4a2713aSLionel Sambuc   // position to the decl itself.  This handles cases like:
4987f4a2713aSLionel Sambuc   //   int *__attr__(x)** D;
4988f4a2713aSLionel Sambuc   // when X is a decl attribute.
4989f4a2713aSLionel Sambuc   for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
4990f4a2713aSLionel Sambuc     if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
4991f4a2713aSLionel Sambuc       ProcessDeclAttributeList(S, D, Attrs, /*IncludeCXX11Attributes=*/false);
4992f4a2713aSLionel Sambuc 
4993f4a2713aSLionel Sambuc   // Finally, apply any attributes on the decl itself.
4994f4a2713aSLionel Sambuc   if (const AttributeList *Attrs = PD.getAttributes())
4995f4a2713aSLionel Sambuc     ProcessDeclAttributeList(S, D, Attrs);
4996f4a2713aSLionel Sambuc }
4997f4a2713aSLionel Sambuc 
4998f4a2713aSLionel Sambuc /// Is the given declaration allowed to use a forbidden type?
isForbiddenTypeAllowed(Sema & S,Decl * decl)4999f4a2713aSLionel Sambuc static bool isForbiddenTypeAllowed(Sema &S, Decl *decl) {
5000f4a2713aSLionel Sambuc   // Private ivars are always okay.  Unfortunately, people don't
5001f4a2713aSLionel Sambuc   // always properly make their ivars private, even in system headers.
5002f4a2713aSLionel Sambuc   // Plus we need to make fields okay, too.
5003f4a2713aSLionel Sambuc   // Function declarations in sys headers will be marked unavailable.
5004f4a2713aSLionel Sambuc   if (!isa<FieldDecl>(decl) && !isa<ObjCPropertyDecl>(decl) &&
5005f4a2713aSLionel Sambuc       !isa<FunctionDecl>(decl))
5006f4a2713aSLionel Sambuc     return false;
5007f4a2713aSLionel Sambuc 
5008f4a2713aSLionel Sambuc   // Require it to be declared in a system header.
5009f4a2713aSLionel Sambuc   return S.Context.getSourceManager().isInSystemHeader(decl->getLocation());
5010f4a2713aSLionel Sambuc }
5011f4a2713aSLionel Sambuc 
5012f4a2713aSLionel Sambuc /// Handle a delayed forbidden-type diagnostic.
handleDelayedForbiddenType(Sema & S,DelayedDiagnostic & diag,Decl * decl)5013f4a2713aSLionel Sambuc static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag,
5014f4a2713aSLionel Sambuc                                        Decl *decl) {
5015f4a2713aSLionel Sambuc   if (decl && isForbiddenTypeAllowed(S, decl)) {
5016*0a6a1f1dSLionel Sambuc     decl->addAttr(UnavailableAttr::CreateImplicit(S.Context,
5017*0a6a1f1dSLionel Sambuc                         "this system declaration uses an unsupported type",
5018*0a6a1f1dSLionel Sambuc                         diag.Loc));
5019f4a2713aSLionel Sambuc     return;
5020f4a2713aSLionel Sambuc   }
5021f4a2713aSLionel Sambuc   if (S.getLangOpts().ObjCAutoRefCount)
5022f4a2713aSLionel Sambuc     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(decl)) {
5023f4a2713aSLionel Sambuc       // FIXME: we may want to suppress diagnostics for all
5024f4a2713aSLionel Sambuc       // kind of forbidden type messages on unavailable functions.
5025f4a2713aSLionel Sambuc       if (FD->hasAttr<UnavailableAttr>() &&
5026f4a2713aSLionel Sambuc           diag.getForbiddenTypeDiagnostic() ==
5027f4a2713aSLionel Sambuc           diag::err_arc_array_param_no_ownership) {
5028f4a2713aSLionel Sambuc         diag.Triggered = true;
5029f4a2713aSLionel Sambuc         return;
5030f4a2713aSLionel Sambuc       }
5031f4a2713aSLionel Sambuc     }
5032f4a2713aSLionel Sambuc 
5033f4a2713aSLionel Sambuc   S.Diag(diag.Loc, diag.getForbiddenTypeDiagnostic())
5034f4a2713aSLionel Sambuc     << diag.getForbiddenTypeOperand() << diag.getForbiddenTypeArgument();
5035f4a2713aSLionel Sambuc   diag.Triggered = true;
5036f4a2713aSLionel Sambuc }
5037f4a2713aSLionel Sambuc 
5038*0a6a1f1dSLionel Sambuc 
isDeclDeprecated(Decl * D)5039*0a6a1f1dSLionel Sambuc static bool isDeclDeprecated(Decl *D) {
5040*0a6a1f1dSLionel Sambuc   do {
5041*0a6a1f1dSLionel Sambuc     if (D->isDeprecated())
5042*0a6a1f1dSLionel Sambuc       return true;
5043*0a6a1f1dSLionel Sambuc     // A category implicitly has the availability of the interface.
5044*0a6a1f1dSLionel Sambuc     if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D))
5045*0a6a1f1dSLionel Sambuc       return CatD->getClassInterface()->isDeprecated();
5046*0a6a1f1dSLionel Sambuc   } while ((D = cast_or_null<Decl>(D->getDeclContext())));
5047*0a6a1f1dSLionel Sambuc   return false;
5048*0a6a1f1dSLionel Sambuc }
5049*0a6a1f1dSLionel Sambuc 
isDeclUnavailable(Decl * D)5050*0a6a1f1dSLionel Sambuc static bool isDeclUnavailable(Decl *D) {
5051*0a6a1f1dSLionel Sambuc   do {
5052*0a6a1f1dSLionel Sambuc     if (D->isUnavailable())
5053*0a6a1f1dSLionel Sambuc       return true;
5054*0a6a1f1dSLionel Sambuc     // A category implicitly has the availability of the interface.
5055*0a6a1f1dSLionel Sambuc     if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D))
5056*0a6a1f1dSLionel Sambuc       return CatD->getClassInterface()->isUnavailable();
5057*0a6a1f1dSLionel Sambuc   } while ((D = cast_or_null<Decl>(D->getDeclContext())));
5058*0a6a1f1dSLionel Sambuc   return false;
5059*0a6a1f1dSLionel Sambuc }
5060*0a6a1f1dSLionel Sambuc 
DoEmitAvailabilityWarning(Sema & S,DelayedDiagnostic::DDKind K,Decl * Ctx,const NamedDecl * D,StringRef Message,SourceLocation Loc,const ObjCInterfaceDecl * UnknownObjCClass,const ObjCPropertyDecl * ObjCProperty,bool ObjCPropertyAccess)5061*0a6a1f1dSLionel Sambuc static void DoEmitAvailabilityWarning(Sema &S, DelayedDiagnostic::DDKind K,
5062*0a6a1f1dSLionel Sambuc                                       Decl *Ctx, const NamedDecl *D,
5063*0a6a1f1dSLionel Sambuc                                       StringRef Message, SourceLocation Loc,
5064*0a6a1f1dSLionel Sambuc                                       const ObjCInterfaceDecl *UnknownObjCClass,
5065*0a6a1f1dSLionel Sambuc                                       const ObjCPropertyDecl *ObjCProperty,
5066*0a6a1f1dSLionel Sambuc                                       bool ObjCPropertyAccess) {
5067*0a6a1f1dSLionel Sambuc   // Diagnostics for deprecated or unavailable.
5068*0a6a1f1dSLionel Sambuc   unsigned diag, diag_message, diag_fwdclass_message;
5069*0a6a1f1dSLionel Sambuc 
5070*0a6a1f1dSLionel Sambuc   // Matches 'diag::note_property_attribute' options.
5071*0a6a1f1dSLionel Sambuc   unsigned property_note_select;
5072*0a6a1f1dSLionel Sambuc 
5073*0a6a1f1dSLionel Sambuc   // Matches diag::note_availability_specified_here.
5074*0a6a1f1dSLionel Sambuc   unsigned available_here_select_kind;
5075*0a6a1f1dSLionel Sambuc 
5076*0a6a1f1dSLionel Sambuc   // Don't warn if our current context is deprecated or unavailable.
5077*0a6a1f1dSLionel Sambuc   switch (K) {
5078*0a6a1f1dSLionel Sambuc   case DelayedDiagnostic::Deprecation:
5079*0a6a1f1dSLionel Sambuc     if (isDeclDeprecated(Ctx))
5080*0a6a1f1dSLionel Sambuc       return;
5081*0a6a1f1dSLionel Sambuc     diag = !ObjCPropertyAccess ? diag::warn_deprecated
5082*0a6a1f1dSLionel Sambuc                                : diag::warn_property_method_deprecated;
5083*0a6a1f1dSLionel Sambuc     diag_message = diag::warn_deprecated_message;
5084*0a6a1f1dSLionel Sambuc     diag_fwdclass_message = diag::warn_deprecated_fwdclass_message;
5085*0a6a1f1dSLionel Sambuc     property_note_select = /* deprecated */ 0;
5086*0a6a1f1dSLionel Sambuc     available_here_select_kind = /* deprecated */ 2;
5087*0a6a1f1dSLionel Sambuc     break;
5088*0a6a1f1dSLionel Sambuc 
5089*0a6a1f1dSLionel Sambuc   case DelayedDiagnostic::Unavailable:
5090*0a6a1f1dSLionel Sambuc     if (isDeclUnavailable(Ctx))
5091*0a6a1f1dSLionel Sambuc       return;
5092*0a6a1f1dSLionel Sambuc     diag = !ObjCPropertyAccess ? diag::err_unavailable
5093*0a6a1f1dSLionel Sambuc                                : diag::err_property_method_unavailable;
5094*0a6a1f1dSLionel Sambuc     diag_message = diag::err_unavailable_message;
5095*0a6a1f1dSLionel Sambuc     diag_fwdclass_message = diag::warn_unavailable_fwdclass_message;
5096*0a6a1f1dSLionel Sambuc     property_note_select = /* unavailable */ 1;
5097*0a6a1f1dSLionel Sambuc     available_here_select_kind = /* unavailable */ 0;
5098*0a6a1f1dSLionel Sambuc     break;
5099*0a6a1f1dSLionel Sambuc 
5100*0a6a1f1dSLionel Sambuc   default:
5101*0a6a1f1dSLionel Sambuc     llvm_unreachable("Neither a deprecation or unavailable kind");
5102*0a6a1f1dSLionel Sambuc   }
5103*0a6a1f1dSLionel Sambuc 
5104*0a6a1f1dSLionel Sambuc   if (!Message.empty()) {
5105*0a6a1f1dSLionel Sambuc     S.Diag(Loc, diag_message) << D << Message;
5106*0a6a1f1dSLionel Sambuc     if (ObjCProperty)
5107*0a6a1f1dSLionel Sambuc       S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
5108*0a6a1f1dSLionel Sambuc           << ObjCProperty->getDeclName() << property_note_select;
5109*0a6a1f1dSLionel Sambuc   } else if (!UnknownObjCClass) {
5110*0a6a1f1dSLionel Sambuc     S.Diag(Loc, diag) << D;
5111*0a6a1f1dSLionel Sambuc     if (ObjCProperty)
5112*0a6a1f1dSLionel Sambuc       S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
5113*0a6a1f1dSLionel Sambuc           << ObjCProperty->getDeclName() << property_note_select;
5114*0a6a1f1dSLionel Sambuc   } else {
5115*0a6a1f1dSLionel Sambuc     S.Diag(Loc, diag_fwdclass_message) << D;
5116*0a6a1f1dSLionel Sambuc     S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
5117*0a6a1f1dSLionel Sambuc   }
5118*0a6a1f1dSLionel Sambuc 
5119*0a6a1f1dSLionel Sambuc   S.Diag(D->getLocation(), diag::note_availability_specified_here)
5120*0a6a1f1dSLionel Sambuc       << D << available_here_select_kind;
5121*0a6a1f1dSLionel Sambuc }
5122*0a6a1f1dSLionel Sambuc 
handleDelayedAvailabilityCheck(Sema & S,DelayedDiagnostic & DD,Decl * Ctx)5123*0a6a1f1dSLionel Sambuc static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
5124*0a6a1f1dSLionel Sambuc                                            Decl *Ctx) {
5125*0a6a1f1dSLionel Sambuc   DD.Triggered = true;
5126*0a6a1f1dSLionel Sambuc   DoEmitAvailabilityWarning(S, (DelayedDiagnostic::DDKind)DD.Kind, Ctx,
5127*0a6a1f1dSLionel Sambuc                             DD.getDeprecationDecl(), DD.getDeprecationMessage(),
5128*0a6a1f1dSLionel Sambuc                             DD.Loc, DD.getUnknownObjCClass(),
5129*0a6a1f1dSLionel Sambuc                             DD.getObjCProperty(), false);
5130*0a6a1f1dSLionel Sambuc }
5131*0a6a1f1dSLionel Sambuc 
PopParsingDeclaration(ParsingDeclState state,Decl * decl)5132f4a2713aSLionel Sambuc void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
5133f4a2713aSLionel Sambuc   assert(DelayedDiagnostics.getCurrentPool());
5134f4a2713aSLionel Sambuc   DelayedDiagnosticPool &poppedPool = *DelayedDiagnostics.getCurrentPool();
5135f4a2713aSLionel Sambuc   DelayedDiagnostics.popWithoutEmitting(state);
5136f4a2713aSLionel Sambuc 
5137f4a2713aSLionel Sambuc   // When delaying diagnostics to run in the context of a parsed
5138f4a2713aSLionel Sambuc   // declaration, we only want to actually emit anything if parsing
5139f4a2713aSLionel Sambuc   // succeeds.
5140f4a2713aSLionel Sambuc   if (!decl) return;
5141f4a2713aSLionel Sambuc 
5142f4a2713aSLionel Sambuc   // We emit all the active diagnostics in this pool or any of its
5143f4a2713aSLionel Sambuc   // parents.  In general, we'll get one pool for the decl spec
5144f4a2713aSLionel Sambuc   // and a child pool for each declarator; in a decl group like:
5145f4a2713aSLionel Sambuc   //   deprecated_typedef foo, *bar, baz();
5146f4a2713aSLionel Sambuc   // only the declarator pops will be passed decls.  This is correct;
5147f4a2713aSLionel Sambuc   // we really do need to consider delayed diagnostics from the decl spec
5148f4a2713aSLionel Sambuc   // for each of the different declarations.
5149f4a2713aSLionel Sambuc   const DelayedDiagnosticPool *pool = &poppedPool;
5150f4a2713aSLionel Sambuc   do {
5151f4a2713aSLionel Sambuc     for (DelayedDiagnosticPool::pool_iterator
5152f4a2713aSLionel Sambuc            i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) {
5153f4a2713aSLionel Sambuc       // This const_cast is a bit lame.  Really, Triggered should be mutable.
5154f4a2713aSLionel Sambuc       DelayedDiagnostic &diag = const_cast<DelayedDiagnostic&>(*i);
5155f4a2713aSLionel Sambuc       if (diag.Triggered)
5156f4a2713aSLionel Sambuc         continue;
5157f4a2713aSLionel Sambuc 
5158f4a2713aSLionel Sambuc       switch (diag.Kind) {
5159f4a2713aSLionel Sambuc       case DelayedDiagnostic::Deprecation:
5160*0a6a1f1dSLionel Sambuc       case DelayedDiagnostic::Unavailable:
5161*0a6a1f1dSLionel Sambuc         // Don't bother giving deprecation/unavailable diagnostics if
5162*0a6a1f1dSLionel Sambuc         // the decl is invalid.
5163f4a2713aSLionel Sambuc         if (!decl->isInvalidDecl())
5164*0a6a1f1dSLionel Sambuc           handleDelayedAvailabilityCheck(*this, diag, decl);
5165f4a2713aSLionel Sambuc         break;
5166f4a2713aSLionel Sambuc 
5167f4a2713aSLionel Sambuc       case DelayedDiagnostic::Access:
5168f4a2713aSLionel Sambuc         HandleDelayedAccessCheck(diag, decl);
5169f4a2713aSLionel Sambuc         break;
5170f4a2713aSLionel Sambuc 
5171f4a2713aSLionel Sambuc       case DelayedDiagnostic::ForbiddenType:
5172f4a2713aSLionel Sambuc         handleDelayedForbiddenType(*this, diag, decl);
5173f4a2713aSLionel Sambuc         break;
5174f4a2713aSLionel Sambuc       }
5175f4a2713aSLionel Sambuc     }
5176f4a2713aSLionel Sambuc   } while ((pool = pool->getParent()));
5177f4a2713aSLionel Sambuc }
5178f4a2713aSLionel Sambuc 
5179f4a2713aSLionel Sambuc /// Given a set of delayed diagnostics, re-emit them as if they had
5180f4a2713aSLionel Sambuc /// been delayed in the current context instead of in the given pool.
5181f4a2713aSLionel Sambuc /// Essentially, this just moves them to the current pool.
redelayDiagnostics(DelayedDiagnosticPool & pool)5182f4a2713aSLionel Sambuc void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) {
5183f4a2713aSLionel Sambuc   DelayedDiagnosticPool *curPool = DelayedDiagnostics.getCurrentPool();
5184f4a2713aSLionel Sambuc   assert(curPool && "re-emitting in undelayed context not supported");
5185f4a2713aSLionel Sambuc   curPool->steal(pool);
5186f4a2713aSLionel Sambuc }
5187f4a2713aSLionel Sambuc 
EmitAvailabilityWarning(AvailabilityDiagnostic AD,NamedDecl * D,StringRef Message,SourceLocation Loc,const ObjCInterfaceDecl * UnknownObjCClass,const ObjCPropertyDecl * ObjCProperty,bool ObjCPropertyAccess)5188*0a6a1f1dSLionel Sambuc void Sema::EmitAvailabilityWarning(AvailabilityDiagnostic AD,
5189*0a6a1f1dSLionel Sambuc                                    NamedDecl *D, StringRef Message,
5190f4a2713aSLionel Sambuc                                    SourceLocation Loc,
5191f4a2713aSLionel Sambuc                                    const ObjCInterfaceDecl *UnknownObjCClass,
5192*0a6a1f1dSLionel Sambuc                                    const ObjCPropertyDecl  *ObjCProperty,
5193*0a6a1f1dSLionel Sambuc                                    bool ObjCPropertyAccess) {
5194f4a2713aSLionel Sambuc   // Delay if we're currently parsing a declaration.
5195f4a2713aSLionel Sambuc   if (DelayedDiagnostics.shouldDelayDiagnostics()) {
5196*0a6a1f1dSLionel Sambuc     DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability(
5197*0a6a1f1dSLionel Sambuc         AD, Loc, D, UnknownObjCClass, ObjCProperty, Message,
5198*0a6a1f1dSLionel Sambuc         ObjCPropertyAccess));
5199f4a2713aSLionel Sambuc     return;
5200f4a2713aSLionel Sambuc   }
5201f4a2713aSLionel Sambuc 
5202*0a6a1f1dSLionel Sambuc   Decl *Ctx = cast<Decl>(getCurLexicalContext());
5203*0a6a1f1dSLionel Sambuc   DelayedDiagnostic::DDKind K;
5204*0a6a1f1dSLionel Sambuc   switch (AD) {
5205*0a6a1f1dSLionel Sambuc     case AD_Deprecation:
5206*0a6a1f1dSLionel Sambuc       K = DelayedDiagnostic::Deprecation;
5207*0a6a1f1dSLionel Sambuc       break;
5208*0a6a1f1dSLionel Sambuc     case AD_Unavailable:
5209*0a6a1f1dSLionel Sambuc       K = DelayedDiagnostic::Unavailable;
5210*0a6a1f1dSLionel Sambuc       break;
5211*0a6a1f1dSLionel Sambuc   }
5212*0a6a1f1dSLionel Sambuc 
5213*0a6a1f1dSLionel Sambuc   DoEmitAvailabilityWarning(*this, K, Ctx, D, Message, Loc,
5214*0a6a1f1dSLionel Sambuc                             UnknownObjCClass, ObjCProperty, ObjCPropertyAccess);
5215f4a2713aSLionel Sambuc }
5216