SemaDeclAttr.cpp revision 6f3d838867538638b9bbf412028e8537ae12f3e5
1//===--- 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" 16#include "clang/AST/DeclObjC.h" 17#include "clang/AST/Expr.h" 18#include "clang/Basic/TargetInfo.h" 19#include "clang/Parse/DeclSpec.h" 20#include <llvm/ADT/StringExtras.h> 21using namespace clang; 22 23//===----------------------------------------------------------------------===// 24// Helper functions 25//===----------------------------------------------------------------------===// 26 27static const FunctionType *getFunctionType(Decl *d, bool blocksToo = true) { 28 QualType Ty; 29 if (ValueDecl *decl = dyn_cast<ValueDecl>(d)) 30 Ty = decl->getType(); 31 else if (FieldDecl *decl = dyn_cast<FieldDecl>(d)) 32 Ty = decl->getType(); 33 else if (TypedefDecl* decl = dyn_cast<TypedefDecl>(d)) 34 Ty = decl->getUnderlyingType(); 35 else 36 return 0; 37 38 if (Ty->isFunctionPointerType()) 39 Ty = Ty->getAsPointerType()->getPointeeType(); 40 else if (blocksToo && Ty->isBlockPointerType()) 41 Ty = Ty->getAsBlockPointerType()->getPointeeType(); 42 43 return Ty->getAsFunctionType(); 44} 45 46// FIXME: We should provide an abstraction around a method or function 47// to provide the following bits of information. 48 49/// isFunctionOrMethod - Return true if the given decl has function 50/// type (function or function-typed variable) or an Objective-C 51/// method. 52static bool isFunctionOrMethod(Decl *d) { 53 return getFunctionType(d, false) || isa<ObjCMethodDecl>(d); 54} 55 56/// isFunctionOrMethodOrBlock - Return true if the given decl has function 57/// type (function or function-typed variable) or an Objective-C 58/// method or a block. 59static bool isFunctionOrMethodOrBlock(Decl *d) { 60 if (isFunctionOrMethod(d)) 61 return true; 62 // check for block is more involved. 63 if (const VarDecl *V = dyn_cast<VarDecl>(d)) { 64 QualType Ty = V->getType(); 65 return Ty->isBlockPointerType(); 66 } 67 return isa<BlockDecl>(d); 68} 69 70/// hasFunctionProto - Return true if the given decl has a argument 71/// information. This decl should have already passed 72/// isFunctionOrMethod or isFunctionOrMethodOrBlock. 73static bool hasFunctionProto(Decl *d) { 74 if (const FunctionType *FnTy = getFunctionType(d)) 75 return isa<FunctionProtoType>(FnTy); 76 else { 77 assert(isa<ObjCMethodDecl>(d) || isa<BlockDecl>(d)); 78 return true; 79 } 80} 81 82/// getFunctionOrMethodNumArgs - Return number of function or method 83/// arguments. It is an error to call this on a K&R function (use 84/// hasFunctionProto first). 85static unsigned getFunctionOrMethodNumArgs(Decl *d) { 86 if (const FunctionType *FnTy = getFunctionType(d)) 87 return cast<FunctionProtoType>(FnTy)->getNumArgs(); 88 if (const BlockDecl *BD = dyn_cast<BlockDecl>(d)) 89 return BD->getNumParams(); 90 return cast<ObjCMethodDecl>(d)->param_size(); 91} 92 93static QualType getFunctionOrMethodArgType(Decl *d, unsigned Idx) { 94 if (const FunctionType *FnTy = getFunctionType(d)) 95 return cast<FunctionProtoType>(FnTy)->getArgType(Idx); 96 if (const BlockDecl *BD = dyn_cast<BlockDecl>(d)) 97 return BD->getParamDecl(Idx)->getType(); 98 99 return cast<ObjCMethodDecl>(d)->param_begin()[Idx]->getType(); 100} 101 102static QualType getFunctionOrMethodResultType(Decl *d) { 103 if (const FunctionType *FnTy = getFunctionType(d)) 104 return cast<FunctionProtoType>(FnTy)->getResultType(); 105 return cast<ObjCMethodDecl>(d)->getResultType(); 106} 107 108static bool isFunctionOrMethodVariadic(Decl *d) { 109 if (const FunctionType *FnTy = getFunctionType(d)) { 110 const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy); 111 return proto->isVariadic(); 112 } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(d)) 113 return BD->IsVariadic(); 114 else { 115 return cast<ObjCMethodDecl>(d)->isVariadic(); 116 } 117} 118 119static inline bool isNSStringType(QualType T, ASTContext &Ctx) { 120 const PointerType *PT = T->getAsPointerType(); 121 if (!PT) 122 return false; 123 124 const ObjCInterfaceType *ClsT =PT->getPointeeType()->getAsObjCInterfaceType(); 125 if (!ClsT) 126 return false; 127 128 IdentifierInfo* ClsName = ClsT->getDecl()->getIdentifier(); 129 130 // FIXME: Should we walk the chain of classes? 131 return ClsName == &Ctx.Idents.get("NSString") || 132 ClsName == &Ctx.Idents.get("NSMutableString"); 133} 134 135static inline bool isCFStringType(QualType T, ASTContext &Ctx) { 136 const PointerType *PT = T->getAsPointerType(); 137 if (!PT) 138 return false; 139 140 const RecordType *RT = PT->getPointeeType()->getAsRecordType(); 141 if (!RT) 142 return false; 143 144 const RecordDecl *RD = RT->getDecl(); 145 if (RD->getTagKind() != TagDecl::TK_struct) 146 return false; 147 148 return RD->getIdentifier() == &Ctx.Idents.get("__CFString"); 149} 150 151//===----------------------------------------------------------------------===// 152// Attribute Implementations 153//===----------------------------------------------------------------------===// 154 155// FIXME: All this manual attribute parsing code is gross. At the 156// least add some helper functions to check most argument patterns (# 157// and types of args). 158 159static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, 160 const AttributeList &Attr, Sema &S) { 161 TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d); 162 if (tDecl == 0) { 163 S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); 164 return; 165 } 166 167 QualType curType = tDecl->getUnderlyingType(); 168 169 Expr *sizeExpr; 170 171 // Special case where the argument is a template id. 172 if (Attr.getParameterName()) { 173 sizeExpr = S.ActOnDeclarationNameExpr(scope, Attr.getLoc(), 174 Attr.getParameterName(), 175 false, 0, false).takeAs<Expr>(); 176 } else { 177 // check the attribute arguments. 178 if (Attr.getNumArgs() != 1) { 179 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 180 return; 181 } 182 sizeExpr = static_cast<Expr *>(Attr.getArg(0)); 183 } 184 185 // Instantiate/Install the vector type, and let Sema build the type for us. 186 // This will run the reguired checks. 187 QualType T = S.BuildExtVectorType(curType, S.Owned(sizeExpr), Attr.getLoc()); 188 if (!T.isNull()) { 189 tDecl->setUnderlyingType(T); 190 191 // Remember this typedef decl, we will need it later for diagnostics. 192 S.ExtVectorDecls.push_back(tDecl); 193 } 194} 195 196 197/// HandleVectorSizeAttribute - this attribute is only applicable to 198/// integral and float scalars, although arrays, pointers, and function 199/// return values are allowed in conjunction with this construct. Aggregates 200/// with this attribute are invalid, even if they are of the same size as a 201/// corresponding scalar. 202/// The raw attribute should contain precisely 1 argument, the vector size 203/// for the variable, measured in bytes. If curType and rawAttr are well 204/// formed, this routine will return a new vector type. 205static void HandleVectorSizeAttr(Decl *D, const AttributeList &Attr, Sema &S) { 206 QualType CurType; 207 if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 208 CurType = VD->getType(); 209 else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) 210 CurType = TD->getUnderlyingType(); 211 else { 212 S.Diag(D->getLocation(), diag::err_attr_wrong_decl) 213 << "vector_size" << SourceRange(Attr.getLoc(), Attr.getLoc()); 214 return; 215 } 216 217 // Check the attribute arugments. 218 if (Attr.getNumArgs() != 1) { 219 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 220 return; 221 } 222 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0)); 223 llvm::APSInt vecSize(32); 224 if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { 225 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 226 << "vector_size" << sizeExpr->getSourceRange(); 227 return; 228 } 229 // navigate to the base type - we need to provide for vector pointers, 230 // vector arrays, and functions returning vectors. 231 if (CurType->isPointerType() || CurType->isArrayType() || 232 CurType->isFunctionType()) { 233 S.Diag(Attr.getLoc(), diag::err_unsupported_vector_size) << CurType; 234 return; 235 /* FIXME: rebuild the type from the inside out, vectorizing the inner type. 236 do { 237 if (PointerType *PT = dyn_cast<PointerType>(canonType)) 238 canonType = PT->getPointeeType().getTypePtr(); 239 else if (ArrayType *AT = dyn_cast<ArrayType>(canonType)) 240 canonType = AT->getElementType().getTypePtr(); 241 else if (FunctionType *FT = dyn_cast<FunctionType>(canonType)) 242 canonType = FT->getResultType().getTypePtr(); 243 } while (canonType->isPointerType() || canonType->isArrayType() || 244 canonType->isFunctionType()); 245 */ 246 } 247 // the base type must be integer or float, and can't already be a vector. 248 if (CurType->isVectorType() || 249 (!CurType->isIntegerType() && !CurType->isRealFloatingType())) { 250 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType; 251 return; 252 } 253 unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType)); 254 // vecSize is specified in bytes - convert to bits. 255 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8); 256 257 // the vector size needs to be an integral multiple of the type size. 258 if (vectorSize % typeSize) { 259 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size) 260 << sizeExpr->getSourceRange(); 261 return; 262 } 263 if (vectorSize == 0) { 264 S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) 265 << sizeExpr->getSourceRange(); 266 return; 267 } 268 269 // Success! Instantiate the vector type, the number of elements is > 0, and 270 // not required to be a power of 2, unlike GCC. 271 CurType = S.Context.getVectorType(CurType, vectorSize/typeSize); 272 273 if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 274 VD->setType(CurType); 275 else 276 cast<TypedefDecl>(D)->setUnderlyingType(CurType); 277} 278 279static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { 280 // check the attribute arguments. 281 if (Attr.getNumArgs() > 0) { 282 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 283 return; 284 } 285 286 if (TagDecl *TD = dyn_cast<TagDecl>(d)) 287 TD->addAttr(S.Context, ::new (S.Context) PackedAttr(1)); 288 else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) { 289 // If the alignment is less than or equal to 8 bits, the packed attribute 290 // has no effect. 291 if (!FD->getType()->isIncompleteType() && 292 S.Context.getTypeAlign(FD->getType()) <= 8) 293 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) 294 << Attr.getName() << FD->getType(); 295 else 296 FD->addAttr(S.Context, ::new (S.Context) PackedAttr(1)); 297 } else 298 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 299} 300 301static void HandleIBOutletAttr(Decl *d, const AttributeList &Attr, Sema &S) { 302 // check the attribute arguments. 303 if (Attr.getNumArgs() > 0) { 304 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 305 return; 306 } 307 308 // The IBOutlet attribute only applies to instance variables of Objective-C 309 // classes. 310 if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d)) 311 d->addAttr(S.Context, ::new (S.Context) IBOutletAttr()); 312 else 313 S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet); 314} 315 316static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { 317 // GCC ignores the nonnull attribute on K&R style function 318 // prototypes, so we ignore it as well 319 if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { 320 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 321 << Attr.getName() << 0 /*function*/; 322 return; 323 } 324 325 unsigned NumArgs = getFunctionOrMethodNumArgs(d); 326 327 // The nonnull attribute only applies to pointers. 328 llvm::SmallVector<unsigned, 10> NonNullArgs; 329 330 for (AttributeList::arg_iterator I=Attr.arg_begin(), 331 E=Attr.arg_end(); I!=E; ++I) { 332 333 334 // The argument must be an integer constant expression. 335 Expr *Ex = static_cast<Expr *>(*I); 336 llvm::APSInt ArgNum(32); 337 if (!Ex->isIntegerConstantExpr(ArgNum, S.Context)) { 338 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 339 << "nonnull" << Ex->getSourceRange(); 340 return; 341 } 342 343 unsigned x = (unsigned) ArgNum.getZExtValue(); 344 345 if (x < 1 || x > NumArgs) { 346 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 347 << "nonnull" << I.getArgNum() << Ex->getSourceRange(); 348 return; 349 } 350 351 --x; 352 353 // Is the function argument a pointer type? 354 QualType T = getFunctionOrMethodArgType(d, x); 355 if (!T->isPointerType() && !T->isBlockPointerType()) { 356 // FIXME: Should also highlight argument in decl. 357 S.Diag(Attr.getLoc(), diag::err_nonnull_pointers_only) 358 << "nonnull" << Ex->getSourceRange(); 359 continue; 360 } 361 362 NonNullArgs.push_back(x); 363 } 364 365 // If no arguments were specified to __attribute__((nonnull)) then all 366 // pointer arguments have a nonnull attribute. 367 if (NonNullArgs.empty()) { 368 for (unsigned I = 0, E = getFunctionOrMethodNumArgs(d); I != E; ++I) { 369 QualType T = getFunctionOrMethodArgType(d, I); 370 if (T->isPointerType() || T->isBlockPointerType()) 371 NonNullArgs.push_back(I); 372 } 373 374 if (NonNullArgs.empty()) { 375 S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers); 376 return; 377 } 378 } 379 380 unsigned* start = &NonNullArgs[0]; 381 unsigned size = NonNullArgs.size(); 382 std::sort(start, start + size); 383 d->addAttr(S.Context, ::new (S.Context) NonNullAttr(start, size)); 384} 385 386static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { 387 // check the attribute arguments. 388 if (Attr.getNumArgs() != 1) { 389 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 390 return; 391 } 392 393 Expr *Arg = static_cast<Expr*>(Attr.getArg(0)); 394 Arg = Arg->IgnoreParenCasts(); 395 StringLiteral *Str = dyn_cast<StringLiteral>(Arg); 396 397 if (Str == 0 || Str->isWide()) { 398 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) 399 << "alias" << 1; 400 return; 401 } 402 403 const char *Alias = Str->getStrData(); 404 unsigned AliasLen = Str->getByteLength(); 405 406 // FIXME: check if target symbol exists in current file 407 408 d->addAttr(S.Context, ::new (S.Context) AliasAttr(std::string(Alias, AliasLen))); 409} 410 411static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, 412 Sema &S) { 413 // check the attribute arguments. 414 if (Attr.getNumArgs() != 0) { 415 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 416 return; 417 } 418 419 if (!isa<FunctionDecl>(d)) { 420 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 421 << Attr.getName() << 0 /*function*/; 422 return; 423 } 424 425 d->addAttr(S.Context, ::new (S.Context) AlwaysInlineAttr()); 426} 427 428static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr, 429 Sema &S) { 430 // check the attribute arguments. 431 if (Attr.getNumArgs() != 0) { 432 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 433 return false; 434 } 435 436 if (!isFunctionOrMethod(d) && !isa<BlockDecl>(d)) { 437 ValueDecl *VD = dyn_cast<ValueDecl>(d); 438 if (VD == 0 || !VD->getType()->isBlockPointerType()) { 439 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 440 << Attr.getName() << 0 /*function*/; 441 return false; 442 } 443 } 444 445 return true; 446} 447 448static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { 449 if (HandleCommonNoReturnAttr(d, Attr, S)) 450 d->addAttr(S.Context, ::new (S.Context) NoReturnAttr()); 451} 452 453static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, 454 Sema &S) { 455 if (HandleCommonNoReturnAttr(d, Attr, S)) 456 d->addAttr(S.Context, ::new (S.Context) AnalyzerNoReturnAttr()); 457} 458 459static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { 460 // check the attribute arguments. 461 if (Attr.getNumArgs() != 0) { 462 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 463 return; 464 } 465 466 if (!isa<VarDecl>(d) && !isFunctionOrMethod(d)) { 467 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 468 << Attr.getName() << 2 /*variable and function*/; 469 return; 470 } 471 472 d->addAttr(S.Context, ::new (S.Context) UnusedAttr()); 473} 474 475static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { 476 // check the attribute arguments. 477 if (Attr.getNumArgs() != 0) { 478 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 479 return; 480 } 481 482 if (const VarDecl *VD = dyn_cast<VarDecl>(d)) { 483 if (VD->hasLocalStorage() || VD->hasExternalStorage()) { 484 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used"; 485 return; 486 } 487 } else if (!isFunctionOrMethod(d)) { 488 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 489 << Attr.getName() << 2 /*variable and function*/; 490 return; 491 } 492 493 d->addAttr(S.Context, ::new (S.Context) UsedAttr()); 494} 495 496static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { 497 // check the attribute arguments. 498 if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) { 499 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 500 << "0 or 1"; 501 return; 502 } 503 504 int priority = 65535; // FIXME: Do not hardcode such constants. 505 if (Attr.getNumArgs() > 0) { 506 Expr *E = static_cast<Expr *>(Attr.getArg(0)); 507 llvm::APSInt Idx(32); 508 if (!E->isIntegerConstantExpr(Idx, S.Context)) { 509 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 510 << "constructor" << 1 << E->getSourceRange(); 511 return; 512 } 513 priority = Idx.getZExtValue(); 514 } 515 516 if (!isa<FunctionDecl>(d)) { 517 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 518 << Attr.getName() << 0 /*function*/; 519 return; 520 } 521 522 d->addAttr(S.Context, ::new (S.Context) ConstructorAttr(priority)); 523} 524 525static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { 526 // check the attribute arguments. 527 if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) { 528 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 529 << "0 or 1"; 530 return; 531 } 532 533 int priority = 65535; // FIXME: Do not hardcode such constants. 534 if (Attr.getNumArgs() > 0) { 535 Expr *E = static_cast<Expr *>(Attr.getArg(0)); 536 llvm::APSInt Idx(32); 537 if (!E->isIntegerConstantExpr(Idx, S.Context)) { 538 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 539 << "destructor" << 1 << E->getSourceRange(); 540 return; 541 } 542 priority = Idx.getZExtValue(); 543 } 544 545 if (!isa<FunctionDecl>(d)) { 546 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 547 << Attr.getName() << 0 /*function*/; 548 return; 549 } 550 551 d->addAttr(S.Context, ::new (S.Context) DestructorAttr(priority)); 552} 553 554static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { 555 // check the attribute arguments. 556 if (Attr.getNumArgs() != 0) { 557 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 558 return; 559 } 560 561 d->addAttr(S.Context, ::new (S.Context) DeprecatedAttr()); 562} 563 564static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { 565 // check the attribute arguments. 566 if (Attr.getNumArgs() != 0) { 567 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 568 return; 569 } 570 571 d->addAttr(S.Context, ::new (S.Context) UnavailableAttr()); 572} 573 574static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { 575 // check the attribute arguments. 576 if (Attr.getNumArgs() != 1) { 577 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 578 return; 579 } 580 581 Expr *Arg = static_cast<Expr*>(Attr.getArg(0)); 582 Arg = Arg->IgnoreParenCasts(); 583 StringLiteral *Str = dyn_cast<StringLiteral>(Arg); 584 585 if (Str == 0 || Str->isWide()) { 586 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) 587 << "visibility" << 1; 588 return; 589 } 590 591 const char *TypeStr = Str->getStrData(); 592 unsigned TypeLen = Str->getByteLength(); 593 VisibilityAttr::VisibilityTypes type; 594 595 if (TypeLen == 7 && !memcmp(TypeStr, "default", 7)) 596 type = VisibilityAttr::DefaultVisibility; 597 else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6)) 598 type = VisibilityAttr::HiddenVisibility; 599 else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8)) 600 type = VisibilityAttr::HiddenVisibility; // FIXME 601 else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9)) 602 type = VisibilityAttr::ProtectedVisibility; 603 else { 604 S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr; 605 return; 606 } 607 608 d->addAttr(S.Context, ::new (S.Context) VisibilityAttr(type)); 609} 610 611static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr, 612 Sema &S) { 613 if (Attr.getNumArgs() != 0) { 614 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 615 return; 616 } 617 618 ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D); 619 if (OCI == 0) { 620 S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface); 621 return; 622 } 623 624 D->addAttr(S.Context, ::new (S.Context) ObjCExceptionAttr()); 625} 626 627static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) { 628 if (Attr.getNumArgs() != 0) { 629 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 630 return; 631 } 632 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { 633 QualType T = TD->getUnderlyingType(); 634 if (!T->isPointerType() || 635 !T->getAsPointerType()->getPointeeType()->isRecordType()) { 636 S.Diag(TD->getLocation(), diag::err_nsobject_attribute); 637 return; 638 } 639 } 640 D->addAttr(S.Context, ::new (S.Context) ObjCNSObjectAttr()); 641} 642 643static void 644HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) { 645 if (Attr.getNumArgs() != 0) { 646 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 647 return; 648 } 649 650 if (!isa<FunctionDecl>(D)) { 651 S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function); 652 return; 653 } 654 655 D->addAttr(S.Context, ::new (S.Context) OverloadableAttr()); 656} 657 658static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { 659 if (!Attr.getParameterName()) { 660 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) 661 << "blocks" << 1; 662 return; 663 } 664 665 if (Attr.getNumArgs() != 0) { 666 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 667 return; 668 } 669 670 BlocksAttr::BlocksAttrTypes type; 671 if (Attr.getParameterName()->isStr("byref")) 672 type = BlocksAttr::ByRef; 673 else { 674 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) 675 << "blocks" << Attr.getParameterName(); 676 return; 677 } 678 679 d->addAttr(S.Context, ::new (S.Context) BlocksAttr(type)); 680} 681 682static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { 683 // check the attribute arguments. 684 if (Attr.getNumArgs() > 2) { 685 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 686 << "0, 1 or 2"; 687 return; 688 } 689 690 int sentinel = 0; 691 if (Attr.getNumArgs() > 0) { 692 Expr *E = static_cast<Expr *>(Attr.getArg(0)); 693 llvm::APSInt Idx(32); 694 if (!E->isIntegerConstantExpr(Idx, S.Context)) { 695 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 696 << "sentinel" << 1 << E->getSourceRange(); 697 return; 698 } 699 sentinel = Idx.getZExtValue(); 700 701 if (sentinel < 0) { 702 S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero) 703 << E->getSourceRange(); 704 return; 705 } 706 } 707 708 int nullPos = 0; 709 if (Attr.getNumArgs() > 1) { 710 Expr *E = static_cast<Expr *>(Attr.getArg(1)); 711 llvm::APSInt Idx(32); 712 if (!E->isIntegerConstantExpr(Idx, S.Context)) { 713 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 714 << "sentinel" << 2 << E->getSourceRange(); 715 return; 716 } 717 nullPos = Idx.getZExtValue(); 718 719 if (nullPos > 1 || nullPos < 0) { 720 // FIXME: This error message could be improved, it would be nice 721 // to say what the bounds actually are. 722 S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one) 723 << E->getSourceRange(); 724 return; 725 } 726 } 727 728 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) { 729 const FunctionType *FT = FD->getType()->getAsFunctionType(); 730 assert(FT && "FunctionDecl has non-function type?"); 731 732 if (isa<FunctionNoProtoType>(FT)) { 733 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_named_arguments); 734 return; 735 } 736 737 if (!cast<FunctionProtoType>(FT)->isVariadic()) { 738 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; 739 return; 740 } 741 } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) { 742 if (!MD->isVariadic()) { 743 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; 744 return; 745 } 746 } else if (isa<BlockDecl>(d)) { 747 // Note! BlockDecl is typeless. Variadic diagnostics 748 // will be issued by the caller. 749 ; 750 } else if (const VarDecl *V = dyn_cast<VarDecl>(d)) { 751 QualType Ty = V->getType(); 752 if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) { 753 const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(d) 754 : Ty->getAsBlockPointerType()->getPointeeType()->getAsFunctionType(); 755 if (!cast<FunctionProtoType>(FT)->isVariadic()) { 756 int m = Ty->isFunctionPointerType() ? 0 : 1; 757 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m; 758 return; 759 } 760 } 761 else { 762 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 763 << Attr.getName() << 6 /*function, method or block */; 764 return; 765 } 766 } else { 767 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 768 << Attr.getName() << 6 /*function, method or block */; 769 return; 770 } 771 d->addAttr(S.Context, ::new (S.Context) SentinelAttr(sentinel, nullPos)); 772} 773 774static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) { 775 // check the attribute arguments. 776 if (Attr.getNumArgs() != 0) { 777 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 778 return; 779 } 780 781 // TODO: could also be applied to methods? 782 FunctionDecl *Fn = dyn_cast<FunctionDecl>(D); 783 if (!Fn) { 784 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 785 << Attr.getName() << 0 /*function*/; 786 return; 787 } 788 789 Fn->addAttr(S.Context, ::new (S.Context) WarnUnusedResultAttr()); 790} 791 792static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) { 793 // check the attribute arguments. 794 if (Attr.getNumArgs() != 0) { 795 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 796 return; 797 } 798 799 // TODO: could also be applied to methods? 800 if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D)) { 801 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 802 << Attr.getName() << 2 /*variable and function*/; 803 return; 804 } 805 806 D->addAttr(S.Context, ::new (S.Context) WeakAttr()); 807} 808 809static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { 810 // check the attribute arguments. 811 if (Attr.getNumArgs() != 0) { 812 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 813 return; 814 } 815 816 // weak_import only applies to variable & function declarations. 817 bool isDef = false; 818 if (VarDecl *VD = dyn_cast<VarDecl>(D)) { 819 isDef = (!VD->hasExternalStorage() || VD->getInit()); 820 } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 821 isDef = FD->getBody(S.Context); 822 } else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D)) { 823 // We ignore weak import on properties and methods 824 return; 825 } else { 826 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 827 << Attr.getName() << 2 /*variable and function*/; 828 return; 829 } 830 831 // Merge should handle any subsequent violations. 832 if (isDef) { 833 S.Diag(Attr.getLoc(), 834 diag::warn_attribute_weak_import_invalid_on_definition) 835 << "weak_import" << 2 /*variable and function*/; 836 return; 837 } 838 839 D->addAttr(S.Context, ::new (S.Context) WeakImportAttr()); 840} 841 842static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { 843 // check the attribute arguments. 844 if (Attr.getNumArgs() != 0) { 845 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 846 return; 847 } 848 849 // Attribute can be applied only to functions or variables. 850 if (isa<VarDecl>(D)) { 851 D->addAttr(S.Context, ::new (S.Context) DLLImportAttr()); 852 return; 853 } 854 855 FunctionDecl *FD = dyn_cast<FunctionDecl>(D); 856 if (!FD) { 857 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 858 << Attr.getName() << 2 /*variable and function*/; 859 return; 860 } 861 862 // Currently, the dllimport attribute is ignored for inlined functions. 863 // Warning is emitted. 864 if (FD->isInline()) { 865 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; 866 return; 867 } 868 869 // The attribute is also overridden by a subsequent declaration as dllexport. 870 // Warning is emitted. 871 for (AttributeList *nextAttr = Attr.getNext(); nextAttr; 872 nextAttr = nextAttr->getNext()) { 873 if (nextAttr->getKind() == AttributeList::AT_dllexport) { 874 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; 875 return; 876 } 877 } 878 879 if (D->getAttr<DLLExportAttr>(S.Context)) { 880 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; 881 return; 882 } 883 884 D->addAttr(S.Context, ::new (S.Context) DLLImportAttr()); 885} 886 887static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { 888 // check the attribute arguments. 889 if (Attr.getNumArgs() != 0) { 890 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 891 return; 892 } 893 894 // Attribute can be applied only to functions or variables. 895 if (isa<VarDecl>(D)) { 896 D->addAttr(S.Context, ::new (S.Context) DLLExportAttr()); 897 return; 898 } 899 900 FunctionDecl *FD = dyn_cast<FunctionDecl>(D); 901 if (!FD) { 902 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 903 << Attr.getName() << 2 /*variable and function*/; 904 return; 905 } 906 907 // Currently, the dllexport attribute is ignored for inlined functions, 908 // unless the -fkeep-inline-functions flag has been used. Warning is emitted; 909 if (FD->isInline()) { 910 // FIXME: ... unless the -fkeep-inline-functions flag has been used. 911 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport"; 912 return; 913 } 914 915 D->addAttr(S.Context, ::new (S.Context) DLLExportAttr()); 916} 917 918static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr, 919 Sema &S) { 920 // Attribute has 3 arguments. 921 if (Attr.getNumArgs() != 3) { 922 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 923 return; 924 } 925 926 unsigned WGSize[3]; 927 for (unsigned i = 0; i < 3; ++i) { 928 Expr *E = static_cast<Expr *>(Attr.getArg(i)); 929 llvm::APSInt ArgNum(32); 930 if (!E->isIntegerConstantExpr(ArgNum, S.Context)) { 931 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 932 << "reqd_work_group_size" << E->getSourceRange(); 933 return; 934 } 935 WGSize[i] = (unsigned) ArgNum.getZExtValue(); 936 } 937 D->addAttr(S.Context, 938 ::new (S.Context) ReqdWorkGroupSizeAttr(WGSize[0], WGSize[1], 939 WGSize[2])); 940} 941 942static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { 943 // Attribute has no arguments. 944 if (Attr.getNumArgs() != 1) { 945 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 946 return; 947 } 948 949 // Make sure that there is a string literal as the sections's single 950 // argument. 951 StringLiteral *SE = 952 dyn_cast<StringLiteral>(static_cast<Expr *>(Attr.getArg(0))); 953 if (!SE) { 954 // FIXME 955 S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string); 956 return; 957 } 958 D->addAttr(S.Context, 959 ::new (S.Context) SectionAttr(std::string(SE->getStrData(), 960 SE->getByteLength()))); 961} 962 963static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { 964 // Attribute has no arguments. 965 if (Attr.getNumArgs() != 0) { 966 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 967 return; 968 } 969 970 // Attribute can be applied only to functions. 971 if (!isa<FunctionDecl>(d)) { 972 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 973 << Attr.getName() << 0 /*function*/; 974 return; 975 } 976 977 // stdcall and fastcall attributes are mutually incompatible. 978 if (d->getAttr<FastCallAttr>(S.Context)) { 979 S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) 980 << "stdcall" << "fastcall"; 981 return; 982 } 983 984 d->addAttr(S.Context, ::new (S.Context) StdCallAttr()); 985} 986 987static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { 988 // Attribute has no arguments. 989 if (Attr.getNumArgs() != 0) { 990 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 991 return; 992 } 993 994 if (!isa<FunctionDecl>(d)) { 995 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 996 << Attr.getName() << 0 /*function*/; 997 return; 998 } 999 1000 // stdcall and fastcall attributes are mutually incompatible. 1001 if (d->getAttr<StdCallAttr>(S.Context)) { 1002 S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) 1003 << "fastcall" << "stdcall"; 1004 return; 1005 } 1006 1007 d->addAttr(S.Context, ::new (S.Context) FastCallAttr()); 1008} 1009 1010static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1011 // check the attribute arguments. 1012 if (Attr.getNumArgs() != 0) { 1013 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1014 return; 1015 } 1016 1017 d->addAttr(S.Context, ::new (S.Context) NoThrowAttr()); 1018} 1019 1020static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1021 // check the attribute arguments. 1022 if (Attr.getNumArgs() != 0) { 1023 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1024 return; 1025 } 1026 1027 d->addAttr(S.Context, ::new (S.Context) ConstAttr()); 1028} 1029 1030static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1031 // check the attribute arguments. 1032 if (Attr.getNumArgs() != 0) { 1033 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1034 return; 1035 } 1036 1037 d->addAttr(S.Context, ::new (S.Context) PureAttr()); 1038} 1039 1040static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1041 // Match gcc which ignores cleanup attrs when compiling C++. 1042 if (S.getLangOptions().CPlusPlus) 1043 return; 1044 1045 if (!Attr.getParameterName()) { 1046 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 1047 return; 1048 } 1049 1050 if (Attr.getNumArgs() != 0) { 1051 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 1052 return; 1053 } 1054 1055 VarDecl *VD = dyn_cast<VarDecl>(d); 1056 1057 if (!VD || !VD->hasLocalStorage()) { 1058 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup"; 1059 return; 1060 } 1061 1062 // Look up the function 1063 NamedDecl *CleanupDecl = S.LookupName(S.TUScope, Attr.getParameterName(), 1064 Sema::LookupOrdinaryName); 1065 if (!CleanupDecl) { 1066 S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_found) << 1067 Attr.getParameterName(); 1068 return; 1069 } 1070 1071 FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl); 1072 if (!FD) { 1073 S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_function) << 1074 Attr.getParameterName(); 1075 return; 1076 } 1077 1078 if (FD->getNumParams() != 1) { 1079 S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_func_must_take_one_arg) << 1080 Attr.getParameterName(); 1081 return; 1082 } 1083 1084 // We're currently more strict than GCC about what function types we accept. 1085 // If this ever proves to be a problem it should be easy to fix. 1086 QualType Ty = S.Context.getPointerType(VD->getType()); 1087 QualType ParamTy = FD->getParamDecl(0)->getType(); 1088 if (S.CheckAssignmentConstraints(ParamTy, Ty) != Sema::Compatible) { 1089 S.Diag(Attr.getLoc(), 1090 diag::err_attribute_cleanup_func_arg_incompatible_type) << 1091 Attr.getParameterName() << ParamTy << Ty; 1092 return; 1093 } 1094 1095 d->addAttr(S.Context, ::new (S.Context) CleanupAttr(FD)); 1096} 1097 1098/// Handle __attribute__((format_arg((idx)))) attribute 1099/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html 1100static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1101 if (Attr.getNumArgs() != 1) { 1102 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 1103 return; 1104 } 1105 if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { 1106 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1107 << Attr.getName() << 0 /*function*/; 1108 return; 1109 } 1110 // FIXME: in C++ the implicit 'this' function parameter also counts. 1111 // this is needed in order to be compatible with GCC 1112 // the index must start with 1. 1113 unsigned NumArgs = getFunctionOrMethodNumArgs(d); 1114 unsigned FirstIdx = 1; 1115 // checks for the 2nd argument 1116 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0)); 1117 llvm::APSInt Idx(32); 1118 if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { 1119 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 1120 << "format" << 2 << IdxExpr->getSourceRange(); 1121 return; 1122 } 1123 1124 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { 1125 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 1126 << "format" << 2 << IdxExpr->getSourceRange(); 1127 return; 1128 } 1129 1130 unsigned ArgIdx = Idx.getZExtValue() - 1; 1131 1132 // make sure the format string is really a string 1133 QualType Ty = getFunctionOrMethodArgType(d, ArgIdx); 1134 1135 bool not_nsstring_type = !isNSStringType(Ty, S.Context); 1136 if (not_nsstring_type && 1137 !isCFStringType(Ty, S.Context) && 1138 (!Ty->isPointerType() || 1139 !Ty->getAsPointerType()->getPointeeType()->isCharType())) { 1140 // FIXME: Should highlight the actual expression that has the wrong type. 1141 S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 1142 << (not_nsstring_type ? "a string type" : "an NSString") 1143 << IdxExpr->getSourceRange(); 1144 return; 1145 } 1146 Ty = getFunctionOrMethodResultType(d); 1147 if (!isNSStringType(Ty, S.Context) && 1148 !isCFStringType(Ty, S.Context) && 1149 (!Ty->isPointerType() || 1150 !Ty->getAsPointerType()->getPointeeType()->isCharType())) { 1151 // FIXME: Should highlight the actual expression that has the wrong type. 1152 S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not) 1153 << (not_nsstring_type ? "string type" : "NSString") 1154 << IdxExpr->getSourceRange(); 1155 return; 1156 } 1157 1158 d->addAttr(S.Context, ::new (S.Context) FormatArgAttr(Idx.getZExtValue())); 1159} 1160 1161/// Handle __attribute__((format(type,idx,firstarg))) attributes 1162/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html 1163static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1164 1165 if (!Attr.getParameterName()) { 1166 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) 1167 << "format" << 1; 1168 return; 1169 } 1170 1171 if (Attr.getNumArgs() != 2) { 1172 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3; 1173 return; 1174 } 1175 1176 if (!isFunctionOrMethodOrBlock(d) || !hasFunctionProto(d)) { 1177 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1178 << Attr.getName() << 0 /*function*/; 1179 return; 1180 } 1181 1182 // FIXME: in C++ the implicit 'this' function parameter also counts. 1183 // this is needed in order to be compatible with GCC 1184 // the index must start in 1 and the limit is numargs+1 1185 unsigned NumArgs = getFunctionOrMethodNumArgs(d); 1186 unsigned FirstIdx = 1; 1187 1188 const char *Format = Attr.getParameterName()->getName(); 1189 unsigned FormatLen = Attr.getParameterName()->getLength(); 1190 1191 // Normalize the argument, __foo__ becomes foo. 1192 if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' && 1193 Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') { 1194 Format += 2; 1195 FormatLen -= 4; 1196 } 1197 1198 bool Supported = false; 1199 bool is_NSString = false; 1200 bool is_strftime = false; 1201 bool is_CFString = false; 1202 1203 switch (FormatLen) { 1204 default: break; 1205 case 5: Supported = !memcmp(Format, "scanf", 5); break; 1206 case 6: Supported = !memcmp(Format, "printf", 6); break; 1207 case 7: Supported = !memcmp(Format, "strfmon", 7); break; 1208 case 8: 1209 Supported = (is_strftime = !memcmp(Format, "strftime", 8)) || 1210 (is_NSString = !memcmp(Format, "NSString", 8)) || 1211 (is_CFString = !memcmp(Format, "CFString", 8)); 1212 break; 1213 } 1214 1215 if (!Supported) { 1216 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) 1217 << "format" << Attr.getParameterName()->getName(); 1218 return; 1219 } 1220 1221 // checks for the 2nd argument 1222 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0)); 1223 llvm::APSInt Idx(32); 1224 if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { 1225 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 1226 << "format" << 2 << IdxExpr->getSourceRange(); 1227 return; 1228 } 1229 1230 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { 1231 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 1232 << "format" << 2 << IdxExpr->getSourceRange(); 1233 return; 1234 } 1235 1236 // FIXME: Do we need to bounds check? 1237 unsigned ArgIdx = Idx.getZExtValue() - 1; 1238 1239 // make sure the format string is really a string 1240 QualType Ty = getFunctionOrMethodArgType(d, ArgIdx); 1241 1242 if (is_CFString) { 1243 if (!isCFStringType(Ty, S.Context)) { 1244 S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 1245 << "a CFString" << IdxExpr->getSourceRange(); 1246 return; 1247 } 1248 } else if (is_NSString) { 1249 // FIXME: do we need to check if the type is NSString*? What are the 1250 // semantics? 1251 if (!isNSStringType(Ty, S.Context)) { 1252 // FIXME: Should highlight the actual expression that has the wrong type. 1253 S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 1254 << "an NSString" << IdxExpr->getSourceRange(); 1255 return; 1256 } 1257 } else if (!Ty->isPointerType() || 1258 !Ty->getAsPointerType()->getPointeeType()->isCharType()) { 1259 // FIXME: Should highlight the actual expression that has the wrong type. 1260 S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 1261 << "a string type" << IdxExpr->getSourceRange(); 1262 return; 1263 } 1264 1265 // check the 3rd argument 1266 Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1)); 1267 llvm::APSInt FirstArg(32); 1268 if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) { 1269 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 1270 << "format" << 3 << FirstArgExpr->getSourceRange(); 1271 return; 1272 } 1273 1274 // check if the function is variadic if the 3rd argument non-zero 1275 if (FirstArg != 0) { 1276 if (isFunctionOrMethodVariadic(d)) { 1277 ++NumArgs; // +1 for ... 1278 } else { 1279 S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic); 1280 return; 1281 } 1282 } 1283 1284 // strftime requires FirstArg to be 0 because it doesn't read from any 1285 // variable the input is just the current time + the format string. 1286 if (is_strftime) { 1287 if (FirstArg != 0) { 1288 S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter) 1289 << FirstArgExpr->getSourceRange(); 1290 return; 1291 } 1292 // if 0 it disables parameter checking (to use with e.g. va_list) 1293 } else if (FirstArg != 0 && FirstArg != NumArgs) { 1294 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 1295 << "format" << 3 << FirstArgExpr->getSourceRange(); 1296 return; 1297 } 1298 1299 d->addAttr(S.Context, 1300 ::new (S.Context) FormatAttr(std::string(Format, FormatLen), 1301 Idx.getZExtValue(), FirstArg.getZExtValue())); 1302} 1303 1304static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, 1305 Sema &S) { 1306 // check the attribute arguments. 1307 if (Attr.getNumArgs() != 0) { 1308 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1309 return; 1310 } 1311 1312 // Try to find the underlying union declaration. 1313 RecordDecl *RD = 0; 1314 TypedefDecl *TD = dyn_cast<TypedefDecl>(d); 1315 if (TD && TD->getUnderlyingType()->isUnionType()) 1316 RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); 1317 else 1318 RD = dyn_cast<RecordDecl>(d); 1319 1320 if (!RD || !RD->isUnion()) { 1321 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1322 << Attr.getName() << 1 /*union*/; 1323 return; 1324 } 1325 1326 if (!RD->isDefinition()) { 1327 S.Diag(Attr.getLoc(), 1328 diag::warn_transparent_union_attribute_not_definition); 1329 return; 1330 } 1331 1332 RecordDecl::field_iterator Field = RD->field_begin(S.Context), 1333 FieldEnd = RD->field_end(S.Context); 1334 if (Field == FieldEnd) { 1335 S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields); 1336 return; 1337 } 1338 1339 FieldDecl *FirstField = *Field; 1340 QualType FirstType = FirstField->getType(); 1341 if (FirstType->isFloatingType() || FirstType->isVectorType()) { 1342 S.Diag(FirstField->getLocation(), 1343 diag::warn_transparent_union_attribute_floating); 1344 return; 1345 } 1346 1347 uint64_t FirstSize = S.Context.getTypeSize(FirstType); 1348 uint64_t FirstAlign = S.Context.getTypeAlign(FirstType); 1349 for (; Field != FieldEnd; ++Field) { 1350 QualType FieldType = Field->getType(); 1351 if (S.Context.getTypeSize(FieldType) != FirstSize || 1352 S.Context.getTypeAlign(FieldType) != FirstAlign) { 1353 // Warn if we drop the attribute. 1354 bool isSize = S.Context.getTypeSize(FieldType) != FirstSize; 1355 unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType) 1356 : S.Context.getTypeAlign(FieldType); 1357 S.Diag(Field->getLocation(), 1358 diag::warn_transparent_union_attribute_field_size_align) 1359 << isSize << Field->getDeclName() << FieldBits; 1360 unsigned FirstBits = isSize? FirstSize : FirstAlign; 1361 S.Diag(FirstField->getLocation(), 1362 diag::note_transparent_union_first_field_size_align) 1363 << isSize << FirstBits; 1364 return; 1365 } 1366 } 1367 1368 RD->addAttr(S.Context, ::new (S.Context) TransparentUnionAttr()); 1369} 1370 1371static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1372 // check the attribute arguments. 1373 if (Attr.getNumArgs() != 1) { 1374 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 1375 return; 1376 } 1377 Expr *argExpr = static_cast<Expr *>(Attr.getArg(0)); 1378 StringLiteral *SE = dyn_cast<StringLiteral>(argExpr); 1379 1380 // Make sure that there is a string literal as the annotation's single 1381 // argument. 1382 if (!SE) { 1383 S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string); 1384 return; 1385 } 1386 d->addAttr(S.Context, 1387 ::new (S.Context) AnnotateAttr(std::string(SE->getStrData(), 1388 SE->getByteLength()))); 1389} 1390 1391static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1392 // check the attribute arguments. 1393 if (Attr.getNumArgs() > 1) { 1394 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 1395 return; 1396 } 1397 1398 unsigned Align = 0; 1399 if (Attr.getNumArgs() == 0) { 1400 // FIXME: This should be the target specific maximum alignment. 1401 // (For now we just use 128 bits which is the maximum on X86). 1402 Align = 128; 1403 d->addAttr(S.Context, ::new (S.Context) AlignedAttr(Align)); 1404 return; 1405 } 1406 1407 Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0)); 1408 llvm::APSInt Alignment(32); 1409 if (!alignmentExpr->isIntegerConstantExpr(Alignment, S.Context)) { 1410 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 1411 << "aligned" << alignmentExpr->getSourceRange(); 1412 return; 1413 } 1414 if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) { 1415 S.Diag(Attr.getLoc(), diag::err_attribute_aligned_not_power_of_two) 1416 << alignmentExpr->getSourceRange(); 1417 return; 1418 } 1419 1420 d->addAttr(S.Context, ::new (S.Context) AlignedAttr(Alignment.getZExtValue() * 8)); 1421} 1422 1423/// HandleModeAttr - This attribute modifies the width of a decl with 1424/// primitive type. 1425/// 1426/// Despite what would be logical, the mode attribute is a decl attribute, 1427/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 1428/// 'G' be HImode, not an intermediate pointer. 1429/// 1430static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { 1431 // This attribute isn't documented, but glibc uses it. It changes 1432 // the width of an int or unsigned int to the specified size. 1433 1434 // Check that there aren't any arguments 1435 if (Attr.getNumArgs() != 0) { 1436 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1437 return; 1438 } 1439 1440 IdentifierInfo *Name = Attr.getParameterName(); 1441 if (!Name) { 1442 S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name); 1443 return; 1444 } 1445 const char *Str = Name->getName(); 1446 unsigned Len = Name->getLength(); 1447 1448 // Normalize the attribute name, __foo__ becomes foo. 1449 if (Len > 4 && Str[0] == '_' && Str[1] == '_' && 1450 Str[Len - 2] == '_' && Str[Len - 1] == '_') { 1451 Str += 2; 1452 Len -= 4; 1453 } 1454 1455 unsigned DestWidth = 0; 1456 bool IntegerMode = true; 1457 bool ComplexMode = false; 1458 switch (Len) { 1459 case 2: 1460 switch (Str[0]) { 1461 case 'Q': DestWidth = 8; break; 1462 case 'H': DestWidth = 16; break; 1463 case 'S': DestWidth = 32; break; 1464 case 'D': DestWidth = 64; break; 1465 case 'X': DestWidth = 96; break; 1466 case 'T': DestWidth = 128; break; 1467 } 1468 if (Str[1] == 'F') { 1469 IntegerMode = false; 1470 } else if (Str[1] == 'C') { 1471 IntegerMode = false; 1472 ComplexMode = true; 1473 } else if (Str[1] != 'I') { 1474 DestWidth = 0; 1475 } 1476 break; 1477 case 4: 1478 // FIXME: glibc uses 'word' to define register_t; this is narrower than a 1479 // pointer on PIC16 and other embedded platforms. 1480 if (!memcmp(Str, "word", 4)) 1481 DestWidth = S.Context.Target.getPointerWidth(0); 1482 if (!memcmp(Str, "byte", 4)) 1483 DestWidth = S.Context.Target.getCharWidth(); 1484 break; 1485 case 7: 1486 if (!memcmp(Str, "pointer", 7)) 1487 DestWidth = S.Context.Target.getPointerWidth(0); 1488 break; 1489 } 1490 1491 QualType OldTy; 1492 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) 1493 OldTy = TD->getUnderlyingType(); 1494 else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 1495 OldTy = VD->getType(); 1496 else { 1497 S.Diag(D->getLocation(), diag::err_attr_wrong_decl) 1498 << "mode" << SourceRange(Attr.getLoc(), Attr.getLoc()); 1499 return; 1500 } 1501 1502 if (!OldTy->getAsBuiltinType() && !OldTy->isComplexType()) 1503 S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); 1504 else if (IntegerMode) { 1505 if (!OldTy->isIntegralType()) 1506 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); 1507 } else if (ComplexMode) { 1508 if (!OldTy->isComplexType()) 1509 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); 1510 } else { 1511 if (!OldTy->isFloatingType()) 1512 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); 1513 } 1514 1515 // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t 1516 // and friends, at least with glibc. 1517 // FIXME: Make sure 32/64-bit integers don't get defined to types of the wrong 1518 // width on unusual platforms. 1519 // FIXME: Make sure floating-point mappings are accurate 1520 // FIXME: Support XF and TF types 1521 QualType NewTy; 1522 switch (DestWidth) { 1523 case 0: 1524 S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name; 1525 return; 1526 default: 1527 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; 1528 return; 1529 case 8: 1530 if (!IntegerMode) { 1531 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; 1532 return; 1533 } 1534 if (OldTy->isSignedIntegerType()) 1535 NewTy = S.Context.SignedCharTy; 1536 else 1537 NewTy = S.Context.UnsignedCharTy; 1538 break; 1539 case 16: 1540 if (!IntegerMode) { 1541 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; 1542 return; 1543 } 1544 if (OldTy->isSignedIntegerType()) 1545 NewTy = S.Context.ShortTy; 1546 else 1547 NewTy = S.Context.UnsignedShortTy; 1548 break; 1549 case 32: 1550 if (!IntegerMode) 1551 NewTy = S.Context.FloatTy; 1552 else if (OldTy->isSignedIntegerType()) 1553 NewTy = S.Context.IntTy; 1554 else 1555 NewTy = S.Context.UnsignedIntTy; 1556 break; 1557 case 64: 1558 if (!IntegerMode) 1559 NewTy = S.Context.DoubleTy; 1560 else if (OldTy->isSignedIntegerType()) 1561 NewTy = S.Context.LongLongTy; 1562 else 1563 NewTy = S.Context.UnsignedLongLongTy; 1564 break; 1565 case 96: 1566 NewTy = S.Context.LongDoubleTy; 1567 break; 1568 case 128: 1569 if (!IntegerMode) { 1570 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; 1571 return; 1572 } 1573 NewTy = S.Context.getFixedWidthIntType(128, OldTy->isSignedIntegerType()); 1574 break; 1575 } 1576 1577 if (ComplexMode) { 1578 NewTy = S.Context.getComplexType(NewTy); 1579 } 1580 1581 // Install the new type. 1582 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) 1583 TD->setUnderlyingType(NewTy); 1584 else 1585 cast<ValueDecl>(D)->setType(NewTy); 1586} 1587 1588static void HandleNodebugAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1589 // check the attribute arguments. 1590 if (Attr.getNumArgs() > 0) { 1591 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1592 return; 1593 } 1594 1595 if (!isFunctionOrMethod(d)) { 1596 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1597 << Attr.getName() << 0 /*function*/; 1598 return; 1599 } 1600 1601 d->addAttr(S.Context, ::new (S.Context) NodebugAttr()); 1602} 1603 1604static void HandleNoinlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1605 // check the attribute arguments. 1606 if (Attr.getNumArgs() != 0) { 1607 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1608 return; 1609 } 1610 1611 if (!isa<FunctionDecl>(d)) { 1612 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1613 << Attr.getName() << 0 /*function*/; 1614 return; 1615 } 1616 1617 d->addAttr(S.Context, ::new (S.Context) NoinlineAttr()); 1618} 1619 1620static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1621 // check the attribute arguments. 1622 if (Attr.getNumArgs() != 0) { 1623 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1624 return; 1625 } 1626 1627 FunctionDecl *Fn = dyn_cast<FunctionDecl>(d); 1628 if (Fn == 0) { 1629 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1630 << Attr.getName() << 0 /*function*/; 1631 return; 1632 } 1633 1634 if (!Fn->isInline()) { 1635 S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline); 1636 return; 1637 } 1638 1639 d->addAttr(S.Context, ::new (S.Context) GNUInlineAttr()); 1640} 1641 1642static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1643 // check the attribute arguments. 1644 if (Attr.getNumArgs() != 1) { 1645 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 1646 return; 1647 } 1648 1649 if (!isFunctionOrMethod(d)) { 1650 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1651 << Attr.getName() << 0 /*function*/; 1652 return; 1653 } 1654 1655 Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0)); 1656 llvm::APSInt NumParams(32); 1657 if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) { 1658 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 1659 << "regparm" << NumParamsExpr->getSourceRange(); 1660 return; 1661 } 1662 1663 if (S.Context.Target.getRegParmMax() == 0) { 1664 S.Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform) 1665 << NumParamsExpr->getSourceRange(); 1666 return; 1667 } 1668 1669 if (NumParams.getLimitedValue(255) > S.Context.Target.getRegParmMax()) { 1670 S.Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number) 1671 << S.Context.Target.getRegParmMax() << NumParamsExpr->getSourceRange(); 1672 return; 1673 } 1674 1675 d->addAttr(S.Context, 1676 ::new (S.Context) RegparmAttr(NumParams.getZExtValue())); 1677} 1678 1679//===----------------------------------------------------------------------===// 1680// Checker-specific attribute handlers. 1681//===----------------------------------------------------------------------===// 1682 1683static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr, 1684 Sema &S) { 1685 1686 QualType RetTy; 1687 1688 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) 1689 RetTy = MD->getResultType(); 1690 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) 1691 RetTy = FD->getResultType(); 1692 else { 1693 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1694 << Attr.getName() << 3 /* function or method */; 1695 return; 1696 } 1697 1698 if (!(S.Context.isObjCNSObjectType(RetTy) || RetTy->getAsPointerType())) { 1699 S.Diag(Attr.getLoc(), diag::warn_ns_attribute_wrong_return_type) 1700 << Attr.getName(); 1701 return; 1702 } 1703 1704 switch (Attr.getKind()) { 1705 default: 1706 assert(0 && "invalid ownership attribute"); 1707 return; 1708 case AttributeList::AT_cf_returns_retained: 1709 d->addAttr(S.Context, ::new (S.Context) CFReturnsRetainedAttr()); 1710 return; 1711 case AttributeList::AT_ns_returns_retained: 1712 d->addAttr(S.Context, ::new (S.Context) NSReturnsRetainedAttr()); 1713 return; 1714 }; 1715} 1716 1717//===----------------------------------------------------------------------===// 1718// Top Level Sema Entry Points 1719//===----------------------------------------------------------------------===// 1720 1721/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if 1722/// the attribute applies to decls. If the attribute is a type attribute, just 1723/// silently ignore it. 1724static void ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr, Sema &S) { 1725 if (Attr.isDeclspecAttribute()) 1726 // FIXME: Try to deal with __declspec attributes! 1727 return; 1728 switch (Attr.getKind()) { 1729 case AttributeList::AT_IBOutlet: HandleIBOutletAttr (D, Attr, S); break; 1730 case AttributeList::AT_address_space: 1731 case AttributeList::AT_objc_gc: 1732 // Ignore these, these are type attributes, handled by ProcessTypeAttributes. 1733 break; 1734 case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break; 1735 case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break; 1736 case AttributeList::AT_always_inline: 1737 HandleAlwaysInlineAttr (D, Attr, S); break; 1738 case AttributeList::AT_analyzer_noreturn: 1739 HandleAnalyzerNoReturnAttr (D, Attr, S); break; 1740 case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break; 1741 case AttributeList::AT_constructor: HandleConstructorAttr(D, Attr, S); break; 1742 case AttributeList::AT_deprecated: HandleDeprecatedAttr(D, Attr, S); break; 1743 case AttributeList::AT_destructor: HandleDestructorAttr(D, Attr, S); break; 1744 case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break; 1745 case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break; 1746 case AttributeList::AT_ext_vector_type: 1747 HandleExtVectorTypeAttr(scope, D, Attr, S); 1748 break; 1749 case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break; 1750 case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break; 1751 case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break; 1752 case AttributeList::AT_gnu_inline: HandleGNUInlineAttr(D, Attr, S); break; 1753 case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break; 1754 case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break; 1755 case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break; 1756 case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break; 1757 1758 // Checker-specific. 1759 case AttributeList::AT_ns_returns_retained: 1760 case AttributeList::AT_cf_returns_retained: 1761 HandleNSReturnsRetainedAttr(D, Attr, S); break; 1762 1763 case AttributeList::AT_reqd_wg_size: 1764 HandleReqdWorkGroupSize(D, Attr, S); break; 1765 1766 case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; 1767 case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break; 1768 case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break; 1769 case AttributeList::AT_unavailable: HandleUnavailableAttr(D, Attr, S); break; 1770 case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break; 1771 case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break; 1772 case AttributeList::AT_vector_size: HandleVectorSizeAttr(D, Attr, S); break; 1773 case AttributeList::AT_visibility: HandleVisibilityAttr(D, Attr, S); break; 1774 case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S); 1775 break; 1776 case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break; 1777 case AttributeList::AT_weak_import: HandleWeakImportAttr(D, Attr, S); break; 1778 case AttributeList::AT_transparent_union: 1779 HandleTransparentUnionAttr(D, Attr, S); 1780 break; 1781 case AttributeList::AT_objc_exception: 1782 HandleObjCExceptionAttr(D, Attr, S); 1783 break; 1784 case AttributeList::AT_overloadable:HandleOverloadableAttr(D, Attr, S); break; 1785 case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break; 1786 case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break; 1787 case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break; 1788 case AttributeList::AT_const: HandleConstAttr (D, Attr, S); break; 1789 case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break; 1790 case AttributeList::AT_cleanup: HandleCleanupAttr (D, Attr, S); break; 1791 case AttributeList::AT_nodebug: HandleNodebugAttr (D, Attr, S); break; 1792 case AttributeList::AT_noinline: HandleNoinlineAttr (D, Attr, S); break; 1793 case AttributeList::AT_regparm: HandleRegparmAttr (D, Attr, S); break; 1794 case AttributeList::IgnoredAttribute: 1795 case AttributeList::AT_no_instrument_function: // Interacts with -pg. 1796 // Just ignore 1797 break; 1798 default: 1799 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 1800 break; 1801 } 1802} 1803 1804/// ProcessDeclAttributeList - Apply all the decl attributes in the specified 1805/// attribute list to the specified decl, ignoring any type attributes. 1806void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList) { 1807 while (AttrList) { 1808 ProcessDeclAttribute(S, D, *AttrList, *this); 1809 AttrList = AttrList->getNext(); 1810 } 1811} 1812 1813/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in 1814/// it, apply them to D. This is a bit tricky because PD can have attributes 1815/// specified in many different places, and we need to find and apply them all. 1816void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { 1817 // Apply decl attributes from the DeclSpec if present. 1818 if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes()) 1819 ProcessDeclAttributeList(S, D, Attrs); 1820 1821 // Walk the declarator structure, applying decl attributes that were in a type 1822 // position to the decl itself. This handles cases like: 1823 // int *__attr__(x)** D; 1824 // when X is a decl attribute. 1825 for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) 1826 if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) 1827 ProcessDeclAttributeList(S, D, Attrs); 1828 1829 // Finally, apply any attributes on the decl itself. 1830 if (const AttributeList *Attrs = PD.getAttributes()) 1831 ProcessDeclAttributeList(S, D, Attrs); 1832} 1833