blob: f515e6883970a62d563a7d0280d6e38e12ed09ff [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
Douglas Gregore737f502010-08-12 20:07:10 +000014#include "clang/Sema/Sema.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"
Chris Lattner797c3c42009-08-10 19:03:04 +000022#include "llvm/ADT/StringExtras.h"
Chris Lattner6b6b5372008-06-26 18:38:35 +000023using namespace clang;
24
Chris Lattnere5c5ee12008-06-29 00:16:31 +000025//===----------------------------------------------------------------------===//
26// Helper functions
27//===----------------------------------------------------------------------===//
28
Ted Kremeneka18d7d82009-08-14 20:49:40 +000029static const FunctionType *getFunctionType(const Decl *d,
30 bool blocksToo = true) {
Chris Lattner6b6b5372008-06-26 18:38:35 +000031 QualType Ty;
Ted Kremeneka18d7d82009-08-14 20:49:40 +000032 if (const ValueDecl *decl = dyn_cast<ValueDecl>(d))
Chris Lattner6b6b5372008-06-26 18:38:35 +000033 Ty = decl->getType();
Ted Kremeneka18d7d82009-08-14 20:49:40 +000034 else if (const FieldDecl *decl = dyn_cast<FieldDecl>(d))
Chris Lattner6b6b5372008-06-26 18:38:35 +000035 Ty = decl->getType();
Ted Kremeneka18d7d82009-08-14 20:49:40 +000036 else if (const TypedefDecl* decl = dyn_cast<TypedefDecl>(d))
Chris Lattner6b6b5372008-06-26 18:38:35 +000037 Ty = decl->getUnderlyingType();
38 else
39 return 0;
Mike Stumpbf916502009-07-24 19:02:52 +000040
Chris Lattner6b6b5372008-06-26 18:38:35 +000041 if (Ty->isFunctionPointerType())
Ted Kremenek6217b802009-07-29 21:53:49 +000042 Ty = Ty->getAs<PointerType>()->getPointeeType();
Fariborz Jahanian755f9d22009-05-18 17:39:25 +000043 else if (blocksToo && Ty->isBlockPointerType())
Ted Kremenek6217b802009-07-29 21:53:49 +000044 Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
Daniel Dunbard3f2c102008-10-19 02:04:16 +000045
John McCall183700f2009-09-21 23:43:11 +000046 return Ty->getAs<FunctionType>();
Chris Lattner6b6b5372008-06-26 18:38:35 +000047}
48
Daniel Dunbar35682492008-09-26 04:12:28 +000049// FIXME: We should provide an abstraction around a method or function
50// to provide the following bits of information.
51
Nuno Lopesd20254f2009-12-20 23:11:08 +000052/// isFunction - Return true if the given decl has function
Ted Kremeneka18d7d82009-08-14 20:49:40 +000053/// type (function or function-typed variable).
54static bool isFunction(const Decl *d) {
55 return getFunctionType(d, false) != NULL;
56}
57
58/// isFunctionOrMethod - Return true if the given decl has function
Daniel Dunbard3f2c102008-10-19 02:04:16 +000059/// type (function or function-typed variable) or an Objective-C
60/// method.
Ted Kremeneka18d7d82009-08-14 20:49:40 +000061static bool isFunctionOrMethod(const Decl *d) {
62 return isFunction(d)|| isa<ObjCMethodDecl>(d);
Daniel Dunbar35682492008-09-26 04:12:28 +000063}
64
Fariborz Jahanian620d89c2009-05-15 23:15:03 +000065/// isFunctionOrMethodOrBlock - Return true if the given decl has function
66/// type (function or function-typed variable) or an Objective-C
67/// method or a block.
Ted Kremeneka18d7d82009-08-14 20:49:40 +000068static bool isFunctionOrMethodOrBlock(const Decl *d) {
Fariborz Jahanian620d89c2009-05-15 23:15:03 +000069 if (isFunctionOrMethod(d))
70 return true;
71 // check for block is more involved.
72 if (const VarDecl *V = dyn_cast<VarDecl>(d)) {
73 QualType Ty = V->getType();
74 return Ty->isBlockPointerType();
75 }
Fariborz Jahaniand66f22d2009-05-19 17:08:59 +000076 return isa<BlockDecl>(d);
Fariborz Jahanian620d89c2009-05-15 23:15:03 +000077}
78
Daniel Dunbard3f2c102008-10-19 02:04:16 +000079/// hasFunctionProto - Return true if the given decl has a argument
80/// information. This decl should have already passed
Fariborz Jahanian620d89c2009-05-15 23:15:03 +000081/// isFunctionOrMethod or isFunctionOrMethodOrBlock.
Ted Kremeneka18d7d82009-08-14 20:49:40 +000082static bool hasFunctionProto(const Decl *d) {
Fariborz Jahanian620d89c2009-05-15 23:15:03 +000083 if (const FunctionType *FnTy = getFunctionType(d))
Douglas Gregor72564e72009-02-26 23:50:07 +000084 return isa<FunctionProtoType>(FnTy);
Fariborz Jahanian620d89c2009-05-15 23:15:03 +000085 else {
Fariborz Jahaniand66f22d2009-05-19 17:08:59 +000086 assert(isa<ObjCMethodDecl>(d) || isa<BlockDecl>(d));
Daniel Dunbard3f2c102008-10-19 02:04:16 +000087 return true;
88 }
89}
90
91/// getFunctionOrMethodNumArgs - Return number of function or method
92/// arguments. It is an error to call this on a K&R function (use
93/// hasFunctionProto first).
Ted Kremeneka18d7d82009-08-14 20:49:40 +000094static unsigned getFunctionOrMethodNumArgs(const Decl *d) {
Chris Lattner89951a82009-02-20 18:43:26 +000095 if (const FunctionType *FnTy = getFunctionType(d))
Douglas Gregor72564e72009-02-26 23:50:07 +000096 return cast<FunctionProtoType>(FnTy)->getNumArgs();
Fariborz Jahaniand66f22d2009-05-19 17:08:59 +000097 if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
98 return BD->getNumParams();
Chris Lattner89951a82009-02-20 18:43:26 +000099 return cast<ObjCMethodDecl>(d)->param_size();
Daniel Dunbar35682492008-09-26 04:12:28 +0000100}
101
Ted Kremeneka18d7d82009-08-14 20:49:40 +0000102static QualType getFunctionOrMethodArgType(const Decl *d, unsigned Idx) {
Chris Lattner89951a82009-02-20 18:43:26 +0000103 if (const FunctionType *FnTy = getFunctionType(d))
Douglas Gregor72564e72009-02-26 23:50:07 +0000104 return cast<FunctionProtoType>(FnTy)->getArgType(Idx);
Fariborz Jahaniand66f22d2009-05-19 17:08:59 +0000105 if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
106 return BD->getParamDecl(Idx)->getType();
Mike Stumpbf916502009-07-24 19:02:52 +0000107
Chris Lattner89951a82009-02-20 18:43:26 +0000108 return cast<ObjCMethodDecl>(d)->param_begin()[Idx]->getType();
Daniel Dunbar35682492008-09-26 04:12:28 +0000109}
110
Ted Kremeneka18d7d82009-08-14 20:49:40 +0000111static QualType getFunctionOrMethodResultType(const Decl *d) {
Fariborz Jahanian5b160922009-05-20 17:41:43 +0000112 if (const FunctionType *FnTy = getFunctionType(d))
113 return cast<FunctionProtoType>(FnTy)->getResultType();
114 return cast<ObjCMethodDecl>(d)->getResultType();
115}
116
Ted Kremeneka18d7d82009-08-14 20:49:40 +0000117static bool isFunctionOrMethodVariadic(const Decl *d) {
Daniel Dunbard3f2c102008-10-19 02:04:16 +0000118 if (const FunctionType *FnTy = getFunctionType(d)) {
Douglas Gregor72564e72009-02-26 23:50:07 +0000119 const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy);
Daniel Dunbar35682492008-09-26 04:12:28 +0000120 return proto->isVariadic();
Fariborz Jahaniand66f22d2009-05-19 17:08:59 +0000121 } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
Ted Kremenekdb9a0ae2010-04-29 16:48:58 +0000122 return BD->isVariadic();
Fariborz Jahaniand66f22d2009-05-19 17:08:59 +0000123 else {
Daniel Dunbar35682492008-09-26 04:12:28 +0000124 return cast<ObjCMethodDecl>(d)->isVariadic();
125 }
126}
127
Chris Lattner6b6b5372008-06-26 18:38:35 +0000128static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
John McCall183700f2009-09-21 23:43:11 +0000129 const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
Chris Lattnerb77792e2008-07-26 22:17:49 +0000130 if (!PT)
Chris Lattner6b6b5372008-06-26 18:38:35 +0000131 return false;
Mike Stumpbf916502009-07-24 19:02:52 +0000132
John McCall506b57e2010-05-17 21:00:27 +0000133 ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface();
134 if (!Cls)
Chris Lattner6b6b5372008-06-26 18:38:35 +0000135 return false;
Mike Stumpbf916502009-07-24 19:02:52 +0000136
John McCall506b57e2010-05-17 21:00:27 +0000137 IdentifierInfo* ClsName = Cls->getIdentifier();
Mike Stumpbf916502009-07-24 19:02:52 +0000138
Chris Lattner6b6b5372008-06-26 18:38:35 +0000139 // FIXME: Should we walk the chain of classes?
140 return ClsName == &Ctx.Idents.get("NSString") ||
141 ClsName == &Ctx.Idents.get("NSMutableString");
142}
143
Daniel Dunbar085e8f72008-09-26 03:32:58 +0000144static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
Ted Kremenek6217b802009-07-29 21:53:49 +0000145 const PointerType *PT = T->getAs<PointerType>();
Daniel Dunbar085e8f72008-09-26 03:32:58 +0000146 if (!PT)
147 return false;
148
Ted Kremenek6217b802009-07-29 21:53:49 +0000149 const RecordType *RT = PT->getPointeeType()->getAs<RecordType>();
Daniel Dunbar085e8f72008-09-26 03:32:58 +0000150 if (!RT)
151 return false;
Mike Stumpbf916502009-07-24 19:02:52 +0000152
Daniel Dunbar085e8f72008-09-26 03:32:58 +0000153 const RecordDecl *RD = RT->getDecl();
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000154 if (RD->getTagKind() != TTK_Struct)
Daniel Dunbar085e8f72008-09-26 03:32:58 +0000155 return false;
156
157 return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
158}
159
Chris Lattnere5c5ee12008-06-29 00:16:31 +0000160//===----------------------------------------------------------------------===//
Chris Lattnere5c5ee12008-06-29 00:16:31 +0000161// Attribute Implementations
162//===----------------------------------------------------------------------===//
163
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000164// FIXME: All this manual attribute parsing code is gross. At the
165// least add some helper functions to check most argument patterns (#
166// and types of args).
167
Mike Stumpbf916502009-07-24 19:02:52 +0000168static void HandleExtVectorTypeAttr(Scope *scope, Decl *d,
Douglas Gregor9cdda0c2009-06-17 21:51:59 +0000169 const AttributeList &Attr, Sema &S) {
Chris Lattner545dd342008-06-28 23:36:30 +0000170 TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
171 if (tDecl == 0) {
Chris Lattner803d0802008-06-29 00:43:07 +0000172 S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
Chris Lattner545dd342008-06-28 23:36:30 +0000173 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000174 }
Mike Stumpbf916502009-07-24 19:02:52 +0000175
Chris Lattner6b6b5372008-06-26 18:38:35 +0000176 QualType curType = tDecl->getUnderlyingType();
Douglas Gregor9cdda0c2009-06-17 21:51:59 +0000177
178 Expr *sizeExpr;
179
180 // Special case where the argument is a template id.
181 if (Attr.getParameterName()) {
John McCallf7a1a742009-11-24 19:00:30 +0000182 CXXScopeSpec SS;
183 UnqualifiedId id;
184 id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
185 sizeExpr = S.ActOnIdExpression(scope, SS, id, false, false).takeAs<Expr>();
Douglas Gregor9cdda0c2009-06-17 21:51:59 +0000186 } else {
187 // check the attribute arguments.
188 if (Attr.getNumArgs() != 1) {
189 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
190 return;
191 }
192 sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000193 }
Douglas Gregor9cdda0c2009-06-17 21:51:59 +0000194
195 // Instantiate/Install the vector type, and let Sema build the type for us.
196 // This will run the reguired checks.
John McCall9ae2f072010-08-23 23:25:46 +0000197 QualType T = S.BuildExtVectorType(curType, sizeExpr, Attr.getLoc());
Douglas Gregor9cdda0c2009-06-17 21:51:59 +0000198 if (!T.isNull()) {
John McCallba6a9bd2009-10-24 08:00:42 +0000199 // FIXME: preserve the old source info.
John McCalla93c9342009-12-07 02:54:59 +0000200 tDecl->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(T));
Mike Stumpbf916502009-07-24 19:02:52 +0000201
Douglas Gregor9cdda0c2009-06-17 21:51:59 +0000202 // Remember this typedef decl, we will need it later for diagnostics.
203 S.ExtVectorDecls.push_back(tDecl);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000204 }
Chris Lattner6b6b5372008-06-26 18:38:35 +0000205}
206
Chris Lattner803d0802008-06-29 00:43:07 +0000207static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000208 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000209 if (Attr.getNumArgs() > 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +0000210 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000211 return;
212 }
Mike Stumpbf916502009-07-24 19:02:52 +0000213
Chris Lattner6b6b5372008-06-26 18:38:35 +0000214 if (TagDecl *TD = dyn_cast<TagDecl>(d))
Sean Huntcf807c42010-08-18 23:23:40 +0000215 TD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000216 else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
217 // If the alignment is less than or equal to 8 bits, the packed attribute
218 // has no effect.
219 if (!FD->getType()->isIncompleteType() &&
Chris Lattner803d0802008-06-29 00:43:07 +0000220 S.Context.getTypeAlign(FD->getType()) <= 8)
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000221 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
Chris Lattner08631c52008-11-23 21:45:46 +0000222 << Attr.getName() << FD->getType();
Chris Lattner6b6b5372008-06-26 18:38:35 +0000223 else
Sean Huntcf807c42010-08-18 23:23:40 +0000224 FD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000225 } else
Chris Lattner3c73c412008-11-19 08:23:25 +0000226 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
Chris Lattner6b6b5372008-06-26 18:38:35 +0000227}
228
Ted Kremenek63e5d7c2010-02-18 03:08:58 +0000229static void HandleIBAction(Decl *d, const AttributeList &Attr, Sema &S) {
Ted Kremenek96329d42008-07-15 22:26:48 +0000230 // check the attribute arguments.
231 if (Attr.getNumArgs() > 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +0000232 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Ted Kremenek96329d42008-07-15 22:26:48 +0000233 return;
234 }
Mike Stumpbf916502009-07-24 19:02:52 +0000235
Ted Kremenek63e5d7c2010-02-18 03:08:58 +0000236 // The IBAction attributes only apply to instance methods.
237 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
238 if (MD->isInstanceMethod()) {
Sean Huntcf807c42010-08-18 23:23:40 +0000239 d->addAttr(::new (S.Context) IBActionAttr(Attr.getLoc(), S.Context));
Ted Kremenek63e5d7c2010-02-18 03:08:58 +0000240 return;
241 }
242
243 S.Diag(Attr.getLoc(), diag::err_attribute_ibaction) << Attr.getName();
244}
245
246static void HandleIBOutlet(Decl *d, const AttributeList &Attr, Sema &S) {
247 // check the attribute arguments.
248 if (Attr.getNumArgs() > 0) {
249 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
250 return;
251 }
252
253 // The IBOutlet attributes only apply to instance variables of
Ted Kremenekefbddd22010-02-17 02:37:45 +0000254 // Objective-C classes.
255 if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d)) {
Sean Huntcf807c42010-08-18 23:23:40 +0000256 d->addAttr(::new (S.Context) IBOutletAttr(Attr.getLoc(), S.Context));
Ted Kremenek63e5d7c2010-02-18 03:08:58 +0000257 return;
Ted Kremenekefbddd22010-02-17 02:37:45 +0000258 }
Ted Kremenek63e5d7c2010-02-18 03:08:58 +0000259
260 S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet) << Attr.getName();
Ted Kremenek96329d42008-07-15 22:26:48 +0000261}
262
Ted Kremenek857e9182010-05-19 17:38:06 +0000263static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr,
264 Sema &S) {
265
266 // The iboutletcollection attribute can have zero or one arguments.
Fariborz Jahaniana8fb24f2010-08-17 20:23:12 +0000267 if (Attr.getParameterName() && Attr.getNumArgs() > 0) {
Ted Kremenek857e9182010-05-19 17:38:06 +0000268 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
269 return;
270 }
271
272 // The IBOutletCollection attributes only apply to instance variables of
273 // Objective-C classes.
274 if (!(isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d))) {
275 S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet) << Attr.getName();
276 return;
277 }
Fariborz Jahanian3a3400b2010-08-17 21:39:27 +0000278 if (const ValueDecl *VD = dyn_cast<ValueDecl>(d))
279 if (!VD->getType()->getAs<ObjCObjectPointerType>()) {
280 S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type)
281 << VD->getType() << 0;
282 return;
283 }
284 if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(d))
285 if (!PD->getType()->getAs<ObjCObjectPointerType>()) {
286 S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type)
287 << PD->getType() << 1;
288 return;
289 }
290
Fariborz Jahaniana8fb24f2010-08-17 20:23:12 +0000291 IdentifierInfo *II = Attr.getParameterName();
292 if (!II)
293 II = &S.Context.Idents.get("id");
Fariborz Jahanian3a3400b2010-08-17 21:39:27 +0000294
John McCallb3d87482010-08-24 05:47:05 +0000295 ParsedType TypeRep = S.getTypeName(*II, Attr.getLoc(),
Fariborz Jahaniana8fb24f2010-08-17 20:23:12 +0000296 S.getScopeForContext(d->getDeclContext()->getParent()));
297 if (!TypeRep) {
298 S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
299 return;
300 }
John McCallb3d87482010-08-24 05:47:05 +0000301 QualType QT = TypeRep.get();
Fariborz Jahaniana8fb24f2010-08-17 20:23:12 +0000302 // Diagnose use of non-object type in iboutletcollection attribute.
303 // FIXME. Gnu attribute extension ignores use of builtin types in
304 // attributes. So, __attribute__((iboutletcollection(char))) will be
305 // treated as __attribute__((iboutletcollection())).
306 if (!QT->isObjCIdType() && !QT->isObjCClassType() &&
307 !QT->isObjCObjectType()) {
308 S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
309 return;
310 }
Sean Huntcf807c42010-08-18 23:23:40 +0000311 d->addAttr(::new (S.Context) IBOutletCollectionAttr(Attr.getLoc(), S.Context,
312 QT));
Ted Kremenek857e9182010-05-19 17:38:06 +0000313}
314
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000315static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Mike Stumpbf916502009-07-24 19:02:52 +0000316 // GCC ignores the nonnull attribute on K&R style function prototypes, so we
317 // ignore it as well
Daniel Dunbard3f2c102008-10-19 02:04:16 +0000318 if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000319 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Ted Kremenek5dc53c92009-05-13 21:07:32 +0000320 << Attr.getName() << 0 /*function*/;
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000321 return;
322 }
Mike Stumpbf916502009-07-24 19:02:52 +0000323
Daniel Dunbard3f2c102008-10-19 02:04:16 +0000324 unsigned NumArgs = getFunctionOrMethodNumArgs(d);
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000325
326 // The nonnull attribute only applies to pointers.
327 llvm::SmallVector<unsigned, 10> NonNullArgs;
Mike Stumpbf916502009-07-24 19:02:52 +0000328
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000329 for (AttributeList::arg_iterator I=Attr.arg_begin(),
330 E=Attr.arg_end(); I!=E; ++I) {
Mike Stumpbf916502009-07-24 19:02:52 +0000331
332
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000333 // The argument must be an integer constant expression.
Ted Kremenekf5e88342008-12-04 19:38:33 +0000334 Expr *Ex = static_cast<Expr *>(*I);
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000335 llvm::APSInt ArgNum(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +0000336 if (Ex->isTypeDependent() || Ex->isValueDependent() ||
337 !Ex->isIntegerConstantExpr(ArgNum, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000338 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
339 << "nonnull" << Ex->getSourceRange();
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000340 return;
341 }
Mike Stumpbf916502009-07-24 19:02:52 +0000342
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000343 unsigned x = (unsigned) ArgNum.getZExtValue();
Mike Stumpbf916502009-07-24 19:02:52 +0000344
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000345 if (x < 1 || x > NumArgs) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000346 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
Chris Lattner30bc9652008-11-19 07:22:31 +0000347 << "nonnull" << I.getArgNum() << Ex->getSourceRange();
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000348 return;
349 }
Mike Stumpbf916502009-07-24 19:02:52 +0000350
Ted Kremenek465172f2008-07-21 22:09:15 +0000351 --x;
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000352
353 // Is the function argument a pointer type?
Mike Stumpbf916502009-07-24 19:02:52 +0000354 QualType T = getFunctionOrMethodArgType(d, x);
Ted Kremenekdbfe99e2009-07-15 23:23:54 +0000355 if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000356 // FIXME: Should also highlight argument in decl.
Douglas Gregorc9ef4052010-08-12 18:48:43 +0000357 S.Diag(Attr.getLoc(), diag::warn_nonnull_pointers_only)
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000358 << "nonnull" << Ex->getSourceRange();
Ted Kremenek7fb43c12008-09-01 19:57:52 +0000359 continue;
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000360 }
Mike Stumpbf916502009-07-24 19:02:52 +0000361
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000362 NonNullArgs.push_back(x);
363 }
Mike Stumpbf916502009-07-24 19:02:52 +0000364
365 // If no arguments were specified to __attribute__((nonnull)) then all pointer
366 // arguments have a nonnull attribute.
Ted Kremenek7fb43c12008-09-01 19:57:52 +0000367 if (NonNullArgs.empty()) {
Ted Kremenek46bbaca2008-11-18 06:52:58 +0000368 for (unsigned I = 0, E = getFunctionOrMethodNumArgs(d); I != E; ++I) {
369 QualType T = getFunctionOrMethodArgType(d, I);
Ted Kremenekdbfe99e2009-07-15 23:23:54 +0000370 if (T->isAnyPointerType() || T->isBlockPointerType())
Daniel Dunbard3f2c102008-10-19 02:04:16 +0000371 NonNullArgs.push_back(I);
Ted Kremenek46bbaca2008-11-18 06:52:58 +0000372 }
Mike Stumpbf916502009-07-24 19:02:52 +0000373
Ted Kremenek7fb43c12008-09-01 19:57:52 +0000374 if (NonNullArgs.empty()) {
375 S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers);
376 return;
377 }
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000378 }
Ted Kremenek7fb43c12008-09-01 19:57:52 +0000379
380 unsigned* start = &NonNullArgs[0];
381 unsigned size = NonNullArgs.size();
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000382 llvm::array_pod_sort(start, start + size);
Sean Huntcf807c42010-08-18 23:23:40 +0000383 d->addAttr(::new (S.Context) NonNullAttr(Attr.getLoc(), S.Context, start,
384 size));
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000385}
386
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000387static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
388 // This attribute must be applied to a function declaration.
389 // The first argument to the attribute must be a string,
390 // the name of the resource, for example "malloc".
391 // The following arguments must be argument indexes, the arguments must be
392 // of integer type for Returns, otherwise of pointer type.
393 // The difference between Holds and Takes is that a pointer may still be used
Jordy Rose2a479922010-08-12 08:54:03 +0000394 // after being held. free() should be __attribute((ownership_takes)), whereas
395 // a list append function may well be __attribute((ownership_holds)).
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000396
397 if (!AL.getParameterName()) {
398 S.Diag(AL.getLoc(), diag::err_attribute_argument_n_not_string)
399 << AL.getName()->getName() << 1;
400 return;
401 }
402 // Figure out our Kind, and check arguments while we're at it.
Sean Huntcf807c42010-08-18 23:23:40 +0000403 OwnershipAttr::OwnershipKind K;
Jordy Rose2a479922010-08-12 08:54:03 +0000404 switch (AL.getKind()) {
405 case AttributeList::AT_ownership_takes:
Sean Huntcf807c42010-08-18 23:23:40 +0000406 K = OwnershipAttr::Takes;
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000407 if (AL.getNumArgs() < 1) {
408 S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
409 return;
410 }
Jordy Rose2a479922010-08-12 08:54:03 +0000411 break;
412 case AttributeList::AT_ownership_holds:
Sean Huntcf807c42010-08-18 23:23:40 +0000413 K = OwnershipAttr::Holds;
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000414 if (AL.getNumArgs() < 1) {
415 S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
416 return;
417 }
Jordy Rose2a479922010-08-12 08:54:03 +0000418 break;
419 case AttributeList::AT_ownership_returns:
Sean Huntcf807c42010-08-18 23:23:40 +0000420 K = OwnershipAttr::Returns;
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000421 if (AL.getNumArgs() > 1) {
422 S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
423 << AL.getNumArgs() + 1;
424 return;
425 }
Jordy Rose2a479922010-08-12 08:54:03 +0000426 break;
427 default:
428 // This should never happen given how we are called.
429 llvm_unreachable("Unknown ownership attribute");
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000430 }
431
432 if (!isFunction(d) || !hasFunctionProto(d)) {
433 S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL.getName()
434 << 0 /*function*/;
435 return;
436 }
437
438 unsigned NumArgs = getFunctionOrMethodNumArgs(d);
439
440 llvm::StringRef Module = AL.getParameterName()->getName();
441
442 // Normalize the argument, __foo__ becomes foo.
443 if (Module.startswith("__") && Module.endswith("__"))
444 Module = Module.substr(2, Module.size() - 4);
445
446 llvm::SmallVector<unsigned, 10> OwnershipArgs;
447
Jordy Rose2a479922010-08-12 08:54:03 +0000448 for (AttributeList::arg_iterator I = AL.arg_begin(), E = AL.arg_end(); I != E;
449 ++I) {
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000450
451 Expr *IdxExpr = static_cast<Expr *>(*I);
452 llvm::APSInt ArgNum(32);
453 if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent()
454 || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) {
455 S.Diag(AL.getLoc(), diag::err_attribute_argument_not_int)
456 << AL.getName()->getName() << IdxExpr->getSourceRange();
457 continue;
458 }
459
460 unsigned x = (unsigned) ArgNum.getZExtValue();
461
462 if (x > NumArgs || x < 1) {
463 S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
464 << AL.getName()->getName() << x << IdxExpr->getSourceRange();
465 continue;
466 }
467 --x;
468 switch (K) {
Sean Huntcf807c42010-08-18 23:23:40 +0000469 case OwnershipAttr::Takes:
470 case OwnershipAttr::Holds: {
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000471 // Is the function argument a pointer type?
472 QualType T = getFunctionOrMethodArgType(d, x);
473 if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
474 // FIXME: Should also highlight argument in decl.
475 S.Diag(AL.getLoc(), diag::err_ownership_type)
Sean Huntcf807c42010-08-18 23:23:40 +0000476 << ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds")
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000477 << "pointer"
478 << IdxExpr->getSourceRange();
479 continue;
480 }
481 break;
482 }
Sean Huntcf807c42010-08-18 23:23:40 +0000483 case OwnershipAttr::Returns: {
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000484 if (AL.getNumArgs() > 1) {
485 // Is the function argument an integer type?
486 Expr *IdxExpr = static_cast<Expr *>(AL.getArg(0));
487 llvm::APSInt ArgNum(32);
488 if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent()
489 || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) {
490 S.Diag(AL.getLoc(), diag::err_ownership_type)
491 << "ownership_returns" << "integer"
492 << IdxExpr->getSourceRange();
493 return;
494 }
495 }
496 break;
497 }
Jordy Rose2a479922010-08-12 08:54:03 +0000498 default:
499 llvm_unreachable("Unknown ownership attribute");
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000500 } // switch
501
502 // Check we don't have a conflict with another ownership attribute.
Sean Huntcf807c42010-08-18 23:23:40 +0000503 for (specific_attr_iterator<OwnershipAttr>
504 i = d->specific_attr_begin<OwnershipAttr>(),
505 e = d->specific_attr_end<OwnershipAttr>();
506 i != e; ++i) {
507 if ((*i)->getOwnKind() != K) {
508 for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end();
509 I!=E; ++I) {
510 if (x == *I) {
511 S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
512 << AL.getName()->getName() << "ownership_*";
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000513 }
514 }
515 }
516 }
517 OwnershipArgs.push_back(x);
518 }
519
520 unsigned* start = OwnershipArgs.data();
521 unsigned size = OwnershipArgs.size();
522 llvm::array_pod_sort(start, start + size);
Sean Huntcf807c42010-08-18 23:23:40 +0000523
524 if (K != OwnershipAttr::Returns && OwnershipArgs.empty()) {
525 S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
526 return;
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000527 }
Sean Huntcf807c42010-08-18 23:23:40 +0000528
529 d->addAttr(::new (S.Context) OwnershipAttr(AL.getLoc(), S.Context, K, Module,
530 start, size));
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000531}
532
Rafael Espindola11e8ce72010-02-23 22:00:30 +0000533static bool isStaticVarOrStaticFunciton(Decl *D) {
534 if (VarDecl *VD = dyn_cast<VarDecl>(D))
535 return VD->getStorageClass() == VarDecl::Static;
536 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
537 return FD->getStorageClass() == FunctionDecl::Static;
538 return false;
539}
540
541static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) {
542 // Check the attribute arguments.
543 if (Attr.getNumArgs() > 1) {
544 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
545 return;
546 }
547
548 // gcc rejects
549 // class c {
550 // static int a __attribute__((weakref ("v2")));
551 // static int b() __attribute__((weakref ("f3")));
552 // };
553 // and ignores the attributes of
554 // void f(void) {
555 // static int a __attribute__((weakref ("v2")));
556 // }
557 // we reject them
558 if (const DeclContext *Ctx = d->getDeclContext()) {
559 Ctx = Ctx->getLookupContext();
560 if (!isa<TranslationUnitDecl>(Ctx) && !isa<NamespaceDecl>(Ctx) ) {
561 S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) <<
Ted Kremenekdd0e4902010-07-31 01:52:11 +0000562 dyn_cast<NamedDecl>(d)->getNameAsString();
Rafael Espindola11e8ce72010-02-23 22:00:30 +0000563 return;
564 }
565 }
566
567 // The GCC manual says
568 //
569 // At present, a declaration to which `weakref' is attached can only
570 // be `static'.
571 //
572 // It also says
573 //
574 // Without a TARGET,
575 // given as an argument to `weakref' or to `alias', `weakref' is
576 // equivalent to `weak'.
577 //
578 // gcc 4.4.1 will accept
579 // int a7 __attribute__((weakref));
580 // as
581 // int a7 __attribute__((weak));
582 // This looks like a bug in gcc. We reject that for now. We should revisit
583 // it if this behaviour is actually used.
584
585 if (!isStaticVarOrStaticFunciton(d)) {
586 S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_static) <<
587 dyn_cast<NamedDecl>(d)->getNameAsString();
588 return;
589 }
590
591 // GCC rejects
592 // static ((alias ("y"), weakref)).
593 // Should we? How to check that weakref is before or after alias?
594
595 if (Attr.getNumArgs() == 1) {
596 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
597 Arg = Arg->IgnoreParenCasts();
598 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
599
600 if (Str == 0 || Str->isWide()) {
601 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
602 << "weakref" << 1;
603 return;
604 }
605 // GCC will accept anything as the argument of weakref. Should we
606 // check for an existing decl?
Sean Huntcf807c42010-08-18 23:23:40 +0000607 d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, Str->getString()));
Rafael Espindola11e8ce72010-02-23 22:00:30 +0000608 }
609
Sean Huntcf807c42010-08-18 23:23:40 +0000610 d->addAttr(::new (S.Context) WeakRefAttr(Attr.getLoc(), S.Context));
Rafael Espindola11e8ce72010-02-23 22:00:30 +0000611}
612
Chris Lattner803d0802008-06-29 00:43:07 +0000613static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000614 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000615 if (Attr.getNumArgs() != 1) {
Chris Lattner3c73c412008-11-19 08:23:25 +0000616 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000617 return;
618 }
Mike Stumpbf916502009-07-24 19:02:52 +0000619
Chris Lattner545dd342008-06-28 23:36:30 +0000620 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000621 Arg = Arg->IgnoreParenCasts();
622 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
Mike Stumpbf916502009-07-24 19:02:52 +0000623
Chris Lattner6b6b5372008-06-26 18:38:35 +0000624 if (Str == 0 || Str->isWide()) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000625 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
Chris Lattner3c73c412008-11-19 08:23:25 +0000626 << "alias" << 1;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000627 return;
628 }
Mike Stumpbf916502009-07-24 19:02:52 +0000629
Chris Lattner6b6b5372008-06-26 18:38:35 +0000630 // FIXME: check if target symbol exists in current file
Mike Stumpbf916502009-07-24 19:02:52 +0000631
Sean Huntcf807c42010-08-18 23:23:40 +0000632 d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, Str->getString()));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000633}
634
Mike Stumpbf916502009-07-24 19:02:52 +0000635static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
Daniel Dunbaraf668b02008-10-28 00:17:57 +0000636 Sema &S) {
637 // check the attribute arguments.
638 if (Attr.getNumArgs() != 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +0000639 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Daniel Dunbaraf668b02008-10-28 00:17:57 +0000640 return;
641 }
Anders Carlsson5bab7882009-02-19 19:16:48 +0000642
Chris Lattnerc5197432009-04-14 17:02:11 +0000643 if (!isa<FunctionDecl>(d)) {
Anders Carlsson5bab7882009-02-19 19:16:48 +0000644 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Ted Kremenek5dc53c92009-05-13 21:07:32 +0000645 << Attr.getName() << 0 /*function*/;
Anders Carlsson5bab7882009-02-19 19:16:48 +0000646 return;
647 }
Mike Stumpbf916502009-07-24 19:02:52 +0000648
Sean Huntcf807c42010-08-18 23:23:40 +0000649 d->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getLoc(), S.Context));
Daniel Dunbaraf668b02008-10-28 00:17:57 +0000650}
651
Ryan Flynn76168e22009-08-09 20:07:29 +0000652static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
653 // check the attribute arguments.
654 if (Attr.getNumArgs() != 0) {
655 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
656 return;
657 }
Mike Stump1eb44332009-09-09 15:08:12 +0000658
Ted Kremenek2cff7d12009-08-15 00:51:46 +0000659 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000660 QualType RetTy = FD->getResultType();
Ted Kremenek2cff7d12009-08-15 00:51:46 +0000661 if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
Sean Huntcf807c42010-08-18 23:23:40 +0000662 d->addAttr(::new (S.Context) MallocAttr(Attr.getLoc(), S.Context));
Ted Kremenek2cff7d12009-08-15 00:51:46 +0000663 return;
664 }
Ryan Flynn76168e22009-08-09 20:07:29 +0000665 }
666
Ted Kremenek2cff7d12009-08-15 00:51:46 +0000667 S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only);
Ryan Flynn76168e22009-08-09 20:07:29 +0000668}
669
Ted Kremenekb7252322009-04-10 00:01:14 +0000670static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Abramo Bagnarae215f722010-04-30 13:10:51 +0000671 /* Diagnostics (if any) was emitted by Sema::ProcessFnAttr(). */
672 assert(Attr.isInvalid() == false);
Sean Huntcf807c42010-08-18 23:23:40 +0000673 d->addAttr(::new (S.Context) NoReturnAttr(Attr.getLoc(), S.Context));
Ted Kremenekb7252322009-04-10 00:01:14 +0000674}
675
676static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
677 Sema &S) {
Ted Kremenekb56c1cc2010-08-19 00:51:58 +0000678
679 // The checking path for 'noreturn' and 'analyzer_noreturn' are different
680 // because 'analyzer_noreturn' does not impact the type.
681
682 if (Attr.getNumArgs() != 0) {
683 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
684 return;
685 }
686
687 if (!isFunctionOrMethod(d) && !isa<BlockDecl>(d)) {
688 ValueDecl *VD = dyn_cast<ValueDecl>(d);
689 if (VD == 0 || (!VD->getType()->isBlockPointerType()
690 && !VD->getType()->isFunctionPointerType())) {
691 S.Diag(Attr.getLoc(),
692 Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
693 : diag::warn_attribute_wrong_decl_type)
694 << Attr.getName() << 0 /*function*/;
695 return;
696 }
697 }
698
699 d->addAttr(::new (S.Context) AnalyzerNoReturnAttr(Attr.getLoc(), S.Context));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000700}
701
John Thompson35cc9622010-08-09 21:53:52 +0000702// PS3 PPU-specific.
703static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr,
704 Sema &S) {
705/*
706 Returning a Vector Class in Registers
707
708 According to the PPU ABI specifications, a class with a single member of vector type is returned in
709 memory when used as the return value of a function. This results in inefficient code when implementing
710 vector classes. To return the value in a single vector register, add the vecreturn attribute to the class
711 definition. This attribute is also applicable to struct types.
712
713 Example:
714
715 struct Vector
716 {
717 __vector float xyzw;
718 } __attribute__((vecreturn));
719
720 Vector Add(Vector lhs, Vector rhs)
721 {
722 Vector result;
723 result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
724 return result; // This will be returned in a register
725 }
726*/
727 if (!isa<CXXRecordDecl>(d)) {
728 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
729 << Attr.getName() << 9 /*class*/;
730 return;
731 }
732
733 if (d->getAttr<VecReturnAttr>()) {
734 S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn";
735 return;
736 }
737
Sean Huntcf807c42010-08-18 23:23:40 +0000738 d->addAttr(::new (S.Context) VecReturnAttr(Attr.getLoc(), S.Context));
John Thompson35cc9622010-08-09 21:53:52 +0000739}
740
Sean Huntbbd37c62009-11-21 08:43:09 +0000741static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
742 if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) {
743 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
John McCall04a67a62010-02-05 21:31:56 +0000744 << Attr.getName() << 8 /*function, method, or parameter*/;
Sean Huntbbd37c62009-11-21 08:43:09 +0000745 return;
746 }
747 // FIXME: Actually store the attribute on the declaration
748}
749
Ted Kremenek73798892008-07-25 04:39:19 +0000750static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
751 // check the attribute arguments.
752 if (Attr.getNumArgs() != 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +0000753 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Ted Kremenek73798892008-07-25 04:39:19 +0000754 return;
755 }
Mike Stumpbf916502009-07-24 19:02:52 +0000756
John McCallaec58602010-03-31 02:47:45 +0000757 if (!isa<VarDecl>(d) && !isa<ObjCIvarDecl>(d) && !isFunctionOrMethod(d) &&
758 !isa<TypeDecl>(d)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000759 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Ted Kremenek5dc53c92009-05-13 21:07:32 +0000760 << Attr.getName() << 2 /*variable and function*/;
Ted Kremenek73798892008-07-25 04:39:19 +0000761 return;
762 }
Mike Stumpbf916502009-07-24 19:02:52 +0000763
Sean Huntcf807c42010-08-18 23:23:40 +0000764 d->addAttr(::new (S.Context) UnusedAttr(Attr.getLoc(), S.Context));
Ted Kremenek73798892008-07-25 04:39:19 +0000765}
766
Daniel Dunbarb805dad2009-02-13 19:23:53 +0000767static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
768 // check the attribute arguments.
769 if (Attr.getNumArgs() != 0) {
770 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
771 return;
772 }
Mike Stumpbf916502009-07-24 19:02:52 +0000773
Daniel Dunbarb805dad2009-02-13 19:23:53 +0000774 if (const VarDecl *VD = dyn_cast<VarDecl>(d)) {
Daniel Dunbar186204b2009-02-13 22:48:56 +0000775 if (VD->hasLocalStorage() || VD->hasExternalStorage()) {
Daniel Dunbarb805dad2009-02-13 19:23:53 +0000776 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used";
777 return;
778 }
779 } else if (!isFunctionOrMethod(d)) {
780 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Ted Kremenek5dc53c92009-05-13 21:07:32 +0000781 << Attr.getName() << 2 /*variable and function*/;
Daniel Dunbarb805dad2009-02-13 19:23:53 +0000782 return;
783 }
Mike Stumpbf916502009-07-24 19:02:52 +0000784
Sean Huntcf807c42010-08-18 23:23:40 +0000785 d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
Daniel Dunbarb805dad2009-02-13 19:23:53 +0000786}
787
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000788static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
789 // check the attribute arguments.
790 if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000791 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
792 << "0 or 1";
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000793 return;
Mike Stumpbf916502009-07-24 19:02:52 +0000794 }
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000795
796 int priority = 65535; // FIXME: Do not hardcode such constants.
797 if (Attr.getNumArgs() > 0) {
798 Expr *E = static_cast<Expr *>(Attr.getArg(0));
799 llvm::APSInt Idx(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +0000800 if (E->isTypeDependent() || E->isValueDependent() ||
801 !E->isIntegerConstantExpr(Idx, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000802 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
Chris Lattner3c73c412008-11-19 08:23:25 +0000803 << "constructor" << 1 << E->getSourceRange();
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000804 return;
805 }
806 priority = Idx.getZExtValue();
807 }
Mike Stumpbf916502009-07-24 19:02:52 +0000808
Chris Lattnerc5197432009-04-14 17:02:11 +0000809 if (!isa<FunctionDecl>(d)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000810 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Ted Kremenek5dc53c92009-05-13 21:07:32 +0000811 << Attr.getName() << 0 /*function*/;
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000812 return;
813 }
814
Sean Huntcf807c42010-08-18 23:23:40 +0000815 d->addAttr(::new (S.Context) ConstructorAttr(Attr.getLoc(), S.Context, priority));
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000816}
817
818static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
819 // check the attribute arguments.
820 if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000821 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
822 << "0 or 1";
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000823 return;
Mike Stumpbf916502009-07-24 19:02:52 +0000824 }
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000825
826 int priority = 65535; // FIXME: Do not hardcode such constants.
827 if (Attr.getNumArgs() > 0) {
828 Expr *E = static_cast<Expr *>(Attr.getArg(0));
829 llvm::APSInt Idx(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +0000830 if (E->isTypeDependent() || E->isValueDependent() ||
831 !E->isIntegerConstantExpr(Idx, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000832 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
Chris Lattner3c73c412008-11-19 08:23:25 +0000833 << "destructor" << 1 << E->getSourceRange();
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000834 return;
835 }
836 priority = Idx.getZExtValue();
837 }
Mike Stumpbf916502009-07-24 19:02:52 +0000838
Anders Carlsson6782fc62008-08-22 22:10:48 +0000839 if (!isa<FunctionDecl>(d)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000840 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Ted Kremenek5dc53c92009-05-13 21:07:32 +0000841 << Attr.getName() << 0 /*function*/;
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000842 return;
843 }
844
Sean Huntcf807c42010-08-18 23:23:40 +0000845 d->addAttr(::new (S.Context) DestructorAttr(Attr.getLoc(), S.Context, priority));
Daniel Dunbar3068ae02008-07-31 22:40:48 +0000846}
847
Chris Lattner803d0802008-06-29 00:43:07 +0000848static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000849 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000850 if (Attr.getNumArgs() != 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +0000851 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000852 return;
853 }
Mike Stumpbf916502009-07-24 19:02:52 +0000854
Sean Huntcf807c42010-08-18 23:23:40 +0000855 d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000856}
857
Fariborz Jahanianbc1c8772008-12-17 01:07:27 +0000858static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
859 // check the attribute arguments.
860 if (Attr.getNumArgs() != 0) {
861 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
862 return;
863 }
Mike Stumpbf916502009-07-24 19:02:52 +0000864
Sean Huntcf807c42010-08-18 23:23:40 +0000865 d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context));
Fariborz Jahanianbc1c8772008-12-17 01:07:27 +0000866}
867
Chris Lattner803d0802008-06-29 00:43:07 +0000868static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000869 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000870 if (Attr.getNumArgs() != 1) {
Chris Lattner3c73c412008-11-19 08:23:25 +0000871 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000872 return;
873 }
Mike Stumpbf916502009-07-24 19:02:52 +0000874
Chris Lattner545dd342008-06-28 23:36:30 +0000875 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000876 Arg = Arg->IgnoreParenCasts();
877 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
Mike Stumpbf916502009-07-24 19:02:52 +0000878
Chris Lattner6b6b5372008-06-26 18:38:35 +0000879 if (Str == 0 || Str->isWide()) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000880 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
Chris Lattner3c73c412008-11-19 08:23:25 +0000881 << "visibility" << 1;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000882 return;
883 }
Mike Stumpbf916502009-07-24 19:02:52 +0000884
Benjamin Kramerc96f4942010-01-23 18:16:35 +0000885 llvm::StringRef TypeStr = Str->getString();
Sean Huntcf807c42010-08-18 23:23:40 +0000886 VisibilityAttr::VisibilityType type;
Mike Stumpbf916502009-07-24 19:02:52 +0000887
Benjamin Kramerc96f4942010-01-23 18:16:35 +0000888 if (TypeStr == "default")
Sean Huntcf807c42010-08-18 23:23:40 +0000889 type = VisibilityAttr::Default;
Benjamin Kramerc96f4942010-01-23 18:16:35 +0000890 else if (TypeStr == "hidden")
Sean Huntcf807c42010-08-18 23:23:40 +0000891 type = VisibilityAttr::Hidden;
Benjamin Kramerc96f4942010-01-23 18:16:35 +0000892 else if (TypeStr == "internal")
Sean Huntcf807c42010-08-18 23:23:40 +0000893 type = VisibilityAttr::Hidden; // FIXME
Benjamin Kramerc96f4942010-01-23 18:16:35 +0000894 else if (TypeStr == "protected")
Sean Huntcf807c42010-08-18 23:23:40 +0000895 type = VisibilityAttr::Protected;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000896 else {
Chris Lattner08631c52008-11-23 21:45:46 +0000897 S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000898 return;
899 }
Mike Stumpbf916502009-07-24 19:02:52 +0000900
Sean Huntcf807c42010-08-18 23:23:40 +0000901 d->addAttr(::new (S.Context) VisibilityAttr(Attr.getLoc(), S.Context, type));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000902}
903
Chris Lattner0db29ec2009-02-14 08:09:34 +0000904static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
905 Sema &S) {
906 if (Attr.getNumArgs() != 0) {
907 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
908 return;
909 }
Mike Stumpbf916502009-07-24 19:02:52 +0000910
Chris Lattner0db29ec2009-02-14 08:09:34 +0000911 ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D);
912 if (OCI == 0) {
913 S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface);
914 return;
915 }
Mike Stumpbf916502009-07-24 19:02:52 +0000916
Sean Huntcf807c42010-08-18 23:23:40 +0000917 D->addAttr(::new (S.Context) ObjCExceptionAttr(Attr.getLoc(), S.Context));
Chris Lattner0db29ec2009-02-14 08:09:34 +0000918}
919
920static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
Fariborz Jahanianfa23c1d2009-01-13 23:34:40 +0000921 if (Attr.getNumArgs() != 0) {
John McCall2b7baf02010-05-28 18:25:28 +0000922 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Fariborz Jahanianfa23c1d2009-01-13 23:34:40 +0000923 return;
924 }
Chris Lattner0db29ec2009-02-14 08:09:34 +0000925 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
Fariborz Jahanianfa23c1d2009-01-13 23:34:40 +0000926 QualType T = TD->getUnderlyingType();
927 if (!T->isPointerType() ||
Ted Kremenek6217b802009-07-29 21:53:49 +0000928 !T->getAs<PointerType>()->getPointeeType()->isRecordType()) {
Fariborz Jahanianfa23c1d2009-01-13 23:34:40 +0000929 S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
930 return;
931 }
932 }
Sean Huntcf807c42010-08-18 23:23:40 +0000933 D->addAttr(::new (S.Context) ObjCNSObjectAttr(Attr.getLoc(), S.Context));
Fariborz Jahanianfa23c1d2009-01-13 23:34:40 +0000934}
935
Mike Stumpbf916502009-07-24 19:02:52 +0000936static void
Douglas Gregorf9201e02009-02-11 23:02:49 +0000937HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) {
938 if (Attr.getNumArgs() != 0) {
John McCall2b7baf02010-05-28 18:25:28 +0000939 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Douglas Gregorf9201e02009-02-11 23:02:49 +0000940 return;
941 }
942
943 if (!isa<FunctionDecl>(D)) {
944 S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function);
945 return;
946 }
947
Sean Huntcf807c42010-08-18 23:23:40 +0000948 D->addAttr(::new (S.Context) OverloadableAttr(Attr.getLoc(), S.Context));
Douglas Gregorf9201e02009-02-11 23:02:49 +0000949}
950
Steve Naroff9eae5762008-09-18 16:44:58 +0000951static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Mike Stumpbf916502009-07-24 19:02:52 +0000952 if (!Attr.getParameterName()) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000953 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
Chris Lattner3c73c412008-11-19 08:23:25 +0000954 << "blocks" << 1;
Steve Naroff9eae5762008-09-18 16:44:58 +0000955 return;
956 }
Mike Stumpbf916502009-07-24 19:02:52 +0000957
Steve Naroff9eae5762008-09-18 16:44:58 +0000958 if (Attr.getNumArgs() != 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +0000959 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Steve Naroff9eae5762008-09-18 16:44:58 +0000960 return;
961 }
Mike Stumpbf916502009-07-24 19:02:52 +0000962
Sean Huntcf807c42010-08-18 23:23:40 +0000963 BlocksAttr::BlockType type;
Chris Lattner92e62b02008-11-20 04:42:34 +0000964 if (Attr.getParameterName()->isStr("byref"))
Steve Naroff9eae5762008-09-18 16:44:58 +0000965 type = BlocksAttr::ByRef;
966 else {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000967 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
Chris Lattner3c73c412008-11-19 08:23:25 +0000968 << "blocks" << Attr.getParameterName();
Steve Naroff9eae5762008-09-18 16:44:58 +0000969 return;
970 }
Mike Stumpbf916502009-07-24 19:02:52 +0000971
Sean Huntcf807c42010-08-18 23:23:40 +0000972 d->addAttr(::new (S.Context) BlocksAttr(Attr.getLoc(), S.Context, type));
Steve Naroff9eae5762008-09-18 16:44:58 +0000973}
974
Anders Carlsson77091822008-10-05 18:05:59 +0000975static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
976 // check the attribute arguments.
977 if (Attr.getNumArgs() > 2) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000978 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
979 << "0, 1 or 2";
Anders Carlsson77091822008-10-05 18:05:59 +0000980 return;
Mike Stumpbf916502009-07-24 19:02:52 +0000981 }
982
Anders Carlsson77091822008-10-05 18:05:59 +0000983 int sentinel = 0;
984 if (Attr.getNumArgs() > 0) {
985 Expr *E = static_cast<Expr *>(Attr.getArg(0));
986 llvm::APSInt Idx(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +0000987 if (E->isTypeDependent() || E->isValueDependent() ||
988 !E->isIntegerConstantExpr(Idx, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000989 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
Chris Lattner3c73c412008-11-19 08:23:25 +0000990 << "sentinel" << 1 << E->getSourceRange();
Anders Carlsson77091822008-10-05 18:05:59 +0000991 return;
992 }
993 sentinel = Idx.getZExtValue();
Mike Stumpbf916502009-07-24 19:02:52 +0000994
Anders Carlsson77091822008-10-05 18:05:59 +0000995 if (sentinel < 0) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +0000996 S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero)
997 << E->getSourceRange();
Anders Carlsson77091822008-10-05 18:05:59 +0000998 return;
999 }
1000 }
1001
1002 int nullPos = 0;
1003 if (Attr.getNumArgs() > 1) {
1004 Expr *E = static_cast<Expr *>(Attr.getArg(1));
1005 llvm::APSInt Idx(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +00001006 if (E->isTypeDependent() || E->isValueDependent() ||
1007 !E->isIntegerConstantExpr(Idx, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001008 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
Chris Lattner3c73c412008-11-19 08:23:25 +00001009 << "sentinel" << 2 << E->getSourceRange();
Anders Carlsson77091822008-10-05 18:05:59 +00001010 return;
1011 }
1012 nullPos = Idx.getZExtValue();
Mike Stumpbf916502009-07-24 19:02:52 +00001013
Anders Carlsson77091822008-10-05 18:05:59 +00001014 if (nullPos > 1 || nullPos < 0) {
1015 // FIXME: This error message could be improved, it would be nice
1016 // to say what the bounds actually are.
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001017 S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
1018 << E->getSourceRange();
Anders Carlsson77091822008-10-05 18:05:59 +00001019 return;
1020 }
1021 }
1022
1023 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
John McCall183700f2009-09-21 23:43:11 +00001024 const FunctionType *FT = FD->getType()->getAs<FunctionType>();
Chris Lattner897cd902009-03-17 23:03:47 +00001025 assert(FT && "FunctionDecl has non-function type?");
Mike Stumpbf916502009-07-24 19:02:52 +00001026
Chris Lattner897cd902009-03-17 23:03:47 +00001027 if (isa<FunctionNoProtoType>(FT)) {
1028 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_named_arguments);
1029 return;
1030 }
Mike Stumpbf916502009-07-24 19:02:52 +00001031
Chris Lattner897cd902009-03-17 23:03:47 +00001032 if (!cast<FunctionProtoType>(FT)->isVariadic()) {
Fariborz Jahanian3bba33d2009-05-15 21:18:04 +00001033 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
Anders Carlsson77091822008-10-05 18:05:59 +00001034 return;
Mike Stumpbf916502009-07-24 19:02:52 +00001035 }
Anders Carlsson77091822008-10-05 18:05:59 +00001036 } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) {
1037 if (!MD->isVariadic()) {
Fariborz Jahanian3bba33d2009-05-15 21:18:04 +00001038 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
Anders Carlsson77091822008-10-05 18:05:59 +00001039 return;
Fariborz Jahanian2f7c3922009-05-14 20:53:39 +00001040 }
1041 } else if (isa<BlockDecl>(d)) {
Mike Stumpbf916502009-07-24 19:02:52 +00001042 // Note! BlockDecl is typeless. Variadic diagnostics will be issued by the
1043 // caller.
Fariborz Jahanian2f7c3922009-05-14 20:53:39 +00001044 ;
1045 } else if (const VarDecl *V = dyn_cast<VarDecl>(d)) {
Fariborz Jahanian2f7c3922009-05-14 20:53:39 +00001046 QualType Ty = V->getType();
Fariborz Jahaniandaf04152009-05-15 20:33:25 +00001047 if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
Mike Stumpbf916502009-07-24 19:02:52 +00001048 const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(d)
John McCall183700f2009-09-21 23:43:11 +00001049 : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
Fariborz Jahanian2f7c3922009-05-14 20:53:39 +00001050 if (!cast<FunctionProtoType>(FT)->isVariadic()) {
Fariborz Jahanian3bba33d2009-05-15 21:18:04 +00001051 int m = Ty->isFunctionPointerType() ? 0 : 1;
1052 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
Fariborz Jahanian2f7c3922009-05-14 20:53:39 +00001053 return;
1054 }
Mike Stumpac5fc7c2009-08-04 21:02:39 +00001055 } else {
Fariborz Jahanian2f7c3922009-05-14 20:53:39 +00001056 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Fariborz Jahanianffb00812009-05-14 20:57:28 +00001057 << Attr.getName() << 6 /*function, method or block */;
Fariborz Jahanian2f7c3922009-05-14 20:53:39 +00001058 return;
1059 }
Anders Carlsson77091822008-10-05 18:05:59 +00001060 } else {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001061 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Fariborz Jahanianffb00812009-05-14 20:57:28 +00001062 << Attr.getName() << 6 /*function, method or block */;
Anders Carlsson77091822008-10-05 18:05:59 +00001063 return;
1064 }
Sean Huntcf807c42010-08-18 23:23:40 +00001065 d->addAttr(::new (S.Context) SentinelAttr(Attr.getLoc(), S.Context, sentinel, nullPos));
Anders Carlsson77091822008-10-05 18:05:59 +00001066}
1067
Chris Lattner026dc962009-02-14 07:37:35 +00001068static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) {
1069 // check the attribute arguments.
1070 if (Attr.getNumArgs() != 0) {
1071 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
1072 return;
1073 }
1074
Fariborz Jahanianf0317742010-03-30 18:22:15 +00001075 if (!isFunction(D) && !isa<ObjCMethodDecl>(D)) {
Chris Lattner026dc962009-02-14 07:37:35 +00001076 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Ted Kremenek5dc53c92009-05-13 21:07:32 +00001077 << Attr.getName() << 0 /*function*/;
Chris Lattner026dc962009-02-14 07:37:35 +00001078 return;
1079 }
Mike Stumpbf916502009-07-24 19:02:52 +00001080
Fariborz Jahanianf0317742010-03-30 18:22:15 +00001081 if (isFunction(D) && getFunctionType(D)->getResultType()->isVoidType()) {
1082 S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
1083 << Attr.getName() << 0;
Nuno Lopesf8577982009-12-22 23:59:52 +00001084 return;
1085 }
Fariborz Jahanianf0317742010-03-30 18:22:15 +00001086 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
1087 if (MD->getResultType()->isVoidType()) {
1088 S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method)
1089 << Attr.getName() << 1;
1090 return;
1091 }
1092
Sean Huntcf807c42010-08-18 23:23:40 +00001093 D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getLoc(), S.Context));
Chris Lattner026dc962009-02-14 07:37:35 +00001094}
1095
1096static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00001097 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +00001098 if (Attr.getNumArgs() != 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001099 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001100 return;
1101 }
Daniel Dunbar6e775db2009-03-06 06:39:57 +00001102
Fariborz Jahanianf23ecd92009-07-16 01:12:24 +00001103 /* weak only applies to non-static declarations */
Rafael Espindola11e8ce72010-02-23 22:00:30 +00001104 if (isStaticVarOrStaticFunciton(D)) {
Fariborz Jahanianf23ecd92009-07-16 01:12:24 +00001105 S.Diag(Attr.getLoc(), diag::err_attribute_weak_static) <<
1106 dyn_cast<NamedDecl>(D)->getNameAsString();
1107 return;
1108 }
1109
Daniel Dunbar6e775db2009-03-06 06:39:57 +00001110 // TODO: could also be applied to methods?
1111 if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D)) {
1112 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Ted Kremenek5dc53c92009-05-13 21:07:32 +00001113 << Attr.getName() << 2 /*variable and function*/;
Daniel Dunbar6e775db2009-03-06 06:39:57 +00001114 return;
1115 }
Mike Stumpbf916502009-07-24 19:02:52 +00001116
Sean Huntcf807c42010-08-18 23:23:40 +00001117 D->addAttr(::new (S.Context) WeakAttr(Attr.getLoc(), S.Context));
Chris Lattner6b6b5372008-06-26 18:38:35 +00001118}
1119
Daniel Dunbar6e775db2009-03-06 06:39:57 +00001120static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
1121 // check the attribute arguments.
1122 if (Attr.getNumArgs() != 0) {
1123 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
1124 return;
Mike Stumpbf916502009-07-24 19:02:52 +00001125 }
Daniel Dunbar6e775db2009-03-06 06:39:57 +00001126
1127 // weak_import only applies to variable & function declarations.
1128 bool isDef = false;
1129 if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
1130 isDef = (!VD->hasExternalStorage() || VD->getInit());
1131 } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Argyrios Kyrtzidis06a54a32010-07-07 11:31:19 +00001132 isDef = FD->hasBody();
Fariborz Jahaniand4edddd2009-05-04 19:35:12 +00001133 } else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D)) {
1134 // We ignore weak import on properties and methods
Mike Stump1c90f4d2009-03-18 17:39:31 +00001135 return;
Fariborz Jahanian5f8f8572009-11-17 19:08:08 +00001136 } else if (!(S.LangOpts.ObjCNonFragileABI && isa<ObjCInterfaceDecl>(D))) {
Fariborz Jahanianc0349742010-04-13 20:22:35 +00001137 // Don't issue the warning for darwin as target; yet, ignore the attribute.
Fariborz Jahanian3be17942010-04-12 16:57:31 +00001138 if (S.Context.Target.getTriple().getOS() != llvm::Triple::Darwin ||
Fariborz Jahanianc0349742010-04-13 20:22:35 +00001139 !isa<ObjCInterfaceDecl>(D))
1140 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Fariborz Jahanian3be17942010-04-12 16:57:31 +00001141 << Attr.getName() << 2 /*variable and function*/;
1142 return;
Daniel Dunbar6e775db2009-03-06 06:39:57 +00001143 }
1144
1145 // Merge should handle any subsequent violations.
1146 if (isDef) {
Mike Stumpbf916502009-07-24 19:02:52 +00001147 S.Diag(Attr.getLoc(),
Daniel Dunbar6e775db2009-03-06 06:39:57 +00001148 diag::warn_attribute_weak_import_invalid_on_definition)
1149 << "weak_import" << 2 /*variable and function*/;
1150 return;
1151 }
1152
Sean Huntcf807c42010-08-18 23:23:40 +00001153 D->addAttr(::new (S.Context) WeakImportAttr(Attr.getLoc(), S.Context));
Daniel Dunbar6e775db2009-03-06 06:39:57 +00001154}
1155
Nate Begeman6f3d8382009-06-26 06:32:41 +00001156static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
1157 Sema &S) {
1158 // Attribute has 3 arguments.
1159 if (Attr.getNumArgs() != 3) {
John McCall2b7baf02010-05-28 18:25:28 +00001160 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Nate Begeman6f3d8382009-06-26 06:32:41 +00001161 return;
1162 }
1163
1164 unsigned WGSize[3];
1165 for (unsigned i = 0; i < 3; ++i) {
1166 Expr *E = static_cast<Expr *>(Attr.getArg(i));
1167 llvm::APSInt ArgNum(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +00001168 if (E->isTypeDependent() || E->isValueDependent() ||
1169 !E->isIntegerConstantExpr(ArgNum, S.Context)) {
Nate Begeman6f3d8382009-06-26 06:32:41 +00001170 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
1171 << "reqd_work_group_size" << E->getSourceRange();
1172 return;
1173 }
1174 WGSize[i] = (unsigned) ArgNum.getZExtValue();
1175 }
Sean Huntcf807c42010-08-18 23:23:40 +00001176 D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(Attr.getLoc(), S.Context,
1177 WGSize[0], WGSize[1],
Nate Begeman6f3d8382009-06-26 06:32:41 +00001178 WGSize[2]));
1179}
1180
Chris Lattner026dc962009-02-14 07:37:35 +00001181static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
Daniel Dunbar17f194f2009-02-12 17:28:23 +00001182 // Attribute has no arguments.
1183 if (Attr.getNumArgs() != 1) {
1184 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
1185 return;
1186 }
1187
1188 // Make sure that there is a string literal as the sections's single
1189 // argument.
Chris Lattner797c3c42009-08-10 19:03:04 +00001190 Expr *ArgExpr = static_cast<Expr *>(Attr.getArg(0));
1191 StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
Daniel Dunbar17f194f2009-02-12 17:28:23 +00001192 if (!SE) {
Chris Lattner797c3c42009-08-10 19:03:04 +00001193 S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) << "section";
Daniel Dunbar17f194f2009-02-12 17:28:23 +00001194 return;
1195 }
Mike Stump1eb44332009-09-09 15:08:12 +00001196
Chris Lattner797c3c42009-08-10 19:03:04 +00001197 // If the target wants to validate the section specifier, make it happen.
Benjamin Kramerbb377ed2009-11-30 17:08:26 +00001198 std::string Error = S.Context.Target.isValidSectionSpecifier(SE->getString());
Chris Lattnera1e1dc72010-01-12 20:58:53 +00001199 if (!Error.empty()) {
1200 S.Diag(SE->getLocStart(), diag::err_attribute_section_invalid_for_target)
1201 << Error;
Chris Lattner797c3c42009-08-10 19:03:04 +00001202 return;
1203 }
Mike Stump1eb44332009-09-09 15:08:12 +00001204
Chris Lattnera1e1dc72010-01-12 20:58:53 +00001205 // This attribute cannot be applied to local variables.
1206 if (isa<VarDecl>(D) && cast<VarDecl>(D)->hasLocalStorage()) {
1207 S.Diag(SE->getLocStart(), diag::err_attribute_section_local_variable);
1208 return;
1209 }
1210
Sean Huntcf807c42010-08-18 23:23:40 +00001211 D->addAttr(::new (S.Context) SectionAttr(Attr.getLoc(), S.Context, SE->getString()));
Daniel Dunbar17f194f2009-02-12 17:28:23 +00001212}
1213
Chris Lattner6b6b5372008-06-26 18:38:35 +00001214
Chris Lattner803d0802008-06-29 00:43:07 +00001215static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00001216 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +00001217 if (Attr.getNumArgs() != 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001218 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001219 return;
1220 }
Mike Stumpbf916502009-07-24 19:02:52 +00001221
Sean Huntcf807c42010-08-18 23:23:40 +00001222 d->addAttr(::new (S.Context) NoThrowAttr(Attr.getLoc(), S.Context));
Chris Lattner6b6b5372008-06-26 18:38:35 +00001223}
1224
Anders Carlsson232eb7d2008-10-05 23:32:53 +00001225static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
1226 // check the attribute arguments.
1227 if (Attr.getNumArgs() != 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001228 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Anders Carlsson232eb7d2008-10-05 23:32:53 +00001229 return;
1230 }
Mike Stumpbf916502009-07-24 19:02:52 +00001231
Sean Huntcf807c42010-08-18 23:23:40 +00001232 d->addAttr(::new (S.Context) ConstAttr(Attr.getLoc(), S.Context));
Anders Carlsson232eb7d2008-10-05 23:32:53 +00001233}
1234
1235static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
1236 // check the attribute arguments.
1237 if (Attr.getNumArgs() != 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001238 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Anders Carlsson232eb7d2008-10-05 23:32:53 +00001239 return;
1240 }
Mike Stumpbf916502009-07-24 19:02:52 +00001241
Sean Huntcf807c42010-08-18 23:23:40 +00001242 d->addAttr(::new (S.Context) PureAttr(Attr.getLoc(), S.Context));
Anders Carlsson232eb7d2008-10-05 23:32:53 +00001243}
1244
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001245static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Mike Stumpbf916502009-07-24 19:02:52 +00001246 if (!Attr.getParameterName()) {
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001247 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
1248 return;
1249 }
Mike Stumpbf916502009-07-24 19:02:52 +00001250
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001251 if (Attr.getNumArgs() != 0) {
1252 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
1253 return;
1254 }
Mike Stumpbf916502009-07-24 19:02:52 +00001255
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001256 VarDecl *VD = dyn_cast<VarDecl>(d);
Mike Stumpbf916502009-07-24 19:02:52 +00001257
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001258 if (!VD || !VD->hasLocalStorage()) {
1259 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup";
1260 return;
1261 }
Mike Stumpbf916502009-07-24 19:02:52 +00001262
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001263 // Look up the function
Douglas Gregorc83c6872010-04-15 22:33:43 +00001264 // FIXME: Lookup probably isn't looking in the right place
1265 // FIXME: The lookup source location should be in the attribute, not the
1266 // start of the attribute.
John McCallf36e02d2009-10-09 21:13:30 +00001267 NamedDecl *CleanupDecl
Douglas Gregorc83c6872010-04-15 22:33:43 +00001268 = S.LookupSingleName(S.TUScope, Attr.getParameterName(), Attr.getLoc(),
John McCallf36e02d2009-10-09 21:13:30 +00001269 Sema::LookupOrdinaryName);
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001270 if (!CleanupDecl) {
Anders Carlsson89941c12009-02-07 23:16:50 +00001271 S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_found) <<
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001272 Attr.getParameterName();
1273 return;
1274 }
Mike Stumpbf916502009-07-24 19:02:52 +00001275
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001276 FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl);
1277 if (!FD) {
Anders Carlsson89941c12009-02-07 23:16:50 +00001278 S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_function) <<
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001279 Attr.getParameterName();
1280 return;
1281 }
1282
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001283 if (FD->getNumParams() != 1) {
Anders Carlsson89941c12009-02-07 23:16:50 +00001284 S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_func_must_take_one_arg) <<
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001285 Attr.getParameterName();
1286 return;
1287 }
Mike Stumpbf916502009-07-24 19:02:52 +00001288
Anders Carlsson89941c12009-02-07 23:16:50 +00001289 // We're currently more strict than GCC about what function types we accept.
1290 // If this ever proves to be a problem it should be easy to fix.
1291 QualType Ty = S.Context.getPointerType(VD->getType());
1292 QualType ParamTy = FD->getParamDecl(0)->getType();
Eli Friedmand5e3e8e2009-04-26 01:30:08 +00001293 if (S.CheckAssignmentConstraints(ParamTy, Ty) != Sema::Compatible) {
Mike Stumpbf916502009-07-24 19:02:52 +00001294 S.Diag(Attr.getLoc(),
Anders Carlsson89941c12009-02-07 23:16:50 +00001295 diag::err_attribute_cleanup_func_arg_incompatible_type) <<
1296 Attr.getParameterName() << ParamTy << Ty;
1297 return;
1298 }
Mike Stumpbf916502009-07-24 19:02:52 +00001299
Sean Huntcf807c42010-08-18 23:23:40 +00001300 d->addAttr(::new (S.Context) CleanupAttr(Attr.getLoc(), S.Context, FD));
Anders Carlssonf6e35d02009-01-31 01:16:18 +00001301}
1302
Mike Stumpbf916502009-07-24 19:02:52 +00001303/// Handle __attribute__((format_arg((idx)))) attribute based on
1304/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
1305static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001306 if (Attr.getNumArgs() != 1) {
1307 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
1308 return;
1309 }
1310 if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
1311 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
1312 << Attr.getName() << 0 /*function*/;
1313 return;
1314 }
Mike Stumpbf916502009-07-24 19:02:52 +00001315 // FIXME: in C++ the implicit 'this' function parameter also counts. this is
1316 // needed in order to be compatible with GCC the index must start with 1.
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001317 unsigned NumArgs = getFunctionOrMethodNumArgs(d);
1318 unsigned FirstIdx = 1;
1319 // checks for the 2nd argument
1320 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
1321 llvm::APSInt Idx(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +00001322 if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
1323 !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001324 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
1325 << "format" << 2 << IdxExpr->getSourceRange();
1326 return;
1327 }
Mike Stumpbf916502009-07-24 19:02:52 +00001328
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001329 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
1330 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
1331 << "format" << 2 << IdxExpr->getSourceRange();
1332 return;
1333 }
Mike Stumpbf916502009-07-24 19:02:52 +00001334
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001335 unsigned ArgIdx = Idx.getZExtValue() - 1;
Mike Stumpbf916502009-07-24 19:02:52 +00001336
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001337 // make sure the format string is really a string
1338 QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
Mike Stumpbf916502009-07-24 19:02:52 +00001339
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001340 bool not_nsstring_type = !isNSStringType(Ty, S.Context);
1341 if (not_nsstring_type &&
1342 !isCFStringType(Ty, S.Context) &&
1343 (!Ty->isPointerType() ||
Ted Kremenek6217b802009-07-29 21:53:49 +00001344 !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001345 // FIXME: Should highlight the actual expression that has the wrong type.
1346 S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
Mike Stumpbf916502009-07-24 19:02:52 +00001347 << (not_nsstring_type ? "a string type" : "an NSString")
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001348 << IdxExpr->getSourceRange();
1349 return;
Mike Stumpbf916502009-07-24 19:02:52 +00001350 }
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001351 Ty = getFunctionOrMethodResultType(d);
1352 if (!isNSStringType(Ty, S.Context) &&
1353 !isCFStringType(Ty, S.Context) &&
1354 (!Ty->isPointerType() ||
Ted Kremenek6217b802009-07-29 21:53:49 +00001355 !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001356 // FIXME: Should highlight the actual expression that has the wrong type.
1357 S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not)
Mike Stumpbf916502009-07-24 19:02:52 +00001358 << (not_nsstring_type ? "string type" : "NSString")
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001359 << IdxExpr->getSourceRange();
1360 return;
Mike Stumpbf916502009-07-24 19:02:52 +00001361 }
1362
Sean Huntcf807c42010-08-18 23:23:40 +00001363 d->addAttr(::new (S.Context) FormatArgAttr(Attr.getLoc(), S.Context, Idx.getZExtValue()));
Fariborz Jahanian5b160922009-05-20 17:41:43 +00001364}
1365
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001366enum FormatAttrKind {
1367 CFStringFormat,
1368 NSStringFormat,
1369 StrftimeFormat,
1370 SupportedFormat,
Chris Lattner3c989022010-03-22 21:08:50 +00001371 IgnoredFormat,
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001372 InvalidFormat
1373};
1374
1375/// getFormatAttrKind - Map from format attribute names to supported format
1376/// types.
1377static FormatAttrKind getFormatAttrKind(llvm::StringRef Format) {
1378 // Check for formats that get handled specially.
1379 if (Format == "NSString")
1380 return NSStringFormat;
1381 if (Format == "CFString")
1382 return CFStringFormat;
1383 if (Format == "strftime")
1384 return StrftimeFormat;
1385
1386 // Otherwise, check for supported formats.
1387 if (Format == "scanf" || Format == "printf" || Format == "printf0" ||
1388 Format == "strfmon" || Format == "cmn_err" || Format == "strftime" ||
1389 Format == "NSString" || Format == "CFString" || Format == "vcmn_err" ||
1390 Format == "zcmn_err")
1391 return SupportedFormat;
1392
Duncan Sandsbc525952010-03-23 14:44:19 +00001393 if (Format == "gcc_diag" || Format == "gcc_cdiag" ||
1394 Format == "gcc_cxxdiag" || Format == "gcc_tdiag")
Chris Lattner3c989022010-03-22 21:08:50 +00001395 return IgnoredFormat;
1396
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001397 return InvalidFormat;
1398}
1399
Fariborz Jahanian521f12d2010-06-18 21:44:06 +00001400/// Handle __attribute__((init_priority(priority))) attributes based on
1401/// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html
1402static void HandleInitPriorityAttr(Decl *d, const AttributeList &Attr,
1403 Sema &S) {
1404 if (!S.getLangOptions().CPlusPlus) {
1405 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
1406 return;
1407 }
1408
Fariborz Jahanianb9d5c222010-06-18 23:14:53 +00001409 if (!isa<VarDecl>(d) || S.getCurFunctionOrMethodDecl()) {
1410 S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
1411 Attr.setInvalid();
1412 return;
1413 }
1414 QualType T = dyn_cast<VarDecl>(d)->getType();
1415 if (S.Context.getAsArrayType(T))
1416 T = S.Context.getBaseElementType(T);
1417 if (!T->getAs<RecordType>()) {
1418 S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
1419 Attr.setInvalid();
1420 return;
1421 }
1422
Fariborz Jahanian521f12d2010-06-18 21:44:06 +00001423 if (Attr.getNumArgs() != 1) {
1424 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
1425 Attr.setInvalid();
1426 return;
1427 }
1428 Expr *priorityExpr = static_cast<Expr *>(Attr.getArg(0));
Fariborz Jahanianb9d5c222010-06-18 23:14:53 +00001429
Fariborz Jahanian521f12d2010-06-18 21:44:06 +00001430 llvm::APSInt priority(32);
1431 if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() ||
1432 !priorityExpr->isIntegerConstantExpr(priority, S.Context)) {
1433 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
1434 << "init_priority" << priorityExpr->getSourceRange();
1435 Attr.setInvalid();
1436 return;
1437 }
Fariborz Jahanian9f967c52010-06-21 18:45:05 +00001438 unsigned prioritynum = priority.getZExtValue();
Fariborz Jahanian521f12d2010-06-18 21:44:06 +00001439 if (prioritynum < 101 || prioritynum > 65535) {
1440 S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range)
1441 << priorityExpr->getSourceRange();
1442 Attr.setInvalid();
1443 return;
1444 }
Sean Huntcf807c42010-08-18 23:23:40 +00001445 d->addAttr(::new (S.Context) InitPriorityAttr(Attr.getLoc(), S.Context, prioritynum));
Fariborz Jahanian521f12d2010-06-18 21:44:06 +00001446}
1447
Mike Stumpbf916502009-07-24 19:02:52 +00001448/// Handle __attribute__((format(type,idx,firstarg))) attributes based on
1449/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
Chris Lattner803d0802008-06-29 00:43:07 +00001450static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00001451
Chris Lattner545dd342008-06-28 23:36:30 +00001452 if (!Attr.getParameterName()) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001453 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
Chris Lattner3c73c412008-11-19 08:23:25 +00001454 << "format" << 1;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001455 return;
1456 }
1457
Chris Lattner545dd342008-06-28 23:36:30 +00001458 if (Attr.getNumArgs() != 2) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001459 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001460 return;
1461 }
1462
Fariborz Jahanian620d89c2009-05-15 23:15:03 +00001463 if (!isFunctionOrMethodOrBlock(d) || !hasFunctionProto(d)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001464 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Ted Kremenek5dc53c92009-05-13 21:07:32 +00001465 << Attr.getName() << 0 /*function*/;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001466 return;
1467 }
1468
Daniel Dunbar35682492008-09-26 04:12:28 +00001469 unsigned NumArgs = getFunctionOrMethodNumArgs(d);
Chris Lattner6b6b5372008-06-26 18:38:35 +00001470 unsigned FirstIdx = 1;
1471
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00001472 llvm::StringRef Format = Attr.getParameterName()->getName();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001473
1474 // Normalize the argument, __foo__ becomes foo.
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001475 if (Format.startswith("__") && Format.endswith("__"))
1476 Format = Format.substr(2, Format.size() - 4);
Chris Lattner6b6b5372008-06-26 18:38:35 +00001477
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001478 // Check for supported formats.
1479 FormatAttrKind Kind = getFormatAttrKind(Format);
Chris Lattner3c989022010-03-22 21:08:50 +00001480
1481 if (Kind == IgnoredFormat)
1482 return;
1483
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001484 if (Kind == InvalidFormat) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001485 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00001486 << "format" << Attr.getParameterName()->getName();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001487 return;
1488 }
1489
1490 // checks for the 2nd argument
Chris Lattner545dd342008-06-28 23:36:30 +00001491 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner803d0802008-06-29 00:43:07 +00001492 llvm::APSInt Idx(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +00001493 if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
1494 !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001495 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
Chris Lattner3c73c412008-11-19 08:23:25 +00001496 << "format" << 2 << IdxExpr->getSourceRange();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001497 return;
1498 }
1499
Anders Carlsson4fb77202009-08-25 14:12:34 +00001500 // FIXME: We should handle the implicit 'this' parameter in a more generic
1501 // way that can be used for other arguments.
1502 bool HasImplicitThisParam = false;
1503 if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(d)) {
1504 if (MD->isInstance()) {
1505 HasImplicitThisParam = true;
1506 NumArgs++;
1507 }
1508 }
Mike Stump1eb44332009-09-09 15:08:12 +00001509
Chris Lattner6b6b5372008-06-26 18:38:35 +00001510 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001511 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
Chris Lattner3c73c412008-11-19 08:23:25 +00001512 << "format" << 2 << IdxExpr->getSourceRange();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001513 return;
1514 }
1515
1516 // FIXME: Do we need to bounds check?
1517 unsigned ArgIdx = Idx.getZExtValue() - 1;
Mike Stumpbf916502009-07-24 19:02:52 +00001518
Sebastian Redl4a2614e2009-11-17 18:02:24 +00001519 if (HasImplicitThisParam) {
1520 if (ArgIdx == 0) {
1521 S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
1522 << "a string type" << IdxExpr->getSourceRange();
1523 return;
1524 }
1525 ArgIdx--;
1526 }
Mike Stump1eb44332009-09-09 15:08:12 +00001527
Chris Lattner6b6b5372008-06-26 18:38:35 +00001528 // make sure the format string is really a string
Daniel Dunbar35682492008-09-26 04:12:28 +00001529 QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
Chris Lattner6b6b5372008-06-26 18:38:35 +00001530
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001531 if (Kind == CFStringFormat) {
Daniel Dunbar085e8f72008-09-26 03:32:58 +00001532 if (!isCFStringType(Ty, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001533 S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
1534 << "a CFString" << IdxExpr->getSourceRange();
Daniel Dunbar085e8f72008-09-26 03:32:58 +00001535 return;
1536 }
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001537 } else if (Kind == NSStringFormat) {
Mike Stump390b4cc2009-05-16 07:39:55 +00001538 // FIXME: do we need to check if the type is NSString*? What are the
1539 // semantics?
Chris Lattner803d0802008-06-29 00:43:07 +00001540 if (!isNSStringType(Ty, S.Context)) {
Mike Stump390b4cc2009-05-16 07:39:55 +00001541 // FIXME: Should highlight the actual expression that has the wrong type.
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001542 S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
1543 << "an NSString" << IdxExpr->getSourceRange();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001544 return;
Mike Stumpbf916502009-07-24 19:02:52 +00001545 }
Chris Lattner6b6b5372008-06-26 18:38:35 +00001546 } else if (!Ty->isPointerType() ||
Ted Kremenek6217b802009-07-29 21:53:49 +00001547 !Ty->getAs<PointerType>()->getPointeeType()->isCharType()) {
Mike Stump390b4cc2009-05-16 07:39:55 +00001548 // FIXME: Should highlight the actual expression that has the wrong type.
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001549 S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
1550 << "a string type" << IdxExpr->getSourceRange();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001551 return;
1552 }
1553
1554 // check the 3rd argument
Chris Lattner545dd342008-06-28 23:36:30 +00001555 Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1));
Chris Lattner803d0802008-06-29 00:43:07 +00001556 llvm::APSInt FirstArg(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +00001557 if (FirstArgExpr->isTypeDependent() || FirstArgExpr->isValueDependent() ||
1558 !FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001559 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
Chris Lattner3c73c412008-11-19 08:23:25 +00001560 << "format" << 3 << FirstArgExpr->getSourceRange();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001561 return;
1562 }
1563
1564 // check if the function is variadic if the 3rd argument non-zero
1565 if (FirstArg != 0) {
Daniel Dunbar35682492008-09-26 04:12:28 +00001566 if (isFunctionOrMethodVariadic(d)) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00001567 ++NumArgs; // +1 for ...
1568 } else {
Chris Lattner803d0802008-06-29 00:43:07 +00001569 S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
Chris Lattner6b6b5372008-06-26 18:38:35 +00001570 return;
1571 }
1572 }
1573
Chris Lattner3c73c412008-11-19 08:23:25 +00001574 // strftime requires FirstArg to be 0 because it doesn't read from any
1575 // variable the input is just the current time + the format string.
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001576 if (Kind == StrftimeFormat) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00001577 if (FirstArg != 0) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001578 S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter)
1579 << FirstArgExpr->getSourceRange();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001580 return;
1581 }
1582 // if 0 it disables parameter checking (to use with e.g. va_list)
1583 } else if (FirstArg != 0 && FirstArg != NumArgs) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001584 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
Chris Lattner3c73c412008-11-19 08:23:25 +00001585 << "format" << 3 << FirstArgExpr->getSourceRange();
Chris Lattner6b6b5372008-06-26 18:38:35 +00001586 return;
1587 }
1588
Sean Huntcf807c42010-08-18 23:23:40 +00001589 d->addAttr(::new (S.Context) FormatAttr(Attr.getLoc(), S.Context, Format,
1590 Idx.getZExtValue(),
Daniel Dunbar2b0d9a22009-10-18 02:09:17 +00001591 FirstArg.getZExtValue()));
Chris Lattner6b6b5372008-06-26 18:38:35 +00001592}
1593
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001594static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
1595 Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00001596 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +00001597 if (Attr.getNumArgs() != 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001598 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001599 return;
1600 }
1601
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001602 // Try to find the underlying union declaration.
1603 RecordDecl *RD = 0;
Eli Friedmanbc887452008-09-02 05:19:23 +00001604 TypedefDecl *TD = dyn_cast<TypedefDecl>(d);
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001605 if (TD && TD->getUnderlyingType()->isUnionType())
1606 RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
1607 else
1608 RD = dyn_cast<RecordDecl>(d);
1609
1610 if (!RD || !RD->isUnion()) {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001611 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Ted Kremenek5dc53c92009-05-13 21:07:32 +00001612 << Attr.getName() << 1 /*union*/;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001613 return;
1614 }
1615
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001616 if (!RD->isDefinition()) {
Mike Stumpbf916502009-07-24 19:02:52 +00001617 S.Diag(Attr.getLoc(),
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001618 diag::warn_transparent_union_attribute_not_definition);
1619 return;
1620 }
Chris Lattner6b6b5372008-06-26 18:38:35 +00001621
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001622 RecordDecl::field_iterator Field = RD->field_begin(),
1623 FieldEnd = RD->field_end();
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001624 if (Field == FieldEnd) {
1625 S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields);
1626 return;
1627 }
Eli Friedmanbc887452008-09-02 05:19:23 +00001628
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001629 FieldDecl *FirstField = *Field;
1630 QualType FirstType = FirstField->getType();
Douglas Gregor90cd6722010-06-30 17:24:13 +00001631 if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) {
Mike Stumpbf916502009-07-24 19:02:52 +00001632 S.Diag(FirstField->getLocation(),
Douglas Gregor90cd6722010-06-30 17:24:13 +00001633 diag::warn_transparent_union_attribute_floating)
1634 << FirstType->isVectorType() << FirstType;
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001635 return;
1636 }
1637
1638 uint64_t FirstSize = S.Context.getTypeSize(FirstType);
1639 uint64_t FirstAlign = S.Context.getTypeAlign(FirstType);
1640 for (; Field != FieldEnd; ++Field) {
1641 QualType FieldType = Field->getType();
1642 if (S.Context.getTypeSize(FieldType) != FirstSize ||
1643 S.Context.getTypeAlign(FieldType) != FirstAlign) {
1644 // Warn if we drop the attribute.
1645 bool isSize = S.Context.getTypeSize(FieldType) != FirstSize;
Mike Stumpbf916502009-07-24 19:02:52 +00001646 unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType)
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001647 : S.Context.getTypeAlign(FieldType);
Mike Stumpbf916502009-07-24 19:02:52 +00001648 S.Diag(Field->getLocation(),
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001649 diag::warn_transparent_union_attribute_field_size_align)
1650 << isSize << Field->getDeclName() << FieldBits;
1651 unsigned FirstBits = isSize? FirstSize : FirstAlign;
Mike Stumpbf916502009-07-24 19:02:52 +00001652 S.Diag(FirstField->getLocation(),
Douglas Gregor0c74e8a2009-04-29 22:16:16 +00001653 diag::note_transparent_union_first_field_size_align)
1654 << isSize << FirstBits;
Eli Friedmanbc887452008-09-02 05:19:23 +00001655 return;
1656 }
1657 }
1658
Sean Huntcf807c42010-08-18 23:23:40 +00001659 RD->addAttr(::new (S.Context) TransparentUnionAttr(Attr.getLoc(), S.Context));
Chris Lattner6b6b5372008-06-26 18:38:35 +00001660}
1661
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001662static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00001663 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +00001664 if (Attr.getNumArgs() != 1) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001665 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001666 return;
1667 }
Chris Lattner797c3c42009-08-10 19:03:04 +00001668 Expr *ArgExpr = static_cast<Expr *>(Attr.getArg(0));
1669 StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
Mike Stumpbf916502009-07-24 19:02:52 +00001670
Chris Lattner6b6b5372008-06-26 18:38:35 +00001671 // Make sure that there is a string literal as the annotation's single
1672 // argument.
1673 if (!SE) {
Chris Lattner797c3c42009-08-10 19:03:04 +00001674 S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate";
Chris Lattner6b6b5372008-06-26 18:38:35 +00001675 return;
1676 }
Sean Huntcf807c42010-08-18 23:23:40 +00001677 d->addAttr(::new (S.Context) AnnotateAttr(Attr.getLoc(), S.Context, SE->getString()));
Chris Lattner6b6b5372008-06-26 18:38:35 +00001678}
1679
Chandler Carruth4ced79f2010-06-25 03:22:07 +00001680static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +00001681 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +00001682 if (Attr.getNumArgs() > 1) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001683 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001684 return;
1685 }
Sean Huntbbd37c62009-11-21 08:43:09 +00001686
1687 //FIXME: The C++0x version of this attribute has more limited applicabilty
1688 // than GNU's, and should error out when it is used to specify a
1689 // weaker alignment, rather than being silently ignored.
Chris Lattner6b6b5372008-06-26 18:38:35 +00001690
Chris Lattner545dd342008-06-28 23:36:30 +00001691 if (Attr.getNumArgs() == 0) {
Sean Huntcf807c42010-08-18 23:23:40 +00001692 D->addAttr(::new (S.Context) AlignedAttr(Attr.getLoc(), S.Context, true, 0));
Chris Lattner6b6b5372008-06-26 18:38:35 +00001693 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001694 }
Mike Stumpbf916502009-07-24 19:02:52 +00001695
Chandler Carruth4ced79f2010-06-25 03:22:07 +00001696 S.AddAlignedAttr(Attr.getLoc(), D, static_cast<Expr *>(Attr.getArg(0)));
1697}
1698
1699void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) {
1700 if (E->isTypeDependent() || E->isValueDependent()) {
1701 // Save dependent expressions in the AST to be instantiated.
Sean Huntcf807c42010-08-18 23:23:40 +00001702 D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E));
Chandler Carruth4ced79f2010-06-25 03:22:07 +00001703 return;
1704 }
1705
Sean Huntcf807c42010-08-18 23:23:40 +00001706 // FIXME: Cache the number on the Attr object?
Chris Lattner49e2d342008-06-28 23:50:44 +00001707 llvm::APSInt Alignment(32);
Chandler Carruth4ced79f2010-06-25 03:22:07 +00001708 if (!E->isIntegerConstantExpr(Alignment, Context)) {
1709 Diag(AttrLoc, diag::err_attribute_argument_not_int)
1710 << "aligned" << E->getSourceRange();
Chris Lattner49e2d342008-06-28 23:50:44 +00001711 return;
1712 }
Daniel Dunbar396b2a22009-02-16 23:37:57 +00001713 if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) {
Chandler Carruth4ced79f2010-06-25 03:22:07 +00001714 Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two)
1715 << E->getSourceRange();
Daniel Dunbar396b2a22009-02-16 23:37:57 +00001716 return;
1717 }
1718
Sean Huntcf807c42010-08-18 23:23:40 +00001719 D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E));
1720}
1721
1722void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, TypeSourceInfo *TS) {
1723 // FIXME: Cache the number on the Attr object if non-dependent?
1724 // FIXME: Perform checking of type validity
1725 D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, false, TS));
1726 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +00001727}
Chris Lattnerfbf13472008-06-27 22:18:37 +00001728
Mike Stumpbf916502009-07-24 19:02:52 +00001729/// HandleModeAttr - This attribute modifies the width of a decl with primitive
1730/// type.
Chris Lattnerfbf13472008-06-27 22:18:37 +00001731///
Mike Stumpbf916502009-07-24 19:02:52 +00001732/// Despite what would be logical, the mode attribute is a decl attribute, not a
1733/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
1734/// HImode, not an intermediate pointer.
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001735static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
Chris Lattnerfbf13472008-06-27 22:18:37 +00001736 // This attribute isn't documented, but glibc uses it. It changes
1737 // the width of an int or unsigned int to the specified size.
1738
1739 // Check that there aren't any arguments
1740 if (Attr.getNumArgs() != 0) {
Chris Lattner3c73c412008-11-19 08:23:25 +00001741 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
Chris Lattnerfbf13472008-06-27 22:18:37 +00001742 return;
1743 }
1744
1745 IdentifierInfo *Name = Attr.getParameterName();
1746 if (!Name) {
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001747 S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
Chris Lattnerfbf13472008-06-27 22:18:37 +00001748 return;
1749 }
Daniel Dunbar210ae982009-10-18 02:09:24 +00001750
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00001751 llvm::StringRef Str = Attr.getParameterName()->getName();
Chris Lattnerfbf13472008-06-27 22:18:37 +00001752
1753 // Normalize the attribute name, __foo__ becomes foo.
Daniel Dunbar210ae982009-10-18 02:09:24 +00001754 if (Str.startswith("__") && Str.endswith("__"))
1755 Str = Str.substr(2, Str.size() - 4);
Chris Lattnerfbf13472008-06-27 22:18:37 +00001756
1757 unsigned DestWidth = 0;
1758 bool IntegerMode = true;
Eli Friedman73397492009-03-03 06:41:03 +00001759 bool ComplexMode = false;
Daniel Dunbar210ae982009-10-18 02:09:24 +00001760 switch (Str.size()) {
Chris Lattnerfbf13472008-06-27 22:18:37 +00001761 case 2:
Eli Friedman73397492009-03-03 06:41:03 +00001762 switch (Str[0]) {
1763 case 'Q': DestWidth = 8; break;
1764 case 'H': DestWidth = 16; break;
1765 case 'S': DestWidth = 32; break;
1766 case 'D': DestWidth = 64; break;
1767 case 'X': DestWidth = 96; break;
1768 case 'T': DestWidth = 128; break;
1769 }
1770 if (Str[1] == 'F') {
1771 IntegerMode = false;
1772 } else if (Str[1] == 'C') {
1773 IntegerMode = false;
1774 ComplexMode = true;
1775 } else if (Str[1] != 'I') {
1776 DestWidth = 0;
1777 }
Chris Lattnerfbf13472008-06-27 22:18:37 +00001778 break;
1779 case 4:
1780 // FIXME: glibc uses 'word' to define register_t; this is narrower than a
1781 // pointer on PIC16 and other embedded platforms.
Daniel Dunbar210ae982009-10-18 02:09:24 +00001782 if (Str == "word")
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001783 DestWidth = S.Context.Target.getPointerWidth(0);
Daniel Dunbar210ae982009-10-18 02:09:24 +00001784 else if (Str == "byte")
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001785 DestWidth = S.Context.Target.getCharWidth();
Chris Lattnerfbf13472008-06-27 22:18:37 +00001786 break;
1787 case 7:
Daniel Dunbar210ae982009-10-18 02:09:24 +00001788 if (Str == "pointer")
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001789 DestWidth = S.Context.Target.getPointerWidth(0);
Chris Lattnerfbf13472008-06-27 22:18:37 +00001790 break;
1791 }
1792
1793 QualType OldTy;
1794 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
1795 OldTy = TD->getUnderlyingType();
1796 else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
1797 OldTy = VD->getType();
1798 else {
Chris Lattnerfa25bbb2008-11-19 05:08:23 +00001799 S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
1800 << "mode" << SourceRange(Attr.getLoc(), Attr.getLoc());
Chris Lattnerfbf13472008-06-27 22:18:37 +00001801 return;
1802 }
Eli Friedman73397492009-03-03 06:41:03 +00001803
John McCall183700f2009-09-21 23:43:11 +00001804 if (!OldTy->getAs<BuiltinType>() && !OldTy->isComplexType())
Eli Friedman73397492009-03-03 06:41:03 +00001805 S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
1806 else if (IntegerMode) {
Douglas Gregor2ade35e2010-06-16 00:17:44 +00001807 if (!OldTy->isIntegralOrEnumerationType())
Eli Friedman73397492009-03-03 06:41:03 +00001808 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
1809 } else if (ComplexMode) {
1810 if (!OldTy->isComplexType())
1811 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
1812 } else {
1813 if (!OldTy->isFloatingType())
1814 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
1815 }
1816
Mike Stump390b4cc2009-05-16 07:39:55 +00001817 // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
1818 // and friends, at least with glibc.
1819 // FIXME: Make sure 32/64-bit integers don't get defined to types of the wrong
1820 // width on unusual platforms.
Eli Friedmanf98aba32009-02-13 02:31:07 +00001821 // FIXME: Make sure floating-point mappings are accurate
1822 // FIXME: Support XF and TF types
Chris Lattnerfbf13472008-06-27 22:18:37 +00001823 QualType NewTy;
1824 switch (DestWidth) {
1825 case 0:
Chris Lattner3c73c412008-11-19 08:23:25 +00001826 S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name;
Chris Lattnerfbf13472008-06-27 22:18:37 +00001827 return;
1828 default:
Chris Lattner3c73c412008-11-19 08:23:25 +00001829 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
Chris Lattnerfbf13472008-06-27 22:18:37 +00001830 return;
1831 case 8:
Eli Friedman73397492009-03-03 06:41:03 +00001832 if (!IntegerMode) {
1833 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
1834 return;
1835 }
Chris Lattnerfbf13472008-06-27 22:18:37 +00001836 if (OldTy->isSignedIntegerType())
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001837 NewTy = S.Context.SignedCharTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00001838 else
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001839 NewTy = S.Context.UnsignedCharTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00001840 break;
1841 case 16:
Eli Friedman73397492009-03-03 06:41:03 +00001842 if (!IntegerMode) {
1843 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
1844 return;
1845 }
Chris Lattnerfbf13472008-06-27 22:18:37 +00001846 if (OldTy->isSignedIntegerType())
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001847 NewTy = S.Context.ShortTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00001848 else
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001849 NewTy = S.Context.UnsignedShortTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00001850 break;
1851 case 32:
1852 if (!IntegerMode)
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001853 NewTy = S.Context.FloatTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00001854 else if (OldTy->isSignedIntegerType())
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001855 NewTy = S.Context.IntTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00001856 else
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001857 NewTy = S.Context.UnsignedIntTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00001858 break;
1859 case 64:
1860 if (!IntegerMode)
Chris Lattner0b2f4da2008-06-29 00:28:59 +00001861 NewTy = S.Context.DoubleTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00001862 else if (OldTy->isSignedIntegerType())
Chandler Carruthaec7caa2010-01-26 06:39:24 +00001863 if (S.Context.Target.getLongWidth() == 64)
1864 NewTy = S.Context.LongTy;
1865 else
1866 NewTy = S.Context.LongLongTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00001867 else
Chandler Carruthaec7caa2010-01-26 06:39:24 +00001868 if (S.Context.Target.getLongWidth() == 64)
1869 NewTy = S.Context.UnsignedLongTy;
1870 else
1871 NewTy = S.Context.UnsignedLongLongTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +00001872 break;
Eli Friedman73397492009-03-03 06:41:03 +00001873 case 96:
1874 NewTy = S.Context.LongDoubleTy;
1875 break;
Eli Friedmanf98aba32009-02-13 02:31:07 +00001876 case 128:
1877 if (!IntegerMode) {
1878 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
1879 return;
1880 }
Anders Carlssonf5f7d862009-12-29 07:07:36 +00001881 if (OldTy->isSignedIntegerType())
1882 NewTy = S.Context.Int128Ty;
1883 else
1884 NewTy = S.Context.UnsignedInt128Ty;
Eli Friedman73397492009-03-03 06:41:03 +00001885 break;
Chris Lattnerfbf13472008-06-27 22:18:37 +00001886 }
1887
Eli Friedman73397492009-03-03 06:41:03 +00001888 if (ComplexMode) {
1889 NewTy = S.Context.getComplexType(NewTy);
Chris Lattnerfbf13472008-06-27 22:18:37 +00001890 }
1891
1892 // Install the new type.
John McCallba6a9bd2009-10-24 08:00:42 +00001893 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
1894 // FIXME: preserve existing source info.
John McCalla93c9342009-12-07 02:54:59 +00001895 TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy));
John McCallba6a9bd2009-10-24 08:00:42 +00001896 } else
Chris Lattnerfbf13472008-06-27 22:18:37 +00001897 cast<ValueDecl>(D)->setType(NewTy);
1898}
Chris Lattner0744e5f2008-06-29 00:23:49 +00001899
Mike Stump1feade82009-08-26 22:31:08 +00001900static void HandleNoDebugAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Anders Carlssond87df372009-02-13 06:46:13 +00001901 // check the attribute arguments.
1902 if (Attr.getNumArgs() > 0) {
1903 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
1904 return;
1905 }
Anders Carlssone896d982009-02-13 08:11:52 +00001906
Anders Carlsson5bab7882009-02-19 19:16:48 +00001907 if (!isFunctionOrMethod(d)) {
Anders Carlssond87df372009-02-13 06:46:13 +00001908 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Ted Kremenek5dc53c92009-05-13 21:07:32 +00001909 << Attr.getName() << 0 /*function*/;
Anders Carlssond87df372009-02-13 06:46:13 +00001910 return;
1911 }
Mike Stumpbf916502009-07-24 19:02:52 +00001912
Sean Huntcf807c42010-08-18 23:23:40 +00001913 d->addAttr(::new (S.Context) NoDebugAttr(Attr.getLoc(), S.Context));
Anders Carlssond87df372009-02-13 06:46:13 +00001914}
1915
Mike Stump1feade82009-08-26 22:31:08 +00001916static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Anders Carlsson5bab7882009-02-19 19:16:48 +00001917 // check the attribute arguments.
1918 if (Attr.getNumArgs() != 0) {
1919 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
1920 return;
1921 }
Mike Stumpbf916502009-07-24 19:02:52 +00001922
Chris Lattnerc5197432009-04-14 17:02:11 +00001923 if (!isa<FunctionDecl>(d)) {
Anders Carlsson5bab7882009-02-19 19:16:48 +00001924 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Ted Kremenek5dc53c92009-05-13 21:07:32 +00001925 << Attr.getName() << 0 /*function*/;
Anders Carlsson5bab7882009-02-19 19:16:48 +00001926 return;
1927 }
Mike Stumpbf916502009-07-24 19:02:52 +00001928
Sean Huntcf807c42010-08-18 23:23:40 +00001929 d->addAttr(::new (S.Context) NoInlineAttr(Attr.getLoc(), S.Context));
Anders Carlsson5bab7882009-02-19 19:16:48 +00001930}
1931
Chris Lattner7255a2d2010-06-22 00:03:40 +00001932static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr,
1933 Sema &S) {
1934 // check the attribute arguments.
1935 if (Attr.getNumArgs() != 0) {
1936 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
1937 return;
1938 }
1939
1940 if (!isa<FunctionDecl>(d)) {
1941 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
1942 << Attr.getName() << 0 /*function*/;
1943 return;
1944 }
1945
Sean Huntcf807c42010-08-18 23:23:40 +00001946 d->addAttr(::new (S.Context) NoInstrumentFunctionAttr(Attr.getLoc(), S.Context));
Chris Lattner7255a2d2010-06-22 00:03:40 +00001947}
1948
Chris Lattnercf2a7212009-04-20 19:12:28 +00001949static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner26e25542009-04-14 16:30:50 +00001950 // check the attribute arguments.
1951 if (Attr.getNumArgs() != 0) {
1952 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
1953 return;
1954 }
Mike Stumpbf916502009-07-24 19:02:52 +00001955
Chris Lattnerc5197432009-04-14 17:02:11 +00001956 FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
1957 if (Fn == 0) {
Chris Lattner26e25542009-04-14 16:30:50 +00001958 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Ted Kremenek5dc53c92009-05-13 21:07:32 +00001959 << Attr.getName() << 0 /*function*/;
Chris Lattner26e25542009-04-14 16:30:50 +00001960 return;
1961 }
Mike Stumpbf916502009-07-24 19:02:52 +00001962
Douglas Gregor0130f3c2009-10-27 21:01:01 +00001963 if (!Fn->isInlineSpecified()) {
Chris Lattnercf2a7212009-04-20 19:12:28 +00001964 S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
Chris Lattnerc5197432009-04-14 17:02:11 +00001965 return;
1966 }
Mike Stumpbf916502009-07-24 19:02:52 +00001967
Sean Huntcf807c42010-08-18 23:23:40 +00001968 d->addAttr(::new (S.Context) GNUInlineAttr(Attr.getLoc(), S.Context));
Chris Lattner26e25542009-04-14 16:30:50 +00001969}
1970
Abramo Bagnarae215f722010-04-30 13:10:51 +00001971static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) {
1972 // Diagnostic is emitted elsewhere: here we store the (valid) Attr
1973 // in the Decl node for syntactic reasoning, e.g., pretty-printing.
1974 assert(Attr.isInvalid() == false);
1975
1976 switch (Attr.getKind()) {
1977 case AttributeList::AT_fastcall:
Sean Huntcf807c42010-08-18 23:23:40 +00001978 d->addAttr(::new (S.Context) FastCallAttr(Attr.getLoc(), S.Context));
Abramo Bagnarae215f722010-04-30 13:10:51 +00001979 return;
1980 case AttributeList::AT_stdcall:
Sean Huntcf807c42010-08-18 23:23:40 +00001981 d->addAttr(::new (S.Context) StdCallAttr(Attr.getLoc(), S.Context));
Abramo Bagnarae215f722010-04-30 13:10:51 +00001982 return;
Douglas Gregorf813a2c2010-05-18 16:57:00 +00001983 case AttributeList::AT_thiscall:
Sean Huntcf807c42010-08-18 23:23:40 +00001984 d->addAttr(::new (S.Context) ThisCallAttr(Attr.getLoc(), S.Context));
Abramo Bagnarae215f722010-04-30 13:10:51 +00001985 case AttributeList::AT_cdecl:
Sean Huntcf807c42010-08-18 23:23:40 +00001986 d->addAttr(::new (S.Context) CDeclAttr(Attr.getLoc(), S.Context));
Abramo Bagnarae215f722010-04-30 13:10:51 +00001987 return;
1988 default:
1989 llvm_unreachable("unexpected attribute kind");
1990 return;
1991 }
1992}
1993
Fariborz Jahanianee760332009-03-27 18:38:55 +00001994static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) {
1995 // check the attribute arguments.
1996 if (Attr.getNumArgs() != 1) {
Eli Friedman55d3aaf2009-03-27 21:06:47 +00001997 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Fariborz Jahanianee760332009-03-27 18:38:55 +00001998 return;
1999 }
Eli Friedman55d3aaf2009-03-27 21:06:47 +00002000
Fariborz Jahanianee760332009-03-27 18:38:55 +00002001 if (!isFunctionOrMethod(d)) {
2002 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
Ted Kremenek5dc53c92009-05-13 21:07:32 +00002003 << Attr.getName() << 0 /*function*/;
Fariborz Jahanianee760332009-03-27 18:38:55 +00002004 return;
2005 }
Eli Friedman55d3aaf2009-03-27 21:06:47 +00002006
2007 Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0));
2008 llvm::APSInt NumParams(32);
Douglas Gregorac06a0e2010-05-18 23:01:22 +00002009 if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() ||
2010 !NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
Eli Friedman55d3aaf2009-03-27 21:06:47 +00002011 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
2012 << "regparm" << NumParamsExpr->getSourceRange();
2013 return;
2014 }
2015
Anton Korobeynikov264a76c2009-04-03 23:38:25 +00002016 if (S.Context.Target.getRegParmMax() == 0) {
2017 S.Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform)
Eli Friedman55d3aaf2009-03-27 21:06:47 +00002018 << NumParamsExpr->getSourceRange();
2019 return;
2020 }
2021
Anton Korobeynikov348f28a2009-04-04 10:27:50 +00002022 if (NumParams.getLimitedValue(255) > S.Context.Target.getRegParmMax()) {
Anton Korobeynikov264a76c2009-04-03 23:38:25 +00002023 S.Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number)
2024 << S.Context.Target.getRegParmMax() << NumParamsExpr->getSourceRange();
Eli Friedman55d3aaf2009-03-27 21:06:47 +00002025 return;
2026 }
2027
Sean Huntcf807c42010-08-18 23:23:40 +00002028 d->addAttr(::new (S.Context) RegparmAttr(Attr.getLoc(), S.Context,
2029 NumParams.getZExtValue()));
Fariborz Jahanianee760332009-03-27 18:38:55 +00002030}
2031
Sean Huntbbd37c62009-11-21 08:43:09 +00002032static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
2033 // check the attribute arguments.
2034 if (Attr.getNumArgs() != 0) {
2035 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
2036 return;
2037 }
2038
2039 if (!isa<CXXRecordDecl>(d)
2040 && (!isa<CXXMethodDecl>(d) || !cast<CXXMethodDecl>(d)->isVirtual())) {
2041 S.Diag(Attr.getLoc(),
2042 Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
2043 : diag::warn_attribute_wrong_decl_type)
2044 << Attr.getName() << 7 /*virtual method or class*/;
2045 return;
2046 }
Sean Hunt7725e672009-11-25 04:20:27 +00002047
2048 // FIXME: Conform to C++0x redeclaration rules.
2049
2050 if (d->getAttr<FinalAttr>()) {
2051 S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "final";
2052 return;
2053 }
Sean Huntbbd37c62009-11-21 08:43:09 +00002054
Sean Huntcf807c42010-08-18 23:23:40 +00002055 d->addAttr(::new (S.Context) FinalAttr(Attr.getLoc(), S.Context));
Sean Huntbbd37c62009-11-21 08:43:09 +00002056}
2057
Chris Lattner0744e5f2008-06-29 00:23:49 +00002058//===----------------------------------------------------------------------===//
Sean Hunt7725e672009-11-25 04:20:27 +00002059// C++0x member checking attributes
2060//===----------------------------------------------------------------------===//
2061
2062static void HandleBaseCheckAttr(Decl *d, const AttributeList &Attr, Sema &S) {
2063 if (Attr.getNumArgs() != 0) {
2064 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
2065 return;
2066 }
2067
2068 if (!isa<CXXRecordDecl>(d)) {
2069 S.Diag(Attr.getLoc(),
2070 Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
2071 : diag::warn_attribute_wrong_decl_type)
2072 << Attr.getName() << 9 /*class*/;
2073 return;
2074 }
2075
2076 if (d->getAttr<BaseCheckAttr>()) {
2077 S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "base_check";
2078 return;
2079 }
2080
Sean Huntcf807c42010-08-18 23:23:40 +00002081 d->addAttr(::new (S.Context) BaseCheckAttr(Attr.getLoc(), S.Context));
Sean Hunt7725e672009-11-25 04:20:27 +00002082}
2083
2084static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) {
2085 if (Attr.getNumArgs() != 0) {
2086 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
2087 return;
2088 }
2089
2090 if (!isa<RecordDecl>(d->getDeclContext())) {
2091 // FIXME: It's not the type that's the problem
2092 S.Diag(Attr.getLoc(),
2093 Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
2094 : diag::warn_attribute_wrong_decl_type)
2095 << Attr.getName() << 11 /*member*/;
2096 return;
2097 }
2098
2099 // FIXME: Conform to C++0x redeclaration rules.
2100
2101 if (d->getAttr<HidingAttr>()) {
2102 S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "hiding";
2103 return;
2104 }
2105
Sean Huntcf807c42010-08-18 23:23:40 +00002106 d->addAttr(::new (S.Context) HidingAttr(Attr.getLoc(), S.Context));
Sean Hunt7725e672009-11-25 04:20:27 +00002107}
2108
2109static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) {
2110 if (Attr.getNumArgs() != 0) {
2111 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
2112 return;
2113 }
2114
2115 if (!isa<CXXMethodDecl>(d) || !cast<CXXMethodDecl>(d)->isVirtual()) {
2116 // FIXME: It's not the type that's the problem
2117 S.Diag(Attr.getLoc(),
2118 Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
2119 : diag::warn_attribute_wrong_decl_type)
2120 << Attr.getName() << 10 /*virtual method*/;
2121 return;
2122 }
2123
2124 // FIXME: Conform to C++0x redeclaration rules.
2125
2126 if (d->getAttr<OverrideAttr>()) {
2127 S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "override";
2128 return;
2129 }
2130
Sean Huntcf807c42010-08-18 23:23:40 +00002131 d->addAttr(::new (S.Context) OverrideAttr(Attr.getLoc(), S.Context));
Sean Hunt7725e672009-11-25 04:20:27 +00002132}
2133
2134//===----------------------------------------------------------------------===//
Ted Kremenekb71368d2009-05-09 02:44:38 +00002135// Checker-specific attribute handlers.
2136//===----------------------------------------------------------------------===//
2137
2138static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr,
2139 Sema &S) {
2140
Ted Kremenek5dc53c92009-05-13 21:07:32 +00002141 QualType RetTy;
Mike Stumpbf916502009-07-24 19:02:52 +00002142
Ted Kremenek5dc53c92009-05-13 21:07:32 +00002143 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
2144 RetTy = MD->getResultType();
2145 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d))
2146 RetTy = FD->getResultType();
2147 else {
Ted Kremenek21531fa2009-08-19 23:56:48 +00002148 SourceLocation L = Attr.getLoc();
2149 S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type)
2150 << SourceRange(L, L) << Attr.getName() << 3 /* function or method */;
Ted Kremenekb71368d2009-05-09 02:44:38 +00002151 return;
2152 }
Mike Stumpbf916502009-07-24 19:02:52 +00002153
Ted Kremenek6217b802009-07-29 21:53:49 +00002154 if (!(S.Context.isObjCNSObjectType(RetTy) || RetTy->getAs<PointerType>()
John McCall183700f2009-09-21 23:43:11 +00002155 || RetTy->getAs<ObjCObjectPointerType>())) {
Ted Kremenek21531fa2009-08-19 23:56:48 +00002156 SourceLocation L = Attr.getLoc();
2157 S.Diag(d->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
2158 << SourceRange(L, L) << Attr.getName();
Mike Stumpbf916502009-07-24 19:02:52 +00002159 return;
Ted Kremenek5dc53c92009-05-13 21:07:32 +00002160 }
Mike Stumpbf916502009-07-24 19:02:52 +00002161
Ted Kremenekb71368d2009-05-09 02:44:38 +00002162 switch (Attr.getKind()) {
2163 default:
2164 assert(0 && "invalid ownership attribute");
2165 return;
Ted Kremenek31c780d2010-02-18 00:05:45 +00002166 case AttributeList::AT_cf_returns_not_retained:
Sean Huntcf807c42010-08-18 23:23:40 +00002167 d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(Attr.getLoc(), S.Context));
Ted Kremenek31c780d2010-02-18 00:05:45 +00002168 return;
2169 case AttributeList::AT_ns_returns_not_retained:
Sean Huntcf807c42010-08-18 23:23:40 +00002170 d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(Attr.getLoc(), S.Context));
Ted Kremenek31c780d2010-02-18 00:05:45 +00002171 return;
Ted Kremenekb71368d2009-05-09 02:44:38 +00002172 case AttributeList::AT_cf_returns_retained:
Sean Huntcf807c42010-08-18 23:23:40 +00002173 d->addAttr(::new (S.Context) CFReturnsRetainedAttr(Attr.getLoc(), S.Context));
Ted Kremenekb71368d2009-05-09 02:44:38 +00002174 return;
2175 case AttributeList::AT_ns_returns_retained:
Sean Huntcf807c42010-08-18 23:23:40 +00002176 d->addAttr(::new (S.Context) NSReturnsRetainedAttr(Attr.getLoc(), S.Context));
Ted Kremenekb71368d2009-05-09 02:44:38 +00002177 return;
2178 };
2179}
2180
Charles Davisf0122fe2010-02-16 18:27:26 +00002181static bool isKnownDeclSpecAttr(const AttributeList &Attr) {
2182 return Attr.getKind() == AttributeList::AT_dllimport ||
2183 Attr.getKind() == AttributeList::AT_dllexport;
2184}
2185
Ted Kremenekb71368d2009-05-09 02:44:38 +00002186//===----------------------------------------------------------------------===//
Chris Lattner0744e5f2008-06-29 00:23:49 +00002187// Top Level Sema Entry Points
2188//===----------------------------------------------------------------------===//
2189
Sebastian Redla89d82c2008-12-21 19:24:58 +00002190/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
Chris Lattner803d0802008-06-29 00:43:07 +00002191/// the attribute applies to decls. If the attribute is a type attribute, just
Sean Huntbbd37c62009-11-21 08:43:09 +00002192/// silently ignore it if a GNU attribute. FIXME: Applying a C++0x attribute to
2193/// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4).
Mike Stumpbf916502009-07-24 19:02:52 +00002194static void ProcessDeclAttribute(Scope *scope, Decl *D,
2195 const AttributeList &Attr, Sema &S) {
Abramo Bagnarae215f722010-04-30 13:10:51 +00002196 if (Attr.isInvalid())
2197 return;
2198
Charles Davisf0122fe2010-02-16 18:27:26 +00002199 if (Attr.isDeclspecAttribute() && !isKnownDeclSpecAttr(Attr))
2200 // FIXME: Try to deal with other __declspec attributes!
Eli Friedman290eeb02009-06-08 23:27:34 +00002201 return;
Chris Lattner803d0802008-06-29 00:43:07 +00002202 switch (Attr.getKind()) {
Ted Kremenek63e5d7c2010-02-18 03:08:58 +00002203 case AttributeList::AT_IBAction: HandleIBAction(D, Attr, S); break;
Ted Kremenek857e9182010-05-19 17:38:06 +00002204 case AttributeList::AT_IBOutlet: HandleIBOutlet(D, Attr, S); break;
2205 case AttributeList::AT_IBOutletCollection:
2206 HandleIBOutletCollection(D, Attr, S); break;
Chris Lattner803d0802008-06-29 00:43:07 +00002207 case AttributeList::AT_address_space:
Fariborz Jahanianba372b82009-02-18 17:52:36 +00002208 case AttributeList::AT_objc_gc:
John Thompson6e132aa2009-12-04 21:51:28 +00002209 case AttributeList::AT_vector_size:
Mike Stumpbf916502009-07-24 19:02:52 +00002210 // Ignore these, these are type attributes, handled by
2211 // ProcessTypeAttributes.
Chris Lattner803d0802008-06-29 00:43:07 +00002212 break;
Sean Hunt7725e672009-11-25 04:20:27 +00002213 case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break;
2214 case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break;
Mike Stumpbf916502009-07-24 19:02:52 +00002215 case AttributeList::AT_always_inline:
Daniel Dunbaraf668b02008-10-28 00:17:57 +00002216 HandleAlwaysInlineAttr (D, Attr, S); break;
Ted Kremenekb7252322009-04-10 00:01:14 +00002217 case AttributeList::AT_analyzer_noreturn:
Mike Stumpbf916502009-07-24 19:02:52 +00002218 HandleAnalyzerNoReturnAttr (D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002219 case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break;
2220 case AttributeList::AT_base_check: HandleBaseCheckAttr (D, Attr, S); break;
Sean Huntbbd37c62009-11-21 08:43:09 +00002221 case AttributeList::AT_carries_dependency:
Sean Hunt7725e672009-11-25 04:20:27 +00002222 HandleDependencyAttr (D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002223 case AttributeList::AT_constructor: HandleConstructorAttr (D, Attr, S); break;
2224 case AttributeList::AT_deprecated: HandleDeprecatedAttr (D, Attr, S); break;
2225 case AttributeList::AT_destructor: HandleDestructorAttr (D, Attr, S); break;
Chris Lattner803d0802008-06-29 00:43:07 +00002226 case AttributeList::AT_ext_vector_type:
Douglas Gregor9cdda0c2009-06-17 21:51:59 +00002227 HandleExtVectorTypeAttr(scope, D, Attr, S);
Chris Lattner803d0802008-06-29 00:43:07 +00002228 break;
Sean Hunt7725e672009-11-25 04:20:27 +00002229 case AttributeList::AT_final: HandleFinalAttr (D, Attr, S); break;
2230 case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break;
2231 case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break;
2232 case AttributeList::AT_gnu_inline: HandleGNUInlineAttr (D, Attr, S); break;
2233 case AttributeList::AT_hiding: HandleHidingAttr (D, Attr, S); break;
2234 case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break;
2235 case AttributeList::AT_malloc: HandleMallocAttr (D, Attr, S); break;
2236 case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break;
Ted Kremenekdd0e4902010-07-31 01:52:11 +00002237 case AttributeList::AT_ownership_returns:
2238 case AttributeList::AT_ownership_takes:
2239 case AttributeList::AT_ownership_holds:
2240 HandleOwnershipAttr (D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002241 case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break;
2242 case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break;
2243 case AttributeList::AT_override: HandleOverrideAttr (D, Attr, S); break;
John Thompson35cc9622010-08-09 21:53:52 +00002244 case AttributeList::AT_vecreturn: HandleVecReturnAttr (D, Attr, S); break;
Ted Kremenekb71368d2009-05-09 02:44:38 +00002245
2246 // Checker-specific.
Ted Kremenek31c780d2010-02-18 00:05:45 +00002247 case AttributeList::AT_ns_returns_not_retained:
2248 case AttributeList::AT_cf_returns_not_retained:
Ted Kremenekb71368d2009-05-09 02:44:38 +00002249 case AttributeList::AT_ns_returns_retained:
2250 case AttributeList::AT_cf_returns_retained:
2251 HandleNSReturnsRetainedAttr(D, Attr, S); break;
2252
Nate Begeman6f3d8382009-06-26 06:32:41 +00002253 case AttributeList::AT_reqd_wg_size:
2254 HandleReqdWorkGroupSize(D, Attr, S); break;
2255
Fariborz Jahanian521f12d2010-06-18 21:44:06 +00002256 case AttributeList::AT_init_priority:
2257 HandleInitPriorityAttr(D, Attr, S); break;
2258
Sean Hunt7725e672009-11-25 04:20:27 +00002259 case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break;
2260 case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002261 case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break;
2262 case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break;
2263 case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002264 case AttributeList::AT_visibility: HandleVisibilityAttr (D, Attr, S); break;
Chris Lattner026dc962009-02-14 07:37:35 +00002265 case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S);
2266 break;
Sean Hunt7725e672009-11-25 04:20:27 +00002267 case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break;
Rafael Espindola11e8ce72010-02-23 22:00:30 +00002268 case AttributeList::AT_weakref: HandleWeakRefAttr (D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002269 case AttributeList::AT_weak_import: HandleWeakImportAttr (D, Attr, S); break;
Chris Lattner803d0802008-06-29 00:43:07 +00002270 case AttributeList::AT_transparent_union:
2271 HandleTransparentUnionAttr(D, Attr, S);
2272 break;
Chris Lattner0db29ec2009-02-14 08:09:34 +00002273 case AttributeList::AT_objc_exception:
2274 HandleObjCExceptionAttr(D, Attr, S);
2275 break;
Douglas Gregorf9201e02009-02-11 23:02:49 +00002276 case AttributeList::AT_overloadable:HandleOverloadableAttr(D, Attr, S); break;
Sean Hunt7725e672009-11-25 04:20:27 +00002277 case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break;
2278 case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break;
2279 case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break;
2280 case AttributeList::AT_const: HandleConstAttr (D, Attr, S); break;
2281 case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break;
2282 case AttributeList::AT_cleanup: HandleCleanupAttr (D, Attr, S); break;
2283 case AttributeList::AT_nodebug: HandleNoDebugAttr (D, Attr, S); break;
2284 case AttributeList::AT_noinline: HandleNoInlineAttr (D, Attr, S); break;
2285 case AttributeList::AT_regparm: HandleRegparmAttr (D, Attr, S); break;
Mike Stumpbf916502009-07-24 19:02:52 +00002286 case AttributeList::IgnoredAttribute:
Anders Carlsson05f8e472009-02-13 08:16:43 +00002287 // Just ignore
2288 break;
Chris Lattner7255a2d2010-06-22 00:03:40 +00002289 case AttributeList::AT_no_instrument_function: // Interacts with -pg.
2290 HandleNoInstrumentFunctionAttr(D, Attr, S);
2291 break;
John McCall04a67a62010-02-05 21:31:56 +00002292 case AttributeList::AT_stdcall:
2293 case AttributeList::AT_cdecl:
2294 case AttributeList::AT_fastcall:
Douglas Gregorf813a2c2010-05-18 16:57:00 +00002295 case AttributeList::AT_thiscall:
Abramo Bagnarae215f722010-04-30 13:10:51 +00002296 HandleCallConvAttr(D, Attr, S);
John McCall04a67a62010-02-05 21:31:56 +00002297 break;
Chris Lattner803d0802008-06-29 00:43:07 +00002298 default:
Anton Korobeynikov82d0a412010-01-10 12:58:08 +00002299 // Ask target about the attribute.
2300 const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
2301 if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S))
Chandler Carruth7d5c45e2010-07-08 09:42:26 +00002302 S.Diag(Attr.getLoc(), diag::warn_unknown_attribute_ignored)
2303 << Attr.getName();
Chris Lattner803d0802008-06-29 00:43:07 +00002304 break;
2305 }
2306}
2307
2308/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
2309/// attribute list to the specified decl, ignoring any type attributes.
Douglas Gregor9cdda0c2009-06-17 21:51:59 +00002310void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList) {
Rafael Espindola11e8ce72010-02-23 22:00:30 +00002311 for (const AttributeList* l = AttrList; l; l = l->getNext()) {
2312 ProcessDeclAttribute(S, D, *l, *this);
2313 }
2314
2315 // GCC accepts
2316 // static int a9 __attribute__((weakref));
2317 // but that looks really pointless. We reject it.
2318 if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
2319 Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) <<
Ted Kremenekdd0e4902010-07-31 01:52:11 +00002320 dyn_cast<NamedDecl>(D)->getNameAsString();
Rafael Espindola11e8ce72010-02-23 22:00:30 +00002321 return;
Chris Lattner803d0802008-06-29 00:43:07 +00002322 }
2323}
2324
Ryan Flynne25ff832009-07-30 03:15:39 +00002325/// DeclClonePragmaWeak - clone existing decl (maybe definition),
2326/// #pragma weak needs a non-definition decl and source may not have one
Mike Stump1eb44332009-09-09 15:08:12 +00002327NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) {
Ryan Flynn7b1fdbd2009-07-31 02:52:19 +00002328 assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
Ryan Flynne25ff832009-07-30 03:15:39 +00002329 NamedDecl *NewD = 0;
2330 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
2331 NewD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(),
2332 FD->getLocation(), DeclarationName(II),
John McCalla93c9342009-12-07 02:54:59 +00002333 FD->getType(), FD->getTypeSourceInfo());
John McCallb6217662010-03-15 10:12:16 +00002334 if (FD->getQualifier()) {
2335 FunctionDecl *NewFD = cast<FunctionDecl>(NewD);
2336 NewFD->setQualifierInfo(FD->getQualifier(), FD->getQualifierRange());
2337 }
Ryan Flynne25ff832009-07-30 03:15:39 +00002338 } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) {
2339 NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
2340 VD->getLocation(), II,
John McCalla93c9342009-12-07 02:54:59 +00002341 VD->getType(), VD->getTypeSourceInfo(),
Douglas Gregor16573fa2010-04-19 22:54:31 +00002342 VD->getStorageClass(),
2343 VD->getStorageClassAsWritten());
John McCallb6217662010-03-15 10:12:16 +00002344 if (VD->getQualifier()) {
2345 VarDecl *NewVD = cast<VarDecl>(NewD);
2346 NewVD->setQualifierInfo(VD->getQualifier(), VD->getQualifierRange());
2347 }
Ryan Flynne25ff832009-07-30 03:15:39 +00002348 }
2349 return NewD;
2350}
2351
2352/// DeclApplyPragmaWeak - A declaration (maybe definition) needs #pragma weak
2353/// applied to it, possibly with an alias.
Ryan Flynn7b1fdbd2009-07-31 02:52:19 +00002354void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
Chris Lattnerc4f1fb12009-09-08 18:10:11 +00002355 if (W.getUsed()) return; // only do this once
2356 W.setUsed(true);
2357 if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
2358 IdentifierInfo *NDId = ND->getIdentifier();
2359 NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias());
Sean Huntcf807c42010-08-18 23:23:40 +00002360 NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context,
2361 NDId->getName()));
2362 NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
Chris Lattnerc4f1fb12009-09-08 18:10:11 +00002363 WeakTopLevelDecl.push_back(NewD);
2364 // FIXME: "hideous" code from Sema::LazilyCreateBuiltin
2365 // to insert Decl at TU scope, sorry.
2366 DeclContext *SavedContext = CurContext;
2367 CurContext = Context.getTranslationUnitDecl();
2368 PushOnScopeChains(NewD, S);
2369 CurContext = SavedContext;
2370 } else { // just add weak to existing
Sean Huntcf807c42010-08-18 23:23:40 +00002371 ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
Ryan Flynne25ff832009-07-30 03:15:39 +00002372 }
2373}
2374
Chris Lattner0744e5f2008-06-29 00:23:49 +00002375/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
2376/// it, apply them to D. This is a bit tricky because PD can have attributes
2377/// specified in many different places, and we need to find and apply them all.
Douglas Gregor9cdda0c2009-06-17 21:51:59 +00002378void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
Ryan Flynne25ff832009-07-30 03:15:39 +00002379 // Handle #pragma weak
2380 if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
2381 if (ND->hasLinkage()) {
2382 WeakInfo W = WeakUndeclaredIdentifiers.lookup(ND->getIdentifier());
2383 if (W != WeakInfo()) {
Ryan Flynn7b1fdbd2009-07-31 02:52:19 +00002384 // Identifier referenced by #pragma weak before it was declared
2385 DeclApplyPragmaWeak(S, ND, W);
Ryan Flynne25ff832009-07-30 03:15:39 +00002386 WeakUndeclaredIdentifiers[ND->getIdentifier()] = W;
2387 }
2388 }
2389 }
2390
Chris Lattner0744e5f2008-06-29 00:23:49 +00002391 // Apply decl attributes from the DeclSpec if present.
2392 if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
Douglas Gregor9cdda0c2009-06-17 21:51:59 +00002393 ProcessDeclAttributeList(S, D, Attrs);
Mike Stumpbf916502009-07-24 19:02:52 +00002394
Chris Lattner0744e5f2008-06-29 00:23:49 +00002395 // Walk the declarator structure, applying decl attributes that were in a type
2396 // position to the decl itself. This handles cases like:
2397 // int *__attr__(x)** D;
2398 // when X is a decl attribute.
2399 for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
2400 if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
Douglas Gregor9cdda0c2009-06-17 21:51:59 +00002401 ProcessDeclAttributeList(S, D, Attrs);
Mike Stumpbf916502009-07-24 19:02:52 +00002402
Chris Lattner0744e5f2008-06-29 00:23:49 +00002403 // Finally, apply any attributes on the decl itself.
2404 if (const AttributeList *Attrs = PD.getAttributes())
Douglas Gregor9cdda0c2009-06-17 21:51:59 +00002405 ProcessDeclAttributeList(S, D, Attrs);
Chris Lattner0744e5f2008-06-29 00:23:49 +00002406}
John McCall54abf7d2009-11-04 02:18:39 +00002407
2408/// PushParsingDeclaration - Enter a new "scope" of deprecation
2409/// warnings.
2410///
2411/// The state token we use is the start index of this scope
2412/// on the warning stack.
2413Action::ParsingDeclStackState Sema::PushParsingDeclaration() {
2414 ParsingDeclDepth++;
John McCall2f514482010-01-27 03:50:35 +00002415 return (ParsingDeclStackState) DelayedDiagnostics.size();
2416}
2417
John McCalld226f652010-08-21 09:40:31 +00002418void Sema::PopParsingDeclaration(ParsingDeclStackState S, Decl *D) {
John McCall2f514482010-01-27 03:50:35 +00002419 assert(ParsingDeclDepth > 0 && "empty ParsingDeclaration stack");
2420 ParsingDeclDepth--;
2421
2422 if (DelayedDiagnostics.empty())
2423 return;
2424
2425 unsigned SavedIndex = (unsigned) S;
2426 assert(SavedIndex <= DelayedDiagnostics.size() &&
2427 "saved index is out of bounds");
2428
John McCall58e6f342010-03-16 05:22:47 +00002429 unsigned E = DelayedDiagnostics.size();
2430
John McCall2f514482010-01-27 03:50:35 +00002431 // We only want to actually emit delayed diagnostics when we
2432 // successfully parsed a decl.
John McCall2f514482010-01-27 03:50:35 +00002433 if (D) {
2434 // We really do want to start with 0 here. We get one push for a
2435 // decl spec and another for each declarator; in a decl group like:
2436 // deprecated_typedef foo, *bar, baz();
2437 // only the declarator pops will be passed decls. This is correct;
2438 // we really do need to consider delayed diagnostics from the decl spec
2439 // for each of the different declarations.
John McCall58e6f342010-03-16 05:22:47 +00002440 for (unsigned I = 0; I != E; ++I) {
John McCall2f514482010-01-27 03:50:35 +00002441 if (DelayedDiagnostics[I].Triggered)
2442 continue;
2443
2444 switch (DelayedDiagnostics[I].Kind) {
2445 case DelayedDiagnostic::Deprecation:
2446 HandleDelayedDeprecationCheck(DelayedDiagnostics[I], D);
2447 break;
2448
2449 case DelayedDiagnostic::Access:
2450 HandleDelayedAccessCheck(DelayedDiagnostics[I], D);
2451 break;
2452 }
2453 }
2454 }
2455
John McCall58e6f342010-03-16 05:22:47 +00002456 // Destroy all the delayed diagnostics we're about to pop off.
2457 for (unsigned I = SavedIndex; I != E; ++I)
2458 DelayedDiagnostics[I].destroy();
2459
John McCall2f514482010-01-27 03:50:35 +00002460 DelayedDiagnostics.set_size(SavedIndex);
John McCall54abf7d2009-11-04 02:18:39 +00002461}
2462
2463static bool isDeclDeprecated(Decl *D) {
2464 do {
2465 if (D->hasAttr<DeprecatedAttr>())
2466 return true;
2467 } while ((D = cast_or_null<Decl>(D->getDeclContext())));
2468 return false;
2469}
2470
John McCall2f514482010-01-27 03:50:35 +00002471void Sema::HandleDelayedDeprecationCheck(Sema::DelayedDiagnostic &DD,
2472 Decl *Ctx) {
2473 if (isDeclDeprecated(Ctx))
John McCall54abf7d2009-11-04 02:18:39 +00002474 return;
2475
John McCall2f514482010-01-27 03:50:35 +00002476 DD.Triggered = true;
2477 Diag(DD.Loc, diag::warn_deprecated)
2478 << DD.DeprecationData.Decl->getDeclName();
John McCall54abf7d2009-11-04 02:18:39 +00002479}
2480
2481void Sema::EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc) {
2482 // Delay if we're currently parsing a declaration.
2483 if (ParsingDeclDepth) {
John McCall2f514482010-01-27 03:50:35 +00002484 DelayedDiagnostics.push_back(DelayedDiagnostic::makeDeprecation(Loc, D));
John McCall54abf7d2009-11-04 02:18:39 +00002485 return;
2486 }
2487
2488 // Otherwise, don't warn if our current context is deprecated.
2489 if (isDeclDeprecated(cast<Decl>(CurContext)))
2490 return;
2491
2492 Diag(Loc, diag::warn_deprecated) << D->getDeclName();
2493}