blob: 3800fa3568178fc7c2c2572c5d2b92d86005438c [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
14#include "Sema.h"
15#include "clang/AST/ASTContext.h"
Chris Lattnerfbf13472008-06-27 22:18:37 +000016#include "clang/Basic/TargetInfo.h"
Chris Lattner6b6b5372008-06-26 18:38:35 +000017using namespace clang;
18
Chris Lattnere5c5ee12008-06-29 00:16:31 +000019//===----------------------------------------------------------------------===//
20// Helper functions
21//===----------------------------------------------------------------------===//
22
Chris Lattner6b6b5372008-06-26 18:38:35 +000023static const FunctionTypeProto *getFunctionProto(Decl *d) {
24 QualType Ty;
Chris Lattner6b6b5372008-06-26 18:38:35 +000025 if (ValueDecl *decl = dyn_cast<ValueDecl>(d))
26 Ty = decl->getType();
27 else if (FieldDecl *decl = dyn_cast<FieldDecl>(d))
28 Ty = decl->getType();
29 else if (TypedefDecl* decl = dyn_cast<TypedefDecl>(d))
30 Ty = decl->getUnderlyingType();
31 else
32 return 0;
33
34 if (Ty->isFunctionPointerType())
35 Ty = Ty->getAsPointerType()->getPointeeType();
36
37 if (const FunctionType *FnTy = Ty->getAsFunctionType())
38 return dyn_cast<FunctionTypeProto>(FnTy->getAsFunctionType());
39
40 return 0;
41}
42
43static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
44 if (!T->isPointerType())
45 return false;
46
47 T = T->getAsPointerType()->getPointeeType().getCanonicalType();
48 ObjCInterfaceType* ClsT = dyn_cast<ObjCInterfaceType>(T.getTypePtr());
49
50 if (!ClsT)
51 return false;
52
53 IdentifierInfo* ClsName = ClsT->getDecl()->getIdentifier();
54
55 // FIXME: Should we walk the chain of classes?
56 return ClsName == &Ctx.Idents.get("NSString") ||
57 ClsName == &Ctx.Idents.get("NSMutableString");
58}
59
Chris Lattnere5c5ee12008-06-29 00:16:31 +000060//===----------------------------------------------------------------------===//
Chris Lattnere5c5ee12008-06-29 00:16:31 +000061// Attribute Implementations
62//===----------------------------------------------------------------------===//
63
Chris Lattner803d0802008-06-29 00:43:07 +000064static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr,
65 Sema &S) {
Chris Lattner545dd342008-06-28 23:36:30 +000066 TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
67 if (tDecl == 0) {
Chris Lattner803d0802008-06-29 00:43:07 +000068 S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
Chris Lattner545dd342008-06-28 23:36:30 +000069 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +000070 }
71
Chris Lattner6b6b5372008-06-26 18:38:35 +000072 QualType curType = tDecl->getUnderlyingType();
73 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +000074 if (Attr.getNumArgs() != 1) {
Chris Lattner803d0802008-06-29 00:43:07 +000075 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
76 std::string("1"));
Chris Lattner6b6b5372008-06-26 18:38:35 +000077 return;
78 }
Chris Lattner545dd342008-06-28 23:36:30 +000079 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +000080 llvm::APSInt vecSize(32);
Chris Lattner803d0802008-06-29 00:43:07 +000081 if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
82 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
83 "ext_vector_type", sizeExpr->getSourceRange());
Chris Lattner6b6b5372008-06-26 18:38:35 +000084 return;
85 }
86 // unlike gcc's vector_size attribute, we do not allow vectors to be defined
87 // in conjunction with complex types (pointers, arrays, functions, etc.).
88 Type *canonType = curType.getCanonicalType().getTypePtr();
89 if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
Chris Lattner803d0802008-06-29 00:43:07 +000090 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
91 curType.getCanonicalType().getAsString());
Chris Lattner6b6b5372008-06-26 18:38:35 +000092 return;
93 }
94 // unlike gcc's vector_size attribute, the size is specified as the
95 // number of elements, not the number of bytes.
96 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
97
98 if (vectorSize == 0) {
Chris Lattner803d0802008-06-29 00:43:07 +000099 S.Diag(Attr.getLoc(), diag::err_attribute_zero_size,
100 sizeExpr->getSourceRange());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000101 return;
102 }
103 // Instantiate/Install the vector type, the number of elements is > 0.
Chris Lattner803d0802008-06-29 00:43:07 +0000104 tDecl->setUnderlyingType(S.Context.getExtVectorType(curType, vectorSize));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000105 // Remember this typedef decl, we will need it later for diagnostics.
Chris Lattner803d0802008-06-29 00:43:07 +0000106 S.ExtVectorDecls.push_back(tDecl);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000107}
108
Chris Lattner065c5a82008-06-28 23:48:25 +0000109
110/// HandleVectorSizeAttribute - this attribute is only applicable to
111/// integral and float scalars, although arrays, pointers, and function
112/// return values are allowed in conjunction with this construct. Aggregates
113/// with this attribute are invalid, even if they are of the same size as a
114/// corresponding scalar.
115/// The raw attribute should contain precisely 1 argument, the vector size
116/// for the variable, measured in bytes. If curType and rawAttr are well
117/// formed, this routine will return a new vector type.
Chris Lattner803d0802008-06-29 00:43:07 +0000118static void HandleVectorSizeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
Chris Lattner065c5a82008-06-28 23:48:25 +0000119 QualType CurType;
120 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
121 CurType = VD->getType();
122 else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
123 CurType = TD->getUnderlyingType();
124 else {
Chris Lattner803d0802008-06-29 00:43:07 +0000125 S.Diag(D->getLocation(), diag::err_attr_wrong_decl,
126 std::string("vector_size"),
127 SourceRange(Attr.getLoc(), Attr.getLoc()));
Chris Lattner065c5a82008-06-28 23:48:25 +0000128 return;
129 }
130
131 // Check the attribute arugments.
Chris Lattner545dd342008-06-28 23:36:30 +0000132 if (Attr.getNumArgs() != 1) {
Chris Lattner803d0802008-06-29 00:43:07 +0000133 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
134 std::string("1"));
Chris Lattner065c5a82008-06-28 23:48:25 +0000135 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000136 }
Chris Lattner545dd342008-06-28 23:36:30 +0000137 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000138 llvm::APSInt vecSize(32);
Chris Lattner803d0802008-06-29 00:43:07 +0000139 if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
140 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
141 "vector_size", sizeExpr->getSourceRange());
Chris Lattner065c5a82008-06-28 23:48:25 +0000142 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000143 }
144 // navigate to the base type - we need to provide for vector pointers,
145 // vector arrays, and functions returning vectors.
Chris Lattner065c5a82008-06-28 23:48:25 +0000146 Type *canonType = CurType.getCanonicalType().getTypePtr();
Chris Lattner6b6b5372008-06-26 18:38:35 +0000147
148 if (canonType->isPointerType() || canonType->isArrayType() ||
149 canonType->isFunctionType()) {
150 assert(0 && "HandleVector(): Complex type construction unimplemented");
151 /* FIXME: rebuild the type from the inside out, vectorizing the inner type.
152 do {
153 if (PointerType *PT = dyn_cast<PointerType>(canonType))
154 canonType = PT->getPointeeType().getTypePtr();
155 else if (ArrayType *AT = dyn_cast<ArrayType>(canonType))
156 canonType = AT->getElementType().getTypePtr();
157 else if (FunctionType *FT = dyn_cast<FunctionType>(canonType))
158 canonType = FT->getResultType().getTypePtr();
159 } while (canonType->isPointerType() || canonType->isArrayType() ||
160 canonType->isFunctionType());
161 */
162 }
163 // the base type must be integer or float.
164 if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
Chris Lattner803d0802008-06-29 00:43:07 +0000165 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
166 CurType.getCanonicalType().getAsString());
Chris Lattner065c5a82008-06-28 23:48:25 +0000167 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000168 }
Chris Lattner803d0802008-06-29 00:43:07 +0000169 unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000170 // vecSize is specified in bytes - convert to bits.
171 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
172
173 // the vector size needs to be an integral multiple of the type size.
174 if (vectorSize % typeSize) {
Chris Lattner803d0802008-06-29 00:43:07 +0000175 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size,
176 sizeExpr->getSourceRange());
Chris Lattner065c5a82008-06-28 23:48:25 +0000177 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000178 }
179 if (vectorSize == 0) {
Chris Lattner803d0802008-06-29 00:43:07 +0000180 S.Diag(Attr.getLoc(), diag::err_attribute_zero_size,
181 sizeExpr->getSourceRange());
Chris Lattner065c5a82008-06-28 23:48:25 +0000182 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000183 }
Chris Lattner065c5a82008-06-28 23:48:25 +0000184
185 // Success! Instantiate the vector type, the number of elements is > 0, and
186 // not required to be a power of 2, unlike GCC.
Chris Lattner803d0802008-06-29 00:43:07 +0000187 CurType = S.Context.getVectorType(CurType, vectorSize/typeSize);
Chris Lattner065c5a82008-06-28 23:48:25 +0000188
189 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
190 VD->setType(CurType);
191 else
192 cast<TypedefDecl>(D)->setUnderlyingType(CurType);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000193}
194
Chris Lattner803d0802008-06-29 00:43:07 +0000195static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000196 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000197 if (Attr.getNumArgs() > 0) {
Chris Lattner803d0802008-06-29 00:43:07 +0000198 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
199 std::string("0"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000200 return;
201 }
202
203 if (TagDecl *TD = dyn_cast<TagDecl>(d))
Chris Lattner49e2d342008-06-28 23:50:44 +0000204 TD->addAttr(new PackedAttr());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000205 else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
206 // If the alignment is less than or equal to 8 bits, the packed attribute
207 // has no effect.
208 if (!FD->getType()->isIncompleteType() &&
Chris Lattner803d0802008-06-29 00:43:07 +0000209 S.Context.getTypeAlign(FD->getType()) <= 8)
210 S.Diag(Attr.getLoc(),
211 diag::warn_attribute_ignored_for_field_of_type,
212 Attr.getName()->getName(), FD->getType().getAsString());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000213 else
Chris Lattner49e2d342008-06-28 23:50:44 +0000214 FD->addAttr(new PackedAttr());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000215 } else
Chris Lattner803d0802008-06-29 00:43:07 +0000216 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored,
217 Attr.getName()->getName());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000218}
219
Ted Kremenek96329d42008-07-15 22:26:48 +0000220static void HandleIBOutletAttr(Decl *d, const AttributeList &Attr, Sema &S) {
221 // check the attribute arguments.
222 if (Attr.getNumArgs() > 0) {
223 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
224 std::string("0"));
225 return;
226 }
227
228 // The IBOutlet attribute only applies to instance variables of Objective-C
229 // classes.
230 if (ObjCIvarDecl *ID = dyn_cast<ObjCIvarDecl>(d))
231 ID->addAttr(new IBOutletAttr());
232 else
233 S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet_non_ivar);
234}
235
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000236static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
237
238 // GCC ignores the nonnull attribute on K&R style function
239 // prototypes, so we ignore it as well
240 const FunctionTypeProto *proto = getFunctionProto(d);
241
242 if (!proto) {
243 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
244 "nonnull", "function");
245 return;
246 }
247
248 unsigned NumArgs = proto->getNumArgs();
249
250 // The nonnull attribute only applies to pointers.
251 llvm::SmallVector<unsigned, 10> NonNullArgs;
252
253 for (AttributeList::arg_iterator I=Attr.arg_begin(),
254 E=Attr.arg_end(); I!=E; ++I) {
255
256
257 // The argument must be an integer constant expression.
258 Expr *Ex = static_cast<Expr *>(Attr.getArg(0));
259 llvm::APSInt ArgNum(32);
260 if (!Ex->isIntegerConstantExpr(ArgNum, S.Context)) {
261 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
262 "nonnull", Ex->getSourceRange());
263 return;
264 }
265
266 unsigned x = (unsigned) ArgNum.getZExtValue();
267
268 if (x < 1 || x > NumArgs) {
269 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
270 "nonnull", Ex->getSourceRange());
271 return;
272 }
273
274 // Is the function argument a pointer type?
275 if (!proto->getArgType(x).getCanonicalType()->isPointerType()) {
276 // FIXME: Should also highlight argument in decl.
277 S.Diag(Attr.getLoc(), diag::err_nonnull_pointers_only,
278 "nonnull", Ex->getSourceRange());
279 return;
280 }
281
282 NonNullArgs.push_back(x);
283 }
284
285 if (!NonNullArgs.empty()) {
286 unsigned* start = &NonNullArgs[0];
287 unsigned size = NonNullArgs.size();
288 std::sort(start, start + size);
289 d->addAttr(new NonNullAttr(start, size));
290 }
291 else
292 d->addAttr(new NonNullAttr());
293}
294
Chris Lattner803d0802008-06-29 00:43:07 +0000295static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000296 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000297 if (Attr.getNumArgs() != 1) {
Chris Lattner803d0802008-06-29 00:43:07 +0000298 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
299 std::string("1"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000300 return;
301 }
302
Chris Lattner545dd342008-06-28 23:36:30 +0000303 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000304 Arg = Arg->IgnoreParenCasts();
305 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
306
307 if (Str == 0 || Str->isWide()) {
Chris Lattner803d0802008-06-29 00:43:07 +0000308 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
309 "alias", std::string("1"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000310 return;
311 }
312
313 const char *Alias = Str->getStrData();
314 unsigned AliasLen = Str->getByteLength();
315
316 // FIXME: check if target symbol exists in current file
317
318 d->addAttr(new AliasAttr(std::string(Alias, AliasLen)));
319}
320
Chris Lattner803d0802008-06-29 00:43:07 +0000321static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000322 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000323 if (Attr.getNumArgs() != 0) {
Chris Lattner803d0802008-06-29 00:43:07 +0000324 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
325 std::string("0"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000326 return;
327 }
328
329 FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000330 if (!Fn) {
Chris Lattner803d0802008-06-29 00:43:07 +0000331 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
332 "noreturn", "function");
Chris Lattner6b6b5372008-06-26 18:38:35 +0000333 return;
334 }
335
336 d->addAttr(new NoReturnAttr());
337}
338
Chris Lattner803d0802008-06-29 00:43:07 +0000339static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000340 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000341 if (Attr.getNumArgs() != 0) {
Chris Lattner803d0802008-06-29 00:43:07 +0000342 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
343 std::string("0"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000344 return;
345 }
346
347 d->addAttr(new DeprecatedAttr());
348}
349
Chris Lattner803d0802008-06-29 00:43:07 +0000350static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000351 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000352 if (Attr.getNumArgs() != 1) {
Chris Lattner803d0802008-06-29 00:43:07 +0000353 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
354 std::string("1"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000355 return;
356 }
357
Chris Lattner545dd342008-06-28 23:36:30 +0000358 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000359 Arg = Arg->IgnoreParenCasts();
360 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
361
362 if (Str == 0 || Str->isWide()) {
Chris Lattner803d0802008-06-29 00:43:07 +0000363 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
364 "visibility", std::string("1"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000365 return;
366 }
367
368 const char *TypeStr = Str->getStrData();
369 unsigned TypeLen = Str->getByteLength();
370 VisibilityAttr::VisibilityTypes type;
371
372 if (TypeLen == 7 && !memcmp(TypeStr, "default", 7))
373 type = VisibilityAttr::DefaultVisibility;
374 else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6))
375 type = VisibilityAttr::HiddenVisibility;
376 else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8))
377 type = VisibilityAttr::HiddenVisibility; // FIXME
378 else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9))
379 type = VisibilityAttr::ProtectedVisibility;
380 else {
Chris Lattner803d0802008-06-29 00:43:07 +0000381 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
382 "visibility", TypeStr);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000383 return;
384 }
385
386 d->addAttr(new VisibilityAttr(type));
387}
388
Chris Lattner803d0802008-06-29 00:43:07 +0000389static void HandleWeakAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000390 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000391 if (Attr.getNumArgs() != 0) {
Chris Lattner803d0802008-06-29 00:43:07 +0000392 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
393 std::string("0"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000394 return;
395 }
396
397 d->addAttr(new WeakAttr());
398}
399
Chris Lattner803d0802008-06-29 00:43:07 +0000400static void HandleDLLImportAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000401 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000402 if (Attr.getNumArgs() != 0) {
Chris Lattner803d0802008-06-29 00:43:07 +0000403 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
404 std::string("0"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000405 return;
406 }
407
408 d->addAttr(new DLLImportAttr());
409}
410
Chris Lattner803d0802008-06-29 00:43:07 +0000411static void HandleDLLExportAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000412 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000413 if (Attr.getNumArgs() != 0) {
Chris Lattner803d0802008-06-29 00:43:07 +0000414 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
415 std::string("0"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000416 return;
417 }
418
419 d->addAttr(new DLLExportAttr());
420}
421
Chris Lattner803d0802008-06-29 00:43:07 +0000422static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000423 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000424 if (Attr.getNumArgs() != 0) {
Chris Lattner803d0802008-06-29 00:43:07 +0000425 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
426 std::string("0"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000427 return;
428 }
429
430 d->addAttr(new StdCallAttr());
431}
432
Chris Lattner803d0802008-06-29 00:43:07 +0000433static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000434 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000435 if (Attr.getNumArgs() != 0) {
Chris Lattner803d0802008-06-29 00:43:07 +0000436 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
437 std::string("0"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000438 return;
439 }
440
441 d->addAttr(new FastCallAttr());
442}
443
Chris Lattner803d0802008-06-29 00:43:07 +0000444static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000445 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000446 if (Attr.getNumArgs() != 0) {
Chris Lattner803d0802008-06-29 00:43:07 +0000447 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
448 std::string("0"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000449 return;
450 }
451
452 d->addAttr(new NoThrowAttr());
453}
454
455/// Handle __attribute__((format(type,idx,firstarg))) attributes
456/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
Chris Lattner803d0802008-06-29 00:43:07 +0000457static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000458
Chris Lattner545dd342008-06-28 23:36:30 +0000459 if (!Attr.getParameterName()) {
Chris Lattner803d0802008-06-29 00:43:07 +0000460 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000461 "format", std::string("1"));
462 return;
463 }
464
Chris Lattner545dd342008-06-28 23:36:30 +0000465 if (Attr.getNumArgs() != 2) {
Chris Lattner803d0802008-06-29 00:43:07 +0000466 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
467 std::string("3"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000468 return;
469 }
470
471 // GCC ignores the format attribute on K&R style function
472 // prototypes, so we ignore it as well
473 const FunctionTypeProto *proto = getFunctionProto(d);
474
475 if (!proto) {
Chris Lattner803d0802008-06-29 00:43:07 +0000476 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
477 "format", "function");
Chris Lattner6b6b5372008-06-26 18:38:35 +0000478 return;
479 }
480
481 // FIXME: in C++ the implicit 'this' function parameter also counts.
482 // this is needed in order to be compatible with GCC
483 // the index must start in 1 and the limit is numargs+1
484 unsigned NumArgs = proto->getNumArgs();
485 unsigned FirstIdx = 1;
486
Chris Lattner545dd342008-06-28 23:36:30 +0000487 const char *Format = Attr.getParameterName()->getName();
488 unsigned FormatLen = Attr.getParameterName()->getLength();
Chris Lattner6b6b5372008-06-26 18:38:35 +0000489
490 // Normalize the argument, __foo__ becomes foo.
491 if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' &&
492 Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') {
493 Format += 2;
494 FormatLen -= 4;
495 }
496
497 bool Supported = false;
498 bool is_NSString = false;
499 bool is_strftime = false;
500
501 switch (FormatLen) {
502 default: break;
Chris Lattner803d0802008-06-29 00:43:07 +0000503 case 5: Supported = !memcmp(Format, "scanf", 5); break;
504 case 6: Supported = !memcmp(Format, "printf", 6); break;
505 case 7: Supported = !memcmp(Format, "strfmon", 7); break;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000506 case 8:
507 Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
508 (is_NSString = !memcmp(Format, "NSString", 8));
509 break;
510 }
511
512 if (!Supported) {
Chris Lattner803d0802008-06-29 00:43:07 +0000513 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
Chris Lattner545dd342008-06-28 23:36:30 +0000514 "format", Attr.getParameterName()->getName());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000515 return;
516 }
517
518 // checks for the 2nd argument
Chris Lattner545dd342008-06-28 23:36:30 +0000519 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner803d0802008-06-29 00:43:07 +0000520 llvm::APSInt Idx(32);
521 if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
522 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000523 "format", std::string("2"), IdxExpr->getSourceRange());
524 return;
525 }
526
527 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
Chris Lattner803d0802008-06-29 00:43:07 +0000528 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000529 "format", std::string("2"), IdxExpr->getSourceRange());
530 return;
531 }
532
533 // FIXME: Do we need to bounds check?
534 unsigned ArgIdx = Idx.getZExtValue() - 1;
535
536 // make sure the format string is really a string
537 QualType Ty = proto->getArgType(ArgIdx);
538
539 if (is_NSString) {
540 // FIXME: do we need to check if the type is NSString*? What are
541 // the semantics?
Chris Lattner803d0802008-06-29 00:43:07 +0000542 if (!isNSStringType(Ty, S.Context)) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000543 // FIXME: Should highlight the actual expression that has the
544 // wrong type.
Chris Lattner803d0802008-06-29 00:43:07 +0000545 S.Diag(Attr.getLoc(), diag::err_format_attribute_not_NSString,
546 IdxExpr->getSourceRange());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000547 return;
548 }
549 } else if (!Ty->isPointerType() ||
550 !Ty->getAsPointerType()->getPointeeType()->isCharType()) {
551 // FIXME: Should highlight the actual expression that has the
552 // wrong type.
Chris Lattner803d0802008-06-29 00:43:07 +0000553 S.Diag(Attr.getLoc(), diag::err_format_attribute_not_string,
554 IdxExpr->getSourceRange());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000555 return;
556 }
557
558 // check the 3rd argument
Chris Lattner545dd342008-06-28 23:36:30 +0000559 Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1));
Chris Lattner803d0802008-06-29 00:43:07 +0000560 llvm::APSInt FirstArg(32);
561 if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) {
562 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000563 "format", std::string("3"), FirstArgExpr->getSourceRange());
564 return;
565 }
566
567 // check if the function is variadic if the 3rd argument non-zero
568 if (FirstArg != 0) {
569 if (proto->isVariadic()) {
570 ++NumArgs; // +1 for ...
571 } else {
Chris Lattner803d0802008-06-29 00:43:07 +0000572 S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000573 return;
574 }
575 }
576
577 // strftime requires FirstArg to be 0 because it doesn't read from any variable
578 // the input is just the current time + the format string
579 if (is_strftime) {
580 if (FirstArg != 0) {
Chris Lattner803d0802008-06-29 00:43:07 +0000581 S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000582 FirstArgExpr->getSourceRange());
583 return;
584 }
585 // if 0 it disables parameter checking (to use with e.g. va_list)
586 } else if (FirstArg != 0 && FirstArg != NumArgs) {
Chris Lattner803d0802008-06-29 00:43:07 +0000587 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000588 "format", std::string("3"), FirstArgExpr->getSourceRange());
589 return;
590 }
591
592 d->addAttr(new FormatAttr(std::string(Format, FormatLen),
593 Idx.getZExtValue(), FirstArg.getZExtValue()));
594}
595
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000596static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
597 Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000598 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000599 if (Attr.getNumArgs() != 0) {
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000600 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000601 std::string("0"));
602 return;
603 }
604
605 TypeDecl *decl = dyn_cast<TypeDecl>(d);
606
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000607 if (!decl || !S.Context.getTypeDeclType(decl)->isUnionType()) {
608 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000609 "transparent_union", "union");
610 return;
611 }
612
613 //QualType QTy = Context.getTypeDeclType(decl);
614 //const RecordType *Ty = QTy->getAsUnionType();
615
616// FIXME
617// Ty->addAttr(new TransparentUnionAttr());
618}
619
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000620static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000621 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000622 if (Attr.getNumArgs() != 1) {
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000623 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
624 std::string("1"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000625 return;
626 }
Chris Lattner545dd342008-06-28 23:36:30 +0000627 Expr *argExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000628 StringLiteral *SE = dyn_cast<StringLiteral>(argExpr);
629
630 // Make sure that there is a string literal as the annotation's single
631 // argument.
632 if (!SE) {
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000633 S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000634 return;
635 }
636 d->addAttr(new AnnotateAttr(std::string(SE->getStrData(),
637 SE->getByteLength())));
638}
639
Chris Lattner803d0802008-06-29 00:43:07 +0000640static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000641 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000642 if (Attr.getNumArgs() > 1) {
Chris Lattner803d0802008-06-29 00:43:07 +0000643 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
644 std::string("1"));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000645 return;
646 }
647
648 unsigned Align = 0;
Chris Lattner545dd342008-06-28 23:36:30 +0000649 if (Attr.getNumArgs() == 0) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000650 // FIXME: This should be the target specific maximum alignment.
651 // (For now we just use 128 bits which is the maximum on X86.
652 Align = 128;
653 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000654 }
Chris Lattner49e2d342008-06-28 23:50:44 +0000655
656 Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0));
657 llvm::APSInt Alignment(32);
Chris Lattner803d0802008-06-29 00:43:07 +0000658 if (!alignmentExpr->isIntegerConstantExpr(Alignment, S.Context)) {
659 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
660 "aligned", alignmentExpr->getSourceRange());
Chris Lattner49e2d342008-06-28 23:50:44 +0000661 return;
662 }
663 d->addAttr(new AlignedAttr(Alignment.getZExtValue() * 8));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000664}
Chris Lattnerfbf13472008-06-27 22:18:37 +0000665
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000666/// HandleModeAttr - This attribute modifies the width of a decl with
Chris Lattner065c5a82008-06-28 23:48:25 +0000667/// primitive type.
Chris Lattnerfbf13472008-06-27 22:18:37 +0000668///
669/// Despite what would be logical, the mode attribute is a decl attribute,
670/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make
671/// 'G' be HImode, not an intermediate pointer.
672///
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000673static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
Chris Lattnerfbf13472008-06-27 22:18:37 +0000674 // This attribute isn't documented, but glibc uses it. It changes
675 // the width of an int or unsigned int to the specified size.
676
677 // Check that there aren't any arguments
678 if (Attr.getNumArgs() != 0) {
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000679 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
680 std::string("0"));
Chris Lattnerfbf13472008-06-27 22:18:37 +0000681 return;
682 }
683
684 IdentifierInfo *Name = Attr.getParameterName();
685 if (!Name) {
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000686 S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
Chris Lattnerfbf13472008-06-27 22:18:37 +0000687 return;
688 }
689 const char *Str = Name->getName();
690 unsigned Len = Name->getLength();
691
692 // Normalize the attribute name, __foo__ becomes foo.
693 if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
694 Str[Len - 2] == '_' && Str[Len - 1] == '_') {
695 Str += 2;
696 Len -= 4;
697 }
698
699 unsigned DestWidth = 0;
700 bool IntegerMode = true;
701 switch (Len) {
702 case 2:
703 if (!memcmp(Str, "QI", 2)) { DestWidth = 8; break; }
704 if (!memcmp(Str, "HI", 2)) { DestWidth = 16; break; }
705 if (!memcmp(Str, "SI", 2)) { DestWidth = 32; break; }
706 if (!memcmp(Str, "DI", 2)) { DestWidth = 64; break; }
707 if (!memcmp(Str, "TI", 2)) { DestWidth = 128; break; }
708 if (!memcmp(Str, "SF", 2)) { DestWidth = 32; IntegerMode = false; break; }
709 if (!memcmp(Str, "DF", 2)) { DestWidth = 64; IntegerMode = false; break; }
710 if (!memcmp(Str, "XF", 2)) { DestWidth = 96; IntegerMode = false; break; }
711 if (!memcmp(Str, "TF", 2)) { DestWidth = 128; IntegerMode = false; break; }
712 break;
713 case 4:
714 // FIXME: glibc uses 'word' to define register_t; this is narrower than a
715 // pointer on PIC16 and other embedded platforms.
716 if (!memcmp(Str, "word", 4))
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000717 DestWidth = S.Context.Target.getPointerWidth(0);
Chris Lattnerfbf13472008-06-27 22:18:37 +0000718 if (!memcmp(Str, "byte", 4))
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000719 DestWidth = S.Context.Target.getCharWidth();
Chris Lattnerfbf13472008-06-27 22:18:37 +0000720 break;
721 case 7:
722 if (!memcmp(Str, "pointer", 7))
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000723 DestWidth = S.Context.Target.getPointerWidth(0);
Chris Lattnerfbf13472008-06-27 22:18:37 +0000724 break;
725 }
726
727 QualType OldTy;
728 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
729 OldTy = TD->getUnderlyingType();
730 else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
731 OldTy = VD->getType();
732 else {
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000733 S.Diag(D->getLocation(), diag::err_attr_wrong_decl, "mode",
734 SourceRange(Attr.getLoc(), Attr.getLoc()));
Chris Lattnerfbf13472008-06-27 22:18:37 +0000735 return;
736 }
737
738 // FIXME: Need proper fixed-width types
739 QualType NewTy;
740 switch (DestWidth) {
741 case 0:
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000742 S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode, Name->getName());
Chris Lattnerfbf13472008-06-27 22:18:37 +0000743 return;
744 default:
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000745 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode, Name->getName());
Chris Lattnerfbf13472008-06-27 22:18:37 +0000746 return;
747 case 8:
748 assert(IntegerMode);
749 if (OldTy->isSignedIntegerType())
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000750 NewTy = S.Context.SignedCharTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +0000751 else
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000752 NewTy = S.Context.UnsignedCharTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +0000753 break;
754 case 16:
755 assert(IntegerMode);
756 if (OldTy->isSignedIntegerType())
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000757 NewTy = S.Context.ShortTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +0000758 else
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000759 NewTy = S.Context.UnsignedShortTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +0000760 break;
761 case 32:
762 if (!IntegerMode)
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000763 NewTy = S.Context.FloatTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +0000764 else if (OldTy->isSignedIntegerType())
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000765 NewTy = S.Context.IntTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +0000766 else
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000767 NewTy = S.Context.UnsignedIntTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +0000768 break;
769 case 64:
770 if (!IntegerMode)
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000771 NewTy = S.Context.DoubleTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +0000772 else if (OldTy->isSignedIntegerType())
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000773 NewTy = S.Context.LongLongTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +0000774 else
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000775 NewTy = S.Context.UnsignedLongLongTy;
Chris Lattnerfbf13472008-06-27 22:18:37 +0000776 break;
777 }
778
779 if (!OldTy->getAsBuiltinType())
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000780 S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
Chris Lattnerfbf13472008-06-27 22:18:37 +0000781 else if (!(IntegerMode && OldTy->isIntegerType()) &&
782 !(!IntegerMode && OldTy->isFloatingType())) {
Chris Lattner0b2f4da2008-06-29 00:28:59 +0000783 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
Chris Lattnerfbf13472008-06-27 22:18:37 +0000784 }
785
786 // Install the new type.
787 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
788 TD->setUnderlyingType(NewTy);
789 else
790 cast<ValueDecl>(D)->setType(NewTy);
791}
Chris Lattner0744e5f2008-06-29 00:23:49 +0000792
793//===----------------------------------------------------------------------===//
794// Top Level Sema Entry Points
795//===----------------------------------------------------------------------===//
796
Chris Lattner803d0802008-06-29 00:43:07 +0000797/// HandleDeclAttribute - Apply the specific attribute to the specified decl if
798/// the attribute applies to decls. If the attribute is a type attribute, just
799/// silently ignore it.
800static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
801 switch (Attr.getKind()) {
802 case AttributeList::AT_address_space:
803 // Ignore this, this is a type attribute, handled by ProcessTypeAttributes.
804 break;
805 case AttributeList::AT_ext_vector_type:
806 HandleExtVectorTypeAttr(D, Attr, S);
807 break;
808 case AttributeList::AT_vector_size: HandleVectorSizeAttr(D, Attr, S); break;
809 case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break;
810 case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break;
811 case AttributeList::AT_deprecated: HandleDeprecatedAttr(D, Attr, S); break;
812 case AttributeList::AT_visibility: HandleVisibilityAttr(D, Attr, S); break;
813 case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break;
814 case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break;
815 case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break;
816 case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break;
817 case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break;
818 case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break;
819 case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break;
820 case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break;
821 case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break;
822 case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break;
823 case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break;
Ted Kremenekeb2b2a32008-07-21 21:53:04 +0000824 case AttributeList::AT_IBOutlet: HandleIBOutletAttr (D, Attr, S); break;
825 case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break;
Chris Lattner803d0802008-06-29 00:43:07 +0000826 case AttributeList::AT_transparent_union:
827 HandleTransparentUnionAttr(D, Attr, S);
828 break;
829 default:
830#if 0
831 // TODO: when we have the full set of attributes, warn about unknown ones.
832 S.Diag(Attr->getLoc(), diag::warn_attribute_ignored,
833 Attr->getName()->getName());
834#endif
835 break;
836 }
837}
838
839/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
840/// attribute list to the specified decl, ignoring any type attributes.
841void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) {
842 while (AttrList) {
843 ProcessDeclAttribute(D, *AttrList, *this);
844 AttrList = AttrList->getNext();
845 }
846}
847
848
Chris Lattner0744e5f2008-06-29 00:23:49 +0000849/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
850/// it, apply them to D. This is a bit tricky because PD can have attributes
851/// specified in many different places, and we need to find and apply them all.
852void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) {
853 // Apply decl attributes from the DeclSpec if present.
854 if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
855 ProcessDeclAttributeList(D, Attrs);
Chris Lattner803d0802008-06-29 00:43:07 +0000856
Chris Lattner0744e5f2008-06-29 00:23:49 +0000857 // Walk the declarator structure, applying decl attributes that were in a type
858 // position to the decl itself. This handles cases like:
859 // int *__attr__(x)** D;
860 // when X is a decl attribute.
861 for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
862 if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
863 ProcessDeclAttributeList(D, Attrs);
864
865 // Finally, apply any attributes on the decl itself.
866 if (const AttributeList *Attrs = PD.getAttributes())
867 ProcessDeclAttributeList(D, Attrs);
868}
869