blob: 9a38f6cf351e9b3f26bff4b7ead908753b6517d6 [file] [log] [blame]
Chris Lattner6953a072008-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
14#include "Sema.h"
15#include "clang/AST/ASTContext.h"
Chris Lattnerdc789562008-06-27 22:18:37 +000016#include "clang/Basic/TargetInfo.h"
Ted Kremenek26151d12008-07-22 16:56:21 +000017#include <llvm/ADT/StringExtras.h>
Chris Lattner6953a072008-06-26 18:38:35 +000018using namespace clang;
19
Chris Lattner2024f0a2008-06-29 00:16:31 +000020//===----------------------------------------------------------------------===//
21// Helper functions
22//===----------------------------------------------------------------------===//
23
Chris Lattner6953a072008-06-26 18:38:35 +000024static const FunctionTypeProto *getFunctionProto(Decl *d) {
25 QualType Ty;
Chris Lattner6953a072008-06-26 18:38:35 +000026 if (ValueDecl *decl = dyn_cast<ValueDecl>(d))
27 Ty = decl->getType();
28 else if (FieldDecl *decl = dyn_cast<FieldDecl>(d))
29 Ty = decl->getType();
30 else if (TypedefDecl* decl = dyn_cast<TypedefDecl>(d))
31 Ty = decl->getUnderlyingType();
32 else
33 return 0;
34
35 if (Ty->isFunctionPointerType())
36 Ty = Ty->getAsPointerType()->getPointeeType();
37
38 if (const FunctionType *FnTy = Ty->getAsFunctionType())
39 return dyn_cast<FunctionTypeProto>(FnTy->getAsFunctionType());
40
41 return 0;
42}
43
44static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
45 if (!T->isPointerType())
46 return false;
47
48 T = T->getAsPointerType()->getPointeeType().getCanonicalType();
49 ObjCInterfaceType* ClsT = dyn_cast<ObjCInterfaceType>(T.getTypePtr());
50
51 if (!ClsT)
52 return false;
53
54 IdentifierInfo* ClsName = ClsT->getDecl()->getIdentifier();
55
56 // FIXME: Should we walk the chain of classes?
57 return ClsName == &Ctx.Idents.get("NSString") ||
58 ClsName == &Ctx.Idents.get("NSMutableString");
59}
60
Chris Lattner2024f0a2008-06-29 00:16:31 +000061//===----------------------------------------------------------------------===//
Chris Lattner2024f0a2008-06-29 00:16:31 +000062// Attribute Implementations
63//===----------------------------------------------------------------------===//
64
Chris Lattner703c52d2008-06-29 00:43:07 +000065static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr,
66 Sema &S) {
Chris Lattner1c151132008-06-28 23:36:30 +000067 TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
68 if (tDecl == 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +000069 S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
Chris Lattner1c151132008-06-28 23:36:30 +000070 return;
Chris Lattner6953a072008-06-26 18:38:35 +000071 }
72
Chris Lattner6953a072008-06-26 18:38:35 +000073 QualType curType = tDecl->getUnderlyingType();
74 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +000075 if (Attr.getNumArgs() != 1) {
Chris Lattner703c52d2008-06-29 00:43:07 +000076 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
77 std::string("1"));
Chris Lattner6953a072008-06-26 18:38:35 +000078 return;
79 }
Chris Lattner1c151132008-06-28 23:36:30 +000080 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +000081 llvm::APSInt vecSize(32);
Chris Lattner703c52d2008-06-29 00:43:07 +000082 if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
83 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
84 "ext_vector_type", sizeExpr->getSourceRange());
Chris Lattner6953a072008-06-26 18:38:35 +000085 return;
86 }
87 // unlike gcc's vector_size attribute, we do not allow vectors to be defined
88 // in conjunction with complex types (pointers, arrays, functions, etc.).
89 Type *canonType = curType.getCanonicalType().getTypePtr();
90 if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
Chris Lattner703c52d2008-06-29 00:43:07 +000091 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
92 curType.getCanonicalType().getAsString());
Chris Lattner6953a072008-06-26 18:38:35 +000093 return;
94 }
95 // unlike gcc's vector_size attribute, the size is specified as the
96 // number of elements, not the number of bytes.
97 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
98
99 if (vectorSize == 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000100 S.Diag(Attr.getLoc(), diag::err_attribute_zero_size,
101 sizeExpr->getSourceRange());
Chris Lattner6953a072008-06-26 18:38:35 +0000102 return;
103 }
104 // Instantiate/Install the vector type, the number of elements is > 0.
Chris Lattner703c52d2008-06-29 00:43:07 +0000105 tDecl->setUnderlyingType(S.Context.getExtVectorType(curType, vectorSize));
Chris Lattner6953a072008-06-26 18:38:35 +0000106 // Remember this typedef decl, we will need it later for diagnostics.
Chris Lattner703c52d2008-06-29 00:43:07 +0000107 S.ExtVectorDecls.push_back(tDecl);
Chris Lattner6953a072008-06-26 18:38:35 +0000108}
109
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000110
111/// HandleVectorSizeAttribute - this attribute is only applicable to
112/// integral and float scalars, although arrays, pointers, and function
113/// return values are allowed in conjunction with this construct. Aggregates
114/// with this attribute are invalid, even if they are of the same size as a
115/// corresponding scalar.
116/// The raw attribute should contain precisely 1 argument, the vector size
117/// for the variable, measured in bytes. If curType and rawAttr are well
118/// formed, this routine will return a new vector type.
Chris Lattner703c52d2008-06-29 00:43:07 +0000119static void HandleVectorSizeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000120 QualType CurType;
121 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
122 CurType = VD->getType();
123 else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
124 CurType = TD->getUnderlyingType();
125 else {
Chris Lattner703c52d2008-06-29 00:43:07 +0000126 S.Diag(D->getLocation(), diag::err_attr_wrong_decl,
127 std::string("vector_size"),
128 SourceRange(Attr.getLoc(), Attr.getLoc()));
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000129 return;
130 }
131
132 // Check the attribute arugments.
Chris Lattner1c151132008-06-28 23:36:30 +0000133 if (Attr.getNumArgs() != 1) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000134 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
135 std::string("1"));
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000136 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000137 }
Chris Lattner1c151132008-06-28 23:36:30 +0000138 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000139 llvm::APSInt vecSize(32);
Chris Lattner703c52d2008-06-29 00:43:07 +0000140 if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
141 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
142 "vector_size", sizeExpr->getSourceRange());
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000143 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000144 }
145 // navigate to the base type - we need to provide for vector pointers,
146 // vector arrays, and functions returning vectors.
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000147 Type *canonType = CurType.getCanonicalType().getTypePtr();
Chris Lattner6953a072008-06-26 18:38:35 +0000148
149 if (canonType->isPointerType() || canonType->isArrayType() ||
150 canonType->isFunctionType()) {
151 assert(0 && "HandleVector(): Complex type construction unimplemented");
152 /* FIXME: rebuild the type from the inside out, vectorizing the inner type.
153 do {
154 if (PointerType *PT = dyn_cast<PointerType>(canonType))
155 canonType = PT->getPointeeType().getTypePtr();
156 else if (ArrayType *AT = dyn_cast<ArrayType>(canonType))
157 canonType = AT->getElementType().getTypePtr();
158 else if (FunctionType *FT = dyn_cast<FunctionType>(canonType))
159 canonType = FT->getResultType().getTypePtr();
160 } while (canonType->isPointerType() || canonType->isArrayType() ||
161 canonType->isFunctionType());
162 */
163 }
164 // the base type must be integer or float.
165 if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000166 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
167 CurType.getCanonicalType().getAsString());
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000168 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000169 }
Chris Lattner703c52d2008-06-29 00:43:07 +0000170 unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
Chris Lattner6953a072008-06-26 18:38:35 +0000171 // vecSize is specified in bytes - convert to bits.
172 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
173
174 // the vector size needs to be an integral multiple of the type size.
175 if (vectorSize % typeSize) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000176 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size,
177 sizeExpr->getSourceRange());
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000178 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000179 }
180 if (vectorSize == 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000181 S.Diag(Attr.getLoc(), diag::err_attribute_zero_size,
182 sizeExpr->getSourceRange());
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000183 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000184 }
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000185
186 // Success! Instantiate the vector type, the number of elements is > 0, and
187 // not required to be a power of 2, unlike GCC.
Chris Lattner703c52d2008-06-29 00:43:07 +0000188 CurType = S.Context.getVectorType(CurType, vectorSize/typeSize);
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000189
190 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
191 VD->setType(CurType);
192 else
193 cast<TypedefDecl>(D)->setUnderlyingType(CurType);
Chris Lattner6953a072008-06-26 18:38:35 +0000194}
195
Chris Lattner703c52d2008-06-29 00:43:07 +0000196static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000197 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000198 if (Attr.getNumArgs() > 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000199 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
200 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000201 return;
202 }
203
204 if (TagDecl *TD = dyn_cast<TagDecl>(d))
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000205 TD->addAttr(new PackedAttr());
Chris Lattner6953a072008-06-26 18:38:35 +0000206 else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
207 // If the alignment is less than or equal to 8 bits, the packed attribute
208 // has no effect.
209 if (!FD->getType()->isIncompleteType() &&
Chris Lattner703c52d2008-06-29 00:43:07 +0000210 S.Context.getTypeAlign(FD->getType()) <= 8)
211 S.Diag(Attr.getLoc(),
212 diag::warn_attribute_ignored_for_field_of_type,
213 Attr.getName()->getName(), FD->getType().getAsString());
Chris Lattner6953a072008-06-26 18:38:35 +0000214 else
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000215 FD->addAttr(new PackedAttr());
Chris Lattner6953a072008-06-26 18:38:35 +0000216 } else
Chris Lattner703c52d2008-06-29 00:43:07 +0000217 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored,
218 Attr.getName()->getName());
Chris Lattner6953a072008-06-26 18:38:35 +0000219}
220
Ted Kremenek4e5bb122008-07-15 22:26:48 +0000221static void HandleIBOutletAttr(Decl *d, const AttributeList &Attr, Sema &S) {
222 // check the attribute arguments.
223 if (Attr.getNumArgs() > 0) {
224 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
225 std::string("0"));
226 return;
227 }
228
229 // The IBOutlet attribute only applies to instance variables of Objective-C
230 // classes.
231 if (ObjCIvarDecl *ID = dyn_cast<ObjCIvarDecl>(d))
232 ID->addAttr(new IBOutletAttr());
233 else
234 S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet_non_ivar);
235}
236
Ted Kremenekc0af2542008-07-21 21:53:04 +0000237static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
238
239 // GCC ignores the nonnull attribute on K&R style function
240 // prototypes, so we ignore it as well
241 const FunctionTypeProto *proto = getFunctionProto(d);
242
243 if (!proto) {
244 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
245 "nonnull", "function");
246 return;
247 }
248
249 unsigned NumArgs = proto->getNumArgs();
250
251 // The nonnull attribute only applies to pointers.
252 llvm::SmallVector<unsigned, 10> NonNullArgs;
253
254 for (AttributeList::arg_iterator I=Attr.arg_begin(),
255 E=Attr.arg_end(); I!=E; ++I) {
256
257
258 // The argument must be an integer constant expression.
259 Expr *Ex = static_cast<Expr *>(Attr.getArg(0));
260 llvm::APSInt ArgNum(32);
261 if (!Ex->isIntegerConstantExpr(ArgNum, S.Context)) {
262 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
263 "nonnull", Ex->getSourceRange());
264 return;
265 }
266
267 unsigned x = (unsigned) ArgNum.getZExtValue();
268
269 if (x < 1 || x > NumArgs) {
270 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Ted Kremenek26151d12008-07-22 16:56:21 +0000271 "nonnull", llvm::utostr_32(I.getArgNum()), Ex->getSourceRange());
Ted Kremenekc0af2542008-07-21 21:53:04 +0000272 return;
273 }
Ted Kremenek178cee22008-07-21 22:09:15 +0000274
275 --x;
Ted Kremenekc0af2542008-07-21 21:53:04 +0000276
277 // Is the function argument a pointer type?
278 if (!proto->getArgType(x).getCanonicalType()->isPointerType()) {
279 // FIXME: Should also highlight argument in decl.
280 S.Diag(Attr.getLoc(), diag::err_nonnull_pointers_only,
281 "nonnull", Ex->getSourceRange());
282 return;
283 }
284
285 NonNullArgs.push_back(x);
286 }
287
288 if (!NonNullArgs.empty()) {
289 unsigned* start = &NonNullArgs[0];
290 unsigned size = NonNullArgs.size();
291 std::sort(start, start + size);
292 d->addAttr(new NonNullAttr(start, size));
293 }
294 else
295 d->addAttr(new NonNullAttr());
296}
297
Chris Lattner703c52d2008-06-29 00:43:07 +0000298static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000299 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000300 if (Attr.getNumArgs() != 1) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000301 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
302 std::string("1"));
Chris Lattner6953a072008-06-26 18:38:35 +0000303 return;
304 }
305
Chris Lattner1c151132008-06-28 23:36:30 +0000306 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000307 Arg = Arg->IgnoreParenCasts();
308 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
309
310 if (Str == 0 || Str->isWide()) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000311 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
312 "alias", std::string("1"));
Chris Lattner6953a072008-06-26 18:38:35 +0000313 return;
314 }
315
316 const char *Alias = Str->getStrData();
317 unsigned AliasLen = Str->getByteLength();
318
319 // FIXME: check if target symbol exists in current file
320
321 d->addAttr(new AliasAttr(std::string(Alias, AliasLen)));
322}
323
Chris Lattner703c52d2008-06-29 00:43:07 +0000324static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000325 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000326 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000327 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
328 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000329 return;
330 }
331
332 FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
Chris Lattner6953a072008-06-26 18:38:35 +0000333 if (!Fn) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000334 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
335 "noreturn", "function");
Chris Lattner6953a072008-06-26 18:38:35 +0000336 return;
337 }
338
339 d->addAttr(new NoReturnAttr());
340}
341
Ted Kremenekce13e1e2008-07-25 04:39:19 +0000342static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
343 // check the attribute arguments.
344 if (Attr.getNumArgs() != 0) {
345 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
346 std::string("0"));
347 return;
348 }
349
350 VarDecl *VD = dyn_cast<VarDecl>(d);
351
352 if (!VD) {
353 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
354 "unused", "variable");
355 return;
356 }
357
358 d->addAttr(new UnusedAttr());
359}
360
Chris Lattner703c52d2008-06-29 00:43:07 +0000361static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000362 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000363 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000364 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
365 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000366 return;
367 }
368
369 d->addAttr(new DeprecatedAttr());
370}
371
Chris Lattner703c52d2008-06-29 00:43:07 +0000372static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000373 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000374 if (Attr.getNumArgs() != 1) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000375 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
376 std::string("1"));
Chris Lattner6953a072008-06-26 18:38:35 +0000377 return;
378 }
379
Chris Lattner1c151132008-06-28 23:36:30 +0000380 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000381 Arg = Arg->IgnoreParenCasts();
382 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
383
384 if (Str == 0 || Str->isWide()) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000385 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
386 "visibility", std::string("1"));
Chris Lattner6953a072008-06-26 18:38:35 +0000387 return;
388 }
389
390 const char *TypeStr = Str->getStrData();
391 unsigned TypeLen = Str->getByteLength();
392 VisibilityAttr::VisibilityTypes type;
393
394 if (TypeLen == 7 && !memcmp(TypeStr, "default", 7))
395 type = VisibilityAttr::DefaultVisibility;
396 else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6))
397 type = VisibilityAttr::HiddenVisibility;
398 else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8))
399 type = VisibilityAttr::HiddenVisibility; // FIXME
400 else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9))
401 type = VisibilityAttr::ProtectedVisibility;
402 else {
Chris Lattner703c52d2008-06-29 00:43:07 +0000403 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
404 "visibility", TypeStr);
Chris Lattner6953a072008-06-26 18:38:35 +0000405 return;
406 }
407
408 d->addAttr(new VisibilityAttr(type));
409}
410
Chris Lattner703c52d2008-06-29 00:43:07 +0000411static void HandleWeakAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000412 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000413 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000414 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
415 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000416 return;
417 }
418
419 d->addAttr(new WeakAttr());
420}
421
Chris Lattner703c52d2008-06-29 00:43:07 +0000422static void HandleDLLImportAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000423 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000424 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000425 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
426 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000427 return;
428 }
429
430 d->addAttr(new DLLImportAttr());
431}
432
Chris Lattner703c52d2008-06-29 00:43:07 +0000433static void HandleDLLExportAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000434 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000435 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000436 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
437 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000438 return;
439 }
440
441 d->addAttr(new DLLExportAttr());
442}
443
Chris Lattner703c52d2008-06-29 00:43:07 +0000444static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000445 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000446 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000447 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
448 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000449 return;
450 }
451
452 d->addAttr(new StdCallAttr());
453}
454
Chris Lattner703c52d2008-06-29 00:43:07 +0000455static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000456 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000457 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000458 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
459 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000460 return;
461 }
462
463 d->addAttr(new FastCallAttr());
464}
465
Chris Lattner703c52d2008-06-29 00:43:07 +0000466static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000467 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000468 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000469 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
470 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000471 return;
472 }
473
474 d->addAttr(new NoThrowAttr());
475}
476
477/// Handle __attribute__((format(type,idx,firstarg))) attributes
478/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
Chris Lattner703c52d2008-06-29 00:43:07 +0000479static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000480
Chris Lattner1c151132008-06-28 23:36:30 +0000481 if (!Attr.getParameterName()) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000482 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6953a072008-06-26 18:38:35 +0000483 "format", std::string("1"));
484 return;
485 }
486
Chris Lattner1c151132008-06-28 23:36:30 +0000487 if (Attr.getNumArgs() != 2) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000488 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
489 std::string("3"));
Chris Lattner6953a072008-06-26 18:38:35 +0000490 return;
491 }
492
493 // GCC ignores the format attribute on K&R style function
494 // prototypes, so we ignore it as well
495 const FunctionTypeProto *proto = getFunctionProto(d);
496
497 if (!proto) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000498 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
499 "format", "function");
Chris Lattner6953a072008-06-26 18:38:35 +0000500 return;
501 }
502
503 // FIXME: in C++ the implicit 'this' function parameter also counts.
504 // this is needed in order to be compatible with GCC
505 // the index must start in 1 and the limit is numargs+1
506 unsigned NumArgs = proto->getNumArgs();
507 unsigned FirstIdx = 1;
508
Chris Lattner1c151132008-06-28 23:36:30 +0000509 const char *Format = Attr.getParameterName()->getName();
510 unsigned FormatLen = Attr.getParameterName()->getLength();
Chris Lattner6953a072008-06-26 18:38:35 +0000511
512 // Normalize the argument, __foo__ becomes foo.
513 if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' &&
514 Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') {
515 Format += 2;
516 FormatLen -= 4;
517 }
518
519 bool Supported = false;
520 bool is_NSString = false;
521 bool is_strftime = false;
522
523 switch (FormatLen) {
524 default: break;
Chris Lattner703c52d2008-06-29 00:43:07 +0000525 case 5: Supported = !memcmp(Format, "scanf", 5); break;
526 case 6: Supported = !memcmp(Format, "printf", 6); break;
527 case 7: Supported = !memcmp(Format, "strfmon", 7); break;
Chris Lattner6953a072008-06-26 18:38:35 +0000528 case 8:
529 Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
530 (is_NSString = !memcmp(Format, "NSString", 8));
531 break;
532 }
533
534 if (!Supported) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000535 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
Chris Lattner1c151132008-06-28 23:36:30 +0000536 "format", Attr.getParameterName()->getName());
Chris Lattner6953a072008-06-26 18:38:35 +0000537 return;
538 }
539
540 // checks for the 2nd argument
Chris Lattner1c151132008-06-28 23:36:30 +0000541 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner703c52d2008-06-29 00:43:07 +0000542 llvm::APSInt Idx(32);
543 if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
544 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +0000545 "format", std::string("2"), IdxExpr->getSourceRange());
546 return;
547 }
548
549 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000550 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6953a072008-06-26 18:38:35 +0000551 "format", std::string("2"), IdxExpr->getSourceRange());
552 return;
553 }
554
555 // FIXME: Do we need to bounds check?
556 unsigned ArgIdx = Idx.getZExtValue() - 1;
557
558 // make sure the format string is really a string
559 QualType Ty = proto->getArgType(ArgIdx);
560
561 if (is_NSString) {
562 // FIXME: do we need to check if the type is NSString*? What are
563 // the semantics?
Chris Lattner703c52d2008-06-29 00:43:07 +0000564 if (!isNSStringType(Ty, S.Context)) {
Chris Lattner6953a072008-06-26 18:38:35 +0000565 // FIXME: Should highlight the actual expression that has the
566 // wrong type.
Chris Lattner703c52d2008-06-29 00:43:07 +0000567 S.Diag(Attr.getLoc(), diag::err_format_attribute_not_NSString,
568 IdxExpr->getSourceRange());
Chris Lattner6953a072008-06-26 18:38:35 +0000569 return;
570 }
571 } else if (!Ty->isPointerType() ||
572 !Ty->getAsPointerType()->getPointeeType()->isCharType()) {
573 // FIXME: Should highlight the actual expression that has the
574 // wrong type.
Chris Lattner703c52d2008-06-29 00:43:07 +0000575 S.Diag(Attr.getLoc(), diag::err_format_attribute_not_string,
576 IdxExpr->getSourceRange());
Chris Lattner6953a072008-06-26 18:38:35 +0000577 return;
578 }
579
580 // check the 3rd argument
Chris Lattner1c151132008-06-28 23:36:30 +0000581 Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1));
Chris Lattner703c52d2008-06-29 00:43:07 +0000582 llvm::APSInt FirstArg(32);
583 if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) {
584 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +0000585 "format", std::string("3"), FirstArgExpr->getSourceRange());
586 return;
587 }
588
589 // check if the function is variadic if the 3rd argument non-zero
590 if (FirstArg != 0) {
591 if (proto->isVariadic()) {
592 ++NumArgs; // +1 for ...
593 } else {
Chris Lattner703c52d2008-06-29 00:43:07 +0000594 S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
Chris Lattner6953a072008-06-26 18:38:35 +0000595 return;
596 }
597 }
598
599 // strftime requires FirstArg to be 0 because it doesn't read from any variable
600 // the input is just the current time + the format string
601 if (is_strftime) {
602 if (FirstArg != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000603 S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter,
Chris Lattner6953a072008-06-26 18:38:35 +0000604 FirstArgExpr->getSourceRange());
605 return;
606 }
607 // if 0 it disables parameter checking (to use with e.g. va_list)
608 } else if (FirstArg != 0 && FirstArg != NumArgs) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000609 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6953a072008-06-26 18:38:35 +0000610 "format", std::string("3"), FirstArgExpr->getSourceRange());
611 return;
612 }
613
614 d->addAttr(new FormatAttr(std::string(Format, FormatLen),
615 Idx.getZExtValue(), FirstArg.getZExtValue()));
616}
617
Chris Lattnerf6690152008-06-29 00:28:59 +0000618static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
619 Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000620 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000621 if (Attr.getNumArgs() != 0) {
Chris Lattnerf6690152008-06-29 00:28:59 +0000622 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000623 std::string("0"));
624 return;
625 }
626
627 TypeDecl *decl = dyn_cast<TypeDecl>(d);
628
Chris Lattnerf6690152008-06-29 00:28:59 +0000629 if (!decl || !S.Context.getTypeDeclType(decl)->isUnionType()) {
630 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6953a072008-06-26 18:38:35 +0000631 "transparent_union", "union");
632 return;
633 }
634
635 //QualType QTy = Context.getTypeDeclType(decl);
636 //const RecordType *Ty = QTy->getAsUnionType();
637
638// FIXME
639// Ty->addAttr(new TransparentUnionAttr());
640}
641
Chris Lattnerf6690152008-06-29 00:28:59 +0000642static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000643 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000644 if (Attr.getNumArgs() != 1) {
Chris Lattnerf6690152008-06-29 00:28:59 +0000645 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
646 std::string("1"));
Chris Lattner6953a072008-06-26 18:38:35 +0000647 return;
648 }
Chris Lattner1c151132008-06-28 23:36:30 +0000649 Expr *argExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000650 StringLiteral *SE = dyn_cast<StringLiteral>(argExpr);
651
652 // Make sure that there is a string literal as the annotation's single
653 // argument.
654 if (!SE) {
Chris Lattnerf6690152008-06-29 00:28:59 +0000655 S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
Chris Lattner6953a072008-06-26 18:38:35 +0000656 return;
657 }
658 d->addAttr(new AnnotateAttr(std::string(SE->getStrData(),
659 SE->getByteLength())));
660}
661
Chris Lattner703c52d2008-06-29 00:43:07 +0000662static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000663 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000664 if (Attr.getNumArgs() > 1) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000665 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
666 std::string("1"));
Chris Lattner6953a072008-06-26 18:38:35 +0000667 return;
668 }
669
670 unsigned Align = 0;
Chris Lattner1c151132008-06-28 23:36:30 +0000671 if (Attr.getNumArgs() == 0) {
Chris Lattner6953a072008-06-26 18:38:35 +0000672 // FIXME: This should be the target specific maximum alignment.
673 // (For now we just use 128 bits which is the maximum on X86.
674 Align = 128;
675 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000676 }
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000677
678 Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0));
679 llvm::APSInt Alignment(32);
Chris Lattner703c52d2008-06-29 00:43:07 +0000680 if (!alignmentExpr->isIntegerConstantExpr(Alignment, S.Context)) {
681 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
682 "aligned", alignmentExpr->getSourceRange());
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000683 return;
684 }
685 d->addAttr(new AlignedAttr(Alignment.getZExtValue() * 8));
Chris Lattner6953a072008-06-26 18:38:35 +0000686}
Chris Lattnerdc789562008-06-27 22:18:37 +0000687
Chris Lattnerf6690152008-06-29 00:28:59 +0000688/// HandleModeAttr - This attribute modifies the width of a decl with
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000689/// primitive type.
Chris Lattnerdc789562008-06-27 22:18:37 +0000690///
691/// Despite what would be logical, the mode attribute is a decl attribute,
692/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make
693/// 'G' be HImode, not an intermediate pointer.
694///
Chris Lattnerf6690152008-06-29 00:28:59 +0000695static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
Chris Lattnerdc789562008-06-27 22:18:37 +0000696 // This attribute isn't documented, but glibc uses it. It changes
697 // the width of an int or unsigned int to the specified size.
698
699 // Check that there aren't any arguments
700 if (Attr.getNumArgs() != 0) {
Chris Lattnerf6690152008-06-29 00:28:59 +0000701 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
702 std::string("0"));
Chris Lattnerdc789562008-06-27 22:18:37 +0000703 return;
704 }
705
706 IdentifierInfo *Name = Attr.getParameterName();
707 if (!Name) {
Chris Lattnerf6690152008-06-29 00:28:59 +0000708 S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
Chris Lattnerdc789562008-06-27 22:18:37 +0000709 return;
710 }
711 const char *Str = Name->getName();
712 unsigned Len = Name->getLength();
713
714 // Normalize the attribute name, __foo__ becomes foo.
715 if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
716 Str[Len - 2] == '_' && Str[Len - 1] == '_') {
717 Str += 2;
718 Len -= 4;
719 }
720
721 unsigned DestWidth = 0;
722 bool IntegerMode = true;
723 switch (Len) {
724 case 2:
725 if (!memcmp(Str, "QI", 2)) { DestWidth = 8; break; }
726 if (!memcmp(Str, "HI", 2)) { DestWidth = 16; break; }
727 if (!memcmp(Str, "SI", 2)) { DestWidth = 32; break; }
728 if (!memcmp(Str, "DI", 2)) { DestWidth = 64; break; }
729 if (!memcmp(Str, "TI", 2)) { DestWidth = 128; break; }
730 if (!memcmp(Str, "SF", 2)) { DestWidth = 32; IntegerMode = false; break; }
731 if (!memcmp(Str, "DF", 2)) { DestWidth = 64; IntegerMode = false; break; }
732 if (!memcmp(Str, "XF", 2)) { DestWidth = 96; IntegerMode = false; break; }
733 if (!memcmp(Str, "TF", 2)) { DestWidth = 128; IntegerMode = false; break; }
734 break;
735 case 4:
736 // FIXME: glibc uses 'word' to define register_t; this is narrower than a
737 // pointer on PIC16 and other embedded platforms.
738 if (!memcmp(Str, "word", 4))
Chris Lattnerf6690152008-06-29 00:28:59 +0000739 DestWidth = S.Context.Target.getPointerWidth(0);
Chris Lattnerdc789562008-06-27 22:18:37 +0000740 if (!memcmp(Str, "byte", 4))
Chris Lattnerf6690152008-06-29 00:28:59 +0000741 DestWidth = S.Context.Target.getCharWidth();
Chris Lattnerdc789562008-06-27 22:18:37 +0000742 break;
743 case 7:
744 if (!memcmp(Str, "pointer", 7))
Chris Lattnerf6690152008-06-29 00:28:59 +0000745 DestWidth = S.Context.Target.getPointerWidth(0);
Chris Lattnerdc789562008-06-27 22:18:37 +0000746 break;
747 }
748
749 QualType OldTy;
750 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
751 OldTy = TD->getUnderlyingType();
752 else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
753 OldTy = VD->getType();
754 else {
Chris Lattnerf6690152008-06-29 00:28:59 +0000755 S.Diag(D->getLocation(), diag::err_attr_wrong_decl, "mode",
756 SourceRange(Attr.getLoc(), Attr.getLoc()));
Chris Lattnerdc789562008-06-27 22:18:37 +0000757 return;
758 }
759
760 // FIXME: Need proper fixed-width types
761 QualType NewTy;
762 switch (DestWidth) {
763 case 0:
Chris Lattnerf6690152008-06-29 00:28:59 +0000764 S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode, Name->getName());
Chris Lattnerdc789562008-06-27 22:18:37 +0000765 return;
766 default:
Chris Lattnerf6690152008-06-29 00:28:59 +0000767 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode, Name->getName());
Chris Lattnerdc789562008-06-27 22:18:37 +0000768 return;
769 case 8:
770 assert(IntegerMode);
771 if (OldTy->isSignedIntegerType())
Chris Lattnerf6690152008-06-29 00:28:59 +0000772 NewTy = S.Context.SignedCharTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000773 else
Chris Lattnerf6690152008-06-29 00:28:59 +0000774 NewTy = S.Context.UnsignedCharTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000775 break;
776 case 16:
777 assert(IntegerMode);
778 if (OldTy->isSignedIntegerType())
Chris Lattnerf6690152008-06-29 00:28:59 +0000779 NewTy = S.Context.ShortTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000780 else
Chris Lattnerf6690152008-06-29 00:28:59 +0000781 NewTy = S.Context.UnsignedShortTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000782 break;
783 case 32:
784 if (!IntegerMode)
Chris Lattnerf6690152008-06-29 00:28:59 +0000785 NewTy = S.Context.FloatTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000786 else if (OldTy->isSignedIntegerType())
Chris Lattnerf6690152008-06-29 00:28:59 +0000787 NewTy = S.Context.IntTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000788 else
Chris Lattnerf6690152008-06-29 00:28:59 +0000789 NewTy = S.Context.UnsignedIntTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000790 break;
791 case 64:
792 if (!IntegerMode)
Chris Lattnerf6690152008-06-29 00:28:59 +0000793 NewTy = S.Context.DoubleTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000794 else if (OldTy->isSignedIntegerType())
Chris Lattnerf6690152008-06-29 00:28:59 +0000795 NewTy = S.Context.LongLongTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000796 else
Chris Lattnerf6690152008-06-29 00:28:59 +0000797 NewTy = S.Context.UnsignedLongLongTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000798 break;
799 }
800
801 if (!OldTy->getAsBuiltinType())
Chris Lattnerf6690152008-06-29 00:28:59 +0000802 S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
Chris Lattnerdc789562008-06-27 22:18:37 +0000803 else if (!(IntegerMode && OldTy->isIntegerType()) &&
804 !(!IntegerMode && OldTy->isFloatingType())) {
Chris Lattnerf6690152008-06-29 00:28:59 +0000805 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
Chris Lattnerdc789562008-06-27 22:18:37 +0000806 }
807
808 // Install the new type.
809 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
810 TD->setUnderlyingType(NewTy);
811 else
812 cast<ValueDecl>(D)->setType(NewTy);
813}
Chris Lattnera72440d2008-06-29 00:23:49 +0000814
815//===----------------------------------------------------------------------===//
816// Top Level Sema Entry Points
817//===----------------------------------------------------------------------===//
818
Chris Lattner703c52d2008-06-29 00:43:07 +0000819/// HandleDeclAttribute - Apply the specific attribute to the specified decl if
820/// the attribute applies to decls. If the attribute is a type attribute, just
821/// silently ignore it.
822static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
823 switch (Attr.getKind()) {
824 case AttributeList::AT_address_space:
825 // Ignore this, this is a type attribute, handled by ProcessTypeAttributes.
826 break;
827 case AttributeList::AT_ext_vector_type:
828 HandleExtVectorTypeAttr(D, Attr, S);
829 break;
830 case AttributeList::AT_vector_size: HandleVectorSizeAttr(D, Attr, S); break;
831 case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break;
832 case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break;
833 case AttributeList::AT_deprecated: HandleDeprecatedAttr(D, Attr, S); break;
834 case AttributeList::AT_visibility: HandleVisibilityAttr(D, Attr, S); break;
835 case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break;
836 case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break;
837 case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break;
838 case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break;
839 case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break;
840 case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break;
841 case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break;
842 case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break;
843 case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break;
844 case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break;
845 case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break;
Ted Kremenekc0af2542008-07-21 21:53:04 +0000846 case AttributeList::AT_IBOutlet: HandleIBOutletAttr (D, Attr, S); break;
847 case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break;
Ted Kremenekce13e1e2008-07-25 04:39:19 +0000848 case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break;
Chris Lattner703c52d2008-06-29 00:43:07 +0000849 case AttributeList::AT_transparent_union:
850 HandleTransparentUnionAttr(D, Attr, S);
851 break;
852 default:
853#if 0
854 // TODO: when we have the full set of attributes, warn about unknown ones.
855 S.Diag(Attr->getLoc(), diag::warn_attribute_ignored,
856 Attr->getName()->getName());
857#endif
858 break;
859 }
860}
861
862/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
863/// attribute list to the specified decl, ignoring any type attributes.
864void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) {
865 while (AttrList) {
866 ProcessDeclAttribute(D, *AttrList, *this);
867 AttrList = AttrList->getNext();
868 }
869}
870
871
Chris Lattnera72440d2008-06-29 00:23:49 +0000872/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
873/// it, apply them to D. This is a bit tricky because PD can have attributes
874/// specified in many different places, and we need to find and apply them all.
875void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) {
876 // Apply decl attributes from the DeclSpec if present.
877 if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
878 ProcessDeclAttributeList(D, Attrs);
Chris Lattner703c52d2008-06-29 00:43:07 +0000879
Chris Lattnera72440d2008-06-29 00:23:49 +0000880 // Walk the declarator structure, applying decl attributes that were in a type
881 // position to the decl itself. This handles cases like:
882 // int *__attr__(x)** D;
883 // when X is a decl attribute.
884 for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
885 if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
886 ProcessDeclAttributeList(D, Attrs);
887
888 // Finally, apply any attributes on the decl itself.
889 if (const AttributeList *Attrs = PD.getAttributes())
890 ProcessDeclAttributeList(D, Attrs);
891}
892