blob: 430b4f99fb24f25c795eb13fd1184bd39af40ea5 [file] [log] [blame]
Chris Lattner6b6b5372008-06-26 18:38:35 +00001//===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements decl-related attribute processing.
11//
12//===----------------------------------------------------------------------===//
13
John McCall2d887082010-08-25 22:03:47 +000014#include "clang/Sema/SemaInternal.h"
Anton Korobeynikov82d0a412010-01-10 12:58:08 +000015#include "TargetAttributesSema.h"
Chris Lattner6b6b5372008-06-26 18:38:35 +000016#include "clang/AST/ASTContext.h"
John McCall384aff82010-08-25 07:42:41 +000017#include "clang/AST/DeclCXX.h"
Daniel Dunbaracc5f3e2008-08-11 06:23:49 +000018#include "clang/AST/DeclObjC.h"
19#include "clang/AST/Expr.h"
Chris Lattnerfbf13472008-06-27 22:18:37 +000020#include "clang/Basic/TargetInfo.h"
John McCall19510852010-08-20 18:27:03 +000021#include "clang/Sema/DeclSpec.h"
John McCall9c3087b2010-08-26 02:13:20 +000022#include "clang/Sema/DelayedDiagnostic.h"
Chris Lattner797c3c42009-08-10 19:03:04 +000023#include "llvm/ADT/StringExtras.h"
Chris Lattner6b6b5372008-06-26 18:38:35 +000024using namespace clang;
John McCall9c3087b2010-08-26 02:13:20 +000025using namespace sema;
Chris Lattner6b6b5372008-06-26 18:38:35 +000026
John McCall883cc2c2011-03-02 12:29:23 +000027/// These constants match the enumerated choices of
28/// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
29enum {
30 ExpectedFunction,
31 ExpectedUnion,
32 ExpectedVariableOrFunction,
33 ExpectedFunctionOrMethod,
34 ExpectedParameter,
35 ExpectedParameterOrMethod,
36 ExpectedFunctionMethodOrBlock,
37 ExpectedClassOrVirtualMethod,
38 ExpectedFunctionMethodOrParameter,
39 ExpectedClass,
40 ExpectedVirtualMethod,
41 ExpectedClassMember,
42 ExpectedVariable,
43 ExpectedMethod,
44 ExpectedVariableFunctionOrLabel
45};
46
Chris Lattnere5c5ee12008-06-29 00:16:31 +000047//===----------------------------------------------------------------------===//
48// Helper functions
49//===----------------------------------------------------------------------===//
50
Ted Kremeneka18d7d82009-08-14 20:49:40 +000051static const FunctionType *getFunctionType(const Decl *d,
52 bool blocksToo = true) {
Chris Lattner6b6b5372008-06-26 18:38:35 +000053 QualType Ty;
Ted Kremeneka18d7d82009-08-14 20:49:40 +000054 if (const ValueDecl *decl = dyn_cast<ValueDecl>(d))
Chris Lattner6b6b5372008-06-26 18:38:35 +000055 Ty = decl->getType();
Ted Kremeneka18d7d82009-08-14 20:49:40 +000056 else if (const FieldDecl *decl = dyn_cast<FieldDecl>(d))
Chris Lattner6b6b5372008-06-26 18:38:35 +000057 Ty = decl->getType();
Richard Smith162e1c12011-04-15 14:24:37 +000058 else if (const TypedefNameDecl* decl = dyn_cast<TypedefNameDecl>(d))
Chris Lattner6b6b5372008-06-26 18:38:35 +000059 Ty = decl->getUnderlyingType();
60 else
61 return 0;
Mike Stumpbf916502009-07-24 19:02:52 +000062
Chris Lattner6b6b5372008-06-26 18:38:35 +000063 if (Ty->isFunctionPointerType())
Ted Kremenek6217b802009-07-29 21:53:49 +000064 Ty = Ty->getAs<PointerType>()->getPointeeType();
Fariborz Jahanian755f9d22009-05-18 17:39:25 +000065 else if (blocksToo && Ty->isBlockPointerType())
Ted Kremenek6217b802009-07-29 21:53:49 +000066 Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
Daniel Dunbard3f2c102008-10-19 02:04:16 +000067
John McCall183700f2009-09-21 23:43:11 +000068 return Ty->getAs<FunctionType>();
Chris Lattner6b6b5372008-06-26 18:38:35 +000069}
70
Daniel Dunbar35682492008-09-26 04:12:28 +000071// FIXME: We should provide an abstraction around a method or function
72// to provide the following bits of information.
73
Nuno Lopesd20254f2009-12-20 23:11:08 +000074/// isFunction - Return true if the given decl has function
Ted Kremeneka18d7d82009-08-14 20:49:40 +000075/// type (function or function-typed variable).
76static bool isFunction(const Decl *d) {
77 return getFunctionType(d, false) != NULL;
78}
79
80/// isFunctionOrMethod - Return true if the given decl has function
Daniel Dunbard3f2c102008-10-19 02:04:16 +000081/// type (function or function-typed variable) or an Objective-C
82/// method.
Ted Kremeneka18d7d82009-08-14 20:49:40 +000083static bool isFunctionOrMethod(const Decl *d) {
84 return isFunction(d)|| isa<ObjCMethodDecl>(d);
Daniel Dunbar35682492008-09-26 04:12:28 +000085}
86
Fariborz Jahanian620d89c2009-05-15 23:15:03 +000087/// isFunctionOrMethodOrBlock - Return true if the given decl has function
88/// type (function or function-typed variable) or an Objective-C
89/// method or a block.
Ted Kremeneka18d7d82009-08-14 20:49:40 +000090static bool isFunctionOrMethodOrBlock(const Decl *d) {
Fariborz Jahanian620d89c2009-05-15 23:15:03 +000091 if (isFunctionOrMethod(d))
92 return true;
93 // check for block is more involved.
94 if (const VarDecl *V = dyn_cast<VarDecl>(d)) {
95 QualType Ty = V->getType();
96 return Ty->isBlockPointerType();
97 }
Fariborz Jahaniand66f22d2009-05-19 17:08:59 +000098 return isa<BlockDecl>(d);
Fariborz Jahanian620d89c2009-05-15 23:15:03 +000099}
100
John McCall711c52b2011-01-05 12:14:39 +0000101/// Return true if the given decl has a declarator that should have
102/// been processed by Sema::GetTypeForDeclarator.
103static bool hasDeclarator(const Decl *d) {
Richard Smith162e1c12011-04-15 14:24:37 +0000104 // In some sense, TypedefNameDecl really *ought* to be a DeclaratorDecl.
105 return isa<DeclaratorDecl>(d) || isa<BlockDecl>(d) || isa<TypedefNameDecl>(d);
John McCall711c52b2011-01-05 12:14:39 +0000106}
107
Daniel Dunbard3f2c102008-10-19 02:04:16 +0000108/// hasFunctionProto - Return true if the given decl has a argument
109/// information. This decl should have already passed
Fariborz Jahanian620d89c2009-05-15 23:15:03 +0000110/// isFunctionOrMethod or isFunctionOrMethodOrBlock.
Ted Kremeneka18d7d82009-08-14 20:49:40 +0000111static bool hasFunctionProto(const Decl *d) {
Fariborz Jahanian620d89c2009-05-15 23:15:03 +0000112 if (const FunctionType *FnTy = getFunctionType(d))
Douglas Gregor72564e72009-02-26 23:50:07 +0000113 return isa<FunctionProtoType>(FnTy);
Fariborz Jahanian620d89c2009-05-15 23:15:03 +0000114 else {
Fariborz Jahaniand66f22d2009-05-19 17:08:59 +0000115 assert(isa<ObjCMethodDecl>(d) || isa<BlockDecl>(d));
Daniel Dunbard3f2c102008-10-19 02:04:16 +0000116 return true;
117 }
118}
119
120/// getFunctionOrMethodNumArgs - Return number of function or method
121/// arguments. It is an error to call this on a K&R function (use
122/// hasFunctionProto first).
Ted Kremeneka18d7d82009-08-14 20:49:40 +0000123static unsigned getFunctionOrMethodNumArgs(const Decl *d) {
Chris Lattner89951a82009-02-20 18:43:26 +0000124 if (const FunctionType *FnTy = getFunctionType(d))
Douglas Gregor72564e72009-02-26 23:50:07 +0000125 return cast<FunctionProtoType>(FnTy)->getNumArgs();
Fariborz Jahaniand66f22d2009-05-19 17:08:59 +0000126 if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
127 return BD->getNumParams();
Chris Lattner89951a82009-02-20 18:43:26 +0000128 return cast<ObjCMethodDecl>(d)->param_size();
Daniel Dunbar35682492008-09-26 04:12:28 +0000129}
130
Ted Kremeneka18d7d82009-08-14 20:49:40 +0000131static QualType getFunctionOrMethodArgType(const Decl *d, unsigned Idx) {
Chris Lattner89951a82009-02-20 18:43:26 +0000132 if (const FunctionType *FnTy = getFunctionType(d))
Douglas Gregor72564e72009-02-26 23:50:07 +0000133 return cast<FunctionProtoType>(FnTy)->getArgType(Idx);
Fariborz Jahaniand66f22d2009-05-19 17:08:59 +0000134 if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
135 return BD->getParamDecl(Idx)->getType();
Mike Stumpbf916502009-07-24 19:02:52 +0000136
Chris Lattner89951a82009-02-20 18:43:26 +0000137 return cast<ObjCMethodDecl>(d)->param_begin()[Idx]->getType();
Daniel Dunbar35682492008-09-26 04:12:28 +0000138}
139
Ted Kremeneka18d7d82009-08-14 20:49:40 +0000140static QualType getFunctionOrMethodResultType(const Decl *d) {
Fariborz Jahanian5b160922009-05-20 17:41:43 +0000141 if (const FunctionType *FnTy = getFunctionType(d))
142 return cast<FunctionProtoType>(FnTy)->getResultType();
143 return cast<ObjCMethodDecl>(d)->getResultType();
144}
145
Ted Kremeneka18d7d82009-08-14 20:49:40 +0000146static bool isFunctionOrMethodVariadic(const Decl *d) {
Daniel Dunbard3f2c102008-10-19 02:04:16 +0000147 if (const FunctionType *FnTy = getFunctionType(d)) {
Douglas Gregor72564e72009-02-26 23:50:07 +0000148 const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy);
Daniel Dunbar35682492008-09-26 04:12:28 +0000149 return proto->isVariadic();
Fariborz Jahaniand66f22d2009-05-19 17:08:59 +0000150 } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
Ted Kremenekdb9a0ae2010-04-29 16:48:58 +0000151 return BD->isVariadic();
Fariborz Jahaniand66f22d2009-05-19 17:08:59 +0000152 else {
Daniel Dunbar35682492008-09-26 04:12:28 +0000153 return cast<ObjCMethodDecl>(d)->isVariadic();
154 }
155}
156
Chandler Carruth07d7e7a2010-11-16 08:35:43 +0000157static bool isInstanceMethod(const Decl *d) {
158 if (const CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(d))
159 return MethodDecl->isInstance();
160 return false;
161}
162
Chris Lattner6b6b5372008-06-26 18:38:35 +0000163static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
John McCall183700f2009-09-21 23:43:11 +0000164 const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
Chris Lattnerb77792e2008-07-26 22:17:49 +0000165 if (!PT)
Chris Lattner6b6b5372008-06-26 18:38:35 +0000166 return false;
Mike Stumpbf916502009-07-24 19:02:52 +0000167
John McCall506b57e2010-05-17 21:00:27 +0000168 ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface();
169 if (!Cls)
Chris Lattner6b6b5372008-06-26 18:38:35 +0000170 return false;
Mike Stumpbf916502009-07-24 19:02:52 +0000171
John McCall506b57e2010-05-17 21:00:27 +0000172 IdentifierInfo* ClsName = Cls->getIdentifier();
Mike Stumpbf916502009-07-24 19:02:52 +0000173
Chris Lattner6b6b5372008-06-26 18:38:35 +0000174 // FIXME: Should we walk the chain of classes?
175 return ClsName == &Ctx.Idents.get("NSString") ||
176 ClsName == &Ctx.Idents.get("NSMutableString");
177}
178
Daniel Dunbar085e8f72008-09-26 03:32:58 +0000179static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
Ted Kremenek6217b802009-07-29 21:53:49 +0000180 const PointerType *PT = T->getAs<PointerType>();
Daniel Dunbar085e8f72008-09-26 03:32:58 +0000181 if (!PT)
182 return false;
183
Ted Kremenek6217b802009-07-29 21:53:49 +0000184 const RecordType *RT = PT->getPointeeType()->getAs<RecordType>();
Daniel Dunbar085e8f72008-09-26 03:32:58 +0000185 if (!RT)
186 return false;
Mike Stumpbf916502009-07-24 19:02:52 +0000187
Daniel Dunbar085e8f72008-09-26 03:32:58 +0000188 const RecordDecl *RD = RT->getDecl();
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000189 if (RD->getTagKind() != TTK_Struct)
Daniel Dunbar085e8f72008-09-26 03:32:58 +0000190 return false;
191
192 return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
193}
194
Chris Lattnere5c5ee12008-06-29 00:16:31 +0000195//===----------------------------------------------------------------------===//
Chris Lattnere5c5ee12008-06-29 00:16:31 +0000196// Attribute Implementations
197//===----------------------------------------------------------------------===//
198
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000199// FIXME: All this manual attribute parsing code is gross. At the
200// least add some helper functions to check most argument patterns (#
201// and types of args).
202
Mike Stumpbf916502009-07-24 19:02:52 +0000203static void HandleExtVectorTypeAttr(Scope *scope, Decl *d,
Douglas Gregor9cdda0c2009-06-17 21:51:59 +0000204 const AttributeList &Attr, Sema &S) {
Richard Smith162e1c12011-04-15 14:24:37 +0000205 TypedefNameDecl *tDecl = dyn_cast<TypedefNameDecl>(d);
Chris Lattner545dd342008-06-28 23:36:30 +0000206 if (tDecl == 0) {
Chris Lattner803d0802008-06-29 00:43:07 +0000207 S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
Chris Lattner545dd342008-06-28 23:36:30 +0000208 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000209 }
Mike Stumpbf916502009-07-24 19:02:52 +0000210
Chris Lattner6b6b5372008-06-26 18:38:35 +0000211 QualType curType = tDecl->getUnderlyingType();
Douglas Gregor9cdda0c2009-06-17 21:51:59 +0000212
213 Expr *sizeExpr;
214
215 // Special case where the argument is a template id.
216 if (Attr.getParameterName()) {
John McCallf7a1a742009-11-24 19:00:30 +0000217 CXXScopeSpec SS;
218 UnqualifiedId id;
219 id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
Douglas Gregor4ac01402011-06-15 16:02:29 +0000220
221 ExprResult Size = S.ActOnIdExpression(scope, SS, id, false, false);
222 if (Size.isInvalid())
223 return;
224
225 sizeExpr = Size.get();
Douglas Gregor9cdda0c2009-06-17 21:51:59 +0000226 } else {
227 // check the attribute arguments.
228 if (Attr.getNumArgs() != 1) {
229 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
230 return;
231 }
Peter Collingbourne7a730022010-11-23 20:45:58 +0000232 sizeExpr = Attr.getArg(0);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000233 }
Douglas Gregor9cdda0c2009-06-17 21:51:59 +0000234
235 // Instantiate/Install the vector type, and let Sema build the type for us.
236 // This will run the reguired checks.
John McCall9ae2f072010-08-23 23:25:46 +0000237 QualType T = S.BuildExtVectorType(curType, sizeExpr, Attr.getLoc());
Douglas Gregor9cdda0c2009-06-17 21:51:59 +0000238 if (!T.isNull()) {
John McCallba6a9bd2009-10-24 08:00:42 +0000239 // FIXME: preserve the old source info.
John McCalla93c9342009-12-07 02:54:59 +0000240 tDecl->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(T));
Mike Stumpbf916502009-07-24 19:02:52 +0000241
Douglas Gregor9cdda0c2009-06-17 21:51:59 +0000242 // Remember this typedef decl, we will need it later for diagnostics.
243 S.ExtVectorDecls.push_back(tDecl);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000244 }
Chris Lattner6b6b5372008-06-26 18:38:35 +0000245}
246
Chris Lattner803d0802008-06-29 00:43:07 +0000247static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000248 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000249 if (Attr.getNumArgs() > 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +0000250 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000251 return;
252 }
Mike Stumpbf916502009-07-24 19:02:52 +0000253
Chris Lattner6b6b5372008-06-26 18:38:35 +0000254 if (TagDecl *TD = dyn_cast<TagDecl>(d))
Sean Huntcf807c42010-08-18 23:23:40 +0000255 TD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000256 else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
257 // If the alignment is less than or equal to 8 bits, the packed attribute
258 // has no effect.
259 if (!FD->getType()->isIncompleteType() &&
Chris Lattner803d0802008-06-29 00:43:07 +0000260 S.Context.getTypeAlign(FD->getType()) <= 8)
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000261 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
Chris Lattner08631c52008-11-23 21:45:46 +0000262 << Attr.getName() << FD->getType();
Chris Lattner6b6b5372008-06-26 18:38:35 +0000263 else
Sean Huntcf807c42010-08-18 23:23:40 +0000264 FD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000265 } else
Chris Lattner3c73c412008-11-19 08:23:25 +0000266 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
Chris Lattner6b6b5372008-06-26 18:38:35 +0000267}
268
Fariborz Jahanianc1a0a732011-04-26 17:54:40 +0000269static void HandleMsStructAttr(Decl *d, const AttributeList &Attr, Sema &S) {
270 if (TagDecl *TD = dyn_cast<TagDecl>(d))
271 TD->addAttr(::new (S.Context) MsStructAttr(Attr.getLoc(), S.Context));
272 else
273 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
274}
275
Ted Kremenek63e5d7c2010-02-18 03:08:58 +0000276static void HandleIBAction(Decl *d, const AttributeList &Attr, Sema &S) {
Ted Kremenek96329d42008-07-15 22:26:48 +0000277 // check the attribute arguments.
278 if (Attr.getNumArgs() > 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +0000279 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Ted Kremenek96329d42008-07-15 22:26:48 +0000280 return;
281 }
Mike Stumpbf916502009-07-24 19:02:52 +0000282
Ted Kremenek63e5d7c2010-02-18 03:08:58 +0000283 // The IBAction attributes only apply to instance methods.
284 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
285 if (MD->isInstanceMethod()) {
Sean Huntcf807c42010-08-18 23:23:40 +0000286 d->addAttr(::new (S.Context) IBActionAttr(Attr.getLoc(), S.Context));
Ted Kremenek63e5d7c2010-02-18 03:08:58 +0000287 return;
288 }
289
Ted Kremenek4ee2bb12011-02-04 06:54:16 +0000290 S.Diag(Attr.getLoc(), diag::warn_attribute_ibaction) << Attr.getName();
Ted Kremenek63e5d7c2010-02-18 03:08:58 +0000291}
292
293static void HandleIBOutlet(Decl *d, const AttributeList &Attr, Sema &S) {
294 // check the attribute arguments.
295 if (Attr.getNumArgs() > 0) {
296 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
297 return;
298 }
299
300 // The IBOutlet attributes only apply to instance variables of
Ted Kremenekefbddd22010-02-17 02:37:45 +0000301 // Objective-C classes.
302 if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d)) {
Sean Huntcf807c42010-08-18 23:23:40 +0000303 d->addAttr(::new (S.Context) IBOutletAttr(Attr.getLoc(), S.Context));
Ted Kremenek63e5d7c2010-02-18 03:08:58 +0000304 return;
Ted Kremenekefbddd22010-02-17 02:37:45 +0000305 }
Ted Kremenek63e5d7c2010-02-18 03:08:58 +0000306
Ted Kremenek4ee2bb12011-02-04 06:54:16 +0000307 S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName();
Ted Kremenek96329d42008-07-15 22:26:48 +0000308}
309
Ted Kremenek857e9182010-05-19 17:38:06 +0000310static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr,
311 Sema &S) {
312
313 // The iboutletcollection attribute can have zero or one arguments.
Fariborz Jahaniana8fb24f2010-08-17 20:23:12 +0000314 if (Attr.getParameterName() && Attr.getNumArgs() > 0) {
Ted Kremenek857e9182010-05-19 17:38:06 +0000315 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
316 return;
317 }
318
319 // The IBOutletCollection attributes only apply to instance variables of
320 // Objective-C classes.
321 if (!(isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d))) {
Ted Kremenek4ee2bb12011-02-04 06:54:16 +0000322 S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName();
Ted Kremenek857e9182010-05-19 17:38:06 +0000323 return;
324 }
Fariborz Jahanian3a3400b2010-08-17 21:39:27 +0000325 if (const ValueDecl *VD = dyn_cast<ValueDecl>(d))
326 if (!VD->getType()->getAs<ObjCObjectPointerType>()) {
327 S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type)
328 << VD->getType() << 0;
329 return;
330 }
331 if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(d))
332 if (!PD->getType()->getAs<ObjCObjectPointerType>()) {
333 S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type)
334 << PD->getType() << 1;
335 return;
336 }
337
Fariborz Jahaniana8fb24f2010-08-17 20:23:12 +0000338 IdentifierInfo *II = Attr.getParameterName();
339 if (!II)
340 II = &S.Context.Idents.get("id");
Fariborz Jahanian3a3400b2010-08-17 21:39:27 +0000341
John McCallb3d87482010-08-24 05:47:05 +0000342 ParsedType TypeRep = S.getTypeName(*II, Attr.getLoc(),
Fariborz Jahaniana8fb24f2010-08-17 20:23:12 +0000343 S.getScopeForContext(d->getDeclContext()->getParent()));
344 if (!TypeRep) {
345 S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
346 return;
347 }
John McCallb3d87482010-08-24 05:47:05 +0000348 QualType QT = TypeRep.get();
Fariborz Jahaniana8fb24f2010-08-17 20:23:12 +0000349 // Diagnose use of non-object type in iboutletcollection attribute.
350 // FIXME. Gnu attribute extension ignores use of builtin types in
351 // attributes. So, __attribute__((iboutletcollection(char))) will be
352 // treated as __attribute__((iboutletcollection())).
353 if (!QT->isObjCIdType() && !QT->isObjCClassType() &&
354 !QT->isObjCObjectType()) {
355 S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
356 return;
357 }
Sean Huntcf807c42010-08-18 23:23:40 +0000358 d->addAttr(::new (S.Context) IBOutletCollectionAttr(Attr.getLoc(), S.Context,
359 QT));
Ted Kremenek857e9182010-05-19 17:38:06 +0000360}
361
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000362static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Mike Stumpbf916502009-07-24 19:02:52 +0000363 // GCC ignores the nonnull attribute on K&R style function prototypes, so we
364 // ignore it as well
Daniel Dunbard3f2c102008-10-19 02:04:16 +0000365 if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000366 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +0000367 << Attr.getName() << ExpectedFunction;
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000368 return;
369 }
Mike Stumpbf916502009-07-24 19:02:52 +0000370
Chandler Carruth07d7e7a2010-11-16 08:35:43 +0000371 // In C++ the implicit 'this' function parameter also counts, and they are
372 // counted from one.
373 bool HasImplicitThisParam = isInstanceMethod(d);
374 unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam;
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000375
376 // The nonnull attribute only applies to pointers.
377 llvm::SmallVector<unsigned, 10> NonNullArgs;
Mike Stumpbf916502009-07-24 19:02:52 +0000378
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000379 for (AttributeList::arg_iterator I=Attr.arg_begin(),
380 E=Attr.arg_end(); I!=E; ++I) {
Mike Stumpbf916502009-07-24 19:02:52 +0000381
382
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000383 // The argument must be an integer constant expression.
Peter Collingbourne7a730022010-11-23 20:45:58 +0000384 Expr *Ex = *I;
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000385 llvm::APSInt ArgNum(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +0000386 if (Ex->isTypeDependent() || Ex->isValueDependent() ||
387 !Ex->isIntegerConstantExpr(ArgNum, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000388 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
389 << "nonnull" << Ex->getSourceRange();
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000390 return;
391 }
Mike Stumpbf916502009-07-24 19:02:52 +0000392
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000393 unsigned x = (unsigned) ArgNum.getZExtValue();
Mike Stumpbf916502009-07-24 19:02:52 +0000394
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000395 if (x < 1 || x > NumArgs) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000396 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
Chris Lattner30bc9652008-11-19 07:22:31 +0000397 << "nonnull" << I.getArgNum() << Ex->getSourceRange();
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000398 return;
399 }
Mike Stumpbf916502009-07-24 19:02:52 +0000400
Ted Kremenek465172f2008-07-21 22:09:15 +0000401 --x;
Chandler Carruth07d7e7a2010-11-16 08:35:43 +0000402 if (HasImplicitThisParam) {
403 if (x == 0) {
404 S.Diag(Attr.getLoc(),
405 diag::err_attribute_invalid_implicit_this_argument)
406 << "nonnull" << Ex->getSourceRange();
407 return;
408 }
409 --x;
410 }
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000411
412 // Is the function argument a pointer type?
Douglas Gregorde436322010-12-15 15:41:46 +0000413 QualType T = getFunctionOrMethodArgType(d, x).getNonReferenceType();
Ted Kremenekdbfe99e2009-07-15 23:23:54 +0000414 if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000415 // FIXME: Should also highlight argument in decl.
Douglas Gregorc9ef4052010-08-12 18:48:43 +0000416 S.Diag(Attr.getLoc(), diag::warn_nonnull_pointers_only)
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000417 << "nonnull" << Ex->getSourceRange();
Ted Kremenek7fb43c12008-09-01 19:57:52 +0000418 continue;
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000419 }
Mike Stumpbf916502009-07-24 19:02:52 +0000420
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000421 NonNullArgs.push_back(x);
422 }
Mike Stumpbf916502009-07-24 19:02:52 +0000423
424 // If no arguments were specified to __attribute__((nonnull)) then all pointer
425 // arguments have a nonnull attribute.
Ted Kremenek7fb43c12008-09-01 19:57:52 +0000426 if (NonNullArgs.empty()) {
Ted Kremenek46bbaca2008-11-18 06:52:58 +0000427 for (unsigned I = 0, E = getFunctionOrMethodNumArgs(d); I != E; ++I) {
Douglas Gregorde436322010-12-15 15:41:46 +0000428 QualType T = getFunctionOrMethodArgType(d, I).getNonReferenceType();
Ted Kremenekdbfe99e2009-07-15 23:23:54 +0000429 if (T->isAnyPointerType() || T->isBlockPointerType())
Daniel Dunbard3f2c102008-10-19 02:04:16 +0000430 NonNullArgs.push_back(I);
Fariborz Jahanianff3a0782010-09-27 22:42:37 +0000431 else if (const RecordType *UT = T->getAsUnionType()) {
432 if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) {
433 RecordDecl *UD = UT->getDecl();
434 for (RecordDecl::field_iterator it = UD->field_begin(),
435 itend = UD->field_end(); it != itend; ++it) {
436 T = it->getType();
437 if (T->isAnyPointerType() || T->isBlockPointerType()) {
438 NonNullArgs.push_back(I);
439 break;
440 }
441 }
442 }
443 }
Ted Kremenek46bbaca2008-11-18 06:52:58 +0000444 }
Mike Stumpbf916502009-07-24 19:02:52 +0000445
Ted Kremenekee1c08c2010-10-21 18:49:36 +0000446 // No pointer arguments?
Fariborz Jahanian60acea42010-09-27 19:05:51 +0000447 if (NonNullArgs.empty()) {
448 // Warn the trivial case only if attribute is not coming from a
449 // macro instantiation.
450 if (Attr.getLoc().isFileID())
451 S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers);
Ted Kremenek7fb43c12008-09-01 19:57:52 +0000452 return;
Fariborz Jahanian60acea42010-09-27 19:05:51 +0000453 }
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000454 }
Ted Kremenek7fb43c12008-09-01 19:57:52 +0000455
456 unsigned* start = &NonNullArgs[0];
457 unsigned size = NonNullArgs.size();
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000458 llvm::array_pod_sort(start, start + size);
Sean Huntcf807c42010-08-18 23:23:40 +0000459 d->addAttr(::new (S.Context) NonNullAttr(Attr.getLoc(), S.Context, start,
460 size));
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000461}
462
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000463static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
464 // This attribute must be applied to a function declaration.
465 // The first argument to the attribute must be a string,
466 // the name of the resource, for example "malloc".
467 // The following arguments must be argument indexes, the arguments must be
468 // of integer type for Returns, otherwise of pointer type.
469 // The difference between Holds and Takes is that a pointer may still be used
Jordy Rose2a479922010-08-12 08:54:03 +0000470 // after being held. free() should be __attribute((ownership_takes)), whereas
471 // a list append function may well be __attribute((ownership_holds)).
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000472
473 if (!AL.getParameterName()) {
474 S.Diag(AL.getLoc(), diag::err_attribute_argument_n_not_string)
475 << AL.getName()->getName() << 1;
476 return;
477 }
478 // Figure out our Kind, and check arguments while we're at it.
Sean Huntcf807c42010-08-18 23:23:40 +0000479 OwnershipAttr::OwnershipKind K;
Jordy Rose2a479922010-08-12 08:54:03 +0000480 switch (AL.getKind()) {
481 case AttributeList::AT_ownership_takes:
Sean Huntcf807c42010-08-18 23:23:40 +0000482 K = OwnershipAttr::Takes;
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000483 if (AL.getNumArgs() < 1) {
484 S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
485 return;
486 }
Jordy Rose2a479922010-08-12 08:54:03 +0000487 break;
488 case AttributeList::AT_ownership_holds:
Sean Huntcf807c42010-08-18 23:23:40 +0000489 K = OwnershipAttr::Holds;
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000490 if (AL.getNumArgs() < 1) {
491 S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
492 return;
493 }
Jordy Rose2a479922010-08-12 08:54:03 +0000494 break;
495 case AttributeList::AT_ownership_returns:
Sean Huntcf807c42010-08-18 23:23:40 +0000496 K = OwnershipAttr::Returns;
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000497 if (AL.getNumArgs() > 1) {
498 S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
499 << AL.getNumArgs() + 1;
500 return;
501 }
Jordy Rose2a479922010-08-12 08:54:03 +0000502 break;
503 default:
504 // This should never happen given how we are called.
505 llvm_unreachable("Unknown ownership attribute");
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000506 }
507
508 if (!isFunction(d) || !hasFunctionProto(d)) {
John McCall883cc2c2011-03-02 12:29:23 +0000509 S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
510 << AL.getName() << ExpectedFunction;
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000511 return;
512 }
513
Chandler Carruth07d7e7a2010-11-16 08:35:43 +0000514 // In C++ the implicit 'this' function parameter also counts, and they are
515 // counted from one.
516 bool HasImplicitThisParam = isInstanceMethod(d);
517 unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam;
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000518
519 llvm::StringRef Module = AL.getParameterName()->getName();
520
521 // Normalize the argument, __foo__ becomes foo.
522 if (Module.startswith("__") && Module.endswith("__"))
523 Module = Module.substr(2, Module.size() - 4);
524
525 llvm::SmallVector<unsigned, 10> OwnershipArgs;
526
Jordy Rose2a479922010-08-12 08:54:03 +0000527 for (AttributeList::arg_iterator I = AL.arg_begin(), E = AL.arg_end(); I != E;
528 ++I) {
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000529
Peter Collingbourne7a730022010-11-23 20:45:58 +0000530 Expr *IdxExpr = *I;
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000531 llvm::APSInt ArgNum(32);
532 if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent()
533 || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) {
534 S.Diag(AL.getLoc(), diag::err_attribute_argument_not_int)
535 << AL.getName()->getName() << IdxExpr->getSourceRange();
536 continue;
537 }
538
539 unsigned x = (unsigned) ArgNum.getZExtValue();
540
541 if (x > NumArgs || x < 1) {
542 S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
543 << AL.getName()->getName() << x << IdxExpr->getSourceRange();
544 continue;
545 }
546 --x;
Chandler Carruth07d7e7a2010-11-16 08:35:43 +0000547 if (HasImplicitThisParam) {
548 if (x == 0) {
549 S.Diag(AL.getLoc(), diag::err_attribute_invalid_implicit_this_argument)
550 << "ownership" << IdxExpr->getSourceRange();
551 return;
552 }
553 --x;
554 }
555
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000556 switch (K) {
Sean Huntcf807c42010-08-18 23:23:40 +0000557 case OwnershipAttr::Takes:
558 case OwnershipAttr::Holds: {
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000559 // Is the function argument a pointer type?
560 QualType T = getFunctionOrMethodArgType(d, x);
561 if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
562 // FIXME: Should also highlight argument in decl.
563 S.Diag(AL.getLoc(), diag::err_ownership_type)
Sean Huntcf807c42010-08-18 23:23:40 +0000564 << ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds")
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000565 << "pointer"
566 << IdxExpr->getSourceRange();
567 continue;
568 }
569 break;
570 }
Sean Huntcf807c42010-08-18 23:23:40 +0000571 case OwnershipAttr::Returns: {
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000572 if (AL.getNumArgs() > 1) {
573 // Is the function argument an integer type?
Peter Collingbourne7a730022010-11-23 20:45:58 +0000574 Expr *IdxExpr = AL.getArg(0);
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000575 llvm::APSInt ArgNum(32);
576 if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent()
577 || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) {
578 S.Diag(AL.getLoc(), diag::err_ownership_type)
579 << "ownership_returns" << "integer"
580 << IdxExpr->getSourceRange();
581 return;
582 }
583 }
584 break;
585 }
Jordy Rose2a479922010-08-12 08:54:03 +0000586 default:
587 llvm_unreachable("Unknown ownership attribute");
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000588 } // switch
589
590 // Check we don't have a conflict with another ownership attribute.
Sean Huntcf807c42010-08-18 23:23:40 +0000591 for (specific_attr_iterator<OwnershipAttr>
592 i = d->specific_attr_begin<OwnershipAttr>(),
593 e = d->specific_attr_end<OwnershipAttr>();
594 i != e; ++i) {
595 if ((*i)->getOwnKind() != K) {
596 for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end();
597 I!=E; ++I) {
598 if (x == *I) {
599 S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
600 << AL.getName()->getName() << "ownership_*";
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000601 }
602 }
603 }
604 }
605 OwnershipArgs.push_back(x);
606 }
607
608 unsigned* start = OwnershipArgs.data();
609 unsigned size = OwnershipArgs.size();
610 llvm::array_pod_sort(start, start + size);
Sean Huntcf807c42010-08-18 23:23:40 +0000611
612 if (K != OwnershipAttr::Returns && OwnershipArgs.empty()) {
613 S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
614 return;
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000615 }
Sean Huntcf807c42010-08-18 23:23:40 +0000616
617 d->addAttr(::new (S.Context) OwnershipAttr(AL.getLoc(), S.Context, K, Module,
618 start, size));
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000619}
620
John McCall332bb2a2011-02-08 22:35:49 +0000621/// Whether this declaration has internal linkage for the purposes of
622/// things that want to complain about things not have internal linkage.
623static bool hasEffectivelyInternalLinkage(NamedDecl *D) {
624 switch (D->getLinkage()) {
625 case NoLinkage:
626 case InternalLinkage:
627 return true;
628
629 // Template instantiations that go from external to unique-external
630 // shouldn't get diagnosed.
631 case UniqueExternalLinkage:
632 return true;
633
634 case ExternalLinkage:
635 return false;
636 }
637 llvm_unreachable("unknown linkage kind!");
Rafael Espindola11e8ce72010-02-23 22:00:30 +0000638 return false;
639}
640
641static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) {
642 // Check the attribute arguments.
643 if (Attr.getNumArgs() > 1) {
644 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
645 return;
646 }
647
John McCall332bb2a2011-02-08 22:35:49 +0000648 if (!isa<VarDecl>(d) && !isa<FunctionDecl>(d)) {
649 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +0000650 << Attr.getName() << ExpectedVariableOrFunction;
John McCall332bb2a2011-02-08 22:35:49 +0000651 return;
652 }
653
654 NamedDecl *nd = cast<NamedDecl>(d);
655
Rafael Espindola11e8ce72010-02-23 22:00:30 +0000656 // gcc rejects
657 // class c {
658 // static int a __attribute__((weakref ("v2")));
659 // static int b() __attribute__((weakref ("f3")));
660 // };
661 // and ignores the attributes of
662 // void f(void) {
663 // static int a __attribute__((weakref ("v2")));
664 // }
665 // we reject them
Sebastian Redl7a126a42010-08-31 00:36:30 +0000666 const DeclContext *Ctx = d->getDeclContext()->getRedeclContext();
667 if (!Ctx->isFileContext()) {
668 S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) <<
John McCall332bb2a2011-02-08 22:35:49 +0000669 nd->getNameAsString();
Sebastian Redl7a126a42010-08-31 00:36:30 +0000670 return;
Rafael Espindola11e8ce72010-02-23 22:00:30 +0000671 }
672
673 // The GCC manual says
674 //
675 // At present, a declaration to which `weakref' is attached can only
676 // be `static'.
677 //
678 // It also says
679 //
680 // Without a TARGET,
681 // given as an argument to `weakref' or to `alias', `weakref' is
682 // equivalent to `weak'.
683 //
684 // gcc 4.4.1 will accept
685 // int a7 __attribute__((weakref));
686 // as
687 // int a7 __attribute__((weak));
688 // This looks like a bug in gcc. We reject that for now. We should revisit
689 // it if this behaviour is actually used.
690
John McCall332bb2a2011-02-08 22:35:49 +0000691 if (!hasEffectivelyInternalLinkage(nd)) {
692 S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_static);
Rafael Espindola11e8ce72010-02-23 22:00:30 +0000693 return;
694 }
695
696 // GCC rejects
697 // static ((alias ("y"), weakref)).
698 // Should we? How to check that weakref is before or after alias?
699
700 if (Attr.getNumArgs() == 1) {
Peter Collingbourne7a730022010-11-23 20:45:58 +0000701 Expr *Arg = Attr.getArg(0);
Rafael Espindola11e8ce72010-02-23 22:00:30 +0000702 Arg = Arg->IgnoreParenCasts();
703 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
704
705 if (Str == 0 || Str->isWide()) {
706 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
707 << "weakref" << 1;
708 return;
709 }
710 // GCC will accept anything as the argument of weakref. Should we
711 // check for an existing decl?
Eric Christopherf48f3672010-12-01 22:13:54 +0000712 d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context,
713 Str->getString()));
Rafael Espindola11e8ce72010-02-23 22:00:30 +0000714 }
715
Sean Huntcf807c42010-08-18 23:23:40 +0000716 d->addAttr(::new (S.Context) WeakRefAttr(Attr.getLoc(), S.Context));
Rafael Espindola11e8ce72010-02-23 22:00:30 +0000717}
718
Chris Lattner803d0802008-06-29 00:43:07 +0000719static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000720 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000721 if (Attr.getNumArgs() != 1) {
Chris Lattner3c73c412008-11-19 08:23:25 +0000722 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000723 return;
724 }
Mike Stumpbf916502009-07-24 19:02:52 +0000725
Peter Collingbourne7a730022010-11-23 20:45:58 +0000726 Expr *Arg = Attr.getArg(0);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000727 Arg = Arg->IgnoreParenCasts();
728 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
Mike Stumpbf916502009-07-24 19:02:52 +0000729
Chris Lattner6b6b5372008-06-26 18:38:35 +0000730 if (Str == 0 || Str->isWide()) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000731 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
Chris Lattner3c73c412008-11-19 08:23:25 +0000732 << "alias" << 1;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000733 return;
734 }
Mike Stumpbf916502009-07-24 19:02:52 +0000735
Daniel Dunbardb57a4c2011-04-19 21:43:27 +0000736 if (S.Context.Target.getTriple().isOSDarwin()) {
Rafael Espindolaf5fe2922010-12-07 15:23:23 +0000737 S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin);
738 return;
739 }
740
Chris Lattner6b6b5372008-06-26 18:38:35 +0000741 // FIXME: check if target symbol exists in current file
Mike Stumpbf916502009-07-24 19:02:52 +0000742
Eric Christopherf48f3672010-12-01 22:13:54 +0000743 d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context,
744 Str->getString()));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000745}
746
Daniel Dunbardd0cb222010-09-29 18:20:25 +0000747static void HandleNakedAttr(Decl *d, const AttributeList &Attr,
Daniel Dunbaraf668b02008-10-28 00:17:57 +0000748 Sema &S) {
Daniel Dunbardd0cb222010-09-29 18:20:25 +0000749 // Check the attribute arguments.
Daniel Dunbaraf668b02008-10-28 00:17:57 +0000750 if (Attr.getNumArgs() != 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +0000751 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Daniel Dunbaraf668b02008-10-28 00:17:57 +0000752 return;
753 }
Anders Carlsson5bab7882009-02-19 19:16:48 +0000754
Chris Lattnerc5197432009-04-14 17:02:11 +0000755 if (!isa<FunctionDecl>(d)) {
Anders Carlsson5bab7882009-02-19 19:16:48 +0000756 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +0000757 << Attr.getName() << ExpectedFunction;
Daniel Dunbardd0cb222010-09-29 18:20:25 +0000758 return;
759 }
760
761 d->addAttr(::new (S.Context) NakedAttr(Attr.getLoc(), S.Context));
762}
763
764static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
765 Sema &S) {
766 // Check the attribute arguments.
Ted Kremenek831efae2011-04-15 05:49:29 +0000767 if (Attr.hasParameterOrArguments()) {
Daniel Dunbardd0cb222010-09-29 18:20:25 +0000768 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
769 return;
770 }
771
772 if (!isa<FunctionDecl>(d)) {
773 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +0000774 << Attr.getName() << ExpectedFunction;
Anders Carlsson5bab7882009-02-19 19:16:48 +0000775 return;
776 }
Mike Stumpbf916502009-07-24 19:02:52 +0000777
Sean Huntcf807c42010-08-18 23:23:40 +0000778 d->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getLoc(), S.Context));
Daniel Dunbaraf668b02008-10-28 00:17:57 +0000779}
780
Ryan Flynn76168e22009-08-09 20:07:29 +0000781static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Daniel Dunbardd0cb222010-09-29 18:20:25 +0000782 // Check the attribute arguments.
Ted Kremenek831efae2011-04-15 05:49:29 +0000783 if (Attr.hasParameterOrArguments()) {
Ryan Flynn76168e22009-08-09 20:07:29 +0000784 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
785 return;
786 }
Mike Stump1eb44332009-09-09 15:08:12 +0000787
Ted Kremenek2cff7d12009-08-15 00:51:46 +0000788 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000789 QualType RetTy = FD->getResultType();
Ted Kremenek2cff7d12009-08-15 00:51:46 +0000790 if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
Sean Huntcf807c42010-08-18 23:23:40 +0000791 d->addAttr(::new (S.Context) MallocAttr(Attr.getLoc(), S.Context));
Ted Kremenek2cff7d12009-08-15 00:51:46 +0000792 return;
793 }
Ryan Flynn76168e22009-08-09 20:07:29 +0000794 }
795
Ted Kremenek2cff7d12009-08-15 00:51:46 +0000796 S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only);
Ryan Flynn76168e22009-08-09 20:07:29 +0000797}
798
Dan Gohman34c26302010-11-17 00:03:07 +0000799static void HandleMayAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
800 // check the attribute arguments.
801 if (Attr.getNumArgs() != 0) {
802 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
803 return;
804 }
805
Dan Gohman34c26302010-11-17 00:03:07 +0000806 d->addAttr(::new (S.Context) MayAliasAttr(Attr.getLoc(), S.Context));
807}
808
Eric Christophera6cf1e72010-12-02 02:45:55 +0000809static void HandleNoCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) {
810 assert(Attr.isInvalid() == false);
Eric Christopher722109c2010-12-03 06:58:14 +0000811 if (isa<VarDecl>(d))
812 d->addAttr(::new (S.Context) NoCommonAttr(Attr.getLoc(), S.Context));
813 else
814 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +0000815 << Attr.getName() << ExpectedVariable;
Eric Christophera6cf1e72010-12-02 02:45:55 +0000816}
817
818static void HandleCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) {
819 assert(Attr.isInvalid() == false);
Eric Christopher722109c2010-12-03 06:58:14 +0000820 if (isa<VarDecl>(d))
821 d->addAttr(::new (S.Context) CommonAttr(Attr.getLoc(), S.Context));
822 else
823 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +0000824 << Attr.getName() << ExpectedVariable;
Eric Christophera6cf1e72010-12-02 02:45:55 +0000825}
826
John McCall711c52b2011-01-05 12:14:39 +0000827static void HandleNoReturnAttr(Decl *d, const AttributeList &attr, Sema &S) {
828 if (hasDeclarator(d)) return;
829
830 if (S.CheckNoReturnAttr(attr)) return;
831
832 if (!isa<ObjCMethodDecl>(d)) {
833 S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +0000834 << attr.getName() << ExpectedFunctionOrMethod;
John McCall711c52b2011-01-05 12:14:39 +0000835 return;
836 }
837
838 d->addAttr(::new (S.Context) NoReturnAttr(attr.getLoc(), S.Context));
839}
840
841bool Sema::CheckNoReturnAttr(const AttributeList &attr) {
Ted Kremenek831efae2011-04-15 05:49:29 +0000842 if (attr.hasParameterOrArguments()) {
John McCall711c52b2011-01-05 12:14:39 +0000843 Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
844 attr.setInvalid();
845 return true;
846 }
847
848 return false;
Ted Kremenekb7252322009-04-10 00:01:14 +0000849}
850
851static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
852 Sema &S) {
Ted Kremenekb56c1cc2010-08-19 00:51:58 +0000853
854 // The checking path for 'noreturn' and 'analyzer_noreturn' are different
855 // because 'analyzer_noreturn' does not impact the type.
856
857 if (Attr.getNumArgs() != 0) {
858 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
859 return;
860 }
861
862 if (!isFunctionOrMethod(d) && !isa<BlockDecl>(d)) {
863 ValueDecl *VD = dyn_cast<ValueDecl>(d);
864 if (VD == 0 || (!VD->getType()->isBlockPointerType()
865 && !VD->getType()->isFunctionPointerType())) {
866 S.Diag(Attr.getLoc(),
867 Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
868 : diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +0000869 << Attr.getName() << ExpectedFunctionMethodOrBlock;
Ted Kremenekb56c1cc2010-08-19 00:51:58 +0000870 return;
871 }
872 }
873
874 d->addAttr(::new (S.Context) AnalyzerNoReturnAttr(Attr.getLoc(), S.Context));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000875}
876
John Thompson35cc9622010-08-09 21:53:52 +0000877// PS3 PPU-specific.
878static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr,
879 Sema &S) {
880/*
881 Returning a Vector Class in Registers
882
Eric Christopherf48f3672010-12-01 22:13:54 +0000883 According to the PPU ABI specifications, a class with a single member of
884 vector type is returned in memory when used as the return value of a function.
885 This results in inefficient code when implementing vector classes. To return
886 the value in a single vector register, add the vecreturn attribute to the
887 class definition. This attribute is also applicable to struct types.
John Thompson35cc9622010-08-09 21:53:52 +0000888
889 Example:
890
891 struct Vector
892 {
893 __vector float xyzw;
894 } __attribute__((vecreturn));
895
896 Vector Add(Vector lhs, Vector rhs)
897 {
898 Vector result;
899 result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
900 return result; // This will be returned in a register
901 }
902*/
John Thompson01add592010-09-18 01:12:07 +0000903 if (!isa<RecordDecl>(d)) {
John Thompson35cc9622010-08-09 21:53:52 +0000904 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +0000905 << Attr.getName() << ExpectedClass;
John Thompson35cc9622010-08-09 21:53:52 +0000906 return;
907 }
908
909 if (d->getAttr<VecReturnAttr>()) {
910 S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn";
911 return;
912 }
913
John Thompson01add592010-09-18 01:12:07 +0000914 RecordDecl *record = cast<RecordDecl>(d);
915 int count = 0;
916
917 if (!isa<CXXRecordDecl>(record)) {
918 S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
919 return;
920 }
921
922 if (!cast<CXXRecordDecl>(record)->isPOD()) {
923 S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_pod_record);
924 return;
925 }
926
Eric Christopherf48f3672010-12-01 22:13:54 +0000927 for (RecordDecl::field_iterator iter = record->field_begin();
928 iter != record->field_end(); iter++) {
John Thompson01add592010-09-18 01:12:07 +0000929 if ((count == 1) || !iter->getType()->isVectorType()) {
930 S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
931 return;
932 }
933 count++;
934 }
935
Sean Huntcf807c42010-08-18 23:23:40 +0000936 d->addAttr(::new (S.Context) VecReturnAttr(Attr.getLoc(), S.Context));
John Thompson35cc9622010-08-09 21:53:52 +0000937}
938
Sean Huntbbd37c62009-11-21 08:43:09 +0000939static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
940 if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) {
941 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +0000942 << Attr.getName() << ExpectedFunctionMethodOrParameter;
Sean Huntbbd37c62009-11-21 08:43:09 +0000943 return;
944 }
945 // FIXME: Actually store the attribute on the declaration
946}
947
Ted Kremenek73798892008-07-25 04:39:19 +0000948static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
949 // check the attribute arguments.
Ted Kremenek831efae2011-04-15 05:49:29 +0000950 if (Attr.hasParameterOrArguments()) {
Chris Lattner3c73c412008-11-19 08:23:25 +0000951 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Ted Kremenek73798892008-07-25 04:39:19 +0000952 return;
953 }
Mike Stumpbf916502009-07-24 19:02:52 +0000954
John McCallaec58602010-03-31 02:47:45 +0000955 if (!isa<VarDecl>(d) && !isa<ObjCIvarDecl>(d) && !isFunctionOrMethod(d) &&
Chris Lattner57ad3782011-02-17 20:34:02 +0000956 !isa<TypeDecl>(d) && !isa<LabelDecl>(d)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000957 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +0000958 << Attr.getName() << ExpectedVariableFunctionOrLabel;
Ted Kremenek73798892008-07-25 04:39:19 +0000959 return;
960 }
Mike Stumpbf916502009-07-24 19:02:52 +0000961
Sean Huntcf807c42010-08-18 23:23:40 +0000962 d->addAttr(::new (S.Context) UnusedAttr(Attr.getLoc(), S.Context));
Ted Kremenek73798892008-07-25 04:39:19 +0000963}
964
Daniel Dunbarb805dad2009-02-13 19:23:53 +0000965static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
966 // check the attribute arguments.
Ted Kremenek831efae2011-04-15 05:49:29 +0000967 if (Attr.hasParameterOrArguments()) {
Daniel Dunbarb805dad2009-02-13 19:23:53 +0000968 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
969 return;
970 }
Mike Stumpbf916502009-07-24 19:02:52 +0000971
Daniel Dunbarb805dad2009-02-13 19:23:53 +0000972 if (const VarDecl *VD = dyn_cast<VarDecl>(d)) {
Daniel Dunbar186204b2009-02-13 22:48:56 +0000973 if (VD->hasLocalStorage() || VD->hasExternalStorage()) {
Daniel Dunbarb805dad2009-02-13 19:23:53 +0000974 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used";
975 return;
976 }
977 } else if (!isFunctionOrMethod(d)) {
978 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +0000979 << Attr.getName() << ExpectedVariableOrFunction;
Daniel Dunbarb805dad2009-02-13 19:23:53 +0000980 return;
981 }
Mike Stumpbf916502009-07-24 19:02:52 +0000982
Sean Huntcf807c42010-08-18 23:23:40 +0000983 d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
Daniel Dunbarb805dad2009-02-13 19:23:53 +0000984}
985
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000986static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
987 // check the attribute arguments.
John McCallbdc49d32011-03-02 12:15:05 +0000988 if (Attr.getNumArgs() > 1) {
989 S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000990 return;
Mike Stumpbf916502009-07-24 19:02:52 +0000991 }
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000992
993 int priority = 65535; // FIXME: Do not hardcode such constants.
994 if (Attr.getNumArgs() > 0) {
Peter Collingbourne7a730022010-11-23 20:45:58 +0000995 Expr *E = Attr.getArg(0);
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000996 llvm::APSInt Idx(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +0000997 if (E->isTypeDependent() || E->isValueDependent() ||
998 !E->isIntegerConstantExpr(Idx, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000999 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
Chris Lattner3c73c412008-11-19 08:23:25 +00001000 << "constructor" << 1 << E->getSourceRange();
Daniel Dunbar3068ae02008-07-31 22:40:48 +00001001 return;
1002 }
1003 priority = Idx.getZExtValue();
1004 }
Mike Stumpbf916502009-07-24 19:02:52 +00001005
Chris Lattnerc5197432009-04-14 17:02:11 +00001006 if (!isa<FunctionDecl>(d)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001007 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00001008 << Attr.getName() << ExpectedFunction;
Daniel Dunbar3068ae02008-07-31 22:40:48 +00001009 return;
1010 }
1011
Eric Christopherf48f3672010-12-01 22:13:54 +00001012 d->addAttr(::new (S.Context) ConstructorAttr(Attr.getLoc(), S.Context,
1013 priority));
Daniel Dunbar3068ae02008-07-31 22:40:48 +00001014}
1015
1016static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
1017 // check the attribute arguments.
John McCallbdc49d32011-03-02 12:15:05 +00001018 if (Attr.getNumArgs() > 1) {
1019 S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
Daniel Dunbar3068ae02008-07-31 22:40:48 +00001020 return;
Mike Stumpbf916502009-07-24 19:02:52 +00001021 }
Daniel Dunbar3068ae02008-07-31 22:40:48 +00001022
1023 int priority = 65535; // FIXME: Do not hardcode such constants.
1024 if (Attr.getNumArgs() > 0) {
Peter Collingbourne7a730022010-11-23 20:45:58 +00001025 Expr *E = Attr.getArg(0);
Daniel Dunbar3068ae02008-07-31 22:40:48 +00001026 llvm::APSInt Idx(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +00001027 if (E->isTypeDependent() || E->isValueDependent() ||
1028 !E->isIntegerConstantExpr(Idx, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001029 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
Chris Lattner3c73c412008-11-19 08:23:25 +00001030 << "destructor" << 1 << E->getSourceRange();
Daniel Dunbar3068ae02008-07-31 22:40:48 +00001031 return;
1032 }
1033 priority = Idx.getZExtValue();
1034 }
Mike Stumpbf916502009-07-24 19:02:52 +00001035
Anders Carlsson6782fc62008-08-22 22:10:48 +00001036 if (!isa<FunctionDecl>(d)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001037 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00001038 << Attr.getName() << ExpectedFunction;
Daniel Dunbar3068ae02008-07-31 22:40:48 +00001039 return;
1040 }
1041
Eric Christopherf48f3672010-12-01 22:13:54 +00001042 d->addAttr(::new (S.Context) DestructorAttr(Attr.getLoc(), S.Context,
1043 priority));
Daniel Dunbar3068ae02008-07-31 22:40:48 +00001044}
1045
Chris Lattner803d0802008-06-29 00:43:07 +00001046static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner951bbb22011-02-24 05:42:24 +00001047 unsigned NumArgs = Attr.getNumArgs();
1048 if (NumArgs > 1) {
John McCallbdc49d32011-03-02 12:15:05 +00001049 S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001050 return;
1051 }
Chris Lattner951bbb22011-02-24 05:42:24 +00001052
Fariborz Jahanianc4b35cf2010-10-06 21:18:44 +00001053 // Handle the case where deprecated attribute has a text message.
Chris Lattner951bbb22011-02-24 05:42:24 +00001054 llvm::StringRef Str;
1055 if (NumArgs == 1) {
1056 StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0));
Fariborz Jahanianc4b35cf2010-10-06 21:18:44 +00001057 if (!SE) {
Chris Lattner951bbb22011-02-24 05:42:24 +00001058 S.Diag(Attr.getArg(0)->getLocStart(), diag::err_attribute_not_string)
1059 << "deprecated";
Fariborz Jahanianc4b35cf2010-10-06 21:18:44 +00001060 return;
1061 }
Chris Lattner951bbb22011-02-24 05:42:24 +00001062 Str = SE->getString();
Fariborz Jahanianc4b35cf2010-10-06 21:18:44 +00001063 }
Mike Stumpbf916502009-07-24 19:02:52 +00001064
Chris Lattner951bbb22011-02-24 05:42:24 +00001065 d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context, Str));
Chris Lattner6b6b5372008-06-26 18:38:35 +00001066}
1067
Fariborz Jahanianbc1c8772008-12-17 01:07:27 +00001068static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner951bbb22011-02-24 05:42:24 +00001069 unsigned NumArgs = Attr.getNumArgs();
1070 if (NumArgs > 1) {
John McCallbdc49d32011-03-02 12:15:05 +00001071 S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1;
Fariborz Jahanianbc1c8772008-12-17 01:07:27 +00001072 return;
1073 }
Chris Lattner951bbb22011-02-24 05:42:24 +00001074
Fariborz Jahanianc784dc12010-10-06 23:12:32 +00001075 // Handle the case where unavailable attribute has a text message.
Chris Lattner951bbb22011-02-24 05:42:24 +00001076 llvm::StringRef Str;
1077 if (NumArgs == 1) {
1078 StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0));
Fariborz Jahanianc784dc12010-10-06 23:12:32 +00001079 if (!SE) {
Chris Lattner951bbb22011-02-24 05:42:24 +00001080 S.Diag(Attr.getArg(0)->getLocStart(),
Fariborz Jahanianc784dc12010-10-06 23:12:32 +00001081 diag::err_attribute_not_string) << "unavailable";
1082 return;
1083 }
Chris Lattner951bbb22011-02-24 05:42:24 +00001084 Str = SE->getString();
Fariborz Jahanianc784dc12010-10-06 23:12:32 +00001085 }
Chris Lattner951bbb22011-02-24 05:42:24 +00001086 d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context, Str));
Fariborz Jahanianbc1c8772008-12-17 01:07:27 +00001087}
1088
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00001089static void HandleAvailabilityAttr(Decl *d, const AttributeList &Attr,
1090 Sema &S) {
1091 IdentifierInfo *Platform = Attr.getParameterName();
1092 SourceLocation PlatformLoc = Attr.getParameterLoc();
1093
1094 llvm::StringRef PlatformName
1095 = AvailabilityAttr::getPrettyPlatformName(Platform->getName());
1096 if (PlatformName.empty()) {
1097 S.Diag(PlatformLoc, diag::warn_availability_unknown_platform)
1098 << Platform;
1099
1100 PlatformName = Platform->getName();
1101 }
1102
1103 AvailabilityChange Introduced = Attr.getAvailabilityIntroduced();
1104 AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated();
1105 AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted();
Douglas Gregorb53e4172011-03-26 03:35:55 +00001106 bool IsUnavailable = Attr.getUnavailableLoc().isValid();
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00001107
1108 // Ensure that Introduced < Deprecated < Obsoleted (although not all
1109 // of these steps are needed).
1110 if (Introduced.isValid() && Deprecated.isValid() &&
1111 !(Introduced.Version < Deprecated.Version)) {
1112 S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering)
1113 << 1 << PlatformName << Deprecated.Version.getAsString()
1114 << 0 << Introduced.Version.getAsString();
1115 return;
1116 }
1117
1118 if (Introduced.isValid() && Obsoleted.isValid() &&
1119 !(Introduced.Version < Obsoleted.Version)) {
1120 S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering)
1121 << 2 << PlatformName << Obsoleted.Version.getAsString()
1122 << 0 << Introduced.Version.getAsString();
1123 return;
1124 }
1125
1126 if (Deprecated.isValid() && Obsoleted.isValid() &&
1127 !(Deprecated.Version < Obsoleted.Version)) {
1128 S.Diag(Deprecated.KeywordLoc, diag::warn_availability_version_ordering)
1129 << 2 << PlatformName << Obsoleted.Version.getAsString()
1130 << 1 << Deprecated.Version.getAsString();
1131 return;
1132 }
1133
1134 d->addAttr(::new (S.Context) AvailabilityAttr(Attr.getLoc(), S.Context,
1135 Platform,
1136 Introduced.Version,
1137 Deprecated.Version,
Douglas Gregorb53e4172011-03-26 03:35:55 +00001138 Obsoleted.Version,
1139 IsUnavailable));
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00001140}
1141
Chris Lattner803d0802008-06-29 00:43:07 +00001142static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00001143 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +00001144 if (Attr.getNumArgs() != 1) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001145 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001146 return;
1147 }
Mike Stumpbf916502009-07-24 19:02:52 +00001148
Peter Collingbourne7a730022010-11-23 20:45:58 +00001149 Expr *Arg = Attr.getArg(0);
Chris Lattner6b6b5372008-06-26 18:38:35 +00001150 Arg = Arg->IgnoreParenCasts();
1151 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
Mike Stumpbf916502009-07-24 19:02:52 +00001152
Chris Lattner6b6b5372008-06-26 18:38:35 +00001153 if (Str == 0 || Str->isWide()) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001154 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
Chris Lattner3c73c412008-11-19 08:23:25 +00001155 << "visibility" << 1;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001156 return;
1157 }
Mike Stumpbf916502009-07-24 19:02:52 +00001158
Benjamin Kramerc96f4942010-01-23 18:16:35 +00001159 llvm::StringRef TypeStr = Str->getString();
Sean Huntcf807c42010-08-18 23:23:40 +00001160 VisibilityAttr::VisibilityType type;
Mike Stumpbf916502009-07-24 19:02:52 +00001161
Benjamin Kramerc96f4942010-01-23 18:16:35 +00001162 if (TypeStr == "default")
Sean Huntcf807c42010-08-18 23:23:40 +00001163 type = VisibilityAttr::Default;
Benjamin Kramerc96f4942010-01-23 18:16:35 +00001164 else if (TypeStr == "hidden")
Sean Huntcf807c42010-08-18 23:23:40 +00001165 type = VisibilityAttr::Hidden;
Benjamin Kramerc96f4942010-01-23 18:16:35 +00001166 else if (TypeStr == "internal")
Sean Huntcf807c42010-08-18 23:23:40 +00001167 type = VisibilityAttr::Hidden; // FIXME
Benjamin Kramerc96f4942010-01-23 18:16:35 +00001168 else if (TypeStr == "protected")
Sean Huntcf807c42010-08-18 23:23:40 +00001169 type = VisibilityAttr::Protected;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001170 else {
Chris Lattner08631c52008-11-23 21:45:46 +00001171 S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001172 return;
1173 }
Mike Stumpbf916502009-07-24 19:02:52 +00001174
Sean Huntcf807c42010-08-18 23:23:40 +00001175 d->addAttr(::new (S.Context) VisibilityAttr(Attr.getLoc(), S.Context, type));
Chris Lattner6b6b5372008-06-26 18:38:35 +00001176}
1177
John McCalld5313b02011-03-02 11:33:24 +00001178static void HandleObjCMethodFamilyAttr(Decl *decl, const AttributeList &attr,
1179 Sema &S) {
1180 ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(decl);
1181 if (!method) {
1182 S.Diag(attr.getLoc(), diag::err_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00001183 << ExpectedMethod;
John McCalld5313b02011-03-02 11:33:24 +00001184 return;
1185 }
1186
1187 if (attr.getNumArgs() != 0 || !attr.getParameterName()) {
1188 if (!attr.getParameterName() && attr.getNumArgs() == 1) {
1189 S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
1190 << "objc_method_family" << 1;
1191 } else {
1192 S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
1193 }
1194 attr.setInvalid();
1195 return;
1196 }
1197
1198 llvm::StringRef param = attr.getParameterName()->getName();
1199 ObjCMethodFamilyAttr::FamilyKind family;
1200 if (param == "none")
1201 family = ObjCMethodFamilyAttr::OMF_None;
1202 else if (param == "alloc")
1203 family = ObjCMethodFamilyAttr::OMF_alloc;
1204 else if (param == "copy")
1205 family = ObjCMethodFamilyAttr::OMF_copy;
1206 else if (param == "init")
1207 family = ObjCMethodFamilyAttr::OMF_init;
1208 else if (param == "mutableCopy")
1209 family = ObjCMethodFamilyAttr::OMF_mutableCopy;
1210 else if (param == "new")
1211 family = ObjCMethodFamilyAttr::OMF_new;
1212 else {
1213 // Just warn and ignore it. This is future-proof against new
1214 // families being used in system headers.
1215 S.Diag(attr.getParameterLoc(), diag::warn_unknown_method_family);
1216 return;
1217 }
1218
1219 decl->addAttr(new (S.Context) ObjCMethodFamilyAttr(attr.getLoc(),
1220 S.Context, family));
1221}
1222
Chris Lattner0db29ec2009-02-14 08:09:34 +00001223static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
1224 Sema &S) {
1225 if (Attr.getNumArgs() != 0) {
1226 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
1227 return;
1228 }
Mike Stumpbf916502009-07-24 19:02:52 +00001229
Chris Lattner0db29ec2009-02-14 08:09:34 +00001230 ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D);
1231 if (OCI == 0) {
1232 S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface);
1233 return;
1234 }
Mike Stumpbf916502009-07-24 19:02:52 +00001235
Sean Huntcf807c42010-08-18 23:23:40 +00001236 D->addAttr(::new (S.Context) ObjCExceptionAttr(Attr.getLoc(), S.Context));
Chris Lattner0db29ec2009-02-14 08:09:34 +00001237}
1238
1239static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
Fariborz Jahanianfa23c1d2009-01-13 23:34:40 +00001240 if (Attr.getNumArgs() != 0) {
John McCall2b7baf02010-05-28 18:25:28 +00001241 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Fariborz Jahanianfa23c1d2009-01-13 23:34:40 +00001242 return;
1243 }
Richard Smith162e1c12011-04-15 14:24:37 +00001244 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
Fariborz Jahanianfa23c1d2009-01-13 23:34:40 +00001245 QualType T = TD->getUnderlyingType();
1246 if (!T->isPointerType() ||
Ted Kremenek6217b802009-07-29 21:53:49 +00001247 !T->getAs<PointerType>()->getPointeeType()->isRecordType()) {
Fariborz Jahanianfa23c1d2009-01-13 23:34:40 +00001248 S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
1249 return;
1250 }
1251 }
Sean Huntcf807c42010-08-18 23:23:40 +00001252 D->addAttr(::new (S.Context) ObjCNSObjectAttr(Attr.getLoc(), S.Context));
Fariborz Jahanianfa23c1d2009-01-13 23:34:40 +00001253}
1254
Mike Stumpbf916502009-07-24 19:02:52 +00001255static void
Douglas Gregorf9201e02009-02-11 23:02:49 +00001256HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) {
1257 if (Attr.getNumArgs() != 0) {
John McCall2b7baf02010-05-28 18:25:28 +00001258 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Douglas Gregorf9201e02009-02-11 23:02:49 +00001259 return;
1260 }
1261
1262 if (!isa<FunctionDecl>(D)) {
1263 S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function);
1264 return;
1265 }
1266
Sean Huntcf807c42010-08-18 23:23:40 +00001267 D->addAttr(::new (S.Context) OverloadableAttr(Attr.getLoc(), S.Context));
Douglas Gregorf9201e02009-02-11 23:02:49 +00001268}
1269
Steve Naroff9eae5762008-09-18 16:44:58 +00001270static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Mike Stumpbf916502009-07-24 19:02:52 +00001271 if (!Attr.getParameterName()) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001272 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
Chris Lattner3c73c412008-11-19 08:23:25 +00001273 << "blocks" << 1;
Steve Naroff9eae5762008-09-18 16:44:58 +00001274 return;
1275 }
Mike Stumpbf916502009-07-24 19:02:52 +00001276
Steve Naroff9eae5762008-09-18 16:44:58 +00001277 if (Attr.getNumArgs() != 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001278 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Steve Naroff9eae5762008-09-18 16:44:58 +00001279 return;
1280 }
Mike Stumpbf916502009-07-24 19:02:52 +00001281
Sean Huntcf807c42010-08-18 23:23:40 +00001282 BlocksAttr::BlockType type;
Chris Lattner92e62b02008-11-20 04:42:34 +00001283 if (Attr.getParameterName()->isStr("byref"))
Steve Naroff9eae5762008-09-18 16:44:58 +00001284 type = BlocksAttr::ByRef;
1285 else {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001286 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
Chris Lattner3c73c412008-11-19 08:23:25 +00001287 << "blocks" << Attr.getParameterName();
Steve Naroff9eae5762008-09-18 16:44:58 +00001288 return;
1289 }
Mike Stumpbf916502009-07-24 19:02:52 +00001290
Sean Huntcf807c42010-08-18 23:23:40 +00001291 d->addAttr(::new (S.Context) BlocksAttr(Attr.getLoc(), S.Context, type));
Steve Naroff9eae5762008-09-18 16:44:58 +00001292}
1293
Anders Carlsson77091822008-10-05 18:05:59 +00001294static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
1295 // check the attribute arguments.
1296 if (Attr.getNumArgs() > 2) {
John McCallbdc49d32011-03-02 12:15:05 +00001297 S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2;
Anders Carlsson77091822008-10-05 18:05:59 +00001298 return;
Mike Stumpbf916502009-07-24 19:02:52 +00001299 }
1300
Anders Carlsson77091822008-10-05 18:05:59 +00001301 int sentinel = 0;
1302 if (Attr.getNumArgs() > 0) {
Peter Collingbourne7a730022010-11-23 20:45:58 +00001303 Expr *E = Attr.getArg(0);
Anders Carlsson77091822008-10-05 18:05:59 +00001304 llvm::APSInt Idx(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +00001305 if (E->isTypeDependent() || E->isValueDependent() ||
1306 !E->isIntegerConstantExpr(Idx, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001307 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
Chris Lattner3c73c412008-11-19 08:23:25 +00001308 << "sentinel" << 1 << E->getSourceRange();
Anders Carlsson77091822008-10-05 18:05:59 +00001309 return;
1310 }
1311 sentinel = Idx.getZExtValue();
Mike Stumpbf916502009-07-24 19:02:52 +00001312
Anders Carlsson77091822008-10-05 18:05:59 +00001313 if (sentinel < 0) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001314 S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero)
1315 << E->getSourceRange();
Anders Carlsson77091822008-10-05 18:05:59 +00001316 return;
1317 }
1318 }
1319
1320 int nullPos = 0;
1321 if (Attr.getNumArgs() > 1) {
Peter Collingbourne7a730022010-11-23 20:45:58 +00001322 Expr *E = Attr.getArg(1);
Anders Carlsson77091822008-10-05 18:05:59 +00001323 llvm::APSInt Idx(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +00001324 if (E->isTypeDependent() || E->isValueDependent() ||
1325 !E->isIntegerConstantExpr(Idx, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001326 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
Chris Lattner3c73c412008-11-19 08:23:25 +00001327 << "sentinel" << 2 << E->getSourceRange();
Anders Carlsson77091822008-10-05 18:05:59 +00001328 return;
1329 }
1330 nullPos = Idx.getZExtValue();
Mike Stumpbf916502009-07-24 19:02:52 +00001331
Anders Carlsson77091822008-10-05 18:05:59 +00001332 if (nullPos > 1 || nullPos < 0) {
1333 // FIXME: This error message could be improved, it would be nice
1334 // to say what the bounds actually are.
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001335 S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
1336 << E->getSourceRange();
Anders Carlsson77091822008-10-05 18:05:59 +00001337 return;
1338 }
1339 }
1340
1341 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
John McCall183700f2009-09-21 23:43:11 +00001342 const FunctionType *FT = FD->getType()->getAs<FunctionType>();
Chris Lattner897cd902009-03-17 23:03:47 +00001343 assert(FT && "FunctionDecl has non-function type?");
Mike Stumpbf916502009-07-24 19:02:52 +00001344
Chris Lattner897cd902009-03-17 23:03:47 +00001345 if (isa<FunctionNoProtoType>(FT)) {
1346 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_named_arguments);
1347 return;
1348 }
Mike Stumpbf916502009-07-24 19:02:52 +00001349
Chris Lattner897cd902009-03-17 23:03:47 +00001350 if (!cast<FunctionProtoType>(FT)->isVariadic()) {
Fariborz Jahanian3bba33d2009-05-15 21:18:04 +00001351 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
Anders Carlsson77091822008-10-05 18:05:59 +00001352 return;
Mike Stumpbf916502009-07-24 19:02:52 +00001353 }
Anders Carlsson77091822008-10-05 18:05:59 +00001354 } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) {
1355 if (!MD->isVariadic()) {
Fariborz Jahanian3bba33d2009-05-15 21:18:04 +00001356 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
Anders Carlsson77091822008-10-05 18:05:59 +00001357 return;
Fariborz Jahanian2f7c3922009-05-14 20:53:39 +00001358 }
1359 } else if (isa<BlockDecl>(d)) {
Mike Stumpbf916502009-07-24 19:02:52 +00001360 // Note! BlockDecl is typeless. Variadic diagnostics will be issued by the
1361 // caller.
Fariborz Jahanian2f7c3922009-05-14 20:53:39 +00001362 ;
1363 } else if (const VarDecl *V = dyn_cast<VarDecl>(d)) {
Fariborz Jahanian2f7c3922009-05-14 20:53:39 +00001364 QualType Ty = V->getType();
Fariborz Jahaniandaf04152009-05-15 20:33:25 +00001365 if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
Mike Stumpbf916502009-07-24 19:02:52 +00001366 const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(d)
Eric Christopherf48f3672010-12-01 22:13:54 +00001367 : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
Fariborz Jahanian2f7c3922009-05-14 20:53:39 +00001368 if (!cast<FunctionProtoType>(FT)->isVariadic()) {
Fariborz Jahanian3bba33d2009-05-15 21:18:04 +00001369 int m = Ty->isFunctionPointerType() ? 0 : 1;
1370 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
Fariborz Jahanian2f7c3922009-05-14 20:53:39 +00001371 return;
1372 }
Mike Stumpac5fc7c2009-08-04 21:02:39 +00001373 } else {
Fariborz Jahanian2f7c3922009-05-14 20:53:39 +00001374 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00001375 << Attr.getName() << ExpectedFunctionMethodOrBlock;
Fariborz Jahanian2f7c3922009-05-14 20:53:39 +00001376 return;
1377 }
Anders Carlsson77091822008-10-05 18:05:59 +00001378 } else {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001379 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00001380 << Attr.getName() << ExpectedFunctionMethodOrBlock;
Anders Carlsson77091822008-10-05 18:05:59 +00001381 return;
1382 }
Eric Christopherf48f3672010-12-01 22:13:54 +00001383 d->addAttr(::new (S.Context) SentinelAttr(Attr.getLoc(), S.Context, sentinel,
1384 nullPos));
Anders Carlsson77091822008-10-05 18:05:59 +00001385}
1386
Chris Lattner026dc962009-02-14 07:37:35 +00001387static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) {
1388 // check the attribute arguments.
1389 if (Attr.getNumArgs() != 0) {
1390 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
1391 return;
1392 }
1393
Fariborz Jahanianf0317742010-03-30 18:22:15 +00001394 if (!isFunction(D) && !isa<ObjCMethodDecl>(D)) {
Chris Lattner026dc962009-02-14 07:37:35 +00001395 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00001396 << Attr.getName() << ExpectedFunctionOrMethod;
Chris Lattner026dc962009-02-14 07:37:35 +00001397 return;
1398 }
Mike Stumpbf916502009-07-24 19:02:52 +00001399
Fariborz Jahanianf0317742010-03-30 18:22:15 +00001400 if (isFunction(D) && getFunctionType(D)->getResultType()->isVoidType()) {
1401 S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
1402 << Attr.getName() << 0;
Nuno Lopesf8577982009-12-22 23:59:52 +00001403 return;
1404 }
Fariborz Jahanianf0317742010-03-30 18:22:15 +00001405 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
1406 if (MD->getResultType()->isVoidType()) {
1407 S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
1408 << Attr.getName() << 1;
1409 return;
1410 }
1411
Sean Huntcf807c42010-08-18 23:23:40 +00001412 D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getLoc(), S.Context));
Chris Lattner026dc962009-02-14 07:37:35 +00001413}
1414
John McCall332bb2a2011-02-08 22:35:49 +00001415static void HandleWeakAttr(Decl *d, const AttributeList &attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00001416 // check the attribute arguments.
Ted Kremenek831efae2011-04-15 05:49:29 +00001417 if (attr.hasParameterOrArguments()) {
John McCall332bb2a2011-02-08 22:35:49 +00001418 S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001419 return;
1420 }
Daniel Dunbar6e775db2009-03-06 06:39:57 +00001421
John McCall332bb2a2011-02-08 22:35:49 +00001422 if (!isa<VarDecl>(d) && !isa<FunctionDecl>(d)) {
1423 S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00001424 << attr.getName() << ExpectedVariableOrFunction;
Fariborz Jahanianf23ecd92009-07-16 01:12:24 +00001425 return;
1426 }
1427
John McCall332bb2a2011-02-08 22:35:49 +00001428 NamedDecl *nd = cast<NamedDecl>(d);
1429
1430 // 'weak' only applies to declarations with external linkage.
1431 if (hasEffectivelyInternalLinkage(nd)) {
1432 S.Diag(attr.getLoc(), diag::err_attribute_weak_static);
Daniel Dunbar6e775db2009-03-06 06:39:57 +00001433 return;
1434 }
Mike Stumpbf916502009-07-24 19:02:52 +00001435
John McCall332bb2a2011-02-08 22:35:49 +00001436 nd->addAttr(::new (S.Context) WeakAttr(attr.getLoc(), S.Context));
Chris Lattner6b6b5372008-06-26 18:38:35 +00001437}
1438
Daniel Dunbar6e775db2009-03-06 06:39:57 +00001439static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
1440 // check the attribute arguments.
1441 if (Attr.getNumArgs() != 0) {
1442 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
1443 return;
Mike Stumpbf916502009-07-24 19:02:52 +00001444 }
Daniel Dunbar6e775db2009-03-06 06:39:57 +00001445
1446 // weak_import only applies to variable & function declarations.
1447 bool isDef = false;
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00001448 if (!D->canBeWeakImported(isDef)) {
1449 if (isDef)
1450 S.Diag(Attr.getLoc(),
1451 diag::warn_attribute_weak_import_invalid_on_definition)
1452 << "weak_import" << 2 /*variable and function*/;
Douglas Gregordef86312011-03-23 13:27:51 +00001453 else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) ||
Daniel Dunbardb57a4c2011-04-19 21:43:27 +00001454 (S.Context.Target.getTriple().isOSDarwin() &&
Douglas Gregordef86312011-03-23 13:27:51 +00001455 isa<ObjCInterfaceDecl>(D))) {
1456 // Nothing to warn about here.
1457 } else
Fariborz Jahanianc0349742010-04-13 20:22:35 +00001458 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00001459 << Attr.getName() << ExpectedVariableOrFunction;
Daniel Dunbar6e775db2009-03-06 06:39:57 +00001460
Daniel Dunbar6e775db2009-03-06 06:39:57 +00001461 return;
1462 }
1463
Sean Huntcf807c42010-08-18 23:23:40 +00001464 D->addAttr(::new (S.Context) WeakImportAttr(Attr.getLoc(), S.Context));
Daniel Dunbar6e775db2009-03-06 06:39:57 +00001465}
1466
Nate Begeman6f3d8382009-06-26 06:32:41 +00001467static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
1468 Sema &S) {
1469 // Attribute has 3 arguments.
1470 if (Attr.getNumArgs() != 3) {
John McCall2b7baf02010-05-28 18:25:28 +00001471 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Nate Begeman6f3d8382009-06-26 06:32:41 +00001472 return;
1473 }
1474
1475 unsigned WGSize[3];
1476 for (unsigned i = 0; i < 3; ++i) {
Peter Collingbourne7a730022010-11-23 20:45:58 +00001477 Expr *E = Attr.getArg(i);
Nate Begeman6f3d8382009-06-26 06:32:41 +00001478 llvm::APSInt ArgNum(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +00001479 if (E->isTypeDependent() || E->isValueDependent() ||
1480 !E->isIntegerConstantExpr(ArgNum, S.Context)) {
Nate Begeman6f3d8382009-06-26 06:32:41 +00001481 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
1482 << "reqd_work_group_size" << E->getSourceRange();
1483 return;
1484 }
1485 WGSize[i] = (unsigned) ArgNum.getZExtValue();
1486 }
Sean Huntcf807c42010-08-18 23:23:40 +00001487 D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(Attr.getLoc(), S.Context,
1488 WGSize[0], WGSize[1],
Nate Begeman6f3d8382009-06-26 06:32:41 +00001489 WGSize[2]));
1490}
1491
Chris Lattner026dc962009-02-14 07:37:35 +00001492static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
Daniel Dunbar17f194f2009-02-12 17:28:23 +00001493 // Attribute has no arguments.
1494 if (Attr.getNumArgs() != 1) {
1495 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
1496 return;
1497 }
1498
1499 // Make sure that there is a string literal as the sections's single
1500 // argument.
Peter Collingbourne7a730022010-11-23 20:45:58 +00001501 Expr *ArgExpr = Attr.getArg(0);
Chris Lattner797c3c42009-08-10 19:03:04 +00001502 StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
Daniel Dunbar17f194f2009-02-12 17:28:23 +00001503 if (!SE) {
Chris Lattner797c3c42009-08-10 19:03:04 +00001504 S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) << "section";
Daniel Dunbar17f194f2009-02-12 17:28:23 +00001505 return;
1506 }
Mike Stump1eb44332009-09-09 15:08:12 +00001507
Chris Lattner797c3c42009-08-10 19:03:04 +00001508 // If the target wants to validate the section specifier, make it happen.
Benjamin Kramerbb377ed2009-11-30 17:08:26 +00001509 std::string Error = S.Context.Target.isValidSectionSpecifier(SE->getString());
Chris Lattnera1e1dc72010-01-12 20:58:53 +00001510 if (!Error.empty()) {
1511 S.Diag(SE->getLocStart(), diag::err_attribute_section_invalid_for_target)
1512 << Error;
Chris Lattner797c3c42009-08-10 19:03:04 +00001513 return;
1514 }
Mike Stump1eb44332009-09-09 15:08:12 +00001515
Chris Lattnera1e1dc72010-01-12 20:58:53 +00001516 // This attribute cannot be applied to local variables.
1517 if (isa<VarDecl>(D) && cast<VarDecl>(D)->hasLocalStorage()) {
1518 S.Diag(SE->getLocStart(), diag::err_attribute_section_local_variable);
1519 return;
1520 }
1521
Eric Christopherf48f3672010-12-01 22:13:54 +00001522 D->addAttr(::new (S.Context) SectionAttr(Attr.getLoc(), S.Context,
1523 SE->getString()));
Daniel Dunbar17f194f2009-02-12 17:28:23 +00001524}
1525
Chris Lattner6b6b5372008-06-26 18:38:35 +00001526
Chris Lattner803d0802008-06-29 00:43:07 +00001527static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00001528 // check the attribute arguments.
Ted Kremenek831efae2011-04-15 05:49:29 +00001529 if (Attr.hasParameterOrArguments()) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001530 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001531 return;
1532 }
Douglas Gregorb30cd4a2011-06-15 05:45:11 +00001533
1534 if (NoThrowAttr *Existing = d->getAttr<NoThrowAttr>()) {
1535 if (Existing->getLocation().isInvalid())
1536 Existing->setLocation(Attr.getLoc());
1537 } else {
1538 d->addAttr(::new (S.Context) NoThrowAttr(Attr.getLoc(), S.Context));
1539 }
Chris Lattner6b6b5372008-06-26 18:38:35 +00001540}
1541
Anders Carlsson232eb7d2008-10-05 23:32:53 +00001542static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
1543 // check the attribute arguments.
Ted Kremenek831efae2011-04-15 05:49:29 +00001544 if (Attr.hasParameterOrArguments()) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001545 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Anders Carlsson232eb7d2008-10-05 23:32:53 +00001546 return;
1547 }
Mike Stumpbf916502009-07-24 19:02:52 +00001548
Douglas Gregorb30cd4a2011-06-15 05:45:11 +00001549 if (ConstAttr *Existing = d->getAttr<ConstAttr>()) {
1550 if (Existing->getLocation().isInvalid())
1551 Existing->setLocation(Attr.getLoc());
1552 } else {
1553 d->addAttr(::new (S.Context) ConstAttr(Attr.getLoc(), S.Context));
1554 }
Anders Carlsson232eb7d2008-10-05 23:32:53 +00001555}
1556
1557static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
1558 // check the attribute arguments.
1559 if (Attr.getNumArgs() != 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001560 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Anders Carlsson232eb7d2008-10-05 23:32:53 +00001561 return;
1562 }
Mike Stumpbf916502009-07-24 19:02:52 +00001563
Sean Huntcf807c42010-08-18 23:23:40 +00001564 d->addAttr(::new (S.Context) PureAttr(Attr.getLoc(), S.Context));
Anders Carlsson232eb7d2008-10-05 23:32:53 +00001565}
1566
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001567static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Mike Stumpbf916502009-07-24 19:02:52 +00001568 if (!Attr.getParameterName()) {
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001569 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
1570 return;
1571 }
Mike Stumpbf916502009-07-24 19:02:52 +00001572
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001573 if (Attr.getNumArgs() != 0) {
1574 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
1575 return;
1576 }
Mike Stumpbf916502009-07-24 19:02:52 +00001577
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001578 VarDecl *VD = dyn_cast<VarDecl>(d);
Mike Stumpbf916502009-07-24 19:02:52 +00001579
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001580 if (!VD || !VD->hasLocalStorage()) {
1581 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup";
1582 return;
1583 }
Mike Stumpbf916502009-07-24 19:02:52 +00001584
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001585 // Look up the function
Douglas Gregorc83c6872010-04-15 22:33:43 +00001586 // FIXME: Lookup probably isn't looking in the right place
John McCallf36e02d2009-10-09 21:13:30 +00001587 NamedDecl *CleanupDecl
Argyrios Kyrtzidisf0b0ccc2010-12-06 17:51:50 +00001588 = S.LookupSingleName(S.TUScope, Attr.getParameterName(),
1589 Attr.getParameterLoc(), Sema::LookupOrdinaryName);
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001590 if (!CleanupDecl) {
Argyrios Kyrtzidisf0b0ccc2010-12-06 17:51:50 +00001591 S.Diag(Attr.getParameterLoc(), diag::err_attribute_cleanup_arg_not_found) <<
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001592 Attr.getParameterName();
1593 return;
1594 }
Mike Stumpbf916502009-07-24 19:02:52 +00001595
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001596 FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl);
1597 if (!FD) {
Argyrios Kyrtzidisf0b0ccc2010-12-06 17:51:50 +00001598 S.Diag(Attr.getParameterLoc(),
1599 diag::err_attribute_cleanup_arg_not_function)
1600 << Attr.getParameterName();
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001601 return;
1602 }
1603
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001604 if (FD->getNumParams() != 1) {
Argyrios Kyrtzidisf0b0ccc2010-12-06 17:51:50 +00001605 S.Diag(Attr.getParameterLoc(),
1606 diag::err_attribute_cleanup_func_must_take_one_arg)
1607 << Attr.getParameterName();
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001608 return;
1609 }
Mike Stumpbf916502009-07-24 19:02:52 +00001610
Anders Carlsson89941c12009-02-07 23:16:50 +00001611 // We're currently more strict than GCC about what function types we accept.
1612 // If this ever proves to be a problem it should be easy to fix.
1613 QualType Ty = S.Context.getPointerType(VD->getType());
1614 QualType ParamTy = FD->getParamDecl(0)->getType();
Douglas Gregorb608b982011-01-28 02:26:04 +00001615 if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(),
1616 ParamTy, Ty) != Sema::Compatible) {
Argyrios Kyrtzidisf0b0ccc2010-12-06 17:51:50 +00001617 S.Diag(Attr.getParameterLoc(),
Anders Carlsson89941c12009-02-07 23:16:50 +00001618 diag::err_attribute_cleanup_func_arg_incompatible_type) <<
1619 Attr.getParameterName() << ParamTy << Ty;
1620 return;
1621 }
Mike Stumpbf916502009-07-24 19:02:52 +00001622
Sean Huntcf807c42010-08-18 23:23:40 +00001623 d->addAttr(::new (S.Context) CleanupAttr(Attr.getLoc(), S.Context, FD));
Argyrios Kyrtzidis223ae5c2010-12-06 17:51:53 +00001624 S.MarkDeclarationReferenced(Attr.getParameterLoc(), FD);
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001625}
1626
Mike Stumpbf916502009-07-24 19:02:52 +00001627/// Handle __attribute__((format_arg((idx)))) attribute based on
1628/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
1629static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001630 if (Attr.getNumArgs() != 1) {
1631 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
1632 return;
1633 }
1634 if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
1635 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00001636 << Attr.getName() << ExpectedFunction;
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001637 return;
1638 }
Chandler Carruth07d7e7a2010-11-16 08:35:43 +00001639
1640 // In C++ the implicit 'this' function parameter also counts, and they are
1641 // counted from one.
1642 bool HasImplicitThisParam = isInstanceMethod(d);
1643 unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam;
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001644 unsigned FirstIdx = 1;
Chandler Carruth07d7e7a2010-11-16 08:35:43 +00001645
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001646 // checks for the 2nd argument
Peter Collingbourne7a730022010-11-23 20:45:58 +00001647 Expr *IdxExpr = Attr.getArg(0);
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001648 llvm::APSInt Idx(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +00001649 if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
1650 !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001651 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
1652 << "format" << 2 << IdxExpr->getSourceRange();
1653 return;
1654 }
Mike Stumpbf916502009-07-24 19:02:52 +00001655
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001656 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
1657 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
1658 << "format" << 2 << IdxExpr->getSourceRange();
1659 return;
1660 }
Mike Stumpbf916502009-07-24 19:02:52 +00001661
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001662 unsigned ArgIdx = Idx.getZExtValue() - 1;
Mike Stumpbf916502009-07-24 19:02:52 +00001663
Chandler Carruth07d7e7a2010-11-16 08:35:43 +00001664 if (HasImplicitThisParam) {
1665 if (ArgIdx == 0) {
1666 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_implicit_this_argument)
1667 << "format_arg" << IdxExpr->getSourceRange();
1668 return;
1669 }
1670 ArgIdx--;
1671 }
1672
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001673 // make sure the format string is really a string
1674 QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
Mike Stumpbf916502009-07-24 19:02:52 +00001675
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001676 bool not_nsstring_type = !isNSStringType(Ty, S.Context);
1677 if (not_nsstring_type &&
1678 !isCFStringType(Ty, S.Context) &&
1679 (!Ty->isPointerType() ||
Ted Kremenek6217b802009-07-29 21:53:49 +00001680 !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001681 // FIXME: Should highlight the actual expression that has the wrong type.
1682 S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
Mike Stumpbf916502009-07-24 19:02:52 +00001683 << (not_nsstring_type ? "a string type" : "an NSString")
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001684 << IdxExpr->getSourceRange();
1685 return;
Mike Stumpbf916502009-07-24 19:02:52 +00001686 }
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001687 Ty = getFunctionOrMethodResultType(d);
1688 if (!isNSStringType(Ty, S.Context) &&
1689 !isCFStringType(Ty, S.Context) &&
1690 (!Ty->isPointerType() ||
Ted Kremenek6217b802009-07-29 21:53:49 +00001691 !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001692 // FIXME: Should highlight the actual expression that has the wrong type.
1693 S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not)
Mike Stumpbf916502009-07-24 19:02:52 +00001694 << (not_nsstring_type ? "string type" : "NSString")
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001695 << IdxExpr->getSourceRange();
1696 return;
Mike Stumpbf916502009-07-24 19:02:52 +00001697 }
1698
Chandler Carruth07d7e7a2010-11-16 08:35:43 +00001699 d->addAttr(::new (S.Context) FormatArgAttr(Attr.getLoc(), S.Context,
1700 Idx.getZExtValue()));
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001701}
1702
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001703enum FormatAttrKind {
1704 CFStringFormat,
1705 NSStringFormat,
1706 StrftimeFormat,
1707 SupportedFormat,
Chris Lattner3c989022010-03-22 21:08:50 +00001708 IgnoredFormat,
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001709 InvalidFormat
1710};
1711
1712/// getFormatAttrKind - Map from format attribute names to supported format
1713/// types.
1714static FormatAttrKind getFormatAttrKind(llvm::StringRef Format) {
1715 // Check for formats that get handled specially.
1716 if (Format == "NSString")
1717 return NSStringFormat;
1718 if (Format == "CFString")
1719 return CFStringFormat;
1720 if (Format == "strftime")
1721 return StrftimeFormat;
1722
1723 // Otherwise, check for supported formats.
1724 if (Format == "scanf" || Format == "printf" || Format == "printf0" ||
1725 Format == "strfmon" || Format == "cmn_err" || Format == "strftime" ||
1726 Format == "NSString" || Format == "CFString" || Format == "vcmn_err" ||
Chris Lattnercd5b3062011-02-18 17:05:55 +00001727 Format == "zcmn_err" ||
1728 Format == "kprintf") // OpenBSD.
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001729 return SupportedFormat;
1730
Duncan Sandsbc525952010-03-23 14:44:19 +00001731 if (Format == "gcc_diag" || Format == "gcc_cdiag" ||
1732 Format == "gcc_cxxdiag" || Format == "gcc_tdiag")
Chris Lattner3c989022010-03-22 21:08:50 +00001733 return IgnoredFormat;
1734
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001735 return InvalidFormat;
1736}
1737
Fariborz Jahanian521f12d2010-06-18 21:44:06 +00001738/// Handle __attribute__((init_priority(priority))) attributes based on
1739/// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html
1740static void HandleInitPriorityAttr(Decl *d, const AttributeList &Attr,
1741 Sema &S) {
1742 if (!S.getLangOptions().CPlusPlus) {
1743 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
1744 return;
1745 }
1746
Fariborz Jahanianb9d5c222010-06-18 23:14:53 +00001747 if (!isa<VarDecl>(d) || S.getCurFunctionOrMethodDecl()) {
1748 S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
1749 Attr.setInvalid();
1750 return;
1751 }
1752 QualType T = dyn_cast<VarDecl>(d)->getType();
1753 if (S.Context.getAsArrayType(T))
1754 T = S.Context.getBaseElementType(T);
1755 if (!T->getAs<RecordType>()) {
1756 S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
1757 Attr.setInvalid();
1758 return;
1759 }
1760
Fariborz Jahanian521f12d2010-06-18 21:44:06 +00001761 if (Attr.getNumArgs() != 1) {
1762 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
1763 Attr.setInvalid();
1764 return;
1765 }
Peter Collingbourne7a730022010-11-23 20:45:58 +00001766 Expr *priorityExpr = Attr.getArg(0);
Fariborz Jahanianb9d5c222010-06-18 23:14:53 +00001767
Fariborz Jahanian521f12d2010-06-18 21:44:06 +00001768 llvm::APSInt priority(32);
1769 if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() ||
1770 !priorityExpr->isIntegerConstantExpr(priority, S.Context)) {
1771 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
1772 << "init_priority" << priorityExpr->getSourceRange();
1773 Attr.setInvalid();
1774 return;
1775 }
Fariborz Jahanian9f967c52010-06-21 18:45:05 +00001776 unsigned prioritynum = priority.getZExtValue();
Fariborz Jahanian521f12d2010-06-18 21:44:06 +00001777 if (prioritynum < 101 || prioritynum > 65535) {
1778 S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range)
1779 << priorityExpr->getSourceRange();
1780 Attr.setInvalid();
1781 return;
1782 }
Eric Christopherf48f3672010-12-01 22:13:54 +00001783 d->addAttr(::new (S.Context) InitPriorityAttr(Attr.getLoc(), S.Context,
1784 prioritynum));
Fariborz Jahanian521f12d2010-06-18 21:44:06 +00001785}
1786
Mike Stumpbf916502009-07-24 19:02:52 +00001787/// Handle __attribute__((format(type,idx,firstarg))) attributes based on
1788/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
Chris Lattner803d0802008-06-29 00:43:07 +00001789static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00001790
Chris Lattner545dd342008-06-28 23:36:30 +00001791 if (!Attr.getParameterName()) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001792 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
Chris Lattner3c73c412008-11-19 08:23:25 +00001793 << "format" << 1;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001794 return;
1795 }
1796
Chris Lattner545dd342008-06-28 23:36:30 +00001797 if (Attr.getNumArgs() != 2) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001798 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001799 return;
1800 }
1801
Fariborz Jahanian620d89c2009-05-15 23:15:03 +00001802 if (!isFunctionOrMethodOrBlock(d) || !hasFunctionProto(d)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001803 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00001804 << Attr.getName() << ExpectedFunction;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001805 return;
1806 }
1807
Chandler Carruth07d7e7a2010-11-16 08:35:43 +00001808 // In C++ the implicit 'this' function parameter also counts, and they are
1809 // counted from one.
1810 bool HasImplicitThisParam = isInstanceMethod(d);
1811 unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001812 unsigned FirstIdx = 1;
1813
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00001814 llvm::StringRef Format = Attr.getParameterName()->getName();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001815
1816 // Normalize the argument, __foo__ becomes foo.
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001817 if (Format.startswith("__") && Format.endswith("__"))
1818 Format = Format.substr(2, Format.size() - 4);
Chris Lattner6b6b5372008-06-26 18:38:35 +00001819
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001820 // Check for supported formats.
1821 FormatAttrKind Kind = getFormatAttrKind(Format);
Chris Lattner3c989022010-03-22 21:08:50 +00001822
1823 if (Kind == IgnoredFormat)
1824 return;
1825
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001826 if (Kind == InvalidFormat) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001827 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00001828 << "format" << Attr.getParameterName()->getName();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001829 return;
1830 }
1831
1832 // checks for the 2nd argument
Peter Collingbourne7a730022010-11-23 20:45:58 +00001833 Expr *IdxExpr = Attr.getArg(0);
Chris Lattner803d0802008-06-29 00:43:07 +00001834 llvm::APSInt Idx(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +00001835 if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
1836 !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001837 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
Chris Lattner3c73c412008-11-19 08:23:25 +00001838 << "format" << 2 << IdxExpr->getSourceRange();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001839 return;
1840 }
1841
1842 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001843 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
Chris Lattner3c73c412008-11-19 08:23:25 +00001844 << "format" << 2 << IdxExpr->getSourceRange();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001845 return;
1846 }
1847
1848 // FIXME: Do we need to bounds check?
1849 unsigned ArgIdx = Idx.getZExtValue() - 1;
Mike Stumpbf916502009-07-24 19:02:52 +00001850
Sebastian Redl4a2614e2009-11-17 18:02:24 +00001851 if (HasImplicitThisParam) {
1852 if (ArgIdx == 0) {
Chandler Carruth07d7e7a2010-11-16 08:35:43 +00001853 S.Diag(Attr.getLoc(),
1854 diag::err_format_attribute_implicit_this_format_string)
1855 << IdxExpr->getSourceRange();
Sebastian Redl4a2614e2009-11-17 18:02:24 +00001856 return;
1857 }
1858 ArgIdx--;
1859 }
Mike Stump1eb44332009-09-09 15:08:12 +00001860
Chris Lattner6b6b5372008-06-26 18:38:35 +00001861 // make sure the format string is really a string
Daniel Dunbar35682492008-09-26 04:12:28 +00001862 QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
Chris Lattner6b6b5372008-06-26 18:38:35 +00001863
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001864 if (Kind == CFStringFormat) {
Daniel Dunbar085e8f72008-09-26 03:32:58 +00001865 if (!isCFStringType(Ty, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001866 S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
1867 << "a CFString" << IdxExpr->getSourceRange();
Daniel Dunbar085e8f72008-09-26 03:32:58 +00001868 return;
1869 }
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001870 } else if (Kind == NSStringFormat) {
Mike Stump390b4cc2009-05-16 07:39:55 +00001871 // FIXME: do we need to check if the type is NSString*? What are the
1872 // semantics?
Chris Lattner803d0802008-06-29 00:43:07 +00001873 if (!isNSStringType(Ty, S.Context)) {
Mike Stump390b4cc2009-05-16 07:39:55 +00001874 // FIXME: Should highlight the actual expression that has the wrong type.
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001875 S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
1876 << "an NSString" << IdxExpr->getSourceRange();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001877 return;
Mike Stumpbf916502009-07-24 19:02:52 +00001878 }
Chris Lattner6b6b5372008-06-26 18:38:35 +00001879 } else if (!Ty->isPointerType() ||
Ted Kremenek6217b802009-07-29 21:53:49 +00001880 !Ty->getAs<PointerType>()->getPointeeType()->isCharType()) {
Mike Stump390b4cc2009-05-16 07:39:55 +00001881 // FIXME: Should highlight the actual expression that has the wrong type.
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001882 S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
1883 << "a string type" << IdxExpr->getSourceRange();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001884 return;
1885 }
1886
1887 // check the 3rd argument
Peter Collingbourne7a730022010-11-23 20:45:58 +00001888 Expr *FirstArgExpr = Attr.getArg(1);
Chris Lattner803d0802008-06-29 00:43:07 +00001889 llvm::APSInt FirstArg(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +00001890 if (FirstArgExpr->isTypeDependent() || FirstArgExpr->isValueDependent() ||
1891 !FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001892 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
Chris Lattner3c73c412008-11-19 08:23:25 +00001893 << "format" << 3 << FirstArgExpr->getSourceRange();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001894 return;
1895 }
1896
1897 // check if the function is variadic if the 3rd argument non-zero
1898 if (FirstArg != 0) {
Daniel Dunbar35682492008-09-26 04:12:28 +00001899 if (isFunctionOrMethodVariadic(d)) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00001900 ++NumArgs; // +1 for ...
1901 } else {
Chris Lattner803d0802008-06-29 00:43:07 +00001902 S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
Chris Lattner6b6b5372008-06-26 18:38:35 +00001903 return;
1904 }
1905 }
1906
Chris Lattner3c73c412008-11-19 08:23:25 +00001907 // strftime requires FirstArg to be 0 because it doesn't read from any
1908 // variable the input is just the current time + the format string.
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001909 if (Kind == StrftimeFormat) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00001910 if (FirstArg != 0) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001911 S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter)
1912 << FirstArgExpr->getSourceRange();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001913 return;
1914 }
1915 // if 0 it disables parameter checking (to use with e.g. va_list)
1916 } else if (FirstArg != 0 && FirstArg != NumArgs) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001917 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
Chris Lattner3c73c412008-11-19 08:23:25 +00001918 << "format" << 3 << FirstArgExpr->getSourceRange();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001919 return;
1920 }
1921
Douglas Gregorb30cd4a2011-06-15 05:45:11 +00001922 // Check whether we already have an equivalent format attribute.
1923 for (specific_attr_iterator<FormatAttr>
1924 i = d->specific_attr_begin<FormatAttr>(),
1925 e = d->specific_attr_end<FormatAttr>();
1926 i != e ; ++i) {
1927 FormatAttr *f = *i;
1928 if (f->getType() == Format &&
1929 f->getFormatIdx() == (int)Idx.getZExtValue() &&
1930 f->getFirstArg() == (int)FirstArg.getZExtValue()) {
1931 // If we don't have a valid location for this attribute, adopt the
1932 // location.
1933 if (f->getLocation().isInvalid())
1934 f->setLocation(Attr.getLoc());
1935 return;
1936 }
1937 }
1938
Sean Huntcf807c42010-08-18 23:23:40 +00001939 d->addAttr(::new (S.Context) FormatAttr(Attr.getLoc(), S.Context, Format,
1940 Idx.getZExtValue(),
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001941 FirstArg.getZExtValue()));
Chris Lattner6b6b5372008-06-26 18:38:35 +00001942}
1943
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001944static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
1945 Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00001946 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +00001947 if (Attr.getNumArgs() != 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001948 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001949 return;
1950 }
1951
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001952 // Try to find the underlying union declaration.
1953 RecordDecl *RD = 0;
Richard Smith162e1c12011-04-15 14:24:37 +00001954 TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(d);
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001955 if (TD && TD->getUnderlyingType()->isUnionType())
1956 RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
1957 else
1958 RD = dyn_cast<RecordDecl>(d);
1959
1960 if (!RD || !RD->isUnion()) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001961 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00001962 << Attr.getName() << ExpectedUnion;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001963 return;
1964 }
1965
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001966 if (!RD->isDefinition()) {
Mike Stumpbf916502009-07-24 19:02:52 +00001967 S.Diag(Attr.getLoc(),
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001968 diag::warn_transparent_union_attribute_not_definition);
1969 return;
1970 }
Chris Lattner6b6b5372008-06-26 18:38:35 +00001971
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001972 RecordDecl::field_iterator Field = RD->field_begin(),
1973 FieldEnd = RD->field_end();
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001974 if (Field == FieldEnd) {
1975 S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields);
1976 return;
1977 }
Eli Friedmanbc887452008-09-02 05:19:23 +00001978
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001979 FieldDecl *FirstField = *Field;
1980 QualType FirstType = FirstField->getType();
Douglas Gregor90cd6722010-06-30 17:24:13 +00001981 if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) {
Mike Stumpbf916502009-07-24 19:02:52 +00001982 S.Diag(FirstField->getLocation(),
Douglas Gregor90cd6722010-06-30 17:24:13 +00001983 diag::warn_transparent_union_attribute_floating)
1984 << FirstType->isVectorType() << FirstType;
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001985 return;
1986 }
1987
1988 uint64_t FirstSize = S.Context.getTypeSize(FirstType);
1989 uint64_t FirstAlign = S.Context.getTypeAlign(FirstType);
1990 for (; Field != FieldEnd; ++Field) {
1991 QualType FieldType = Field->getType();
1992 if (S.Context.getTypeSize(FieldType) != FirstSize ||
1993 S.Context.getTypeAlign(FieldType) != FirstAlign) {
1994 // Warn if we drop the attribute.
1995 bool isSize = S.Context.getTypeSize(FieldType) != FirstSize;
Mike Stumpbf916502009-07-24 19:02:52 +00001996 unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType)
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001997 : S.Context.getTypeAlign(FieldType);
Mike Stumpbf916502009-07-24 19:02:52 +00001998 S.Diag(Field->getLocation(),
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001999 diag::warn_transparent_union_attribute_field_size_align)
2000 << isSize << Field->getDeclName() << FieldBits;
2001 unsigned FirstBits = isSize? FirstSize : FirstAlign;
Mike Stumpbf916502009-07-24 19:02:52 +00002002 S.Diag(FirstField->getLocation(),
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00002003 diag::note_transparent_union_first_field_size_align)
2004 << isSize << FirstBits;
Eli Friedmanbc887452008-09-02 05:19:23 +00002005 return;
2006 }
2007 }
2008
Sean Huntcf807c42010-08-18 23:23:40 +00002009 RD->addAttr(::new (S.Context) TransparentUnionAttr(Attr.getLoc(), S.Context));
Chris Lattner6b6b5372008-06-26 18:38:35 +00002010}
2011
Chris Lattner0b2f4da2008-06-29 00:28:59 +00002012static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00002013 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +00002014 if (Attr.getNumArgs() != 1) {
Chris Lattner3c73c412008-11-19 08:23:25 +00002015 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Chris Lattner6b6b5372008-06-26 18:38:35 +00002016 return;
2017 }
Peter Collingbourne7a730022010-11-23 20:45:58 +00002018 Expr *ArgExpr = Attr.getArg(0);
Chris Lattner797c3c42009-08-10 19:03:04 +00002019 StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
Mike Stumpbf916502009-07-24 19:02:52 +00002020
Chris Lattner6b6b5372008-06-26 18:38:35 +00002021 // Make sure that there is a string literal as the annotation's single
2022 // argument.
2023 if (!SE) {
Chris Lattner797c3c42009-08-10 19:03:04 +00002024 S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate";
Chris Lattner6b6b5372008-06-26 18:38:35 +00002025 return;
2026 }
Eric Christopherf48f3672010-12-01 22:13:54 +00002027 d->addAttr(::new (S.Context) AnnotateAttr(Attr.getLoc(), S.Context,
2028 SE->getString()));
Chris Lattner6b6b5372008-06-26 18:38:35 +00002029}
2030
Chandler Carruth4ced79f2010-06-25 03:22:07 +00002031static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00002032 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +00002033 if (Attr.getNumArgs() > 1) {
Chris Lattner3c73c412008-11-19 08:23:25 +00002034 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Chris Lattner6b6b5372008-06-26 18:38:35 +00002035 return;
2036 }
Sean Huntbbd37c62009-11-21 08:43:09 +00002037
2038 //FIXME: The C++0x version of this attribute has more limited applicabilty
2039 // than GNU's, and should error out when it is used to specify a
2040 // weaker alignment, rather than being silently ignored.
Chris Lattner6b6b5372008-06-26 18:38:35 +00002041
Chris Lattner545dd342008-06-28 23:36:30 +00002042 if (Attr.getNumArgs() == 0) {
Sean Huntcf807c42010-08-18 23:23:40 +00002043 D->addAttr(::new (S.Context) AlignedAttr(Attr.getLoc(), S.Context, true, 0));
Chris Lattner6b6b5372008-06-26 18:38:35 +00002044 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +00002045 }
Mike Stumpbf916502009-07-24 19:02:52 +00002046
Peter Collingbourne7a730022010-11-23 20:45:58 +00002047 S.AddAlignedAttr(Attr.getLoc(), D, Attr.getArg(0));
Chandler Carruth4ced79f2010-06-25 03:22:07 +00002048}
2049
2050void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) {
2051 if (E->isTypeDependent() || E->isValueDependent()) {
2052 // Save dependent expressions in the AST to be instantiated.
Sean Huntcf807c42010-08-18 23:23:40 +00002053 D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E));
Chandler Carruth4ced79f2010-06-25 03:22:07 +00002054 return;
2055 }
2056
Sean Huntcf807c42010-08-18 23:23:40 +00002057 // FIXME: Cache the number on the Attr object?
Chris Lattner49e2d342008-06-28 23:50:44 +00002058 llvm::APSInt Alignment(32);
Chandler Carruth4ced79f2010-06-25 03:22:07 +00002059 if (!E->isIntegerConstantExpr(Alignment, Context)) {
2060 Diag(AttrLoc, diag::err_attribute_argument_not_int)
2061 << "aligned" << E->getSourceRange();
Chris Lattner49e2d342008-06-28 23:50:44 +00002062 return;
2063 }
Daniel Dunbar396b2a22009-02-16 23:37:57 +00002064 if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) {
Chandler Carruth4ced79f2010-06-25 03:22:07 +00002065 Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two)
2066 << E->getSourceRange();
Daniel Dunbar396b2a22009-02-16 23:37:57 +00002067 return;
2068 }
2069
Sean Huntcf807c42010-08-18 23:23:40 +00002070 D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E));
2071}
2072
2073void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, TypeSourceInfo *TS) {
2074 // FIXME: Cache the number on the Attr object if non-dependent?
2075 // FIXME: Perform checking of type validity
2076 D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, false, TS));
2077 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +00002078}
Chris Lattnerfbf13472008-06-27 22:18:37 +00002079
Mike Stumpbf916502009-07-24 19:02:52 +00002080/// HandleModeAttr - This attribute modifies the width of a decl with primitive
2081/// type.
Chris Lattnerfbf13472008-06-27 22:18:37 +00002082///
Mike Stumpbf916502009-07-24 19:02:52 +00002083/// Despite what would be logical, the mode attribute is a decl attribute, not a
2084/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
2085/// HImode, not an intermediate pointer.
Chris Lattner0b2f4da2008-06-29 00:28:59 +00002086static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
Chris Lattnerfbf13472008-06-27 22:18:37 +00002087 // This attribute isn't documented, but glibc uses it. It changes
2088 // the width of an int or unsigned int to the specified size.
2089
2090 // Check that there aren't any arguments
2091 if (Attr.getNumArgs() != 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +00002092 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Chris Lattnerfbf13472008-06-27 22:18:37 +00002093 return;
2094 }
2095
2096 IdentifierInfo *Name = Attr.getParameterName();
2097 if (!Name) {
Chris Lattner0b2f4da2008-06-29 00:28:59 +00002098 S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
Chris Lattnerfbf13472008-06-27 22:18:37 +00002099 return;
2100 }
Daniel Dunbar210ae982009-10-18 02:09:24 +00002101
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00002102 llvm::StringRef Str = Attr.getParameterName()->getName();
Chris Lattnerfbf13472008-06-27 22:18:37 +00002103
2104 // Normalize the attribute name, __foo__ becomes foo.
Daniel Dunbar210ae982009-10-18 02:09:24 +00002105 if (Str.startswith("__") && Str.endswith("__"))
2106 Str = Str.substr(2, Str.size() - 4);
Chris Lattnerfbf13472008-06-27 22:18:37 +00002107
2108 unsigned DestWidth = 0;
2109 bool IntegerMode = true;
Eli Friedman73397492009-03-03 06:41:03 +00002110 bool ComplexMode = false;
Daniel Dunbar210ae982009-10-18 02:09:24 +00002111 switch (Str.size()) {
Chris Lattnerfbf13472008-06-27 22:18:37 +00002112 case 2:
Eli Friedman73397492009-03-03 06:41:03 +00002113 switch (Str[0]) {
2114 case 'Q': DestWidth = 8; break;
2115 case 'H': DestWidth = 16; break;
2116 case 'S': DestWidth = 32; break;
2117 case 'D': DestWidth = 64; break;
2118 case 'X': DestWidth = 96; break;
2119 case 'T': DestWidth = 128; break;
2120 }
2121 if (Str[1] == 'F') {
2122 IntegerMode = false;
2123 } else if (Str[1] == 'C') {
2124 IntegerMode = false;
2125 ComplexMode = true;
2126 } else if (Str[1] != 'I') {
2127 DestWidth = 0;
2128 }
Chris Lattnerfbf13472008-06-27 22:18:37 +00002129 break;
2130 case 4:
2131 // FIXME: glibc uses 'word' to define register_t; this is narrower than a
2132 // pointer on PIC16 and other embedded platforms.
Daniel Dunbar210ae982009-10-18 02:09:24 +00002133 if (Str == "word")
Chris Lattner0b2f4da2008-06-29 00:28:59 +00002134 DestWidth = S.Context.Target.getPointerWidth(0);
Daniel Dunbar210ae982009-10-18 02:09:24 +00002135 else if (Str == "byte")
Chris Lattner0b2f4da2008-06-29 00:28:59 +00002136 DestWidth = S.Context.Target.getCharWidth();
Chris Lattnerfbf13472008-06-27 22:18:37 +00002137 break;
2138 case 7:
Daniel Dunbar210ae982009-10-18 02:09:24 +00002139 if (Str == "pointer")
Chris Lattner0b2f4da2008-06-29 00:28:59 +00002140 DestWidth = S.Context.Target.getPointerWidth(0);
Chris Lattnerfbf13472008-06-27 22:18:37 +00002141 break;
2142 }
2143
2144 QualType OldTy;
Richard Smith162e1c12011-04-15 14:24:37 +00002145 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
Chris Lattnerfbf13472008-06-27 22:18:37 +00002146 OldTy = TD->getUnderlyingType();
2147 else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
2148 OldTy = VD->getType();
2149 else {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00002150 S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
2151 << "mode" << SourceRange(Attr.getLoc(), Attr.getLoc());
Chris Lattnerfbf13472008-06-27 22:18:37 +00002152 return;
2153 }
Eli Friedman73397492009-03-03 06:41:03 +00002154
John McCall183700f2009-09-21 23:43:11 +00002155 if (!OldTy->getAs<BuiltinType>() && !OldTy->isComplexType())
Eli Friedman73397492009-03-03 06:41:03 +00002156 S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
2157 else if (IntegerMode) {
Douglas Gregor2ade35e2010-06-16 00:17:44 +00002158 if (!OldTy->isIntegralOrEnumerationType())
Eli Friedman73397492009-03-03 06:41:03 +00002159 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
2160 } else if (ComplexMode) {
2161 if (!OldTy->isComplexType())
2162 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
2163 } else {
2164 if (!OldTy->isFloatingType())
2165 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
2166 }
2167
Mike Stump390b4cc2009-05-16 07:39:55 +00002168 // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
2169 // and friends, at least with glibc.
2170 // FIXME: Make sure 32/64-bit integers don't get defined to types of the wrong
2171 // width on unusual platforms.
Eli Friedmanf98aba32009-02-13 02:31:07 +00002172 // FIXME: Make sure floating-point mappings are accurate
2173 // FIXME: Support XF and TF types
Chris Lattnerfbf13472008-06-27 22:18:37 +00002174 QualType NewTy;
2175 switch (DestWidth) {
2176 case 0:
Chris Lattner3c73c412008-11-19 08:23:25 +00002177 S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name;
Chris Lattnerfbf13472008-06-27 22:18:37 +00002178 return;
2179 default:
Chris Lattner3c73c412008-11-19 08:23:25 +00002180 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
Chris Lattnerfbf13472008-06-27 22:18:37 +00002181 return;
2182 case 8:
Eli Friedman73397492009-03-03 06:41:03 +00002183 if (!IntegerMode) {
2184 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
2185 return;
2186 }
Chris Lattnerfbf13472008-06-27 22:18:37 +00002187 if (OldTy->isSignedIntegerType())
Chris Lattner0b2f4da2008-06-29 00:28:59 +00002188 NewTy = S.Context.SignedCharTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00002189 else
Chris Lattner0b2f4da2008-06-29 00:28:59 +00002190 NewTy = S.Context.UnsignedCharTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00002191 break;
2192 case 16:
Eli Friedman73397492009-03-03 06:41:03 +00002193 if (!IntegerMode) {
2194 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
2195 return;
2196 }
Chris Lattnerfbf13472008-06-27 22:18:37 +00002197 if (OldTy->isSignedIntegerType())
Chris Lattner0b2f4da2008-06-29 00:28:59 +00002198 NewTy = S.Context.ShortTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00002199 else
Chris Lattner0b2f4da2008-06-29 00:28:59 +00002200 NewTy = S.Context.UnsignedShortTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00002201 break;
2202 case 32:
2203 if (!IntegerMode)
Chris Lattner0b2f4da2008-06-29 00:28:59 +00002204 NewTy = S.Context.FloatTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00002205 else if (OldTy->isSignedIntegerType())
Chris Lattner0b2f4da2008-06-29 00:28:59 +00002206 NewTy = S.Context.IntTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00002207 else
Chris Lattner0b2f4da2008-06-29 00:28:59 +00002208 NewTy = S.Context.UnsignedIntTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00002209 break;
2210 case 64:
2211 if (!IntegerMode)
Chris Lattner0b2f4da2008-06-29 00:28:59 +00002212 NewTy = S.Context.DoubleTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00002213 else if (OldTy->isSignedIntegerType())
Chandler Carruthaec7caa2010-01-26 06:39:24 +00002214 if (S.Context.Target.getLongWidth() == 64)
2215 NewTy = S.Context.LongTy;
2216 else
2217 NewTy = S.Context.LongLongTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00002218 else
Chandler Carruthaec7caa2010-01-26 06:39:24 +00002219 if (S.Context.Target.getLongWidth() == 64)
2220 NewTy = S.Context.UnsignedLongTy;
2221 else
2222 NewTy = S.Context.UnsignedLongLongTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00002223 break;
Eli Friedman73397492009-03-03 06:41:03 +00002224 case 96:
2225 NewTy = S.Context.LongDoubleTy;
2226 break;
Eli Friedmanf98aba32009-02-13 02:31:07 +00002227 case 128:
2228 if (!IntegerMode) {
2229 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
2230 return;
2231 }
Anders Carlssonf5f7d862009-12-29 07:07:36 +00002232 if (OldTy->isSignedIntegerType())
2233 NewTy = S.Context.Int128Ty;
2234 else
2235 NewTy = S.Context.UnsignedInt128Ty;
Eli Friedman73397492009-03-03 06:41:03 +00002236 break;
Chris Lattnerfbf13472008-06-27 22:18:37 +00002237 }
2238
Eli Friedman73397492009-03-03 06:41:03 +00002239 if (ComplexMode) {
2240 NewTy = S.Context.getComplexType(NewTy);
Chris Lattnerfbf13472008-06-27 22:18:37 +00002241 }
2242
2243 // Install the new type.
Richard Smith162e1c12011-04-15 14:24:37 +00002244 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
John McCallba6a9bd2009-10-24 08:00:42 +00002245 // FIXME: preserve existing source info.
John McCalla93c9342009-12-07 02:54:59 +00002246 TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy));
John McCallba6a9bd2009-10-24 08:00:42 +00002247 } else
Chris Lattnerfbf13472008-06-27 22:18:37 +00002248 cast<ValueDecl>(D)->setType(NewTy);
2249}
Chris Lattner0744e5f2008-06-29 00:23:49 +00002250
Mike Stump1feade82009-08-26 22:31:08 +00002251static void HandleNoDebugAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Anders Carlssond87df372009-02-13 06:46:13 +00002252 // check the attribute arguments.
2253 if (Attr.getNumArgs() > 0) {
2254 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
2255 return;
2256 }
Anders Carlssone896d982009-02-13 08:11:52 +00002257
Anders Carlsson5bab7882009-02-19 19:16:48 +00002258 if (!isFunctionOrMethod(d)) {
Anders Carlssond87df372009-02-13 06:46:13 +00002259 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00002260 << Attr.getName() << ExpectedFunction;
Anders Carlssond87df372009-02-13 06:46:13 +00002261 return;
2262 }
Mike Stumpbf916502009-07-24 19:02:52 +00002263
Sean Huntcf807c42010-08-18 23:23:40 +00002264 d->addAttr(::new (S.Context) NoDebugAttr(Attr.getLoc(), S.Context));
Anders Carlssond87df372009-02-13 06:46:13 +00002265}
2266
Mike Stump1feade82009-08-26 22:31:08 +00002267static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Anders Carlsson5bab7882009-02-19 19:16:48 +00002268 // check the attribute arguments.
2269 if (Attr.getNumArgs() != 0) {
2270 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
2271 return;
2272 }
Mike Stumpbf916502009-07-24 19:02:52 +00002273
Chris Lattnerc5197432009-04-14 17:02:11 +00002274 if (!isa<FunctionDecl>(d)) {
Anders Carlsson5bab7882009-02-19 19:16:48 +00002275 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00002276 << Attr.getName() << ExpectedFunction;
Anders Carlsson5bab7882009-02-19 19:16:48 +00002277 return;
2278 }
Mike Stumpbf916502009-07-24 19:02:52 +00002279
Sean Huntcf807c42010-08-18 23:23:40 +00002280 d->addAttr(::new (S.Context) NoInlineAttr(Attr.getLoc(), S.Context));
Anders Carlsson5bab7882009-02-19 19:16:48 +00002281}
2282
Chris Lattner7255a2d2010-06-22 00:03:40 +00002283static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr,
2284 Sema &S) {
2285 // check the attribute arguments.
2286 if (Attr.getNumArgs() != 0) {
2287 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
2288 return;
2289 }
2290
2291 if (!isa<FunctionDecl>(d)) {
2292 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00002293 << Attr.getName() << ExpectedFunction;
Chris Lattner7255a2d2010-06-22 00:03:40 +00002294 return;
2295 }
2296
Eric Christopherf48f3672010-12-01 22:13:54 +00002297 d->addAttr(::new (S.Context) NoInstrumentFunctionAttr(Attr.getLoc(),
2298 S.Context));
Chris Lattner7255a2d2010-06-22 00:03:40 +00002299}
2300
Peter Collingbourneced76712010-12-01 03:15:31 +00002301static void HandleConstantAttr(Decl *d, const AttributeList &Attr, Sema &S) {
2302 if (S.LangOpts.CUDA) {
2303 // check the attribute arguments.
Ted Kremenek831efae2011-04-15 05:49:29 +00002304 if (Attr.hasParameterOrArguments()) {
Peter Collingbourneced76712010-12-01 03:15:31 +00002305 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
2306 return;
2307 }
2308
2309 if (!isa<VarDecl>(d)) {
2310 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00002311 << Attr.getName() << ExpectedVariable;
Peter Collingbourneced76712010-12-01 03:15:31 +00002312 return;
2313 }
2314
2315 d->addAttr(::new (S.Context) CUDAConstantAttr(Attr.getLoc(), S.Context));
2316 } else {
2317 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "constant";
2318 }
2319}
2320
2321static void HandleDeviceAttr(Decl *d, const AttributeList &Attr, Sema &S) {
2322 if (S.LangOpts.CUDA) {
2323 // check the attribute arguments.
2324 if (Attr.getNumArgs() != 0) {
2325 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
2326 return;
2327 }
2328
2329 if (!isa<FunctionDecl>(d) && !isa<VarDecl>(d)) {
2330 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00002331 << Attr.getName() << ExpectedVariableOrFunction;
Peter Collingbourneced76712010-12-01 03:15:31 +00002332 return;
2333 }
2334
2335 d->addAttr(::new (S.Context) CUDADeviceAttr(Attr.getLoc(), S.Context));
2336 } else {
2337 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "device";
2338 }
2339}
2340
2341static void HandleGlobalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
2342 if (S.LangOpts.CUDA) {
2343 // check the attribute arguments.
2344 if (Attr.getNumArgs() != 0) {
2345 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
2346 return;
2347 }
2348
2349 if (!isa<FunctionDecl>(d)) {
2350 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00002351 << Attr.getName() << ExpectedFunction;
Peter Collingbourneced76712010-12-01 03:15:31 +00002352 return;
2353 }
2354
Peter Collingbourne2c2c8dd2010-12-12 23:02:57 +00002355 FunctionDecl *FD = cast<FunctionDecl>(d);
2356 if (!FD->getResultType()->isVoidType()) {
Abramo Bagnara723df242010-12-14 22:11:44 +00002357 TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
Peter Collingbourne2c2c8dd2010-12-12 23:02:57 +00002358 if (FunctionTypeLoc* FTL = dyn_cast<FunctionTypeLoc>(&TL)) {
2359 S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
2360 << FD->getType()
2361 << FixItHint::CreateReplacement(FTL->getResultLoc().getSourceRange(),
2362 "void");
2363 } else {
2364 S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
2365 << FD->getType();
2366 }
2367 return;
2368 }
2369
Peter Collingbourneced76712010-12-01 03:15:31 +00002370 d->addAttr(::new (S.Context) CUDAGlobalAttr(Attr.getLoc(), S.Context));
2371 } else {
2372 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "global";
2373 }
2374}
2375
2376static void HandleHostAttr(Decl *d, const AttributeList &Attr, Sema &S) {
2377 if (S.LangOpts.CUDA) {
2378 // check the attribute arguments.
2379 if (Attr.getNumArgs() != 0) {
2380 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
2381 return;
2382 }
2383
2384 if (!isa<FunctionDecl>(d)) {
2385 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00002386 << Attr.getName() << ExpectedFunction;
Peter Collingbourneced76712010-12-01 03:15:31 +00002387 return;
2388 }
2389
2390 d->addAttr(::new (S.Context) CUDAHostAttr(Attr.getLoc(), S.Context));
2391 } else {
2392 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "host";
2393 }
2394}
2395
2396static void HandleSharedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
2397 if (S.LangOpts.CUDA) {
2398 // check the attribute arguments.
2399 if (Attr.getNumArgs() != 0) {
2400 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
2401 return;
2402 }
2403
2404 if (!isa<VarDecl>(d)) {
2405 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00002406 << Attr.getName() << ExpectedVariable;
Peter Collingbourneced76712010-12-01 03:15:31 +00002407 return;
2408 }
2409
2410 d->addAttr(::new (S.Context) CUDASharedAttr(Attr.getLoc(), S.Context));
2411 } else {
2412 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "shared";
2413 }
2414}
2415
Chris Lattnercf2a7212009-04-20 19:12:28 +00002416static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner26e25542009-04-14 16:30:50 +00002417 // check the attribute arguments.
2418 if (Attr.getNumArgs() != 0) {
2419 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
2420 return;
2421 }
Mike Stumpbf916502009-07-24 19:02:52 +00002422
Chris Lattnerc5197432009-04-14 17:02:11 +00002423 FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
2424 if (Fn == 0) {
Chris Lattner26e25542009-04-14 16:30:50 +00002425 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00002426 << Attr.getName() << ExpectedFunction;
Chris Lattner26e25542009-04-14 16:30:50 +00002427 return;
2428 }
Mike Stumpbf916502009-07-24 19:02:52 +00002429
Douglas Gregor0130f3c2009-10-27 21:01:01 +00002430 if (!Fn->isInlineSpecified()) {
Chris Lattnercf2a7212009-04-20 19:12:28 +00002431 S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
Chris Lattnerc5197432009-04-14 17:02:11 +00002432 return;
2433 }
Mike Stumpbf916502009-07-24 19:02:52 +00002434
Sean Huntcf807c42010-08-18 23:23:40 +00002435 d->addAttr(::new (S.Context) GNUInlineAttr(Attr.getLoc(), S.Context));
Chris Lattner26e25542009-04-14 16:30:50 +00002436}
2437
John McCall711c52b2011-01-05 12:14:39 +00002438static void HandleCallConvAttr(Decl *d, const AttributeList &attr, Sema &S) {
2439 if (hasDeclarator(d)) return;
Abramo Bagnarae215f722010-04-30 13:10:51 +00002440
John McCall711c52b2011-01-05 12:14:39 +00002441 // Diagnostic is emitted elsewhere: here we store the (valid) attr
2442 // in the Decl node for syntactic reasoning, e.g., pretty-printing.
2443 CallingConv CC;
2444 if (S.CheckCallingConvAttr(attr, CC))
2445 return;
2446
2447 if (!isa<ObjCMethodDecl>(d)) {
2448 S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00002449 << attr.getName() << ExpectedFunctionOrMethod;
John McCall711c52b2011-01-05 12:14:39 +00002450 return;
2451 }
2452
2453 switch (attr.getKind()) {
Abramo Bagnarae215f722010-04-30 13:10:51 +00002454 case AttributeList::AT_fastcall:
John McCall711c52b2011-01-05 12:14:39 +00002455 d->addAttr(::new (S.Context) FastCallAttr(attr.getLoc(), S.Context));
Abramo Bagnarae215f722010-04-30 13:10:51 +00002456 return;
2457 case AttributeList::AT_stdcall:
John McCall711c52b2011-01-05 12:14:39 +00002458 d->addAttr(::new (S.Context) StdCallAttr(attr.getLoc(), S.Context));
Abramo Bagnarae215f722010-04-30 13:10:51 +00002459 return;
Douglas Gregorf813a2c2010-05-18 16:57:00 +00002460 case AttributeList::AT_thiscall:
John McCall711c52b2011-01-05 12:14:39 +00002461 d->addAttr(::new (S.Context) ThisCallAttr(attr.getLoc(), S.Context));
Douglas Gregor04633eb2010-08-30 23:30:49 +00002462 return;
Abramo Bagnarae215f722010-04-30 13:10:51 +00002463 case AttributeList::AT_cdecl:
John McCall711c52b2011-01-05 12:14:39 +00002464 d->addAttr(::new (S.Context) CDeclAttr(attr.getLoc(), S.Context));
Abramo Bagnarae215f722010-04-30 13:10:51 +00002465 return;
Dawn Perchik52fc3142010-09-03 01:29:35 +00002466 case AttributeList::AT_pascal:
John McCall711c52b2011-01-05 12:14:39 +00002467 d->addAttr(::new (S.Context) PascalAttr(attr.getLoc(), S.Context));
Dawn Perchik52fc3142010-09-03 01:29:35 +00002468 return;
Anton Korobeynikov414d8962011-04-14 20:06:49 +00002469 case AttributeList::AT_pcs: {
2470 Expr *Arg = attr.getArg(0);
2471 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
2472 if (Str == 0 || Str->isWide()) {
2473 S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
2474 << "pcs" << 1;
2475 attr.setInvalid();
2476 return;
2477 }
2478
2479 llvm::StringRef StrRef = Str->getString();
2480 PcsAttr::PCSType PCS;
2481 if (StrRef == "aapcs")
2482 PCS = PcsAttr::AAPCS;
2483 else if (StrRef == "aapcs-vfp")
2484 PCS = PcsAttr::AAPCS_VFP;
2485 else {
2486 S.Diag(attr.getLoc(), diag::err_invalid_pcs);
2487 attr.setInvalid();
2488 return;
2489 }
2490
2491 d->addAttr(::new (S.Context) PcsAttr(attr.getLoc(), S.Context, PCS));
2492 }
Abramo Bagnarae215f722010-04-30 13:10:51 +00002493 default:
2494 llvm_unreachable("unexpected attribute kind");
2495 return;
2496 }
2497}
2498
Peter Collingbournef315fa82011-02-14 01:42:53 +00002499static void HandleOpenCLKernelAttr(Decl *d, const AttributeList &Attr, Sema &S){
2500 assert(Attr.isInvalid() == false);
2501 d->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getLoc(), S.Context));
2502}
2503
John McCall711c52b2011-01-05 12:14:39 +00002504bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) {
2505 if (attr.isInvalid())
2506 return true;
2507
Ted Kremenek831efae2011-04-15 05:49:29 +00002508 if ((attr.getNumArgs() != 0 &&
2509 !(attr.getKind() == AttributeList::AT_pcs && attr.getNumArgs() == 1)) ||
2510 attr.getParameterName()) {
John McCall711c52b2011-01-05 12:14:39 +00002511 Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
2512 attr.setInvalid();
2513 return true;
2514 }
2515
Anton Korobeynikov414d8962011-04-14 20:06:49 +00002516 // TODO: diagnose uses of these conventions on the wrong target. Or, better
2517 // move to TargetAttributesSema one day.
John McCall711c52b2011-01-05 12:14:39 +00002518 switch (attr.getKind()) {
2519 case AttributeList::AT_cdecl: CC = CC_C; break;
2520 case AttributeList::AT_fastcall: CC = CC_X86FastCall; break;
2521 case AttributeList::AT_stdcall: CC = CC_X86StdCall; break;
2522 case AttributeList::AT_thiscall: CC = CC_X86ThisCall; break;
2523 case AttributeList::AT_pascal: CC = CC_X86Pascal; break;
Anton Korobeynikov414d8962011-04-14 20:06:49 +00002524 case AttributeList::AT_pcs: {
2525 Expr *Arg = attr.getArg(0);
2526 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
2527 if (Str == 0 || Str->isWide()) {
2528 Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
2529 << "pcs" << 1;
2530 attr.setInvalid();
2531 return true;
2532 }
2533
2534 llvm::StringRef StrRef = Str->getString();
2535 if (StrRef == "aapcs") {
2536 CC = CC_AAPCS;
2537 break;
2538 } else if (StrRef == "aapcs-vfp") {
2539 CC = CC_AAPCS_VFP;
2540 break;
2541 }
2542 // FALLS THROUGH
2543 }
John McCall711c52b2011-01-05 12:14:39 +00002544 default: llvm_unreachable("unexpected attribute kind"); return true;
2545 }
2546
2547 return false;
2548}
2549
2550static void HandleRegparmAttr(Decl *d, const AttributeList &attr, Sema &S) {
2551 if (hasDeclarator(d)) return;
2552
2553 unsigned numParams;
2554 if (S.CheckRegparmAttr(attr, numParams))
2555 return;
2556
2557 if (!isa<ObjCMethodDecl>(d)) {
2558 S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00002559 << attr.getName() << ExpectedFunctionOrMethod;
Fariborz Jahanianee760332009-03-27 18:38:55 +00002560 return;
2561 }
Eli Friedman55d3aaf2009-03-27 21:06:47 +00002562
John McCall711c52b2011-01-05 12:14:39 +00002563 d->addAttr(::new (S.Context) RegparmAttr(attr.getLoc(), S.Context, numParams));
2564}
2565
2566/// Checks a regparm attribute, returning true if it is ill-formed and
2567/// otherwise setting numParams to the appropriate value.
2568bool Sema::CheckRegparmAttr(const AttributeList &attr, unsigned &numParams) {
2569 if (attr.isInvalid())
2570 return true;
2571
2572 if (attr.getNumArgs() != 1) {
2573 Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
2574 attr.setInvalid();
2575 return true;
Fariborz Jahanianee760332009-03-27 18:38:55 +00002576 }
Eli Friedman55d3aaf2009-03-27 21:06:47 +00002577
John McCall711c52b2011-01-05 12:14:39 +00002578 Expr *NumParamsExpr = attr.getArg(0);
Eli Friedman55d3aaf2009-03-27 21:06:47 +00002579 llvm::APSInt NumParams(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +00002580 if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() ||
John McCall711c52b2011-01-05 12:14:39 +00002581 !NumParamsExpr->isIntegerConstantExpr(NumParams, Context)) {
2582 Diag(attr.getLoc(), diag::err_attribute_argument_not_int)
Eli Friedman55d3aaf2009-03-27 21:06:47 +00002583 << "regparm" << NumParamsExpr->getSourceRange();
John McCall711c52b2011-01-05 12:14:39 +00002584 attr.setInvalid();
2585 return true;
Eli Friedman55d3aaf2009-03-27 21:06:47 +00002586 }
2587
John McCall711c52b2011-01-05 12:14:39 +00002588 if (Context.Target.getRegParmMax() == 0) {
2589 Diag(attr.getLoc(), diag::err_attribute_regparm_wrong_platform)
Eli Friedman55d3aaf2009-03-27 21:06:47 +00002590 << NumParamsExpr->getSourceRange();
John McCall711c52b2011-01-05 12:14:39 +00002591 attr.setInvalid();
2592 return true;
Eli Friedman55d3aaf2009-03-27 21:06:47 +00002593 }
2594
John McCall711c52b2011-01-05 12:14:39 +00002595 numParams = NumParams.getZExtValue();
2596 if (numParams > Context.Target.getRegParmMax()) {
2597 Diag(attr.getLoc(), diag::err_attribute_regparm_invalid_number)
2598 << Context.Target.getRegParmMax() << NumParamsExpr->getSourceRange();
2599 attr.setInvalid();
2600 return true;
Eli Friedman55d3aaf2009-03-27 21:06:47 +00002601 }
2602
John McCall711c52b2011-01-05 12:14:39 +00002603 return false;
Fariborz Jahanianee760332009-03-27 18:38:55 +00002604}
2605
Peter Collingbourne7b381982010-12-12 23:03:07 +00002606static void HandleLaunchBoundsAttr(Decl *d, const AttributeList &Attr, Sema &S){
2607 if (S.LangOpts.CUDA) {
2608 // check the attribute arguments.
2609 if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) {
John McCallbdc49d32011-03-02 12:15:05 +00002610 // FIXME: 0 is not okay.
2611 S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2;
Peter Collingbourne7b381982010-12-12 23:03:07 +00002612 return;
2613 }
2614
2615 if (!isFunctionOrMethod(d)) {
2616 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00002617 << Attr.getName() << ExpectedFunctionOrMethod;
Peter Collingbourne7b381982010-12-12 23:03:07 +00002618 return;
2619 }
2620
2621 Expr *MaxThreadsExpr = Attr.getArg(0);
2622 llvm::APSInt MaxThreads(32);
2623 if (MaxThreadsExpr->isTypeDependent() ||
2624 MaxThreadsExpr->isValueDependent() ||
2625 !MaxThreadsExpr->isIntegerConstantExpr(MaxThreads, S.Context)) {
2626 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
2627 << "launch_bounds" << 1 << MaxThreadsExpr->getSourceRange();
2628 return;
2629 }
2630
2631 llvm::APSInt MinBlocks(32);
2632 if (Attr.getNumArgs() > 1) {
2633 Expr *MinBlocksExpr = Attr.getArg(1);
2634 if (MinBlocksExpr->isTypeDependent() ||
2635 MinBlocksExpr->isValueDependent() ||
2636 !MinBlocksExpr->isIntegerConstantExpr(MinBlocks, S.Context)) {
2637 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
2638 << "launch_bounds" << 2 << MinBlocksExpr->getSourceRange();
2639 return;
2640 }
2641 }
2642
2643 d->addAttr(::new (S.Context) CUDALaunchBoundsAttr(Attr.getLoc(), S.Context,
2644 MaxThreads.getZExtValue(),
2645 MinBlocks.getZExtValue()));
2646 } else {
2647 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "launch_bounds";
2648 }
2649}
2650
Chris Lattner0744e5f2008-06-29 00:23:49 +00002651//===----------------------------------------------------------------------===//
Ted Kremenekb71368d2009-05-09 02:44:38 +00002652// Checker-specific attribute handlers.
2653//===----------------------------------------------------------------------===//
2654
John McCallc7ad3812011-01-25 03:31:58 +00002655static bool isValidSubjectOfNSAttribute(Sema &S, QualType type) {
2656 return type->isObjCObjectPointerType() || S.Context.isObjCNSObjectType(type);
2657}
2658static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) {
2659 return type->isPointerType() || isValidSubjectOfNSAttribute(S, type);
2660}
2661
2662static void HandleNSConsumedAttr(Decl *d, const AttributeList &attr, Sema &S) {
2663 ParmVarDecl *param = dyn_cast<ParmVarDecl>(d);
2664 if (!param) {
2665 S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00002666 << SourceRange(attr.getLoc()) << attr.getName() << ExpectedParameter;
John McCallc7ad3812011-01-25 03:31:58 +00002667 return;
2668 }
2669
2670 bool typeOK, cf;
2671 if (attr.getKind() == AttributeList::AT_ns_consumed) {
2672 typeOK = isValidSubjectOfNSAttribute(S, param->getType());
2673 cf = false;
2674 } else {
2675 typeOK = isValidSubjectOfCFAttribute(S, param->getType());
2676 cf = true;
2677 }
2678
2679 if (!typeOK) {
2680 S.Diag(d->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type)
2681 << SourceRange(attr.getLoc()) << attr.getName() << cf;
2682 return;
2683 }
2684
2685 if (cf)
2686 param->addAttr(::new (S.Context) CFConsumedAttr(attr.getLoc(), S.Context));
2687 else
2688 param->addAttr(::new (S.Context) NSConsumedAttr(attr.getLoc(), S.Context));
2689}
2690
2691static void HandleNSConsumesSelfAttr(Decl *d, const AttributeList &attr,
2692 Sema &S) {
2693 if (!isa<ObjCMethodDecl>(d)) {
2694 S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type)
John McCall883cc2c2011-03-02 12:29:23 +00002695 << SourceRange(attr.getLoc()) << attr.getName() << ExpectedMethod;
John McCallc7ad3812011-01-25 03:31:58 +00002696 return;
2697 }
2698
2699 d->addAttr(::new (S.Context) NSConsumesSelfAttr(attr.getLoc(), S.Context));
2700}
2701
2702static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &attr,
Ted Kremenekb71368d2009-05-09 02:44:38 +00002703 Sema &S) {
2704
John McCallc7ad3812011-01-25 03:31:58 +00002705 QualType returnType;
Mike Stumpbf916502009-07-24 19:02:52 +00002706
Ted Kremenek5dc53c92009-05-13 21:07:32 +00002707 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
John McCallc7ad3812011-01-25 03:31:58 +00002708 returnType = MD->getResultType();
Ted Kremenek5dc53c92009-05-13 21:07:32 +00002709 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d))
John McCallc7ad3812011-01-25 03:31:58 +00002710 returnType = FD->getResultType();
Ted Kremenek5dc53c92009-05-13 21:07:32 +00002711 else {
Ted Kremenek21531fa2009-08-19 23:56:48 +00002712 S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type)
John McCallc7ad3812011-01-25 03:31:58 +00002713 << SourceRange(attr.getLoc()) << attr.getName()
John McCall883cc2c2011-03-02 12:29:23 +00002714 << ExpectedFunctionOrMethod;
Ted Kremenekb71368d2009-05-09 02:44:38 +00002715 return;
2716 }
Mike Stumpbf916502009-07-24 19:02:52 +00002717
John McCallc7ad3812011-01-25 03:31:58 +00002718 bool typeOK;
2719 bool cf;
2720 switch (attr.getKind()) {
2721 default: llvm_unreachable("invalid ownership attribute"); return;
2722 case AttributeList::AT_ns_returns_autoreleased:
2723 case AttributeList::AT_ns_returns_retained:
2724 case AttributeList::AT_ns_returns_not_retained:
2725 typeOK = isValidSubjectOfNSAttribute(S, returnType);
2726 cf = false;
2727 break;
2728
2729 case AttributeList::AT_cf_returns_retained:
2730 case AttributeList::AT_cf_returns_not_retained:
2731 typeOK = isValidSubjectOfCFAttribute(S, returnType);
2732 cf = true;
2733 break;
2734 }
2735
2736 if (!typeOK) {
Ted Kremenek21531fa2009-08-19 23:56:48 +00002737 S.Diag(d->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
John McCallc7ad3812011-01-25 03:31:58 +00002738 << SourceRange(attr.getLoc())
2739 << attr.getName() << isa<ObjCMethodDecl>(d) << cf;
Mike Stumpbf916502009-07-24 19:02:52 +00002740 return;
Ted Kremenek5dc53c92009-05-13 21:07:32 +00002741 }
Mike Stumpbf916502009-07-24 19:02:52 +00002742
John McCallc7ad3812011-01-25 03:31:58 +00002743 switch (attr.getKind()) {
Ted Kremenekb71368d2009-05-09 02:44:38 +00002744 default:
2745 assert(0 && "invalid ownership attribute");
2746 return;
John McCallc7ad3812011-01-25 03:31:58 +00002747 case AttributeList::AT_ns_returns_autoreleased:
2748 d->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(attr.getLoc(),
2749 S.Context));
2750 return;
Ted Kremenek31c780d2010-02-18 00:05:45 +00002751 case AttributeList::AT_cf_returns_not_retained:
John McCallc7ad3812011-01-25 03:31:58 +00002752 d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(attr.getLoc(),
Eric Christopherf48f3672010-12-01 22:13:54 +00002753 S.Context));
Ted Kremenek31c780d2010-02-18 00:05:45 +00002754 return;
2755 case AttributeList::AT_ns_returns_not_retained:
John McCallc7ad3812011-01-25 03:31:58 +00002756 d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(attr.getLoc(),
Eric Christopherf48f3672010-12-01 22:13:54 +00002757 S.Context));
Ted Kremenek31c780d2010-02-18 00:05:45 +00002758 return;
Ted Kremenekb71368d2009-05-09 02:44:38 +00002759 case AttributeList::AT_cf_returns_retained:
John McCallc7ad3812011-01-25 03:31:58 +00002760 d->addAttr(::new (S.Context) CFReturnsRetainedAttr(attr.getLoc(),
Eric Christopherf48f3672010-12-01 22:13:54 +00002761 S.Context));
Ted Kremenekb71368d2009-05-09 02:44:38 +00002762 return;
2763 case AttributeList::AT_ns_returns_retained:
John McCallc7ad3812011-01-25 03:31:58 +00002764 d->addAttr(::new (S.Context) NSReturnsRetainedAttr(attr.getLoc(),
Eric Christopherf48f3672010-12-01 22:13:54 +00002765 S.Context));
Ted Kremenekb71368d2009-05-09 02:44:38 +00002766 return;
2767 };
2768}
2769
Charles Davisf0122fe2010-02-16 18:27:26 +00002770static bool isKnownDeclSpecAttr(const AttributeList &Attr) {
2771 return Attr.getKind() == AttributeList::AT_dllimport ||
Francois Pichet11542142010-12-19 06:50:37 +00002772 Attr.getKind() == AttributeList::AT_dllexport ||
2773 Attr.getKind() == AttributeList::AT_uuid;
2774}
2775
2776//===----------------------------------------------------------------------===//
2777// Microsoft specific attribute handlers.
2778//===----------------------------------------------------------------------===//
2779
2780static void HandleUuidAttr(Decl *d, const AttributeList &Attr, Sema &S) {
2781 if (S.LangOpts.Microsoft || S.LangOpts.Borland) {
2782 // check the attribute arguments.
2783 if (Attr.getNumArgs() != 1) {
2784 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
2785 return;
2786 }
2787 Expr *Arg = Attr.getArg(0);
2788 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
Francois Pichetd3d3be92010-12-20 01:41:49 +00002789 if (Str == 0 || Str->isWide()) {
2790 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
2791 << "uuid" << 1;
2792 return;
2793 }
2794
2795 llvm::StringRef StrRef = Str->getString();
2796
2797 bool IsCurly = StrRef.size() > 1 && StrRef.front() == '{' &&
2798 StrRef.back() == '}';
2799
2800 // Validate GUID length.
2801 if (IsCurly && StrRef.size() != 38) {
2802 S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
2803 return;
2804 }
2805 if (!IsCurly && StrRef.size() != 36) {
2806 S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
2807 return;
2808 }
2809
2810 // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or
2811 // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
Anders Carlssonf89e0422011-01-23 21:07:30 +00002812 llvm::StringRef::iterator I = StrRef.begin();
2813 if (IsCurly) // Skip the optional '{'
2814 ++I;
2815
2816 for (int i = 0; i < 36; ++i) {
Francois Pichetd3d3be92010-12-20 01:41:49 +00002817 if (i == 8 || i == 13 || i == 18 || i == 23) {
2818 if (*I != '-') {
2819 S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
2820 return;
2821 }
2822 } else if (!isxdigit(*I)) {
2823 S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
2824 return;
2825 }
2826 I++;
2827 }
Francois Pichet11542142010-12-19 06:50:37 +00002828
2829 d->addAttr(::new (S.Context) UuidAttr(Attr.getLoc(), S.Context,
2830 Str->getString()));
Francois Pichetd3d3be92010-12-20 01:41:49 +00002831 } else
Francois Pichet11542142010-12-19 06:50:37 +00002832 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid";
Charles Davisf0122fe2010-02-16 18:27:26 +00002833}
2834
Ted Kremenekb71368d2009-05-09 02:44:38 +00002835//===----------------------------------------------------------------------===//
Chris Lattner0744e5f2008-06-29 00:23:49 +00002836// Top Level Sema Entry Points
2837//===----------------------------------------------------------------------===//
2838
Peter Collingbourne60700392011-01-21 02:08:45 +00002839static void ProcessNonInheritableDeclAttr(Scope *scope, Decl *D,
2840 const AttributeList &Attr, Sema &S) {
2841 switch (Attr.getKind()) {
2842 case AttributeList::AT_device: HandleDeviceAttr (D, Attr, S); break;
2843 case AttributeList::AT_host: HandleHostAttr (D, Attr, S); break;
2844 case AttributeList::AT_overloadable:HandleOverloadableAttr(D, Attr, S); break;
2845 default:
2846 break;
2847 }
2848}
Abramo Bagnarae215f722010-04-30 13:10:51 +00002849
Peter Collingbourne60700392011-01-21 02:08:45 +00002850static void ProcessInheritableDeclAttr(Scope *scope, Decl *D,
2851 const AttributeList &Attr, Sema &S) {
Chris Lattner803d0802008-06-29 00:43:07 +00002852 switch (Attr.getKind()) {
Ted Kremenek63e5d7c2010-02-18 03:08:58 +00002853 case AttributeList::AT_IBAction: HandleIBAction(D, Attr, S); break;
Ted Kremenek857e9182010-05-19 17:38:06 +00002854 case AttributeList::AT_IBOutlet: HandleIBOutlet(D, Attr, S); break;
2855 case AttributeList::AT_IBOutletCollection:
2856 HandleIBOutletCollection(D, Attr, S); break;
Chris Lattner803d0802008-06-29 00:43:07 +00002857 case AttributeList::AT_address_space:
Peter Collingbourne207f4d82011-03-18 22:38:29 +00002858 case AttributeList::AT_opencl_image_access:
Fariborz Jahanianba372b82009-02-18 17:52:36 +00002859 case AttributeList::AT_objc_gc:
John Thompson6e132aa2009-12-04 21:51:28 +00002860 case AttributeList::AT_vector_size:
Bob Wilson4211bb62010-11-16 00:32:24 +00002861 case AttributeList::AT_neon_vector_type:
2862 case AttributeList::AT_neon_polyvector_type:
Mike Stumpbf916502009-07-24 19:02:52 +00002863 // Ignore these, these are type attributes, handled by
2864 // ProcessTypeAttributes.
Chris Lattner803d0802008-06-29 00:43:07 +00002865 break;
Peter Collingbourne60700392011-01-21 02:08:45 +00002866 case AttributeList::AT_device:
2867 case AttributeList::AT_host:
2868 case AttributeList::AT_overloadable:
2869 // Ignore, this is a non-inheritable attribute, handled
2870 // by ProcessNonInheritableDeclAttr.
2871 break;
Sean Hunt7725e672009-11-25 04:20:27 +00002872 case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break;
2873 case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break;
Mike Stumpbf916502009-07-24 19:02:52 +00002874 case AttributeList::AT_always_inline:
Daniel Dunbaraf668b02008-10-28 00:17:57 +00002875 HandleAlwaysInlineAttr (D, Attr, S); break;
Ted Kremenekb7252322009-04-10 00:01:14 +00002876 case AttributeList::AT_analyzer_noreturn:
Mike Stumpbf916502009-07-24 19:02:52 +00002877 HandleAnalyzerNoReturnAttr (D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002878 case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break;
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00002879 case AttributeList::AT_availability:HandleAvailabilityAttr(D, Attr, S); break;
Sean Huntbbd37c62009-11-21 08:43:09 +00002880 case AttributeList::AT_carries_dependency:
Sean Hunt7725e672009-11-25 04:20:27 +00002881 HandleDependencyAttr (D, Attr, S); break;
Eric Christophera6cf1e72010-12-02 02:45:55 +00002882 case AttributeList::AT_common: HandleCommonAttr (D, Attr, S); break;
Peter Collingbourneced76712010-12-01 03:15:31 +00002883 case AttributeList::AT_constant: HandleConstantAttr (D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002884 case AttributeList::AT_constructor: HandleConstructorAttr (D, Attr, S); break;
2885 case AttributeList::AT_deprecated: HandleDeprecatedAttr (D, Attr, S); break;
2886 case AttributeList::AT_destructor: HandleDestructorAttr (D, Attr, S); break;
Chris Lattner803d0802008-06-29 00:43:07 +00002887 case AttributeList::AT_ext_vector_type:
Douglas Gregor9cdda0c2009-06-17 21:51:59 +00002888 HandleExtVectorTypeAttr(scope, D, Attr, S);
Chris Lattner803d0802008-06-29 00:43:07 +00002889 break;
Sean Hunt7725e672009-11-25 04:20:27 +00002890 case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break;
2891 case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break;
Peter Collingbourneced76712010-12-01 03:15:31 +00002892 case AttributeList::AT_global: HandleGlobalAttr (D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002893 case AttributeList::AT_gnu_inline: HandleGNUInlineAttr (D, Attr, S); break;
Peter Collingbourne7b381982010-12-12 23:03:07 +00002894 case AttributeList::AT_launch_bounds:
2895 HandleLaunchBoundsAttr(D, Attr, S);
2896 break;
Sean Hunt7725e672009-11-25 04:20:27 +00002897 case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break;
2898 case AttributeList::AT_malloc: HandleMallocAttr (D, Attr, S); break;
Dan Gohman34c26302010-11-17 00:03:07 +00002899 case AttributeList::AT_may_alias: HandleMayAliasAttr (D, Attr, S); break;
Eric Christophera6cf1e72010-12-02 02:45:55 +00002900 case AttributeList::AT_nocommon: HandleNoCommonAttr (D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002901 case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break;
Ted Kremenekdd0e4902010-07-31 01:52:11 +00002902 case AttributeList::AT_ownership_returns:
2903 case AttributeList::AT_ownership_takes:
2904 case AttributeList::AT_ownership_holds:
2905 HandleOwnershipAttr (D, Attr, S); break;
Daniel Dunbardd0cb222010-09-29 18:20:25 +00002906 case AttributeList::AT_naked: HandleNakedAttr (D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002907 case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break;
2908 case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break;
Peter Collingbourneced76712010-12-01 03:15:31 +00002909 case AttributeList::AT_shared: HandleSharedAttr (D, Attr, S); break;
John Thompson35cc9622010-08-09 21:53:52 +00002910 case AttributeList::AT_vecreturn: HandleVecReturnAttr (D, Attr, S); break;
Ted Kremenekb71368d2009-05-09 02:44:38 +00002911
2912 // Checker-specific.
John McCallc7ad3812011-01-25 03:31:58 +00002913 case AttributeList::AT_cf_consumed:
2914 case AttributeList::AT_ns_consumed: HandleNSConsumedAttr (D, Attr, S); break;
2915 case AttributeList::AT_ns_consumes_self:
2916 HandleNSConsumesSelfAttr(D, Attr, S); break;
2917
2918 case AttributeList::AT_ns_returns_autoreleased:
Ted Kremenek31c780d2010-02-18 00:05:45 +00002919 case AttributeList::AT_ns_returns_not_retained:
2920 case AttributeList::AT_cf_returns_not_retained:
Ted Kremenekb71368d2009-05-09 02:44:38 +00002921 case AttributeList::AT_ns_returns_retained:
2922 case AttributeList::AT_cf_returns_retained:
2923 HandleNSReturnsRetainedAttr(D, Attr, S); break;
2924
Nate Begeman6f3d8382009-06-26 06:32:41 +00002925 case AttributeList::AT_reqd_wg_size:
2926 HandleReqdWorkGroupSize(D, Attr, S); break;
2927
Fariborz Jahanian521f12d2010-06-18 21:44:06 +00002928 case AttributeList::AT_init_priority:
2929 HandleInitPriorityAttr(D, Attr, S); break;
2930
Sean Hunt7725e672009-11-25 04:20:27 +00002931 case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break;
Fariborz Jahanianc1a0a732011-04-26 17:54:40 +00002932 case AttributeList::AT_MsStruct: HandleMsStructAttr (D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002933 case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002934 case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break;
2935 case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break;
2936 case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002937 case AttributeList::AT_visibility: HandleVisibilityAttr (D, Attr, S); break;
Chris Lattner026dc962009-02-14 07:37:35 +00002938 case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S);
2939 break;
Sean Hunt7725e672009-11-25 04:20:27 +00002940 case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break;
Rafael Espindola11e8ce72010-02-23 22:00:30 +00002941 case AttributeList::AT_weakref: HandleWeakRefAttr (D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002942 case AttributeList::AT_weak_import: HandleWeakImportAttr (D, Attr, S); break;
Chris Lattner803d0802008-06-29 00:43:07 +00002943 case AttributeList::AT_transparent_union:
2944 HandleTransparentUnionAttr(D, Attr, S);
2945 break;
Chris Lattner0db29ec2009-02-14 08:09:34 +00002946 case AttributeList::AT_objc_exception:
2947 HandleObjCExceptionAttr(D, Attr, S);
2948 break;
John McCalld5313b02011-03-02 11:33:24 +00002949 case AttributeList::AT_objc_method_family:
2950 HandleObjCMethodFamilyAttr(D, Attr, S);
2951 break;
Sean Hunt7725e672009-11-25 04:20:27 +00002952 case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break;
2953 case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break;
2954 case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break;
2955 case AttributeList::AT_const: HandleConstAttr (D, Attr, S); break;
2956 case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break;
2957 case AttributeList::AT_cleanup: HandleCleanupAttr (D, Attr, S); break;
2958 case AttributeList::AT_nodebug: HandleNoDebugAttr (D, Attr, S); break;
2959 case AttributeList::AT_noinline: HandleNoInlineAttr (D, Attr, S); break;
2960 case AttributeList::AT_regparm: HandleRegparmAttr (D, Attr, S); break;
Mike Stumpbf916502009-07-24 19:02:52 +00002961 case AttributeList::IgnoredAttribute:
Anders Carlsson05f8e472009-02-13 08:16:43 +00002962 // Just ignore
2963 break;
Chris Lattner7255a2d2010-06-22 00:03:40 +00002964 case AttributeList::AT_no_instrument_function: // Interacts with -pg.
2965 HandleNoInstrumentFunctionAttr(D, Attr, S);
2966 break;
John McCall04a67a62010-02-05 21:31:56 +00002967 case AttributeList::AT_stdcall:
2968 case AttributeList::AT_cdecl:
2969 case AttributeList::AT_fastcall:
Douglas Gregorf813a2c2010-05-18 16:57:00 +00002970 case AttributeList::AT_thiscall:
Dawn Perchik52fc3142010-09-03 01:29:35 +00002971 case AttributeList::AT_pascal:
Anton Korobeynikov414d8962011-04-14 20:06:49 +00002972 case AttributeList::AT_pcs:
Abramo Bagnarae215f722010-04-30 13:10:51 +00002973 HandleCallConvAttr(D, Attr, S);
John McCall04a67a62010-02-05 21:31:56 +00002974 break;
Peter Collingbournef315fa82011-02-14 01:42:53 +00002975 case AttributeList::AT_opencl_kernel_function:
2976 HandleOpenCLKernelAttr(D, Attr, S);
2977 break;
Francois Pichet11542142010-12-19 06:50:37 +00002978 case AttributeList::AT_uuid:
2979 HandleUuidAttr(D, Attr, S);
2980 break;
Chris Lattner803d0802008-06-29 00:43:07 +00002981 default:
Anton Korobeynikov82d0a412010-01-10 12:58:08 +00002982 // Ask target about the attribute.
2983 const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
2984 if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S))
Chandler Carruth7d5c45e2010-07-08 09:42:26 +00002985 S.Diag(Attr.getLoc(), diag::warn_unknown_attribute_ignored)
2986 << Attr.getName();
Chris Lattner803d0802008-06-29 00:43:07 +00002987 break;
2988 }
2989}
2990
Peter Collingbourne60700392011-01-21 02:08:45 +00002991/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
2992/// the attribute applies to decls. If the attribute is a type attribute, just
2993/// silently ignore it if a GNU attribute. FIXME: Applying a C++0x attribute to
2994/// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4).
2995static void ProcessDeclAttribute(Scope *scope, Decl *D,
2996 const AttributeList &Attr, Sema &S,
2997 bool NonInheritable, bool Inheritable) {
2998 if (Attr.isInvalid())
2999 return;
3000
3001 if (Attr.isDeclspecAttribute() && !isKnownDeclSpecAttr(Attr))
3002 // FIXME: Try to deal with other __declspec attributes!
3003 return;
3004
3005 if (NonInheritable)
3006 ProcessNonInheritableDeclAttr(scope, D, Attr, S);
3007
3008 if (Inheritable)
3009 ProcessInheritableDeclAttr(scope, D, Attr, S);
3010}
3011
Chris Lattner803d0802008-06-29 00:43:07 +00003012/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
3013/// attribute list to the specified decl, ignoring any type attributes.
Eric Christopherf48f3672010-12-01 22:13:54 +00003014void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
Peter Collingbourne60700392011-01-21 02:08:45 +00003015 const AttributeList *AttrList,
3016 bool NonInheritable, bool Inheritable) {
Rafael Espindola11e8ce72010-02-23 22:00:30 +00003017 for (const AttributeList* l = AttrList; l; l = l->getNext()) {
Peter Collingbourne60700392011-01-21 02:08:45 +00003018 ProcessDeclAttribute(S, D, *l, *this, NonInheritable, Inheritable);
Rafael Espindola11e8ce72010-02-23 22:00:30 +00003019 }
3020
3021 // GCC accepts
3022 // static int a9 __attribute__((weakref));
3023 // but that looks really pointless. We reject it.
Peter Collingbourne60700392011-01-21 02:08:45 +00003024 if (Inheritable && D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
Rafael Espindola11e8ce72010-02-23 22:00:30 +00003025 Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) <<
Ted Kremenekdd0e4902010-07-31 01:52:11 +00003026 dyn_cast<NamedDecl>(D)->getNameAsString();
Rafael Espindola11e8ce72010-02-23 22:00:30 +00003027 return;
Chris Lattner803d0802008-06-29 00:43:07 +00003028 }
3029}
3030
Ryan Flynne25ff832009-07-30 03:15:39 +00003031/// DeclClonePragmaWeak - clone existing decl (maybe definition),
3032/// #pragma weak needs a non-definition decl and source may not have one
Mike Stump1eb44332009-09-09 15:08:12 +00003033NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) {
Ryan Flynn7b1fdbd2009-07-31 02:52:19 +00003034 assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
Ryan Flynne25ff832009-07-30 03:15:39 +00003035 NamedDecl *NewD = 0;
3036 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
3037 NewD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(),
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00003038 FD->getInnerLocStart(),
Ryan Flynne25ff832009-07-30 03:15:39 +00003039 FD->getLocation(), DeclarationName(II),
John McCalla93c9342009-12-07 02:54:59 +00003040 FD->getType(), FD->getTypeSourceInfo());
John McCallb6217662010-03-15 10:12:16 +00003041 if (FD->getQualifier()) {
3042 FunctionDecl *NewFD = cast<FunctionDecl>(NewD);
Douglas Gregorc22b5ff2011-02-25 02:25:35 +00003043 NewFD->setQualifierInfo(FD->getQualifierLoc());
John McCallb6217662010-03-15 10:12:16 +00003044 }
Ryan Flynne25ff832009-07-30 03:15:39 +00003045 } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) {
3046 NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00003047 VD->getInnerLocStart(), VD->getLocation(), II,
John McCalla93c9342009-12-07 02:54:59 +00003048 VD->getType(), VD->getTypeSourceInfo(),
Douglas Gregor16573fa2010-04-19 22:54:31 +00003049 VD->getStorageClass(),
3050 VD->getStorageClassAsWritten());
John McCallb6217662010-03-15 10:12:16 +00003051 if (VD->getQualifier()) {
3052 VarDecl *NewVD = cast<VarDecl>(NewD);
Douglas Gregorc22b5ff2011-02-25 02:25:35 +00003053 NewVD->setQualifierInfo(VD->getQualifierLoc());
John McCallb6217662010-03-15 10:12:16 +00003054 }
Ryan Flynne25ff832009-07-30 03:15:39 +00003055 }
3056 return NewD;
3057}
3058
3059/// DeclApplyPragmaWeak - A declaration (maybe definition) needs #pragma weak
3060/// applied to it, possibly with an alias.
Ryan Flynn7b1fdbd2009-07-31 02:52:19 +00003061void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
Chris Lattnerc4f1fb12009-09-08 18:10:11 +00003062 if (W.getUsed()) return; // only do this once
3063 W.setUsed(true);
3064 if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
3065 IdentifierInfo *NDId = ND->getIdentifier();
3066 NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias());
Sean Huntcf807c42010-08-18 23:23:40 +00003067 NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context,
3068 NDId->getName()));
3069 NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
Chris Lattnerc4f1fb12009-09-08 18:10:11 +00003070 WeakTopLevelDecl.push_back(NewD);
3071 // FIXME: "hideous" code from Sema::LazilyCreateBuiltin
3072 // to insert Decl at TU scope, sorry.
3073 DeclContext *SavedContext = CurContext;
3074 CurContext = Context.getTranslationUnitDecl();
3075 PushOnScopeChains(NewD, S);
3076 CurContext = SavedContext;
3077 } else { // just add weak to existing
Sean Huntcf807c42010-08-18 23:23:40 +00003078 ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
Ryan Flynne25ff832009-07-30 03:15:39 +00003079 }
3080}
3081
Chris Lattner0744e5f2008-06-29 00:23:49 +00003082/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
3083/// it, apply them to D. This is a bit tricky because PD can have attributes
3084/// specified in many different places, and we need to find and apply them all.
Peter Collingbourne60700392011-01-21 02:08:45 +00003085void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD,
3086 bool NonInheritable, bool Inheritable) {
John McCalld4aff0e2010-10-27 00:59:00 +00003087 // It's valid to "forward-declare" #pragma weak, in which case we
3088 // have to do this.
Peter Collingbourne60700392011-01-21 02:08:45 +00003089 if (Inheritable && !WeakUndeclaredIdentifiers.empty()) {
John McCalld4aff0e2010-10-27 00:59:00 +00003090 if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
3091 if (IdentifierInfo *Id = ND->getIdentifier()) {
3092 llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I
3093 = WeakUndeclaredIdentifiers.find(Id);
3094 if (I != WeakUndeclaredIdentifiers.end() && ND->hasLinkage()) {
3095 WeakInfo W = I->second;
3096 DeclApplyPragmaWeak(S, ND, W);
3097 WeakUndeclaredIdentifiers[Id] = W;
3098 }
Ryan Flynne25ff832009-07-30 03:15:39 +00003099 }
3100 }
3101 }
3102
Chris Lattner0744e5f2008-06-29 00:23:49 +00003103 // Apply decl attributes from the DeclSpec if present.
John McCall7f040a92010-12-24 02:08:15 +00003104 if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList())
Peter Collingbourne60700392011-01-21 02:08:45 +00003105 ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable);
Mike Stumpbf916502009-07-24 19:02:52 +00003106
Chris Lattner0744e5f2008-06-29 00:23:49 +00003107 // Walk the declarator structure, applying decl attributes that were in a type
3108 // position to the decl itself. This handles cases like:
3109 // int *__attr__(x)** D;
3110 // when X is a decl attribute.
3111 for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
3112 if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
Peter Collingbourne60700392011-01-21 02:08:45 +00003113 ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable);
Mike Stumpbf916502009-07-24 19:02:52 +00003114
Chris Lattner0744e5f2008-06-29 00:23:49 +00003115 // Finally, apply any attributes on the decl itself.
3116 if (const AttributeList *Attrs = PD.getAttributes())
Peter Collingbourne60700392011-01-21 02:08:45 +00003117 ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable);
Chris Lattner0744e5f2008-06-29 00:23:49 +00003118}
John McCall54abf7d2009-11-04 02:18:39 +00003119
John McCalleee1d542011-02-14 07:13:47 +00003120// This duplicates a vector push_back but hides the need to know the
3121// size of the type.
3122void Sema::DelayedDiagnostics::add(const DelayedDiagnostic &diag) {
3123 assert(StackSize <= StackCapacity);
3124
3125 // Grow the stack if necessary.
3126 if (StackSize == StackCapacity) {
3127 unsigned newCapacity = 2 * StackCapacity + 2;
3128 char *newBuffer = new char[newCapacity * sizeof(DelayedDiagnostic)];
3129 const char *oldBuffer = (const char*) Stack;
3130
3131 if (StackCapacity)
3132 memcpy(newBuffer, oldBuffer, StackCapacity * sizeof(DelayedDiagnostic));
3133
3134 delete[] oldBuffer;
3135 Stack = reinterpret_cast<sema::DelayedDiagnostic*>(newBuffer);
3136 StackCapacity = newCapacity;
3137 }
3138
3139 assert(StackSize < StackCapacity);
3140 new (&Stack[StackSize++]) DelayedDiagnostic(diag);
John McCall2f514482010-01-27 03:50:35 +00003141}
3142
John McCalleee1d542011-02-14 07:13:47 +00003143void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state,
3144 Decl *decl) {
3145 DelayedDiagnostics &DD = S.DelayedDiagnostics;
John McCall2f514482010-01-27 03:50:35 +00003146
John McCalleee1d542011-02-14 07:13:47 +00003147 // Check the invariants.
3148 assert(DD.StackSize >= state.SavedStackSize);
3149 assert(state.SavedStackSize >= DD.ActiveStackBase);
3150 assert(DD.ParsingDepth > 0);
3151
3152 // Drop the parsing depth.
3153 DD.ParsingDepth--;
3154
3155 // If there are no active diagnostics, we're done.
3156 if (DD.StackSize == DD.ActiveStackBase)
John McCall2f514482010-01-27 03:50:35 +00003157 return;
3158
John McCall2f514482010-01-27 03:50:35 +00003159 // We only want to actually emit delayed diagnostics when we
3160 // successfully parsed a decl.
John McCalleee1d542011-02-14 07:13:47 +00003161 if (decl) {
3162 // We emit all the active diagnostics, not just those starting
3163 // from the saved state. The idea is this: we get one push for a
John McCall2f514482010-01-27 03:50:35 +00003164 // decl spec and another for each declarator; in a decl group like:
3165 // deprecated_typedef foo, *bar, baz();
3166 // only the declarator pops will be passed decls. This is correct;
3167 // we really do need to consider delayed diagnostics from the decl spec
3168 // for each of the different declarations.
John McCalleee1d542011-02-14 07:13:47 +00003169 for (unsigned i = DD.ActiveStackBase, e = DD.StackSize; i != e; ++i) {
3170 DelayedDiagnostic &diag = DD.Stack[i];
3171 if (diag.Triggered)
John McCall2f514482010-01-27 03:50:35 +00003172 continue;
3173
John McCalleee1d542011-02-14 07:13:47 +00003174 switch (diag.Kind) {
John McCall2f514482010-01-27 03:50:35 +00003175 case DelayedDiagnostic::Deprecation:
John McCalleee1d542011-02-14 07:13:47 +00003176 S.HandleDelayedDeprecationCheck(diag, decl);
John McCall2f514482010-01-27 03:50:35 +00003177 break;
3178
3179 case DelayedDiagnostic::Access:
John McCalleee1d542011-02-14 07:13:47 +00003180 S.HandleDelayedAccessCheck(diag, decl);
John McCall2f514482010-01-27 03:50:35 +00003181 break;
3182 }
3183 }
3184 }
3185
John McCall58e6f342010-03-16 05:22:47 +00003186 // Destroy all the delayed diagnostics we're about to pop off.
John McCalleee1d542011-02-14 07:13:47 +00003187 for (unsigned i = state.SavedStackSize, e = DD.StackSize; i != e; ++i)
Douglas Gregor29233802011-03-23 15:13:44 +00003188 DD.Stack[i].Destroy();
John McCall58e6f342010-03-16 05:22:47 +00003189
John McCalleee1d542011-02-14 07:13:47 +00003190 DD.StackSize = state.SavedStackSize;
John McCall54abf7d2009-11-04 02:18:39 +00003191}
3192
3193static bool isDeclDeprecated(Decl *D) {
3194 do {
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00003195 if (D->isDeprecated())
John McCall54abf7d2009-11-04 02:18:39 +00003196 return true;
3197 } while ((D = cast_or_null<Decl>(D->getDeclContext())));
3198 return false;
3199}
3200
John McCall9c3087b2010-08-26 02:13:20 +00003201void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD,
John McCall2f514482010-01-27 03:50:35 +00003202 Decl *Ctx) {
3203 if (isDeclDeprecated(Ctx))
John McCall54abf7d2009-11-04 02:18:39 +00003204 return;
3205
John McCall2f514482010-01-27 03:50:35 +00003206 DD.Triggered = true;
Benjamin Kramerce2d1862010-10-09 15:49:00 +00003207 if (!DD.getDeprecationMessage().empty())
Fariborz Jahanianc4b35cf2010-10-06 21:18:44 +00003208 Diag(DD.Loc, diag::warn_deprecated_message)
Benjamin Kramerce2d1862010-10-09 15:49:00 +00003209 << DD.getDeprecationDecl()->getDeclName()
3210 << DD.getDeprecationMessage();
Fariborz Jahanianc4b35cf2010-10-06 21:18:44 +00003211 else
3212 Diag(DD.Loc, diag::warn_deprecated)
Benjamin Kramerce2d1862010-10-09 15:49:00 +00003213 << DD.getDeprecationDecl()->getDeclName();
John McCall54abf7d2009-11-04 02:18:39 +00003214}
3215
Benjamin Kramerce2d1862010-10-09 15:49:00 +00003216void Sema::EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message,
Fariborz Jahanian8e5fc9b2010-12-21 00:44:01 +00003217 SourceLocation Loc,
Fariborz Jahanian89ebaed2011-04-23 17:27:19 +00003218 const ObjCInterfaceDecl *UnknownObjCClass) {
John McCall54abf7d2009-11-04 02:18:39 +00003219 // Delay if we're currently parsing a declaration.
John McCalleee1d542011-02-14 07:13:47 +00003220 if (DelayedDiagnostics.shouldDelayDiagnostics()) {
3221 DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, Message));
John McCall54abf7d2009-11-04 02:18:39 +00003222 return;
3223 }
3224
3225 // Otherwise, don't warn if our current context is deprecated.
3226 if (isDeclDeprecated(cast<Decl>(CurContext)))
3227 return;
Benjamin Kramerce2d1862010-10-09 15:49:00 +00003228 if (!Message.empty())
Fariborz Jahanianc4b35cf2010-10-06 21:18:44 +00003229 Diag(Loc, diag::warn_deprecated_message) << D->getDeclName()
3230 << Message;
Fariborz Jahanian8e5fc9b2010-12-21 00:44:01 +00003231 else {
Peter Collingbourne743b82b2011-01-02 19:53:12 +00003232 if (!UnknownObjCClass)
Fariborz Jahanian8e5fc9b2010-12-21 00:44:01 +00003233 Diag(Loc, diag::warn_deprecated) << D->getDeclName();
Fariborz Jahanian89ebaed2011-04-23 17:27:19 +00003234 else {
Fariborz Jahanian8e5fc9b2010-12-21 00:44:01 +00003235 Diag(Loc, diag::warn_deprecated_fwdclass_message) << D->getDeclName();
Fariborz Jahanian89ebaed2011-04-23 17:27:19 +00003236 Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
3237 }
Fariborz Jahanian8e5fc9b2010-12-21 00:44:01 +00003238 }
John McCall54abf7d2009-11-04 02:18:39 +00003239}