blob: ed616655d98c39dafdaf052c25863263c11d3b8b [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"
Chris Lattner6953a072008-06-26 18:38:35 +000017using namespace clang;
18
Chris Lattner2024f0a2008-06-29 00:16:31 +000019//===----------------------------------------------------------------------===//
20// Helper functions
21//===----------------------------------------------------------------------===//
22
Chris Lattner6953a072008-06-26 18:38:35 +000023static const FunctionTypeProto *getFunctionProto(Decl *d) {
24 QualType Ty;
Chris Lattner6953a072008-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 Lattner2024f0a2008-06-29 00:16:31 +000060//===----------------------------------------------------------------------===//
Chris Lattner2024f0a2008-06-29 00:16:31 +000061// Attribute Implementations
62//===----------------------------------------------------------------------===//
63
Chris Lattner1c151132008-06-28 23:36:30 +000064void Sema::HandleExtVectorTypeAttribute(Decl *d, const AttributeList &Attr) {
65 TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
66 if (tDecl == 0) {
67 Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
68 return;
Chris Lattner6953a072008-06-26 18:38:35 +000069 }
70
Chris Lattner6953a072008-06-26 18:38:35 +000071 QualType curType = tDecl->getUnderlyingType();
72 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +000073 if (Attr.getNumArgs() != 1) {
74 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +000075 std::string("1"));
76 return;
77 }
Chris Lattner1c151132008-06-28 23:36:30 +000078 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +000079 llvm::APSInt vecSize(32);
80 if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) {
Chris Lattner1c151132008-06-28 23:36:30 +000081 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +000082 "ext_vector_type", sizeExpr->getSourceRange());
83 return;
84 }
85 // unlike gcc's vector_size attribute, we do not allow vectors to be defined
86 // in conjunction with complex types (pointers, arrays, functions, etc.).
87 Type *canonType = curType.getCanonicalType().getTypePtr();
88 if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
Chris Lattner1c151132008-06-28 23:36:30 +000089 Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
Chris Lattner6953a072008-06-26 18:38:35 +000090 curType.getCanonicalType().getAsString());
91 return;
92 }
93 // unlike gcc's vector_size attribute, the size is specified as the
94 // number of elements, not the number of bytes.
95 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
96
97 if (vectorSize == 0) {
Chris Lattner1c151132008-06-28 23:36:30 +000098 Diag(Attr.getLoc(), diag::err_attribute_zero_size,
Chris Lattner6953a072008-06-26 18:38:35 +000099 sizeExpr->getSourceRange());
100 return;
101 }
102 // Instantiate/Install the vector type, the number of elements is > 0.
103 tDecl->setUnderlyingType(Context.getExtVectorType(curType, vectorSize));
104 // Remember this typedef decl, we will need it later for diagnostics.
105 ExtVectorDecls.push_back(tDecl);
106}
107
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000108
109/// HandleVectorSizeAttribute - this attribute is only applicable to
110/// integral and float scalars, although arrays, pointers, and function
111/// return values are allowed in conjunction with this construct. Aggregates
112/// with this attribute are invalid, even if they are of the same size as a
113/// corresponding scalar.
114/// The raw attribute should contain precisely 1 argument, the vector size
115/// for the variable, measured in bytes. If curType and rawAttr are well
116/// formed, this routine will return a new vector type.
117void Sema::HandleVectorSizeAttribute(Decl *D, const AttributeList &Attr) {
118 QualType CurType;
119 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
120 CurType = VD->getType();
121 else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
122 CurType = TD->getUnderlyingType();
123 else {
124 Diag(D->getLocation(), diag::err_attr_wrong_decl,std::string("vector_size"),
125 SourceRange(Attr.getLoc(), Attr.getLoc()));
126 return;
127 }
128
129 // Check the attribute arugments.
Chris Lattner1c151132008-06-28 23:36:30 +0000130 if (Attr.getNumArgs() != 1) {
131 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000132 std::string("1"));
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000133 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000134 }
Chris Lattner1c151132008-06-28 23:36:30 +0000135 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000136 llvm::APSInt vecSize(32);
137 if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) {
Chris Lattner1c151132008-06-28 23:36:30 +0000138 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +0000139 "vector_size", sizeExpr->getSourceRange());
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000140 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000141 }
142 // navigate to the base type - we need to provide for vector pointers,
143 // vector arrays, and functions returning vectors.
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000144 Type *canonType = CurType.getCanonicalType().getTypePtr();
Chris Lattner6953a072008-06-26 18:38:35 +0000145
146 if (canonType->isPointerType() || canonType->isArrayType() ||
147 canonType->isFunctionType()) {
148 assert(0 && "HandleVector(): Complex type construction unimplemented");
149 /* FIXME: rebuild the type from the inside out, vectorizing the inner type.
150 do {
151 if (PointerType *PT = dyn_cast<PointerType>(canonType))
152 canonType = PT->getPointeeType().getTypePtr();
153 else if (ArrayType *AT = dyn_cast<ArrayType>(canonType))
154 canonType = AT->getElementType().getTypePtr();
155 else if (FunctionType *FT = dyn_cast<FunctionType>(canonType))
156 canonType = FT->getResultType().getTypePtr();
157 } while (canonType->isPointerType() || canonType->isArrayType() ||
158 canonType->isFunctionType());
159 */
160 }
161 // the base type must be integer or float.
162 if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
Chris Lattner1c151132008-06-28 23:36:30 +0000163 Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000164 CurType.getCanonicalType().getAsString());
165 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000166 }
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000167 unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(CurType));
Chris Lattner6953a072008-06-26 18:38:35 +0000168 // vecSize is specified in bytes - convert to bits.
169 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
170
171 // the vector size needs to be an integral multiple of the type size.
172 if (vectorSize % typeSize) {
Chris Lattner1c151132008-06-28 23:36:30 +0000173 Diag(Attr.getLoc(), diag::err_attribute_invalid_size,
Chris Lattner6953a072008-06-26 18:38:35 +0000174 sizeExpr->getSourceRange());
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000175 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000176 }
177 if (vectorSize == 0) {
Chris Lattner1c151132008-06-28 23:36:30 +0000178 Diag(Attr.getLoc(), diag::err_attribute_zero_size,
Chris Lattner6953a072008-06-26 18:38:35 +0000179 sizeExpr->getSourceRange());
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000180 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000181 }
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000182
183 // Success! Instantiate the vector type, the number of elements is > 0, and
184 // not required to be a power of 2, unlike GCC.
185 CurType = Context.getVectorType(CurType, vectorSize/typeSize);
186
187 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
188 VD->setType(CurType);
189 else
190 cast<TypedefDecl>(D)->setUnderlyingType(CurType);
Chris Lattner6953a072008-06-26 18:38:35 +0000191}
192
Chris Lattner1c151132008-06-28 23:36:30 +0000193void Sema::HandlePackedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000194 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000195 if (Attr.getNumArgs() > 0) {
196 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000197 std::string("0"));
198 return;
199 }
200
201 if (TagDecl *TD = dyn_cast<TagDecl>(d))
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000202 TD->addAttr(new PackedAttr());
Chris Lattner6953a072008-06-26 18:38:35 +0000203 else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
204 // If the alignment is less than or equal to 8 bits, the packed attribute
205 // has no effect.
206 if (!FD->getType()->isIncompleteType() &&
207 Context.getTypeAlign(FD->getType()) <= 8)
Chris Lattner1c151132008-06-28 23:36:30 +0000208 Diag(Attr.getLoc(),
Chris Lattner6953a072008-06-26 18:38:35 +0000209 diag::warn_attribute_ignored_for_field_of_type,
Chris Lattner1c151132008-06-28 23:36:30 +0000210 Attr.getName()->getName(), FD->getType().getAsString());
Chris Lattner6953a072008-06-26 18:38:35 +0000211 else
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000212 FD->addAttr(new PackedAttr());
Chris Lattner6953a072008-06-26 18:38:35 +0000213 } else
Chris Lattner1c151132008-06-28 23:36:30 +0000214 Diag(Attr.getLoc(), diag::warn_attribute_ignored,
215 Attr.getName()->getName());
Chris Lattner6953a072008-06-26 18:38:35 +0000216}
217
Chris Lattner1c151132008-06-28 23:36:30 +0000218void Sema::HandleAliasAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000219 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000220 if (Attr.getNumArgs() != 1) {
221 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000222 std::string("1"));
223 return;
224 }
225
Chris Lattner1c151132008-06-28 23:36:30 +0000226 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000227 Arg = Arg->IgnoreParenCasts();
228 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
229
230 if (Str == 0 || Str->isWide()) {
Chris Lattner1c151132008-06-28 23:36:30 +0000231 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6953a072008-06-26 18:38:35 +0000232 "alias", std::string("1"));
233 return;
234 }
235
236 const char *Alias = Str->getStrData();
237 unsigned AliasLen = Str->getByteLength();
238
239 // FIXME: check if target symbol exists in current file
240
241 d->addAttr(new AliasAttr(std::string(Alias, AliasLen)));
242}
243
Chris Lattner1c151132008-06-28 23:36:30 +0000244void Sema::HandleNoReturnAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000245 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000246 if (Attr.getNumArgs() != 0) {
247 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000248 std::string("0"));
249 return;
250 }
251
252 FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
Chris Lattner6953a072008-06-26 18:38:35 +0000253 if (!Fn) {
Chris Lattner1c151132008-06-28 23:36:30 +0000254 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6953a072008-06-26 18:38:35 +0000255 "noreturn", "function");
256 return;
257 }
258
259 d->addAttr(new NoReturnAttr());
260}
261
Chris Lattner1c151132008-06-28 23:36:30 +0000262void Sema::HandleDeprecatedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000263 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000264 if (Attr.getNumArgs() != 0) {
265 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000266 std::string("0"));
267 return;
268 }
269
270 d->addAttr(new DeprecatedAttr());
271}
272
Chris Lattner1c151132008-06-28 23:36:30 +0000273void Sema::HandleVisibilityAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000274 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000275 if (Attr.getNumArgs() != 1) {
276 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000277 std::string("1"));
278 return;
279 }
280
Chris Lattner1c151132008-06-28 23:36:30 +0000281 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000282 Arg = Arg->IgnoreParenCasts();
283 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
284
285 if (Str == 0 || Str->isWide()) {
Chris Lattner1c151132008-06-28 23:36:30 +0000286 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6953a072008-06-26 18:38:35 +0000287 "visibility", std::string("1"));
288 return;
289 }
290
291 const char *TypeStr = Str->getStrData();
292 unsigned TypeLen = Str->getByteLength();
293 VisibilityAttr::VisibilityTypes type;
294
295 if (TypeLen == 7 && !memcmp(TypeStr, "default", 7))
296 type = VisibilityAttr::DefaultVisibility;
297 else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6))
298 type = VisibilityAttr::HiddenVisibility;
299 else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8))
300 type = VisibilityAttr::HiddenVisibility; // FIXME
301 else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9))
302 type = VisibilityAttr::ProtectedVisibility;
303 else {
Chris Lattner1c151132008-06-28 23:36:30 +0000304 Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
Chris Lattner6953a072008-06-26 18:38:35 +0000305 "visibility", TypeStr);
306 return;
307 }
308
309 d->addAttr(new VisibilityAttr(type));
310}
311
Chris Lattner1c151132008-06-28 23:36:30 +0000312void Sema::HandleWeakAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000313 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000314 if (Attr.getNumArgs() != 0) {
315 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000316 std::string("0"));
317 return;
318 }
319
320 d->addAttr(new WeakAttr());
321}
322
Chris Lattner1c151132008-06-28 23:36:30 +0000323void Sema::HandleDLLImportAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000324 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000325 if (Attr.getNumArgs() != 0) {
326 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000327 std::string("0"));
328 return;
329 }
330
331 d->addAttr(new DLLImportAttr());
332}
333
Chris Lattner1c151132008-06-28 23:36:30 +0000334void Sema::HandleDLLExportAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000335 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000336 if (Attr.getNumArgs() != 0) {
337 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000338 std::string("0"));
339 return;
340 }
341
342 d->addAttr(new DLLExportAttr());
343}
344
Chris Lattner1c151132008-06-28 23:36:30 +0000345void Sema::HandleStdCallAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000346 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000347 if (Attr.getNumArgs() != 0) {
348 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000349 std::string("0"));
350 return;
351 }
352
353 d->addAttr(new StdCallAttr());
354}
355
Chris Lattner1c151132008-06-28 23:36:30 +0000356void Sema::HandleFastCallAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000357 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000358 if (Attr.getNumArgs() != 0) {
359 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000360 std::string("0"));
361 return;
362 }
363
364 d->addAttr(new FastCallAttr());
365}
366
Chris Lattner1c151132008-06-28 23:36:30 +0000367void Sema::HandleNothrowAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000368 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000369 if (Attr.getNumArgs() != 0) {
370 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000371 std::string("0"));
372 return;
373 }
374
375 d->addAttr(new NoThrowAttr());
376}
377
378/// Handle __attribute__((format(type,idx,firstarg))) attributes
379/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
Chris Lattner1c151132008-06-28 23:36:30 +0000380void Sema::HandleFormatAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000381
Chris Lattner1c151132008-06-28 23:36:30 +0000382 if (!Attr.getParameterName()) {
383 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6953a072008-06-26 18:38:35 +0000384 "format", std::string("1"));
385 return;
386 }
387
Chris Lattner1c151132008-06-28 23:36:30 +0000388 if (Attr.getNumArgs() != 2) {
389 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000390 std::string("3"));
391 return;
392 }
393
394 // GCC ignores the format attribute on K&R style function
395 // prototypes, so we ignore it as well
396 const FunctionTypeProto *proto = getFunctionProto(d);
397
398 if (!proto) {
Chris Lattner1c151132008-06-28 23:36:30 +0000399 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000400 "format", "function");
Chris Lattner6953a072008-06-26 18:38:35 +0000401 return;
402 }
403
404 // FIXME: in C++ the implicit 'this' function parameter also counts.
405 // this is needed in order to be compatible with GCC
406 // the index must start in 1 and the limit is numargs+1
407 unsigned NumArgs = proto->getNumArgs();
408 unsigned FirstIdx = 1;
409
Chris Lattner1c151132008-06-28 23:36:30 +0000410 const char *Format = Attr.getParameterName()->getName();
411 unsigned FormatLen = Attr.getParameterName()->getLength();
Chris Lattner6953a072008-06-26 18:38:35 +0000412
413 // Normalize the argument, __foo__ becomes foo.
414 if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' &&
415 Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') {
416 Format += 2;
417 FormatLen -= 4;
418 }
419
420 bool Supported = false;
421 bool is_NSString = false;
422 bool is_strftime = false;
423
424 switch (FormatLen) {
425 default: break;
426 case 5:
427 Supported = !memcmp(Format, "scanf", 5);
428 break;
429 case 6:
430 Supported = !memcmp(Format, "printf", 6);
431 break;
432 case 7:
433 Supported = !memcmp(Format, "strfmon", 7);
434 break;
435 case 8:
436 Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
437 (is_NSString = !memcmp(Format, "NSString", 8));
438 break;
439 }
440
441 if (!Supported) {
Chris Lattner1c151132008-06-28 23:36:30 +0000442 Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
443 "format", Attr.getParameterName()->getName());
Chris Lattner6953a072008-06-26 18:38:35 +0000444 return;
445 }
446
447 // checks for the 2nd argument
Chris Lattner1c151132008-06-28 23:36:30 +0000448 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000449 llvm::APSInt Idx(Context.getTypeSize(IdxExpr->getType()));
450 if (!IdxExpr->isIntegerConstantExpr(Idx, Context)) {
Chris Lattner1c151132008-06-28 23:36:30 +0000451 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +0000452 "format", std::string("2"), IdxExpr->getSourceRange());
453 return;
454 }
455
456 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
Chris Lattner1c151132008-06-28 23:36:30 +0000457 Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6953a072008-06-26 18:38:35 +0000458 "format", std::string("2"), IdxExpr->getSourceRange());
459 return;
460 }
461
462 // FIXME: Do we need to bounds check?
463 unsigned ArgIdx = Idx.getZExtValue() - 1;
464
465 // make sure the format string is really a string
466 QualType Ty = proto->getArgType(ArgIdx);
467
468 if (is_NSString) {
469 // FIXME: do we need to check if the type is NSString*? What are
470 // the semantics?
471 if (!isNSStringType(Ty, Context)) {
472 // FIXME: Should highlight the actual expression that has the
473 // wrong type.
Chris Lattner1c151132008-06-28 23:36:30 +0000474 Diag(Attr.getLoc(), diag::err_format_attribute_not_NSString,
Chris Lattner6953a072008-06-26 18:38:35 +0000475 IdxExpr->getSourceRange());
476 return;
477 }
478 } else if (!Ty->isPointerType() ||
479 !Ty->getAsPointerType()->getPointeeType()->isCharType()) {
480 // FIXME: Should highlight the actual expression that has the
481 // wrong type.
Chris Lattner1c151132008-06-28 23:36:30 +0000482 Diag(Attr.getLoc(), diag::err_format_attribute_not_string,
Chris Lattner6953a072008-06-26 18:38:35 +0000483 IdxExpr->getSourceRange());
484 return;
485 }
486
487 // check the 3rd argument
Chris Lattner1c151132008-06-28 23:36:30 +0000488 Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1));
Chris Lattner6953a072008-06-26 18:38:35 +0000489 llvm::APSInt FirstArg(Context.getTypeSize(FirstArgExpr->getType()));
490 if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, Context)) {
Chris Lattner1c151132008-06-28 23:36:30 +0000491 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +0000492 "format", std::string("3"), FirstArgExpr->getSourceRange());
493 return;
494 }
495
496 // check if the function is variadic if the 3rd argument non-zero
497 if (FirstArg != 0) {
498 if (proto->isVariadic()) {
499 ++NumArgs; // +1 for ...
500 } else {
501 Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
502 return;
503 }
504 }
505
506 // strftime requires FirstArg to be 0 because it doesn't read from any variable
507 // the input is just the current time + the format string
508 if (is_strftime) {
509 if (FirstArg != 0) {
Chris Lattner1c151132008-06-28 23:36:30 +0000510 Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter,
Chris Lattner6953a072008-06-26 18:38:35 +0000511 FirstArgExpr->getSourceRange());
512 return;
513 }
514 // if 0 it disables parameter checking (to use with e.g. va_list)
515 } else if (FirstArg != 0 && FirstArg != NumArgs) {
Chris Lattner1c151132008-06-28 23:36:30 +0000516 Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6953a072008-06-26 18:38:35 +0000517 "format", std::string("3"), FirstArgExpr->getSourceRange());
518 return;
519 }
520
521 d->addAttr(new FormatAttr(std::string(Format, FormatLen),
522 Idx.getZExtValue(), FirstArg.getZExtValue()));
523}
524
525void Sema::HandleTransparentUnionAttribute(Decl *d,
Chris Lattner1c151132008-06-28 23:36:30 +0000526 const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000527 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000528 if (Attr.getNumArgs() != 0) {
529 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000530 std::string("0"));
531 return;
532 }
533
534 TypeDecl *decl = dyn_cast<TypeDecl>(d);
535
536 if (!decl || !Context.getTypeDeclType(decl)->isUnionType()) {
Chris Lattner1c151132008-06-28 23:36:30 +0000537 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6953a072008-06-26 18:38:35 +0000538 "transparent_union", "union");
539 return;
540 }
541
542 //QualType QTy = Context.getTypeDeclType(decl);
543 //const RecordType *Ty = QTy->getAsUnionType();
544
545// FIXME
546// Ty->addAttr(new TransparentUnionAttr());
547}
548
Chris Lattner1c151132008-06-28 23:36:30 +0000549void Sema::HandleAnnotateAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000550 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000551 if (Attr.getNumArgs() != 1) {
552 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000553 std::string("1"));
554 return;
555 }
Chris Lattner1c151132008-06-28 23:36:30 +0000556 Expr *argExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000557 StringLiteral *SE = dyn_cast<StringLiteral>(argExpr);
558
559 // Make sure that there is a string literal as the annotation's single
560 // argument.
561 if (!SE) {
Chris Lattner1c151132008-06-28 23:36:30 +0000562 Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
Chris Lattner6953a072008-06-26 18:38:35 +0000563 return;
564 }
565 d->addAttr(new AnnotateAttr(std::string(SE->getStrData(),
566 SE->getByteLength())));
567}
568
Chris Lattner1c151132008-06-28 23:36:30 +0000569void Sema::HandleAlignedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000570 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000571 if (Attr.getNumArgs() > 1) {
572 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000573 std::string("1"));
574 return;
575 }
576
577 unsigned Align = 0;
Chris Lattner1c151132008-06-28 23:36:30 +0000578 if (Attr.getNumArgs() == 0) {
Chris Lattner6953a072008-06-26 18:38:35 +0000579 // FIXME: This should be the target specific maximum alignment.
580 // (For now we just use 128 bits which is the maximum on X86.
581 Align = 128;
582 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000583 }
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000584
585 Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0));
586 llvm::APSInt Alignment(32);
587 if (!alignmentExpr->isIntegerConstantExpr(Alignment, Context)) {
588 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
589 "aligned", alignmentExpr->getSourceRange());
590 return;
591 }
592 d->addAttr(new AlignedAttr(Alignment.getZExtValue() * 8));
Chris Lattner6953a072008-06-26 18:38:35 +0000593}
Chris Lattnerdc789562008-06-27 22:18:37 +0000594
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000595/// HandleModeAttribute - This attribute modifies the width of a decl with
596/// primitive type.
Chris Lattnerdc789562008-06-27 22:18:37 +0000597///
598/// Despite what would be logical, the mode attribute is a decl attribute,
599/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make
600/// 'G' be HImode, not an intermediate pointer.
601///
602void Sema::HandleModeAttribute(Decl *D, const AttributeList &Attr) {
603 // This attribute isn't documented, but glibc uses it. It changes
604 // the width of an int or unsigned int to the specified size.
605
606 // Check that there aren't any arguments
607 if (Attr.getNumArgs() != 0) {
608 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
609 std::string("0"));
610 return;
611 }
612
613 IdentifierInfo *Name = Attr.getParameterName();
614 if (!Name) {
615 Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
616 return;
617 }
618 const char *Str = Name->getName();
619 unsigned Len = Name->getLength();
620
621 // Normalize the attribute name, __foo__ becomes foo.
622 if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
623 Str[Len - 2] == '_' && Str[Len - 1] == '_') {
624 Str += 2;
625 Len -= 4;
626 }
627
628 unsigned DestWidth = 0;
629 bool IntegerMode = true;
630 switch (Len) {
631 case 2:
632 if (!memcmp(Str, "QI", 2)) { DestWidth = 8; break; }
633 if (!memcmp(Str, "HI", 2)) { DestWidth = 16; break; }
634 if (!memcmp(Str, "SI", 2)) { DestWidth = 32; break; }
635 if (!memcmp(Str, "DI", 2)) { DestWidth = 64; break; }
636 if (!memcmp(Str, "TI", 2)) { DestWidth = 128; break; }
637 if (!memcmp(Str, "SF", 2)) { DestWidth = 32; IntegerMode = false; break; }
638 if (!memcmp(Str, "DF", 2)) { DestWidth = 64; IntegerMode = false; break; }
639 if (!memcmp(Str, "XF", 2)) { DestWidth = 96; IntegerMode = false; break; }
640 if (!memcmp(Str, "TF", 2)) { DestWidth = 128; IntegerMode = false; break; }
641 break;
642 case 4:
643 // FIXME: glibc uses 'word' to define register_t; this is narrower than a
644 // pointer on PIC16 and other embedded platforms.
645 if (!memcmp(Str, "word", 4))
646 DestWidth = Context.Target.getPointerWidth(0);
647 if (!memcmp(Str, "byte", 4))
648 DestWidth = Context.Target.getCharWidth();
649 break;
650 case 7:
651 if (!memcmp(Str, "pointer", 7))
652 DestWidth = Context.Target.getPointerWidth(0);
653 break;
654 }
655
656 QualType OldTy;
657 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
658 OldTy = TD->getUnderlyingType();
659 else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
660 OldTy = VD->getType();
661 else {
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000662 Diag(D->getLocation(), diag::err_attr_wrong_decl, "mode",
Chris Lattnerdc789562008-06-27 22:18:37 +0000663 SourceRange(Attr.getLoc(), Attr.getLoc()));
664 return;
665 }
666
667 // FIXME: Need proper fixed-width types
668 QualType NewTy;
669 switch (DestWidth) {
670 case 0:
671 Diag(Attr.getLoc(), diag::err_unknown_machine_mode, Name->getName());
672 return;
673 default:
674 Diag(Attr.getLoc(), diag::err_unsupported_machine_mode, Name->getName());
675 return;
676 case 8:
677 assert(IntegerMode);
678 if (OldTy->isSignedIntegerType())
679 NewTy = Context.SignedCharTy;
680 else
681 NewTy = Context.UnsignedCharTy;
682 break;
683 case 16:
684 assert(IntegerMode);
685 if (OldTy->isSignedIntegerType())
686 NewTy = Context.ShortTy;
687 else
688 NewTy = Context.UnsignedShortTy;
689 break;
690 case 32:
691 if (!IntegerMode)
692 NewTy = Context.FloatTy;
693 else if (OldTy->isSignedIntegerType())
694 NewTy = Context.IntTy;
695 else
696 NewTy = Context.UnsignedIntTy;
697 break;
698 case 64:
699 if (!IntegerMode)
700 NewTy = Context.DoubleTy;
701 else if (OldTy->isSignedIntegerType())
702 NewTy = Context.LongLongTy;
703 else
704 NewTy = Context.UnsignedLongLongTy;
705 break;
706 }
707
708 if (!OldTy->getAsBuiltinType())
709 Diag(Attr.getLoc(), diag::err_mode_not_primitive);
710 else if (!(IntegerMode && OldTy->isIntegerType()) &&
711 !(!IntegerMode && OldTy->isFloatingType())) {
712 Diag(Attr.getLoc(), diag::err_mode_wrong_type);
713 }
714
715 // Install the new type.
716 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
717 TD->setUnderlyingType(NewTy);
718 else
719 cast<ValueDecl>(D)->setType(NewTy);
720}
Chris Lattnera72440d2008-06-29 00:23:49 +0000721
722//===----------------------------------------------------------------------===//
723// Top Level Sema Entry Points
724//===----------------------------------------------------------------------===//
725
726/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
727/// it, apply them to D. This is a bit tricky because PD can have attributes
728/// specified in many different places, and we need to find and apply them all.
729void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) {
730 // Apply decl attributes from the DeclSpec if present.
731 if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
732 ProcessDeclAttributeList(D, Attrs);
733
734 // Walk the declarator structure, applying decl attributes that were in a type
735 // position to the decl itself. This handles cases like:
736 // int *__attr__(x)** D;
737 // when X is a decl attribute.
738 for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
739 if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
740 ProcessDeclAttributeList(D, Attrs);
741
742 // Finally, apply any attributes on the decl itself.
743 if (const AttributeList *Attrs = PD.getAttributes())
744 ProcessDeclAttributeList(D, Attrs);
745}
746
747/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
748/// attribute list to the specified decl, ignoring any type attributes.
749void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) {
750 while (AttrList) {
751 ProcessDeclAttribute(D, *AttrList);
752 AttrList = AttrList->getNext();
753 }
754}
755
756/// HandleDeclAttribute - Apply the specific attribute to the specified decl if
757/// the attribute applies to decls. If the attribute is a type attribute, just
758/// silently ignore it.
759void Sema::ProcessDeclAttribute(Decl *D, const AttributeList &Attr) {
760 switch (Attr.getKind()) {
761 case AttributeList::AT_address_space:
762 // Ignore this, this is a type attribute, handled by ProcessTypeAttributes.
763 break;
764 case AttributeList::AT_vector_size: HandleVectorSizeAttribute(D, Attr); break;
765 case AttributeList::AT_ext_vector_type:
766 HandleExtVectorTypeAttribute(D, Attr);
767 break;
768 case AttributeList::AT_mode: HandleModeAttribute(D, Attr); break;
769 case AttributeList::AT_alias: HandleAliasAttribute(D, Attr); break;
770 case AttributeList::AT_deprecated: HandleDeprecatedAttribute(D, Attr);break;
771 case AttributeList::AT_visibility: HandleVisibilityAttribute(D, Attr);break;
772 case AttributeList::AT_weak: HandleWeakAttribute(D, Attr); break;
773 case AttributeList::AT_dllimport: HandleDLLImportAttribute(D, Attr); break;
774 case AttributeList::AT_dllexport: HandleDLLExportAttribute(D, Attr); break;
775 case AttributeList::AT_nothrow: HandleNothrowAttribute(D, Attr); break;
776 case AttributeList::AT_stdcall: HandleStdCallAttribute(D, Attr); break;
777 case AttributeList::AT_fastcall: HandleFastCallAttribute(D, Attr); break;
778 case AttributeList::AT_aligned: HandleAlignedAttribute(D, Attr); break;
779 case AttributeList::AT_packed: HandlePackedAttribute(D, Attr); break;
780 case AttributeList::AT_annotate: HandleAnnotateAttribute(D, Attr); break;
781 case AttributeList::AT_noreturn: HandleNoReturnAttribute(D, Attr); break;
782 case AttributeList::AT_format: HandleFormatAttribute(D, Attr); break;
783 case AttributeList::AT_transparent_union:
784 HandleTransparentUnionAttribute(D, Attr);
785 break;
786 default:
787#if 0
788 // TODO: when we have the full set of attributes, warn about unknown ones.
789 Diag(Attr->getLoc(), diag::warn_attribute_ignored,
790 Attr->getName()->getName());
791#endif
792 break;
793 }
794}
795