SemaDeclAttr.cpp revision 14108da7f7fc059772711e4ffee1322a27b152a7
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 ObjCObjectPointerType *PT = T->getAsObjCObjectPointerType(); 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(::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(::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(::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(::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(::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(::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(::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(::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(::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(::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(::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(::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(::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(::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(::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(::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(::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(::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(::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(::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(::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(::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(); 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(::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(::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>()) { 880 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; 881 return; 882 } 883 884 D->addAttr(::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(::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(::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(::new (S.Context) ReqdWorkGroupSizeAttr(WGSize[0], WGSize[1], 938 WGSize[2])); 939} 940 941static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { 942 // Attribute has no arguments. 943 if (Attr.getNumArgs() != 1) { 944 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 945 return; 946 } 947 948 // Make sure that there is a string literal as the sections's single 949 // argument. 950 StringLiteral *SE = 951 dyn_cast<StringLiteral>(static_cast<Expr *>(Attr.getArg(0))); 952 if (!SE) { 953 // FIXME 954 S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string); 955 return; 956 } 957 D->addAttr(::new (S.Context) SectionAttr(std::string(SE->getStrData(), 958 SE->getByteLength()))); 959} 960 961static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { 962 // Attribute has no arguments. 963 if (Attr.getNumArgs() != 0) { 964 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 965 return; 966 } 967 968 // Attribute can be applied only to functions. 969 if (!isa<FunctionDecl>(d)) { 970 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 971 << Attr.getName() << 0 /*function*/; 972 return; 973 } 974 975 // stdcall and fastcall attributes are mutually incompatible. 976 if (d->getAttr<FastCallAttr>()) { 977 S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) 978 << "stdcall" << "fastcall"; 979 return; 980 } 981 982 d->addAttr(::new (S.Context) StdCallAttr()); 983} 984 985static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { 986 // Attribute has no arguments. 987 if (Attr.getNumArgs() != 0) { 988 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 989 return; 990 } 991 992 if (!isa<FunctionDecl>(d)) { 993 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 994 << Attr.getName() << 0 /*function*/; 995 return; 996 } 997 998 // stdcall and fastcall attributes are mutually incompatible. 999 if (d->getAttr<StdCallAttr>()) { 1000 S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) 1001 << "fastcall" << "stdcall"; 1002 return; 1003 } 1004 1005 d->addAttr(::new (S.Context) FastCallAttr()); 1006} 1007 1008static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1009 // check the attribute arguments. 1010 if (Attr.getNumArgs() != 0) { 1011 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1012 return; 1013 } 1014 1015 d->addAttr(::new (S.Context) NoThrowAttr()); 1016} 1017 1018static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1019 // check the attribute arguments. 1020 if (Attr.getNumArgs() != 0) { 1021 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1022 return; 1023 } 1024 1025 d->addAttr(::new (S.Context) ConstAttr()); 1026} 1027 1028static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1029 // check the attribute arguments. 1030 if (Attr.getNumArgs() != 0) { 1031 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1032 return; 1033 } 1034 1035 d->addAttr(::new (S.Context) PureAttr()); 1036} 1037 1038static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1039 // Match gcc which ignores cleanup attrs when compiling C++. 1040 if (S.getLangOptions().CPlusPlus) 1041 return; 1042 1043 if (!Attr.getParameterName()) { 1044 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 1045 return; 1046 } 1047 1048 if (Attr.getNumArgs() != 0) { 1049 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 1050 return; 1051 } 1052 1053 VarDecl *VD = dyn_cast<VarDecl>(d); 1054 1055 if (!VD || !VD->hasLocalStorage()) { 1056 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup"; 1057 return; 1058 } 1059 1060 // Look up the function 1061 NamedDecl *CleanupDecl = S.LookupName(S.TUScope, Attr.getParameterName(), 1062 Sema::LookupOrdinaryName); 1063 if (!CleanupDecl) { 1064 S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_found) << 1065 Attr.getParameterName(); 1066 return; 1067 } 1068 1069 FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl); 1070 if (!FD) { 1071 S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_function) << 1072 Attr.getParameterName(); 1073 return; 1074 } 1075 1076 if (FD->getNumParams() != 1) { 1077 S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_func_must_take_one_arg) << 1078 Attr.getParameterName(); 1079 return; 1080 } 1081 1082 // We're currently more strict than GCC about what function types we accept. 1083 // If this ever proves to be a problem it should be easy to fix. 1084 QualType Ty = S.Context.getPointerType(VD->getType()); 1085 QualType ParamTy = FD->getParamDecl(0)->getType(); 1086 if (S.CheckAssignmentConstraints(ParamTy, Ty) != Sema::Compatible) { 1087 S.Diag(Attr.getLoc(), 1088 diag::err_attribute_cleanup_func_arg_incompatible_type) << 1089 Attr.getParameterName() << ParamTy << Ty; 1090 return; 1091 } 1092 1093 d->addAttr(::new (S.Context) CleanupAttr(FD)); 1094} 1095 1096/// Handle __attribute__((format_arg((idx)))) attribute 1097/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html 1098static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1099 if (Attr.getNumArgs() != 1) { 1100 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 1101 return; 1102 } 1103 if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { 1104 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1105 << Attr.getName() << 0 /*function*/; 1106 return; 1107 } 1108 // FIXME: in C++ the implicit 'this' function parameter also counts. 1109 // this is needed in order to be compatible with GCC 1110 // the index must start with 1. 1111 unsigned NumArgs = getFunctionOrMethodNumArgs(d); 1112 unsigned FirstIdx = 1; 1113 // checks for the 2nd argument 1114 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0)); 1115 llvm::APSInt Idx(32); 1116 if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { 1117 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 1118 << "format" << 2 << IdxExpr->getSourceRange(); 1119 return; 1120 } 1121 1122 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { 1123 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 1124 << "format" << 2 << IdxExpr->getSourceRange(); 1125 return; 1126 } 1127 1128 unsigned ArgIdx = Idx.getZExtValue() - 1; 1129 1130 // make sure the format string is really a string 1131 QualType Ty = getFunctionOrMethodArgType(d, ArgIdx); 1132 1133 bool not_nsstring_type = !isNSStringType(Ty, S.Context); 1134 if (not_nsstring_type && 1135 !isCFStringType(Ty, S.Context) && 1136 (!Ty->isPointerType() || 1137 !Ty->getAsPointerType()->getPointeeType()->isCharType())) { 1138 // FIXME: Should highlight the actual expression that has the wrong type. 1139 S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 1140 << (not_nsstring_type ? "a string type" : "an NSString") 1141 << IdxExpr->getSourceRange(); 1142 return; 1143 } 1144 Ty = getFunctionOrMethodResultType(d); 1145 if (!isNSStringType(Ty, S.Context) && 1146 !isCFStringType(Ty, S.Context) && 1147 (!Ty->isPointerType() || 1148 !Ty->getAsPointerType()->getPointeeType()->isCharType())) { 1149 // FIXME: Should highlight the actual expression that has the wrong type. 1150 S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not) 1151 << (not_nsstring_type ? "string type" : "NSString") 1152 << IdxExpr->getSourceRange(); 1153 return; 1154 } 1155 1156 d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue())); 1157} 1158 1159/// Handle __attribute__((format(type,idx,firstarg))) attributes 1160/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html 1161static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1162 1163 if (!Attr.getParameterName()) { 1164 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) 1165 << "format" << 1; 1166 return; 1167 } 1168 1169 if (Attr.getNumArgs() != 2) { 1170 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3; 1171 return; 1172 } 1173 1174 if (!isFunctionOrMethodOrBlock(d) || !hasFunctionProto(d)) { 1175 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1176 << Attr.getName() << 0 /*function*/; 1177 return; 1178 } 1179 1180 // FIXME: in C++ the implicit 'this' function parameter also counts. 1181 // this is needed in order to be compatible with GCC 1182 // the index must start in 1 and the limit is numargs+1 1183 unsigned NumArgs = getFunctionOrMethodNumArgs(d); 1184 unsigned FirstIdx = 1; 1185 1186 const char *Format = Attr.getParameterName()->getName(); 1187 unsigned FormatLen = Attr.getParameterName()->getLength(); 1188 1189 // Normalize the argument, __foo__ becomes foo. 1190 if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' && 1191 Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') { 1192 Format += 2; 1193 FormatLen -= 4; 1194 } 1195 1196 bool Supported = false; 1197 bool is_NSString = false; 1198 bool is_strftime = false; 1199 bool is_CFString = false; 1200 1201 switch (FormatLen) { 1202 default: break; 1203 case 5: Supported = !memcmp(Format, "scanf", 5); break; 1204 case 6: Supported = !memcmp(Format, "printf", 6); break; 1205 case 7: Supported = !memcmp(Format, "strfmon", 7); break; 1206 case 8: 1207 Supported = (is_strftime = !memcmp(Format, "strftime", 8)) || 1208 (is_NSString = !memcmp(Format, "NSString", 8)) || 1209 (is_CFString = !memcmp(Format, "CFString", 8)); 1210 break; 1211 } 1212 1213 if (!Supported) { 1214 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) 1215 << "format" << Attr.getParameterName()->getName(); 1216 return; 1217 } 1218 1219 // checks for the 2nd argument 1220 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0)); 1221 llvm::APSInt Idx(32); 1222 if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { 1223 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 1224 << "format" << 2 << IdxExpr->getSourceRange(); 1225 return; 1226 } 1227 1228 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { 1229 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 1230 << "format" << 2 << IdxExpr->getSourceRange(); 1231 return; 1232 } 1233 1234 // FIXME: Do we need to bounds check? 1235 unsigned ArgIdx = Idx.getZExtValue() - 1; 1236 1237 // make sure the format string is really a string 1238 QualType Ty = getFunctionOrMethodArgType(d, ArgIdx); 1239 1240 if (is_CFString) { 1241 if (!isCFStringType(Ty, S.Context)) { 1242 S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 1243 << "a CFString" << IdxExpr->getSourceRange(); 1244 return; 1245 } 1246 } else if (is_NSString) { 1247 // FIXME: do we need to check if the type is NSString*? What are the 1248 // semantics? 1249 if (!isNSStringType(Ty, S.Context)) { 1250 // FIXME: Should highlight the actual expression that has the wrong type. 1251 S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 1252 << "an NSString" << IdxExpr->getSourceRange(); 1253 return; 1254 } 1255 } else if (!Ty->isPointerType() || 1256 !Ty->getAsPointerType()->getPointeeType()->isCharType()) { 1257 // FIXME: Should highlight the actual expression that has the wrong type. 1258 S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 1259 << "a string type" << IdxExpr->getSourceRange(); 1260 return; 1261 } 1262 1263 // check the 3rd argument 1264 Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1)); 1265 llvm::APSInt FirstArg(32); 1266 if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) { 1267 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 1268 << "format" << 3 << FirstArgExpr->getSourceRange(); 1269 return; 1270 } 1271 1272 // check if the function is variadic if the 3rd argument non-zero 1273 if (FirstArg != 0) { 1274 if (isFunctionOrMethodVariadic(d)) { 1275 ++NumArgs; // +1 for ... 1276 } else { 1277 S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic); 1278 return; 1279 } 1280 } 1281 1282 // strftime requires FirstArg to be 0 because it doesn't read from any 1283 // variable the input is just the current time + the format string. 1284 if (is_strftime) { 1285 if (FirstArg != 0) { 1286 S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter) 1287 << FirstArgExpr->getSourceRange(); 1288 return; 1289 } 1290 // if 0 it disables parameter checking (to use with e.g. va_list) 1291 } else if (FirstArg != 0 && FirstArg != NumArgs) { 1292 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 1293 << "format" << 3 << FirstArgExpr->getSourceRange(); 1294 return; 1295 } 1296 1297 d->addAttr(::new (S.Context) FormatAttr(std::string(Format, FormatLen), 1298 Idx.getZExtValue(), FirstArg.getZExtValue())); 1299} 1300 1301static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, 1302 Sema &S) { 1303 // check the attribute arguments. 1304 if (Attr.getNumArgs() != 0) { 1305 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1306 return; 1307 } 1308 1309 // Try to find the underlying union declaration. 1310 RecordDecl *RD = 0; 1311 TypedefDecl *TD = dyn_cast<TypedefDecl>(d); 1312 if (TD && TD->getUnderlyingType()->isUnionType()) 1313 RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); 1314 else 1315 RD = dyn_cast<RecordDecl>(d); 1316 1317 if (!RD || !RD->isUnion()) { 1318 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1319 << Attr.getName() << 1 /*union*/; 1320 return; 1321 } 1322 1323 if (!RD->isDefinition()) { 1324 S.Diag(Attr.getLoc(), 1325 diag::warn_transparent_union_attribute_not_definition); 1326 return; 1327 } 1328 1329 RecordDecl::field_iterator Field = RD->field_begin(), 1330 FieldEnd = RD->field_end(); 1331 if (Field == FieldEnd) { 1332 S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields); 1333 return; 1334 } 1335 1336 FieldDecl *FirstField = *Field; 1337 QualType FirstType = FirstField->getType(); 1338 if (FirstType->isFloatingType() || FirstType->isVectorType()) { 1339 S.Diag(FirstField->getLocation(), 1340 diag::warn_transparent_union_attribute_floating); 1341 return; 1342 } 1343 1344 uint64_t FirstSize = S.Context.getTypeSize(FirstType); 1345 uint64_t FirstAlign = S.Context.getTypeAlign(FirstType); 1346 for (; Field != FieldEnd; ++Field) { 1347 QualType FieldType = Field->getType(); 1348 if (S.Context.getTypeSize(FieldType) != FirstSize || 1349 S.Context.getTypeAlign(FieldType) != FirstAlign) { 1350 // Warn if we drop the attribute. 1351 bool isSize = S.Context.getTypeSize(FieldType) != FirstSize; 1352 unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType) 1353 : S.Context.getTypeAlign(FieldType); 1354 S.Diag(Field->getLocation(), 1355 diag::warn_transparent_union_attribute_field_size_align) 1356 << isSize << Field->getDeclName() << FieldBits; 1357 unsigned FirstBits = isSize? FirstSize : FirstAlign; 1358 S.Diag(FirstField->getLocation(), 1359 diag::note_transparent_union_first_field_size_align) 1360 << isSize << FirstBits; 1361 return; 1362 } 1363 } 1364 1365 RD->addAttr(::new (S.Context) TransparentUnionAttr()); 1366} 1367 1368static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1369 // check the attribute arguments. 1370 if (Attr.getNumArgs() != 1) { 1371 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 1372 return; 1373 } 1374 Expr *argExpr = static_cast<Expr *>(Attr.getArg(0)); 1375 StringLiteral *SE = dyn_cast<StringLiteral>(argExpr); 1376 1377 // Make sure that there is a string literal as the annotation's single 1378 // argument. 1379 if (!SE) { 1380 S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string); 1381 return; 1382 } 1383 d->addAttr(::new (S.Context) AnnotateAttr(std::string(SE->getStrData(), 1384 SE->getByteLength()))); 1385} 1386 1387static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1388 // check the attribute arguments. 1389 if (Attr.getNumArgs() > 1) { 1390 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 1391 return; 1392 } 1393 1394 unsigned Align = 0; 1395 if (Attr.getNumArgs() == 0) { 1396 // FIXME: This should be the target specific maximum alignment. 1397 // (For now we just use 128 bits which is the maximum on X86). 1398 Align = 128; 1399 d->addAttr(::new (S.Context) AlignedAttr(Align)); 1400 return; 1401 } 1402 1403 Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0)); 1404 llvm::APSInt Alignment(32); 1405 if (!alignmentExpr->isIntegerConstantExpr(Alignment, S.Context)) { 1406 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 1407 << "aligned" << alignmentExpr->getSourceRange(); 1408 return; 1409 } 1410 if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) { 1411 S.Diag(Attr.getLoc(), diag::err_attribute_aligned_not_power_of_two) 1412 << alignmentExpr->getSourceRange(); 1413 return; 1414 } 1415 1416 d->addAttr(::new (S.Context) AlignedAttr(Alignment.getZExtValue() * 8)); 1417} 1418 1419/// HandleModeAttr - This attribute modifies the width of a decl with 1420/// primitive type. 1421/// 1422/// Despite what would be logical, the mode attribute is a decl attribute, 1423/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 1424/// 'G' be HImode, not an intermediate pointer. 1425/// 1426static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { 1427 // This attribute isn't documented, but glibc uses it. It changes 1428 // the width of an int or unsigned int to the specified size. 1429 1430 // Check that there aren't any arguments 1431 if (Attr.getNumArgs() != 0) { 1432 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1433 return; 1434 } 1435 1436 IdentifierInfo *Name = Attr.getParameterName(); 1437 if (!Name) { 1438 S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name); 1439 return; 1440 } 1441 const char *Str = Name->getName(); 1442 unsigned Len = Name->getLength(); 1443 1444 // Normalize the attribute name, __foo__ becomes foo. 1445 if (Len > 4 && Str[0] == '_' && Str[1] == '_' && 1446 Str[Len - 2] == '_' && Str[Len - 1] == '_') { 1447 Str += 2; 1448 Len -= 4; 1449 } 1450 1451 unsigned DestWidth = 0; 1452 bool IntegerMode = true; 1453 bool ComplexMode = false; 1454 switch (Len) { 1455 case 2: 1456 switch (Str[0]) { 1457 case 'Q': DestWidth = 8; break; 1458 case 'H': DestWidth = 16; break; 1459 case 'S': DestWidth = 32; break; 1460 case 'D': DestWidth = 64; break; 1461 case 'X': DestWidth = 96; break; 1462 case 'T': DestWidth = 128; break; 1463 } 1464 if (Str[1] == 'F') { 1465 IntegerMode = false; 1466 } else if (Str[1] == 'C') { 1467 IntegerMode = false; 1468 ComplexMode = true; 1469 } else if (Str[1] != 'I') { 1470 DestWidth = 0; 1471 } 1472 break; 1473 case 4: 1474 // FIXME: glibc uses 'word' to define register_t; this is narrower than a 1475 // pointer on PIC16 and other embedded platforms. 1476 if (!memcmp(Str, "word", 4)) 1477 DestWidth = S.Context.Target.getPointerWidth(0); 1478 if (!memcmp(Str, "byte", 4)) 1479 DestWidth = S.Context.Target.getCharWidth(); 1480 break; 1481 case 7: 1482 if (!memcmp(Str, "pointer", 7)) 1483 DestWidth = S.Context.Target.getPointerWidth(0); 1484 break; 1485 } 1486 1487 QualType OldTy; 1488 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) 1489 OldTy = TD->getUnderlyingType(); 1490 else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 1491 OldTy = VD->getType(); 1492 else { 1493 S.Diag(D->getLocation(), diag::err_attr_wrong_decl) 1494 << "mode" << SourceRange(Attr.getLoc(), Attr.getLoc()); 1495 return; 1496 } 1497 1498 if (!OldTy->getAsBuiltinType() && !OldTy->isComplexType()) 1499 S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); 1500 else if (IntegerMode) { 1501 if (!OldTy->isIntegralType()) 1502 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); 1503 } else if (ComplexMode) { 1504 if (!OldTy->isComplexType()) 1505 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); 1506 } else { 1507 if (!OldTy->isFloatingType()) 1508 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); 1509 } 1510 1511 // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t 1512 // and friends, at least with glibc. 1513 // FIXME: Make sure 32/64-bit integers don't get defined to types of the wrong 1514 // width on unusual platforms. 1515 // FIXME: Make sure floating-point mappings are accurate 1516 // FIXME: Support XF and TF types 1517 QualType NewTy; 1518 switch (DestWidth) { 1519 case 0: 1520 S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name; 1521 return; 1522 default: 1523 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; 1524 return; 1525 case 8: 1526 if (!IntegerMode) { 1527 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; 1528 return; 1529 } 1530 if (OldTy->isSignedIntegerType()) 1531 NewTy = S.Context.SignedCharTy; 1532 else 1533 NewTy = S.Context.UnsignedCharTy; 1534 break; 1535 case 16: 1536 if (!IntegerMode) { 1537 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; 1538 return; 1539 } 1540 if (OldTy->isSignedIntegerType()) 1541 NewTy = S.Context.ShortTy; 1542 else 1543 NewTy = S.Context.UnsignedShortTy; 1544 break; 1545 case 32: 1546 if (!IntegerMode) 1547 NewTy = S.Context.FloatTy; 1548 else if (OldTy->isSignedIntegerType()) 1549 NewTy = S.Context.IntTy; 1550 else 1551 NewTy = S.Context.UnsignedIntTy; 1552 break; 1553 case 64: 1554 if (!IntegerMode) 1555 NewTy = S.Context.DoubleTy; 1556 else if (OldTy->isSignedIntegerType()) 1557 NewTy = S.Context.LongLongTy; 1558 else 1559 NewTy = S.Context.UnsignedLongLongTy; 1560 break; 1561 case 96: 1562 NewTy = S.Context.LongDoubleTy; 1563 break; 1564 case 128: 1565 if (!IntegerMode) { 1566 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; 1567 return; 1568 } 1569 NewTy = S.Context.getFixedWidthIntType(128, OldTy->isSignedIntegerType()); 1570 break; 1571 } 1572 1573 if (ComplexMode) { 1574 NewTy = S.Context.getComplexType(NewTy); 1575 } 1576 1577 // Install the new type. 1578 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) 1579 TD->setUnderlyingType(NewTy); 1580 else 1581 cast<ValueDecl>(D)->setType(NewTy); 1582} 1583 1584static void HandleNodebugAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1585 // check the attribute arguments. 1586 if (Attr.getNumArgs() > 0) { 1587 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1588 return; 1589 } 1590 1591 if (!isFunctionOrMethod(d)) { 1592 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1593 << Attr.getName() << 0 /*function*/; 1594 return; 1595 } 1596 1597 d->addAttr(::new (S.Context) NodebugAttr()); 1598} 1599 1600static void HandleNoinlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1601 // check the attribute arguments. 1602 if (Attr.getNumArgs() != 0) { 1603 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1604 return; 1605 } 1606 1607 if (!isa<FunctionDecl>(d)) { 1608 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1609 << Attr.getName() << 0 /*function*/; 1610 return; 1611 } 1612 1613 d->addAttr(::new (S.Context) NoinlineAttr()); 1614} 1615 1616static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1617 // check the attribute arguments. 1618 if (Attr.getNumArgs() != 0) { 1619 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1620 return; 1621 } 1622 1623 FunctionDecl *Fn = dyn_cast<FunctionDecl>(d); 1624 if (Fn == 0) { 1625 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1626 << Attr.getName() << 0 /*function*/; 1627 return; 1628 } 1629 1630 if (!Fn->isInline()) { 1631 S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline); 1632 return; 1633 } 1634 1635 d->addAttr(::new (S.Context) GNUInlineAttr()); 1636} 1637 1638static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1639 // check the attribute arguments. 1640 if (Attr.getNumArgs() != 1) { 1641 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 1642 return; 1643 } 1644 1645 if (!isFunctionOrMethod(d)) { 1646 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1647 << Attr.getName() << 0 /*function*/; 1648 return; 1649 } 1650 1651 Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0)); 1652 llvm::APSInt NumParams(32); 1653 if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) { 1654 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 1655 << "regparm" << NumParamsExpr->getSourceRange(); 1656 return; 1657 } 1658 1659 if (S.Context.Target.getRegParmMax() == 0) { 1660 S.Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform) 1661 << NumParamsExpr->getSourceRange(); 1662 return; 1663 } 1664 1665 if (NumParams.getLimitedValue(255) > S.Context.Target.getRegParmMax()) { 1666 S.Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number) 1667 << S.Context.Target.getRegParmMax() << NumParamsExpr->getSourceRange(); 1668 return; 1669 } 1670 1671 d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue())); 1672} 1673 1674//===----------------------------------------------------------------------===// 1675// Checker-specific attribute handlers. 1676//===----------------------------------------------------------------------===// 1677 1678static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr, 1679 Sema &S) { 1680 1681 QualType RetTy; 1682 1683 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) 1684 RetTy = MD->getResultType(); 1685 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) 1686 RetTy = FD->getResultType(); 1687 else { 1688 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1689 << Attr.getName() << 3 /* function or method */; 1690 return; 1691 } 1692 1693 if (!(S.Context.isObjCNSObjectType(RetTy) || RetTy->getAsPointerType() 1694 || RetTy->getAsObjCObjectPointerType())) { 1695 S.Diag(Attr.getLoc(), diag::warn_ns_attribute_wrong_return_type) 1696 << Attr.getName(); 1697 return; 1698 } 1699 1700 switch (Attr.getKind()) { 1701 default: 1702 assert(0 && "invalid ownership attribute"); 1703 return; 1704 case AttributeList::AT_cf_returns_retained: 1705 d->addAttr(::new (S.Context) CFReturnsRetainedAttr()); 1706 return; 1707 case AttributeList::AT_ns_returns_retained: 1708 d->addAttr(::new (S.Context) NSReturnsRetainedAttr()); 1709 return; 1710 }; 1711} 1712 1713//===----------------------------------------------------------------------===// 1714// Top Level Sema Entry Points 1715//===----------------------------------------------------------------------===// 1716 1717/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if 1718/// the attribute applies to decls. If the attribute is a type attribute, just 1719/// silently ignore it. 1720static void ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr, Sema &S) { 1721 if (Attr.isDeclspecAttribute()) 1722 // FIXME: Try to deal with __declspec attributes! 1723 return; 1724 switch (Attr.getKind()) { 1725 case AttributeList::AT_IBOutlet: HandleIBOutletAttr (D, Attr, S); break; 1726 case AttributeList::AT_address_space: 1727 case AttributeList::AT_objc_gc: 1728 // Ignore these, these are type attributes, handled by ProcessTypeAttributes. 1729 break; 1730 case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break; 1731 case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break; 1732 case AttributeList::AT_always_inline: 1733 HandleAlwaysInlineAttr (D, Attr, S); break; 1734 case AttributeList::AT_analyzer_noreturn: 1735 HandleAnalyzerNoReturnAttr (D, Attr, S); break; 1736 case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break; 1737 case AttributeList::AT_constructor: HandleConstructorAttr(D, Attr, S); break; 1738 case AttributeList::AT_deprecated: HandleDeprecatedAttr(D, Attr, S); break; 1739 case AttributeList::AT_destructor: HandleDestructorAttr(D, Attr, S); break; 1740 case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break; 1741 case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break; 1742 case AttributeList::AT_ext_vector_type: 1743 HandleExtVectorTypeAttr(scope, D, Attr, S); 1744 break; 1745 case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break; 1746 case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break; 1747 case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break; 1748 case AttributeList::AT_gnu_inline: HandleGNUInlineAttr(D, Attr, S); break; 1749 case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break; 1750 case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break; 1751 case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break; 1752 case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break; 1753 1754 // Checker-specific. 1755 case AttributeList::AT_ns_returns_retained: 1756 case AttributeList::AT_cf_returns_retained: 1757 HandleNSReturnsRetainedAttr(D, Attr, S); break; 1758 1759 case AttributeList::AT_reqd_wg_size: 1760 HandleReqdWorkGroupSize(D, Attr, S); break; 1761 1762 case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; 1763 case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break; 1764 case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break; 1765 case AttributeList::AT_unavailable: HandleUnavailableAttr(D, Attr, S); break; 1766 case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break; 1767 case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break; 1768 case AttributeList::AT_vector_size: HandleVectorSizeAttr(D, Attr, S); break; 1769 case AttributeList::AT_visibility: HandleVisibilityAttr(D, Attr, S); break; 1770 case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S); 1771 break; 1772 case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break; 1773 case AttributeList::AT_weak_import: HandleWeakImportAttr(D, Attr, S); break; 1774 case AttributeList::AT_transparent_union: 1775 HandleTransparentUnionAttr(D, Attr, S); 1776 break; 1777 case AttributeList::AT_objc_exception: 1778 HandleObjCExceptionAttr(D, Attr, S); 1779 break; 1780 case AttributeList::AT_overloadable:HandleOverloadableAttr(D, Attr, S); break; 1781 case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break; 1782 case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break; 1783 case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break; 1784 case AttributeList::AT_const: HandleConstAttr (D, Attr, S); break; 1785 case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break; 1786 case AttributeList::AT_cleanup: HandleCleanupAttr (D, Attr, S); break; 1787 case AttributeList::AT_nodebug: HandleNodebugAttr (D, Attr, S); break; 1788 case AttributeList::AT_noinline: HandleNoinlineAttr (D, Attr, S); break; 1789 case AttributeList::AT_regparm: HandleRegparmAttr (D, Attr, S); break; 1790 case AttributeList::IgnoredAttribute: 1791 case AttributeList::AT_no_instrument_function: // Interacts with -pg. 1792 // Just ignore 1793 break; 1794 default: 1795 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 1796 break; 1797 } 1798} 1799 1800/// ProcessDeclAttributeList - Apply all the decl attributes in the specified 1801/// attribute list to the specified decl, ignoring any type attributes. 1802void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList) { 1803 while (AttrList) { 1804 ProcessDeclAttribute(S, D, *AttrList, *this); 1805 AttrList = AttrList->getNext(); 1806 } 1807} 1808 1809/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in 1810/// it, apply them to D. This is a bit tricky because PD can have attributes 1811/// specified in many different places, and we need to find and apply them all. 1812void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { 1813 // Apply decl attributes from the DeclSpec if present. 1814 if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes()) 1815 ProcessDeclAttributeList(S, D, Attrs); 1816 1817 // Walk the declarator structure, applying decl attributes that were in a type 1818 // position to the decl itself. This handles cases like: 1819 // int *__attr__(x)** D; 1820 // when X is a decl attribute. 1821 for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) 1822 if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) 1823 ProcessDeclAttributeList(S, D, Attrs); 1824 1825 // Finally, apply any attributes on the decl itself. 1826 if (const AttributeList *Attrs = PD.getAttributes()) 1827 ProcessDeclAttributeList(S, D, Attrs); 1828} 1829