blob: edf9a664e24b8bb849543596da0b313b6263de7f [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 Kremenek178cee22008-07-21 22:09:15 +000017#include <sstream>
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) {
Ted Kremenek178cee22008-07-21 22:09:15 +0000270 std::ostringstream os;
271 os << I.getArgNum();
Ted Kremenekc0af2542008-07-21 21:53:04 +0000272 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Ted Kremenek178cee22008-07-21 22:09:15 +0000273 "nonnull", os.str(), Ex->getSourceRange());
Ted Kremenekc0af2542008-07-21 21:53:04 +0000274 return;
275 }
Ted Kremenek178cee22008-07-21 22:09:15 +0000276
277 --x;
Ted Kremenekc0af2542008-07-21 21:53:04 +0000278
279 // Is the function argument a pointer type?
280 if (!proto->getArgType(x).getCanonicalType()->isPointerType()) {
281 // FIXME: Should also highlight argument in decl.
282 S.Diag(Attr.getLoc(), diag::err_nonnull_pointers_only,
283 "nonnull", Ex->getSourceRange());
284 return;
285 }
286
287 NonNullArgs.push_back(x);
288 }
289
290 if (!NonNullArgs.empty()) {
291 unsigned* start = &NonNullArgs[0];
292 unsigned size = NonNullArgs.size();
293 std::sort(start, start + size);
294 d->addAttr(new NonNullAttr(start, size));
295 }
296 else
297 d->addAttr(new NonNullAttr());
298}
299
Chris Lattner703c52d2008-06-29 00:43:07 +0000300static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000301 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000302 if (Attr.getNumArgs() != 1) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000303 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
304 std::string("1"));
Chris Lattner6953a072008-06-26 18:38:35 +0000305 return;
306 }
307
Chris Lattner1c151132008-06-28 23:36:30 +0000308 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000309 Arg = Arg->IgnoreParenCasts();
310 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
311
312 if (Str == 0 || Str->isWide()) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000313 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
314 "alias", std::string("1"));
Chris Lattner6953a072008-06-26 18:38:35 +0000315 return;
316 }
317
318 const char *Alias = Str->getStrData();
319 unsigned AliasLen = Str->getByteLength();
320
321 // FIXME: check if target symbol exists in current file
322
323 d->addAttr(new AliasAttr(std::string(Alias, AliasLen)));
324}
325
Chris Lattner703c52d2008-06-29 00:43:07 +0000326static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000327 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000328 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000329 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
330 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000331 return;
332 }
333
334 FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
Chris Lattner6953a072008-06-26 18:38:35 +0000335 if (!Fn) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000336 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
337 "noreturn", "function");
Chris Lattner6953a072008-06-26 18:38:35 +0000338 return;
339 }
340
341 d->addAttr(new NoReturnAttr());
342}
343
Chris Lattner703c52d2008-06-29 00:43:07 +0000344static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000345 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000346 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000347 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
348 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000349 return;
350 }
351
352 d->addAttr(new DeprecatedAttr());
353}
354
Chris Lattner703c52d2008-06-29 00:43:07 +0000355static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000356 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000357 if (Attr.getNumArgs() != 1) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000358 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
359 std::string("1"));
Chris Lattner6953a072008-06-26 18:38:35 +0000360 return;
361 }
362
Chris Lattner1c151132008-06-28 23:36:30 +0000363 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000364 Arg = Arg->IgnoreParenCasts();
365 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
366
367 if (Str == 0 || Str->isWide()) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000368 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
369 "visibility", std::string("1"));
Chris Lattner6953a072008-06-26 18:38:35 +0000370 return;
371 }
372
373 const char *TypeStr = Str->getStrData();
374 unsigned TypeLen = Str->getByteLength();
375 VisibilityAttr::VisibilityTypes type;
376
377 if (TypeLen == 7 && !memcmp(TypeStr, "default", 7))
378 type = VisibilityAttr::DefaultVisibility;
379 else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6))
380 type = VisibilityAttr::HiddenVisibility;
381 else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8))
382 type = VisibilityAttr::HiddenVisibility; // FIXME
383 else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9))
384 type = VisibilityAttr::ProtectedVisibility;
385 else {
Chris Lattner703c52d2008-06-29 00:43:07 +0000386 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
387 "visibility", TypeStr);
Chris Lattner6953a072008-06-26 18:38:35 +0000388 return;
389 }
390
391 d->addAttr(new VisibilityAttr(type));
392}
393
Chris Lattner703c52d2008-06-29 00:43:07 +0000394static void HandleWeakAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000395 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000396 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000397 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
398 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000399 return;
400 }
401
402 d->addAttr(new WeakAttr());
403}
404
Chris Lattner703c52d2008-06-29 00:43:07 +0000405static void HandleDLLImportAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000406 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000407 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000408 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
409 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000410 return;
411 }
412
413 d->addAttr(new DLLImportAttr());
414}
415
Chris Lattner703c52d2008-06-29 00:43:07 +0000416static void HandleDLLExportAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000417 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000418 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000419 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
420 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000421 return;
422 }
423
424 d->addAttr(new DLLExportAttr());
425}
426
Chris Lattner703c52d2008-06-29 00:43:07 +0000427static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000428 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000429 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000430 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
431 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000432 return;
433 }
434
435 d->addAttr(new StdCallAttr());
436}
437
Chris Lattner703c52d2008-06-29 00:43:07 +0000438static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000439 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000440 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000441 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
442 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000443 return;
444 }
445
446 d->addAttr(new FastCallAttr());
447}
448
Chris Lattner703c52d2008-06-29 00:43:07 +0000449static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000450 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000451 if (Attr.getNumArgs() != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000452 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
453 std::string("0"));
Chris Lattner6953a072008-06-26 18:38:35 +0000454 return;
455 }
456
457 d->addAttr(new NoThrowAttr());
458}
459
460/// Handle __attribute__((format(type,idx,firstarg))) attributes
461/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
Chris Lattner703c52d2008-06-29 00:43:07 +0000462static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000463
Chris Lattner1c151132008-06-28 23:36:30 +0000464 if (!Attr.getParameterName()) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000465 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6953a072008-06-26 18:38:35 +0000466 "format", std::string("1"));
467 return;
468 }
469
Chris Lattner1c151132008-06-28 23:36:30 +0000470 if (Attr.getNumArgs() != 2) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000471 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
472 std::string("3"));
Chris Lattner6953a072008-06-26 18:38:35 +0000473 return;
474 }
475
476 // GCC ignores the format attribute on K&R style function
477 // prototypes, so we ignore it as well
478 const FunctionTypeProto *proto = getFunctionProto(d);
479
480 if (!proto) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000481 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
482 "format", "function");
Chris Lattner6953a072008-06-26 18:38:35 +0000483 return;
484 }
485
486 // FIXME: in C++ the implicit 'this' function parameter also counts.
487 // this is needed in order to be compatible with GCC
488 // the index must start in 1 and the limit is numargs+1
489 unsigned NumArgs = proto->getNumArgs();
490 unsigned FirstIdx = 1;
491
Chris Lattner1c151132008-06-28 23:36:30 +0000492 const char *Format = Attr.getParameterName()->getName();
493 unsigned FormatLen = Attr.getParameterName()->getLength();
Chris Lattner6953a072008-06-26 18:38:35 +0000494
495 // Normalize the argument, __foo__ becomes foo.
496 if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' &&
497 Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') {
498 Format += 2;
499 FormatLen -= 4;
500 }
501
502 bool Supported = false;
503 bool is_NSString = false;
504 bool is_strftime = false;
505
506 switch (FormatLen) {
507 default: break;
Chris Lattner703c52d2008-06-29 00:43:07 +0000508 case 5: Supported = !memcmp(Format, "scanf", 5); break;
509 case 6: Supported = !memcmp(Format, "printf", 6); break;
510 case 7: Supported = !memcmp(Format, "strfmon", 7); break;
Chris Lattner6953a072008-06-26 18:38:35 +0000511 case 8:
512 Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
513 (is_NSString = !memcmp(Format, "NSString", 8));
514 break;
515 }
516
517 if (!Supported) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000518 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
Chris Lattner1c151132008-06-28 23:36:30 +0000519 "format", Attr.getParameterName()->getName());
Chris Lattner6953a072008-06-26 18:38:35 +0000520 return;
521 }
522
523 // checks for the 2nd argument
Chris Lattner1c151132008-06-28 23:36:30 +0000524 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner703c52d2008-06-29 00:43:07 +0000525 llvm::APSInt Idx(32);
526 if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
527 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +0000528 "format", std::string("2"), IdxExpr->getSourceRange());
529 return;
530 }
531
532 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000533 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6953a072008-06-26 18:38:35 +0000534 "format", std::string("2"), IdxExpr->getSourceRange());
535 return;
536 }
537
538 // FIXME: Do we need to bounds check?
539 unsigned ArgIdx = Idx.getZExtValue() - 1;
540
541 // make sure the format string is really a string
542 QualType Ty = proto->getArgType(ArgIdx);
543
544 if (is_NSString) {
545 // FIXME: do we need to check if the type is NSString*? What are
546 // the semantics?
Chris Lattner703c52d2008-06-29 00:43:07 +0000547 if (!isNSStringType(Ty, S.Context)) {
Chris Lattner6953a072008-06-26 18:38:35 +0000548 // FIXME: Should highlight the actual expression that has the
549 // wrong type.
Chris Lattner703c52d2008-06-29 00:43:07 +0000550 S.Diag(Attr.getLoc(), diag::err_format_attribute_not_NSString,
551 IdxExpr->getSourceRange());
Chris Lattner6953a072008-06-26 18:38:35 +0000552 return;
553 }
554 } else if (!Ty->isPointerType() ||
555 !Ty->getAsPointerType()->getPointeeType()->isCharType()) {
556 // FIXME: Should highlight the actual expression that has the
557 // wrong type.
Chris Lattner703c52d2008-06-29 00:43:07 +0000558 S.Diag(Attr.getLoc(), diag::err_format_attribute_not_string,
559 IdxExpr->getSourceRange());
Chris Lattner6953a072008-06-26 18:38:35 +0000560 return;
561 }
562
563 // check the 3rd argument
Chris Lattner1c151132008-06-28 23:36:30 +0000564 Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1));
Chris Lattner703c52d2008-06-29 00:43:07 +0000565 llvm::APSInt FirstArg(32);
566 if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) {
567 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +0000568 "format", std::string("3"), FirstArgExpr->getSourceRange());
569 return;
570 }
571
572 // check if the function is variadic if the 3rd argument non-zero
573 if (FirstArg != 0) {
574 if (proto->isVariadic()) {
575 ++NumArgs; // +1 for ...
576 } else {
Chris Lattner703c52d2008-06-29 00:43:07 +0000577 S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
Chris Lattner6953a072008-06-26 18:38:35 +0000578 return;
579 }
580 }
581
582 // strftime requires FirstArg to be 0 because it doesn't read from any variable
583 // the input is just the current time + the format string
584 if (is_strftime) {
585 if (FirstArg != 0) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000586 S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter,
Chris Lattner6953a072008-06-26 18:38:35 +0000587 FirstArgExpr->getSourceRange());
588 return;
589 }
590 // if 0 it disables parameter checking (to use with e.g. va_list)
591 } else if (FirstArg != 0 && FirstArg != NumArgs) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000592 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6953a072008-06-26 18:38:35 +0000593 "format", std::string("3"), FirstArgExpr->getSourceRange());
594 return;
595 }
596
597 d->addAttr(new FormatAttr(std::string(Format, FormatLen),
598 Idx.getZExtValue(), FirstArg.getZExtValue()));
599}
600
Chris Lattnerf6690152008-06-29 00:28:59 +0000601static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
602 Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000603 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000604 if (Attr.getNumArgs() != 0) {
Chris Lattnerf6690152008-06-29 00:28:59 +0000605 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000606 std::string("0"));
607 return;
608 }
609
610 TypeDecl *decl = dyn_cast<TypeDecl>(d);
611
Chris Lattnerf6690152008-06-29 00:28:59 +0000612 if (!decl || !S.Context.getTypeDeclType(decl)->isUnionType()) {
613 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6953a072008-06-26 18:38:35 +0000614 "transparent_union", "union");
615 return;
616 }
617
618 //QualType QTy = Context.getTypeDeclType(decl);
619 //const RecordType *Ty = QTy->getAsUnionType();
620
621// FIXME
622// Ty->addAttr(new TransparentUnionAttr());
623}
624
Chris Lattnerf6690152008-06-29 00:28:59 +0000625static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000626 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000627 if (Attr.getNumArgs() != 1) {
Chris Lattnerf6690152008-06-29 00:28:59 +0000628 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
629 std::string("1"));
Chris Lattner6953a072008-06-26 18:38:35 +0000630 return;
631 }
Chris Lattner1c151132008-06-28 23:36:30 +0000632 Expr *argExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000633 StringLiteral *SE = dyn_cast<StringLiteral>(argExpr);
634
635 // Make sure that there is a string literal as the annotation's single
636 // argument.
637 if (!SE) {
Chris Lattnerf6690152008-06-29 00:28:59 +0000638 S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
Chris Lattner6953a072008-06-26 18:38:35 +0000639 return;
640 }
641 d->addAttr(new AnnotateAttr(std::string(SE->getStrData(),
642 SE->getByteLength())));
643}
644
Chris Lattner703c52d2008-06-29 00:43:07 +0000645static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
Chris Lattner6953a072008-06-26 18:38:35 +0000646 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000647 if (Attr.getNumArgs() > 1) {
Chris Lattner703c52d2008-06-29 00:43:07 +0000648 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
649 std::string("1"));
Chris Lattner6953a072008-06-26 18:38:35 +0000650 return;
651 }
652
653 unsigned Align = 0;
Chris Lattner1c151132008-06-28 23:36:30 +0000654 if (Attr.getNumArgs() == 0) {
Chris Lattner6953a072008-06-26 18:38:35 +0000655 // FIXME: This should be the target specific maximum alignment.
656 // (For now we just use 128 bits which is the maximum on X86.
657 Align = 128;
658 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000659 }
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000660
661 Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0));
662 llvm::APSInt Alignment(32);
Chris Lattner703c52d2008-06-29 00:43:07 +0000663 if (!alignmentExpr->isIntegerConstantExpr(Alignment, S.Context)) {
664 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
665 "aligned", alignmentExpr->getSourceRange());
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000666 return;
667 }
668 d->addAttr(new AlignedAttr(Alignment.getZExtValue() * 8));
Chris Lattner6953a072008-06-26 18:38:35 +0000669}
Chris Lattnerdc789562008-06-27 22:18:37 +0000670
Chris Lattnerf6690152008-06-29 00:28:59 +0000671/// HandleModeAttr - This attribute modifies the width of a decl with
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000672/// primitive type.
Chris Lattnerdc789562008-06-27 22:18:37 +0000673///
674/// Despite what would be logical, the mode attribute is a decl attribute,
675/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make
676/// 'G' be HImode, not an intermediate pointer.
677///
Chris Lattnerf6690152008-06-29 00:28:59 +0000678static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
Chris Lattnerdc789562008-06-27 22:18:37 +0000679 // This attribute isn't documented, but glibc uses it. It changes
680 // the width of an int or unsigned int to the specified size.
681
682 // Check that there aren't any arguments
683 if (Attr.getNumArgs() != 0) {
Chris Lattnerf6690152008-06-29 00:28:59 +0000684 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
685 std::string("0"));
Chris Lattnerdc789562008-06-27 22:18:37 +0000686 return;
687 }
688
689 IdentifierInfo *Name = Attr.getParameterName();
690 if (!Name) {
Chris Lattnerf6690152008-06-29 00:28:59 +0000691 S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
Chris Lattnerdc789562008-06-27 22:18:37 +0000692 return;
693 }
694 const char *Str = Name->getName();
695 unsigned Len = Name->getLength();
696
697 // Normalize the attribute name, __foo__ becomes foo.
698 if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
699 Str[Len - 2] == '_' && Str[Len - 1] == '_') {
700 Str += 2;
701 Len -= 4;
702 }
703
704 unsigned DestWidth = 0;
705 bool IntegerMode = true;
706 switch (Len) {
707 case 2:
708 if (!memcmp(Str, "QI", 2)) { DestWidth = 8; break; }
709 if (!memcmp(Str, "HI", 2)) { DestWidth = 16; break; }
710 if (!memcmp(Str, "SI", 2)) { DestWidth = 32; break; }
711 if (!memcmp(Str, "DI", 2)) { DestWidth = 64; break; }
712 if (!memcmp(Str, "TI", 2)) { DestWidth = 128; break; }
713 if (!memcmp(Str, "SF", 2)) { DestWidth = 32; IntegerMode = false; break; }
714 if (!memcmp(Str, "DF", 2)) { DestWidth = 64; IntegerMode = false; break; }
715 if (!memcmp(Str, "XF", 2)) { DestWidth = 96; IntegerMode = false; break; }
716 if (!memcmp(Str, "TF", 2)) { DestWidth = 128; IntegerMode = false; break; }
717 break;
718 case 4:
719 // FIXME: glibc uses 'word' to define register_t; this is narrower than a
720 // pointer on PIC16 and other embedded platforms.
721 if (!memcmp(Str, "word", 4))
Chris Lattnerf6690152008-06-29 00:28:59 +0000722 DestWidth = S.Context.Target.getPointerWidth(0);
Chris Lattnerdc789562008-06-27 22:18:37 +0000723 if (!memcmp(Str, "byte", 4))
Chris Lattnerf6690152008-06-29 00:28:59 +0000724 DestWidth = S.Context.Target.getCharWidth();
Chris Lattnerdc789562008-06-27 22:18:37 +0000725 break;
726 case 7:
727 if (!memcmp(Str, "pointer", 7))
Chris Lattnerf6690152008-06-29 00:28:59 +0000728 DestWidth = S.Context.Target.getPointerWidth(0);
Chris Lattnerdc789562008-06-27 22:18:37 +0000729 break;
730 }
731
732 QualType OldTy;
733 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
734 OldTy = TD->getUnderlyingType();
735 else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
736 OldTy = VD->getType();
737 else {
Chris Lattnerf6690152008-06-29 00:28:59 +0000738 S.Diag(D->getLocation(), diag::err_attr_wrong_decl, "mode",
739 SourceRange(Attr.getLoc(), Attr.getLoc()));
Chris Lattnerdc789562008-06-27 22:18:37 +0000740 return;
741 }
742
743 // FIXME: Need proper fixed-width types
744 QualType NewTy;
745 switch (DestWidth) {
746 case 0:
Chris Lattnerf6690152008-06-29 00:28:59 +0000747 S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode, Name->getName());
Chris Lattnerdc789562008-06-27 22:18:37 +0000748 return;
749 default:
Chris Lattnerf6690152008-06-29 00:28:59 +0000750 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode, Name->getName());
Chris Lattnerdc789562008-06-27 22:18:37 +0000751 return;
752 case 8:
753 assert(IntegerMode);
754 if (OldTy->isSignedIntegerType())
Chris Lattnerf6690152008-06-29 00:28:59 +0000755 NewTy = S.Context.SignedCharTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000756 else
Chris Lattnerf6690152008-06-29 00:28:59 +0000757 NewTy = S.Context.UnsignedCharTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000758 break;
759 case 16:
760 assert(IntegerMode);
761 if (OldTy->isSignedIntegerType())
Chris Lattnerf6690152008-06-29 00:28:59 +0000762 NewTy = S.Context.ShortTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000763 else
Chris Lattnerf6690152008-06-29 00:28:59 +0000764 NewTy = S.Context.UnsignedShortTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000765 break;
766 case 32:
767 if (!IntegerMode)
Chris Lattnerf6690152008-06-29 00:28:59 +0000768 NewTy = S.Context.FloatTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000769 else if (OldTy->isSignedIntegerType())
Chris Lattnerf6690152008-06-29 00:28:59 +0000770 NewTy = S.Context.IntTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000771 else
Chris Lattnerf6690152008-06-29 00:28:59 +0000772 NewTy = S.Context.UnsignedIntTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000773 break;
774 case 64:
775 if (!IntegerMode)
Chris Lattnerf6690152008-06-29 00:28:59 +0000776 NewTy = S.Context.DoubleTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000777 else if (OldTy->isSignedIntegerType())
Chris Lattnerf6690152008-06-29 00:28:59 +0000778 NewTy = S.Context.LongLongTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000779 else
Chris Lattnerf6690152008-06-29 00:28:59 +0000780 NewTy = S.Context.UnsignedLongLongTy;
Chris Lattnerdc789562008-06-27 22:18:37 +0000781 break;
782 }
783
784 if (!OldTy->getAsBuiltinType())
Chris Lattnerf6690152008-06-29 00:28:59 +0000785 S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
Chris Lattnerdc789562008-06-27 22:18:37 +0000786 else if (!(IntegerMode && OldTy->isIntegerType()) &&
787 !(!IntegerMode && OldTy->isFloatingType())) {
Chris Lattnerf6690152008-06-29 00:28:59 +0000788 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
Chris Lattnerdc789562008-06-27 22:18:37 +0000789 }
790
791 // Install the new type.
792 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
793 TD->setUnderlyingType(NewTy);
794 else
795 cast<ValueDecl>(D)->setType(NewTy);
796}
Chris Lattnera72440d2008-06-29 00:23:49 +0000797
798//===----------------------------------------------------------------------===//
799// Top Level Sema Entry Points
800//===----------------------------------------------------------------------===//
801
Chris Lattner703c52d2008-06-29 00:43:07 +0000802/// HandleDeclAttribute - Apply the specific attribute to the specified decl if
803/// the attribute applies to decls. If the attribute is a type attribute, just
804/// silently ignore it.
805static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
806 switch (Attr.getKind()) {
807 case AttributeList::AT_address_space:
808 // Ignore this, this is a type attribute, handled by ProcessTypeAttributes.
809 break;
810 case AttributeList::AT_ext_vector_type:
811 HandleExtVectorTypeAttr(D, Attr, S);
812 break;
813 case AttributeList::AT_vector_size: HandleVectorSizeAttr(D, Attr, S); break;
814 case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break;
815 case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break;
816 case AttributeList::AT_deprecated: HandleDeprecatedAttr(D, Attr, S); break;
817 case AttributeList::AT_visibility: HandleVisibilityAttr(D, Attr, S); break;
818 case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break;
819 case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break;
820 case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break;
821 case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break;
822 case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break;
823 case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break;
824 case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break;
825 case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break;
826 case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break;
827 case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break;
828 case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break;
Ted Kremenekc0af2542008-07-21 21:53:04 +0000829 case AttributeList::AT_IBOutlet: HandleIBOutletAttr (D, Attr, S); break;
830 case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break;
Chris Lattner703c52d2008-06-29 00:43:07 +0000831 case AttributeList::AT_transparent_union:
832 HandleTransparentUnionAttr(D, Attr, S);
833 break;
834 default:
835#if 0
836 // TODO: when we have the full set of attributes, warn about unknown ones.
837 S.Diag(Attr->getLoc(), diag::warn_attribute_ignored,
838 Attr->getName()->getName());
839#endif
840 break;
841 }
842}
843
844/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
845/// attribute list to the specified decl, ignoring any type attributes.
846void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) {
847 while (AttrList) {
848 ProcessDeclAttribute(D, *AttrList, *this);
849 AttrList = AttrList->getNext();
850 }
851}
852
853
Chris Lattnera72440d2008-06-29 00:23:49 +0000854/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
855/// it, apply them to D. This is a bit tricky because PD can have attributes
856/// specified in many different places, and we need to find and apply them all.
857void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) {
858 // Apply decl attributes from the DeclSpec if present.
859 if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
860 ProcessDeclAttributeList(D, Attrs);
Chris Lattner703c52d2008-06-29 00:43:07 +0000861
Chris Lattnera72440d2008-06-29 00:23:49 +0000862 // Walk the declarator structure, applying decl attributes that were in a type
863 // position to the decl itself. This handles cases like:
864 // int *__attr__(x)** D;
865 // when X is a decl attribute.
866 for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
867 if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
868 ProcessDeclAttributeList(D, Attrs);
869
870 // Finally, apply any attributes on the decl itself.
871 if (const AttributeList *Attrs = PD.getAttributes())
872 ProcessDeclAttributeList(D, Attrs);
873}
874