SemaDeclAttr.cpp revision 30bc96544346bea42921cf6837e66cef80d664b4
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/Diagnostic.h" 19#include "clang/Basic/TargetInfo.h" 20#include "clang/Parse/DeclSpec.h" 21#include <llvm/ADT/StringExtras.h> 22using namespace clang; 23 24//===----------------------------------------------------------------------===// 25// Helper functions 26//===----------------------------------------------------------------------===// 27 28static const FunctionType *getFunctionType(Decl *d) { 29 QualType Ty; 30 if (ValueDecl *decl = dyn_cast<ValueDecl>(d)) 31 Ty = decl->getType(); 32 else if (FieldDecl *decl = dyn_cast<FieldDecl>(d)) 33 Ty = decl->getType(); 34 else if (TypedefDecl* decl = dyn_cast<TypedefDecl>(d)) 35 Ty = decl->getUnderlyingType(); 36 else 37 return 0; 38 39 if (Ty->isFunctionPointerType()) 40 Ty = Ty->getAsPointerType()->getPointeeType(); 41 42 return Ty->getAsFunctionType(); 43} 44 45// FIXME: We should provide an abstraction around a method or function 46// to provide the following bits of information. 47 48/// isFunctionOrMethod - Return true if the given decl has function 49/// type (function or function-typed variable) or an Objective-C 50/// method. 51static bool isFunctionOrMethod(Decl *d) { 52 return getFunctionType(d) || isa<ObjCMethodDecl>(d); 53} 54 55/// hasFunctionProto - Return true if the given decl has a argument 56/// information. This decl should have already passed 57/// isFunctionOrMethod. 58static bool hasFunctionProto(Decl *d) { 59 if (const FunctionType *FnTy = getFunctionType(d)) { 60 return isa<FunctionTypeProto>(FnTy); 61 } else { 62 assert(isa<ObjCMethodDecl>(d)); 63 return true; 64 } 65} 66 67/// getFunctionOrMethodNumArgs - Return number of function or method 68/// arguments. It is an error to call this on a K&R function (use 69/// hasFunctionProto first). 70static unsigned getFunctionOrMethodNumArgs(Decl *d) { 71 if (const FunctionType *FnTy = getFunctionType(d)) { 72 const FunctionTypeProto *proto = cast<FunctionTypeProto>(FnTy); 73 return proto->getNumArgs(); 74 } else { 75 return cast<ObjCMethodDecl>(d)->getNumParams(); 76 } 77} 78 79static QualType getFunctionOrMethodArgType(Decl *d, unsigned Idx) { 80 if (const FunctionType *FnTy = getFunctionType(d)) { 81 const FunctionTypeProto *proto = cast<FunctionTypeProto>(FnTy); 82 return proto->getArgType(Idx); 83 } else { 84 return cast<ObjCMethodDecl>(d)->getParamDecl(Idx)->getType(); 85 } 86} 87 88static bool isFunctionOrMethodVariadic(Decl *d) { 89 if (const FunctionType *FnTy = getFunctionType(d)) { 90 const FunctionTypeProto *proto = cast<FunctionTypeProto>(FnTy); 91 return proto->isVariadic(); 92 } else { 93 return cast<ObjCMethodDecl>(d)->isVariadic(); 94 } 95} 96 97static inline bool isNSStringType(QualType T, ASTContext &Ctx) { 98 const PointerType *PT = T->getAsPointerType(); 99 if (!PT) 100 return false; 101 102 const ObjCInterfaceType *ClsT =PT->getPointeeType()->getAsObjCInterfaceType(); 103 if (!ClsT) 104 return false; 105 106 IdentifierInfo* ClsName = ClsT->getDecl()->getIdentifier(); 107 108 // FIXME: Should we walk the chain of classes? 109 return ClsName == &Ctx.Idents.get("NSString") || 110 ClsName == &Ctx.Idents.get("NSMutableString"); 111} 112 113static inline bool isCFStringType(QualType T, ASTContext &Ctx) { 114 const PointerType *PT = T->getAsPointerType(); 115 if (!PT) 116 return false; 117 118 const RecordType *RT = PT->getPointeeType()->getAsRecordType(); 119 if (!RT) 120 return false; 121 122 const RecordDecl *RD = RT->getDecl(); 123 if (RD->getTagKind() != TagDecl::TK_struct) 124 return false; 125 126 return RD->getIdentifier() == &Ctx.Idents.get("__CFString"); 127} 128 129//===----------------------------------------------------------------------===// 130// Attribute Implementations 131//===----------------------------------------------------------------------===// 132 133// FIXME: All this manual attribute parsing code is gross. At the 134// least add some helper functions to check most argument patterns (# 135// and types of args). 136 137static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr, 138 Sema &S) { 139 TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d); 140 if (tDecl == 0) { 141 S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); 142 return; 143 } 144 145 QualType curType = tDecl->getUnderlyingType(); 146 // check the attribute arguments. 147 if (Attr.getNumArgs() != 1) { 148 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "1"; 149 return; 150 } 151 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0)); 152 llvm::APSInt vecSize(32); 153 if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { 154 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 155 << "ext_vector_type" << sizeExpr->getSourceRange(); 156 return; 157 } 158 // unlike gcc's vector_size attribute, we do not allow vectors to be defined 159 // in conjunction with complex types (pointers, arrays, functions, etc.). 160 if (!curType->isIntegerType() && !curType->isRealFloatingType()) { 161 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) 162 << curType.getAsString(); 163 return; 164 } 165 // unlike gcc's vector_size attribute, the size is specified as the 166 // number of elements, not the number of bytes. 167 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue()); 168 169 if (vectorSize == 0) { 170 S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) 171 << sizeExpr->getSourceRange(); 172 return; 173 } 174 // Instantiate/Install the vector type, the number of elements is > 0. 175 tDecl->setUnderlyingType(S.Context.getExtVectorType(curType, vectorSize)); 176 // Remember this typedef decl, we will need it later for diagnostics. 177 S.ExtVectorDecls.push_back(tDecl); 178} 179 180 181/// HandleVectorSizeAttribute - this attribute is only applicable to 182/// integral and float scalars, although arrays, pointers, and function 183/// return values are allowed in conjunction with this construct. Aggregates 184/// with this attribute are invalid, even if they are of the same size as a 185/// corresponding scalar. 186/// The raw attribute should contain precisely 1 argument, the vector size 187/// for the variable, measured in bytes. If curType and rawAttr are well 188/// formed, this routine will return a new vector type. 189static void HandleVectorSizeAttr(Decl *D, const AttributeList &Attr, Sema &S) { 190 QualType CurType; 191 if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 192 CurType = VD->getType(); 193 else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) 194 CurType = TD->getUnderlyingType(); 195 else { 196 S.Diag(D->getLocation(), diag::err_attr_wrong_decl) 197 << "vector_size" << SourceRange(Attr.getLoc(), Attr.getLoc()); 198 return; 199 } 200 201 // Check the attribute arugments. 202 if (Attr.getNumArgs() != 1) { 203 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "1"; 204 return; 205 } 206 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0)); 207 llvm::APSInt vecSize(32); 208 if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { 209 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 210 << "vector_size" << sizeExpr->getSourceRange(); 211 return; 212 } 213 // navigate to the base type - we need to provide for vector pointers, 214 // vector arrays, and functions returning vectors. 215 if (CurType->isPointerType() || CurType->isArrayType() || 216 CurType->isFunctionType()) { 217 assert(0 && "HandleVector(): Complex type construction unimplemented"); 218 /* FIXME: rebuild the type from the inside out, vectorizing the inner type. 219 do { 220 if (PointerType *PT = dyn_cast<PointerType>(canonType)) 221 canonType = PT->getPointeeType().getTypePtr(); 222 else if (ArrayType *AT = dyn_cast<ArrayType>(canonType)) 223 canonType = AT->getElementType().getTypePtr(); 224 else if (FunctionType *FT = dyn_cast<FunctionType>(canonType)) 225 canonType = FT->getResultType().getTypePtr(); 226 } while (canonType->isPointerType() || canonType->isArrayType() || 227 canonType->isFunctionType()); 228 */ 229 } 230 // the base type must be integer or float. 231 if (!CurType->isIntegerType() && !CurType->isRealFloatingType()) { 232 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) 233 << CurType.getAsString(); 234 return; 235 } 236 unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType)); 237 // vecSize is specified in bytes - convert to bits. 238 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8); 239 240 // the vector size needs to be an integral multiple of the type size. 241 if (vectorSize % typeSize) { 242 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size) 243 << sizeExpr->getSourceRange(); 244 return; 245 } 246 if (vectorSize == 0) { 247 S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) 248 << sizeExpr->getSourceRange(); 249 return; 250 } 251 252 // Success! Instantiate the vector type, the number of elements is > 0, and 253 // not required to be a power of 2, unlike GCC. 254 CurType = S.Context.getVectorType(CurType, vectorSize/typeSize); 255 256 if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 257 VD->setType(CurType); 258 else 259 cast<TypedefDecl>(D)->setUnderlyingType(CurType); 260} 261 262static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { 263 // check the attribute arguments. 264 if (Attr.getNumArgs() > 0) { 265 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 266 return; 267 } 268 269 if (TagDecl *TD = dyn_cast<TagDecl>(d)) 270 TD->addAttr(new PackedAttr(1)); 271 else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) { 272 // If the alignment is less than or equal to 8 bits, the packed attribute 273 // has no effect. 274 if (!FD->getType()->isIncompleteType() && 275 S.Context.getTypeAlign(FD->getType()) <= 8) 276 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) 277 << Attr.getName()->getName() << FD->getType().getAsString(); 278 else 279 FD->addAttr(new PackedAttr(1)); 280 } else 281 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) 282 << Attr.getName()->getName(); 283} 284 285static void HandleIBOutletAttr(Decl *d, const AttributeList &Attr, Sema &S) { 286 // check the attribute arguments. 287 if (Attr.getNumArgs() > 0) { 288 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 289 return; 290 } 291 292 // The IBOutlet attribute only applies to instance variables of Objective-C 293 // classes. 294 if (ObjCIvarDecl *ID = dyn_cast<ObjCIvarDecl>(d)) 295 ID->addAttr(new IBOutletAttr()); 296 else 297 S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet_non_ivar); 298} 299 300static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { 301 // GCC ignores the nonnull attribute on K&R style function 302 // prototypes, so we ignore it as well 303 if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { 304 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 305 << "nonnull" << "function"; 306 return; 307 } 308 309 unsigned NumArgs = getFunctionOrMethodNumArgs(d); 310 311 // The nonnull attribute only applies to pointers. 312 llvm::SmallVector<unsigned, 10> NonNullArgs; 313 314 for (AttributeList::arg_iterator I=Attr.arg_begin(), 315 E=Attr.arg_end(); I!=E; ++I) { 316 317 318 // The argument must be an integer constant expression. 319 Expr *Ex = static_cast<Expr *>(Attr.getArg(0)); 320 llvm::APSInt ArgNum(32); 321 if (!Ex->isIntegerConstantExpr(ArgNum, S.Context)) { 322 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 323 << "nonnull" << Ex->getSourceRange(); 324 return; 325 } 326 327 unsigned x = (unsigned) ArgNum.getZExtValue(); 328 329 if (x < 1 || x > NumArgs) { 330 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 331 << "nonnull" << I.getArgNum() << Ex->getSourceRange(); 332 return; 333 } 334 335 --x; 336 337 // Is the function argument a pointer type? 338 QualType T = getFunctionOrMethodArgType(d, x); 339 if (!T->isPointerType() && !T->isBlockPointerType()) { 340 // FIXME: Should also highlight argument in decl. 341 S.Diag(Attr.getLoc(), diag::err_nonnull_pointers_only) 342 << "nonnull" << Ex->getSourceRange(); 343 continue; 344 } 345 346 NonNullArgs.push_back(x); 347 } 348 349 // If no arguments were specified to __attribute__((nonnull)) then all 350 // pointer arguments have a nonnull attribute. 351 if (NonNullArgs.empty()) { 352 for (unsigned I = 0, E = getFunctionOrMethodNumArgs(d); I != E; ++I) { 353 QualType T = getFunctionOrMethodArgType(d, I); 354 if (T->isPointerType() || T->isBlockPointerType()) 355 NonNullArgs.push_back(I); 356 } 357 358 if (NonNullArgs.empty()) { 359 S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers); 360 return; 361 } 362 } 363 364 unsigned* start = &NonNullArgs[0]; 365 unsigned size = NonNullArgs.size(); 366 std::sort(start, start + size); 367 d->addAttr(new NonNullAttr(start, size)); 368} 369 370static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { 371 // check the attribute arguments. 372 if (Attr.getNumArgs() != 1) { 373 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "1"; 374 return; 375 } 376 377 Expr *Arg = static_cast<Expr*>(Attr.getArg(0)); 378 Arg = Arg->IgnoreParenCasts(); 379 StringLiteral *Str = dyn_cast<StringLiteral>(Arg); 380 381 if (Str == 0 || Str->isWide()) { 382 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) 383 << "alias" << "1"; 384 return; 385 } 386 387 const char *Alias = Str->getStrData(); 388 unsigned AliasLen = Str->getByteLength(); 389 390 // FIXME: check if target symbol exists in current file 391 392 d->addAttr(new AliasAttr(std::string(Alias, AliasLen))); 393} 394 395static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, 396 Sema &S) { 397 // check the attribute arguments. 398 if (Attr.getNumArgs() != 0) { 399 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 400 return; 401 } 402 403 d->addAttr(new AlwaysInlineAttr()); 404} 405 406static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { 407 // check the attribute arguments. 408 if (Attr.getNumArgs() != 0) { 409 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 410 return; 411 } 412 413 if (!isFunctionOrMethod(d)) { 414 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 415 << "noreturn" << "function"; 416 return; 417 } 418 419 d->addAttr(new NoReturnAttr()); 420} 421 422static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { 423 // check the attribute arguments. 424 if (Attr.getNumArgs() != 0) { 425 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 426 return; 427 } 428 429 if (!isa<VarDecl>(d) && !isFunctionOrMethod(d)) { 430 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 431 << "unused" << "variable and function"; 432 return; 433 } 434 435 d->addAttr(new UnusedAttr()); 436} 437 438static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { 439 // check the attribute arguments. 440 if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) { 441 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 442 << "0 or 1"; 443 return; 444 } 445 446 int priority = 65535; // FIXME: Do not hardcode such constants. 447 if (Attr.getNumArgs() > 0) { 448 Expr *E = static_cast<Expr *>(Attr.getArg(0)); 449 llvm::APSInt Idx(32); 450 if (!E->isIntegerConstantExpr(Idx, S.Context)) { 451 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 452 << "constructor" << "1" << E->getSourceRange(); 453 return; 454 } 455 priority = Idx.getZExtValue(); 456 } 457 458 FunctionDecl *Fn = dyn_cast<FunctionDecl>(d); 459 if (!Fn) { 460 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 461 << "constructor" << "function"; 462 return; 463 } 464 465 d->addAttr(new ConstructorAttr(priority)); 466} 467 468static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { 469 // check the attribute arguments. 470 if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) { 471 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 472 << "0 or 1"; 473 return; 474 } 475 476 int priority = 65535; // FIXME: Do not hardcode such constants. 477 if (Attr.getNumArgs() > 0) { 478 Expr *E = static_cast<Expr *>(Attr.getArg(0)); 479 llvm::APSInt Idx(32); 480 if (!E->isIntegerConstantExpr(Idx, S.Context)) { 481 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 482 << "destructor" << "1" << E->getSourceRange(); 483 return; 484 } 485 priority = Idx.getZExtValue(); 486 } 487 488 if (!isa<FunctionDecl>(d)) { 489 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 490 << "destructor" << "function"; 491 return; 492 } 493 494 d->addAttr(new DestructorAttr(priority)); 495} 496 497static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { 498 // check the attribute arguments. 499 if (Attr.getNumArgs() != 0) { 500 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 501 return; 502 } 503 504 d->addAttr(new DeprecatedAttr()); 505} 506 507static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { 508 // check the attribute arguments. 509 if (Attr.getNumArgs() != 1) { 510 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "1"; 511 return; 512 } 513 514 Expr *Arg = static_cast<Expr*>(Attr.getArg(0)); 515 Arg = Arg->IgnoreParenCasts(); 516 StringLiteral *Str = dyn_cast<StringLiteral>(Arg); 517 518 if (Str == 0 || Str->isWide()) { 519 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) 520 << "visibility" << "1"; 521 return; 522 } 523 524 const char *TypeStr = Str->getStrData(); 525 unsigned TypeLen = Str->getByteLength(); 526 VisibilityAttr::VisibilityTypes type; 527 528 if (TypeLen == 7 && !memcmp(TypeStr, "default", 7)) 529 type = VisibilityAttr::DefaultVisibility; 530 else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6)) 531 type = VisibilityAttr::HiddenVisibility; 532 else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8)) 533 type = VisibilityAttr::HiddenVisibility; // FIXME 534 else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9)) 535 type = VisibilityAttr::ProtectedVisibility; 536 else { 537 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) 538 << "visibility" << TypeStr; 539 return; 540 } 541 542 d->addAttr(new VisibilityAttr(type)); 543} 544 545static void HandleObjCGCAttr(Decl *d, const AttributeList &Attr, Sema &S) { 546 if (!Attr.getParameterName()) { 547 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) 548 << "objc_gc" << "1"; 549 return; 550 } 551 552 if (Attr.getNumArgs() != 0) { 553 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 554 << "1"; 555 return; 556 } 557 558 const char *TypeStr = Attr.getParameterName()->getName(); 559 unsigned TypeLen = Attr.getParameterName()->getLength(); 560 561 ObjCGCAttr::GCAttrTypes type; 562 563 if (TypeLen == 4 && !memcmp(TypeStr, "weak", 4)) 564 type = ObjCGCAttr::Weak; 565 else if (TypeLen == 6 && !memcmp(TypeStr, "strong", 6)) 566 type = ObjCGCAttr::Strong; 567 else { 568 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) 569 << "objc_gc" << TypeStr; 570 return; 571 } 572 573 d->addAttr(new ObjCGCAttr(type)); 574} 575 576static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { 577 if (!Attr.getParameterName()) { 578 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) 579 << "blocks" << "1"; 580 return; 581 } 582 583 if (Attr.getNumArgs() != 0) { 584 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 585 << "1"; 586 return; 587 } 588 const char *TypeStr = Attr.getParameterName()->getName(); 589 unsigned TypeLen = Attr.getParameterName()->getLength(); 590 591 BlocksAttr::BlocksAttrTypes type; 592 593 if (TypeLen == 5 && !memcmp(TypeStr, "byref", 5)) 594 type = BlocksAttr::ByRef; 595 else { 596 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) 597 << "blocks" << TypeStr; 598 return; 599 } 600 601 d->addAttr(new BlocksAttr(type)); 602} 603 604static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { 605 // check the attribute arguments. 606 if (Attr.getNumArgs() > 2) { 607 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 608 << "0, 1 or 2"; 609 return; 610 } 611 612 int sentinel = 0; 613 if (Attr.getNumArgs() > 0) { 614 Expr *E = static_cast<Expr *>(Attr.getArg(0)); 615 llvm::APSInt Idx(32); 616 if (!E->isIntegerConstantExpr(Idx, S.Context)) { 617 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 618 << "sentinel" << "1" << E->getSourceRange(); 619 return; 620 } 621 sentinel = Idx.getZExtValue(); 622 623 if (sentinel < 0) { 624 S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero) 625 << E->getSourceRange(); 626 return; 627 } 628 } 629 630 int nullPos = 0; 631 if (Attr.getNumArgs() > 1) { 632 Expr *E = static_cast<Expr *>(Attr.getArg(1)); 633 llvm::APSInt Idx(32); 634 if (!E->isIntegerConstantExpr(Idx, S.Context)) { 635 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 636 << "sentinel" << "2" << E->getSourceRange(); 637 return; 638 } 639 nullPos = Idx.getZExtValue(); 640 641 if (nullPos > 1 || nullPos < 0) { 642 // FIXME: This error message could be improved, it would be nice 643 // to say what the bounds actually are. 644 S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one) 645 << E->getSourceRange(); 646 return; 647 } 648 } 649 650 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) { 651 QualType FT = FD->getType(); 652 if (!FT->getAsFunctionTypeProto()->isVariadic()) { 653 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic); 654 return; 655 } 656 } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) { 657 if (!MD->isVariadic()) { 658 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic); 659 return; 660 } 661 } else { 662 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 663 << "sentinel" << "function or method"; 664 return; 665 } 666 667 // FIXME: Actually create the attribute. 668} 669 670static void HandleWeakAttr(Decl *d, const AttributeList &Attr, Sema &S) { 671 // check the attribute arguments. 672 if (Attr.getNumArgs() != 0) { 673 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 674 return; 675 } 676 677 d->addAttr(new WeakAttr()); 678} 679 680static void HandleDLLImportAttr(Decl *d, const AttributeList &Attr, Sema &S) { 681 // check the attribute arguments. 682 if (Attr.getNumArgs() != 0) { 683 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 684 return; 685 } 686 687 d->addAttr(new DLLImportAttr()); 688} 689 690static void HandleDLLExportAttr(Decl *d, const AttributeList &Attr, Sema &S) { 691 // check the attribute arguments. 692 if (Attr.getNumArgs() != 0) { 693 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 694 return; 695 } 696 697 d->addAttr(new DLLExportAttr()); 698} 699 700static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { 701 // check the attribute arguments. 702 if (Attr.getNumArgs() != 0) { 703 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 704 return; 705 } 706 707 d->addAttr(new StdCallAttr()); 708} 709 710static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { 711 // check the attribute arguments. 712 if (Attr.getNumArgs() != 0) { 713 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 714 return; 715 } 716 717 d->addAttr(new FastCallAttr()); 718} 719 720static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { 721 // check the attribute arguments. 722 if (Attr.getNumArgs() != 0) { 723 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 724 return; 725 } 726 727 d->addAttr(new NoThrowAttr()); 728} 729 730static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { 731 // check the attribute arguments. 732 if (Attr.getNumArgs() != 0) { 733 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 734 return; 735 } 736 737 d->addAttr(new ConstAttr()); 738} 739 740static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { 741 // check the attribute arguments. 742 if (Attr.getNumArgs() != 0) { 743 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 744 return; 745 } 746 747 d->addAttr(new PureAttr()); 748} 749 750/// Handle __attribute__((format(type,idx,firstarg))) attributes 751/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html 752static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { 753 754 if (!Attr.getParameterName()) { 755 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) 756 << "format" << "1"; 757 return; 758 } 759 760 if (Attr.getNumArgs() != 2) { 761 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "3"; 762 return; 763 } 764 765 if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { 766 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 767 << "format" << "function"; 768 return; 769 } 770 771 // FIXME: in C++ the implicit 'this' function parameter also counts. 772 // this is needed in order to be compatible with GCC 773 // the index must start in 1 and the limit is numargs+1 774 unsigned NumArgs = getFunctionOrMethodNumArgs(d); 775 unsigned FirstIdx = 1; 776 777 const char *Format = Attr.getParameterName()->getName(); 778 unsigned FormatLen = Attr.getParameterName()->getLength(); 779 780 // Normalize the argument, __foo__ becomes foo. 781 if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' && 782 Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') { 783 Format += 2; 784 FormatLen -= 4; 785 } 786 787 bool Supported = false; 788 bool is_NSString = false; 789 bool is_strftime = false; 790 bool is_CFString = false; 791 792 switch (FormatLen) { 793 default: break; 794 case 5: Supported = !memcmp(Format, "scanf", 5); break; 795 case 6: Supported = !memcmp(Format, "printf", 6); break; 796 case 7: Supported = !memcmp(Format, "strfmon", 7); break; 797 case 8: 798 Supported = (is_strftime = !memcmp(Format, "strftime", 8)) || 799 (is_NSString = !memcmp(Format, "NSString", 8)) || 800 (is_CFString = !memcmp(Format, "CFString", 8)); 801 break; 802 } 803 804 if (!Supported) { 805 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) 806 << "format" << Attr.getParameterName()->getName(); 807 return; 808 } 809 810 // checks for the 2nd argument 811 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0)); 812 llvm::APSInt Idx(32); 813 if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { 814 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 815 << "format" << "2" << IdxExpr->getSourceRange(); 816 return; 817 } 818 819 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { 820 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 821 << "format" << "2" << IdxExpr->getSourceRange(); 822 return; 823 } 824 825 // FIXME: Do we need to bounds check? 826 unsigned ArgIdx = Idx.getZExtValue() - 1; 827 828 // make sure the format string is really a string 829 QualType Ty = getFunctionOrMethodArgType(d, ArgIdx); 830 831 if (is_CFString) { 832 if (!isCFStringType(Ty, S.Context)) { 833 S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 834 << "a CFString" << IdxExpr->getSourceRange(); 835 return; 836 } 837 } else if (is_NSString) { 838 // FIXME: do we need to check if the type is NSString*? What are 839 // the semantics? 840 if (!isNSStringType(Ty, S.Context)) { 841 // FIXME: Should highlight the actual expression that has the 842 // wrong type. 843 S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 844 << "an NSString" << IdxExpr->getSourceRange(); 845 return; 846 } 847 } else if (!Ty->isPointerType() || 848 !Ty->getAsPointerType()->getPointeeType()->isCharType()) { 849 // FIXME: Should highlight the actual expression that has the 850 // wrong type. 851 S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 852 << "a string type" << IdxExpr->getSourceRange(); 853 return; 854 } 855 856 // check the 3rd argument 857 Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1)); 858 llvm::APSInt FirstArg(32); 859 if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) { 860 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 861 << "format" << "3" << FirstArgExpr->getSourceRange(); 862 return; 863 } 864 865 // check if the function is variadic if the 3rd argument non-zero 866 if (FirstArg != 0) { 867 if (isFunctionOrMethodVariadic(d)) { 868 ++NumArgs; // +1 for ... 869 } else { 870 S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic); 871 return; 872 } 873 } 874 875 // strftime requires FirstArg to be 0 because it doesn't read from any variable 876 // the input is just the current time + the format string 877 if (is_strftime) { 878 if (FirstArg != 0) { 879 S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter) 880 << FirstArgExpr->getSourceRange(); 881 return; 882 } 883 // if 0 it disables parameter checking (to use with e.g. va_list) 884 } else if (FirstArg != 0 && FirstArg != NumArgs) { 885 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 886 << "format" << "3" << FirstArgExpr->getSourceRange(); 887 return; 888 } 889 890 d->addAttr(new FormatAttr(std::string(Format, FormatLen), 891 Idx.getZExtValue(), FirstArg.getZExtValue())); 892} 893 894static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, 895 Sema &S) { 896 // check the attribute arguments. 897 if (Attr.getNumArgs() != 0) { 898 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 899 return; 900 } 901 902 // FIXME: This shouldn't be restricted to typedefs 903 TypedefDecl *TD = dyn_cast<TypedefDecl>(d); 904 if (!TD || !TD->getUnderlyingType()->isUnionType()) { 905 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 906 << "transparent_union" << "union"; 907 return; 908 } 909 910 RecordDecl* RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); 911 912 // FIXME: Should we do a check for RD->isDefinition()? 913 914 // FIXME: This isn't supposed to be restricted to pointers, but otherwise 915 // we might silently generate incorrect code; see following code 916 for (int i = 0; i < RD->getNumMembers(); i++) { 917 if (!RD->getMember(i)->getType()->isPointerType()) { 918 S.Diag(Attr.getLoc(), diag::warn_transparent_union_nonpointer); 919 return; 920 } 921 } 922 923 // FIXME: This is a complete hack; we should be properly propagating 924 // transparent_union through Sema. That said, this is close enough to 925 // correctly compile all the common cases of transparent_union without 926 // errors or warnings 927 QualType NewTy = S.Context.VoidPtrTy; 928 NewTy.addConst(); 929 TD->setUnderlyingType(NewTy); 930} 931 932static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { 933 // check the attribute arguments. 934 if (Attr.getNumArgs() != 1) { 935 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "1"; 936 return; 937 } 938 Expr *argExpr = static_cast<Expr *>(Attr.getArg(0)); 939 StringLiteral *SE = dyn_cast<StringLiteral>(argExpr); 940 941 // Make sure that there is a string literal as the annotation's single 942 // argument. 943 if (!SE) { 944 S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string); 945 return; 946 } 947 d->addAttr(new AnnotateAttr(std::string(SE->getStrData(), 948 SE->getByteLength()))); 949} 950 951static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) { 952 // check the attribute arguments. 953 if (Attr.getNumArgs() > 1) { 954 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "1"; 955 return; 956 } 957 958 unsigned Align = 0; 959 if (Attr.getNumArgs() == 0) { 960 // FIXME: This should be the target specific maximum alignment. 961 // (For now we just use 128 bits which is the maximum on X86. 962 Align = 128; 963 return; 964 } 965 966 Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0)); 967 llvm::APSInt Alignment(32); 968 if (!alignmentExpr->isIntegerConstantExpr(Alignment, S.Context)) { 969 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 970 << "aligned" << alignmentExpr->getSourceRange(); 971 return; 972 } 973 d->addAttr(new AlignedAttr(Alignment.getZExtValue() * 8)); 974} 975 976/// HandleModeAttr - This attribute modifies the width of a decl with 977/// primitive type. 978/// 979/// Despite what would be logical, the mode attribute is a decl attribute, 980/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 981/// 'G' be HImode, not an intermediate pointer. 982/// 983static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { 984 // This attribute isn't documented, but glibc uses it. It changes 985 // the width of an int or unsigned int to the specified size. 986 987 // Check that there aren't any arguments 988 if (Attr.getNumArgs() != 0) { 989 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0"; 990 return; 991 } 992 993 IdentifierInfo *Name = Attr.getParameterName(); 994 if (!Name) { 995 S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name); 996 return; 997 } 998 const char *Str = Name->getName(); 999 unsigned Len = Name->getLength(); 1000 1001 // Normalize the attribute name, __foo__ becomes foo. 1002 if (Len > 4 && Str[0] == '_' && Str[1] == '_' && 1003 Str[Len - 2] == '_' && Str[Len - 1] == '_') { 1004 Str += 2; 1005 Len -= 4; 1006 } 1007 1008 unsigned DestWidth = 0; 1009 bool IntegerMode = true; 1010 switch (Len) { 1011 case 2: 1012 if (!memcmp(Str, "QI", 2)) { DestWidth = 8; break; } 1013 if (!memcmp(Str, "HI", 2)) { DestWidth = 16; break; } 1014 if (!memcmp(Str, "SI", 2)) { DestWidth = 32; break; } 1015 if (!memcmp(Str, "DI", 2)) { DestWidth = 64; break; } 1016 if (!memcmp(Str, "TI", 2)) { DestWidth = 128; break; } 1017 if (!memcmp(Str, "SF", 2)) { DestWidth = 32; IntegerMode = false; break; } 1018 if (!memcmp(Str, "DF", 2)) { DestWidth = 64; IntegerMode = false; break; } 1019 if (!memcmp(Str, "XF", 2)) { DestWidth = 96; IntegerMode = false; break; } 1020 if (!memcmp(Str, "TF", 2)) { DestWidth = 128; IntegerMode = false; break; } 1021 break; 1022 case 4: 1023 // FIXME: glibc uses 'word' to define register_t; this is narrower than a 1024 // pointer on PIC16 and other embedded platforms. 1025 if (!memcmp(Str, "word", 4)) 1026 DestWidth = S.Context.Target.getPointerWidth(0); 1027 if (!memcmp(Str, "byte", 4)) 1028 DestWidth = S.Context.Target.getCharWidth(); 1029 break; 1030 case 7: 1031 if (!memcmp(Str, "pointer", 7)) 1032 DestWidth = S.Context.Target.getPointerWidth(0); 1033 break; 1034 } 1035 1036 QualType OldTy; 1037 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) 1038 OldTy = TD->getUnderlyingType(); 1039 else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 1040 OldTy = VD->getType(); 1041 else { 1042 S.Diag(D->getLocation(), diag::err_attr_wrong_decl) 1043 << "mode" << SourceRange(Attr.getLoc(), Attr.getLoc()); 1044 return; 1045 } 1046 1047 // FIXME: Need proper fixed-width types 1048 QualType NewTy; 1049 switch (DestWidth) { 1050 case 0: 1051 S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name->getName(); 1052 return; 1053 default: 1054 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) <<Name->getName(); 1055 return; 1056 case 8: 1057 assert(IntegerMode); 1058 if (OldTy->isSignedIntegerType()) 1059 NewTy = S.Context.SignedCharTy; 1060 else 1061 NewTy = S.Context.UnsignedCharTy; 1062 break; 1063 case 16: 1064 assert(IntegerMode); 1065 if (OldTy->isSignedIntegerType()) 1066 NewTy = S.Context.ShortTy; 1067 else 1068 NewTy = S.Context.UnsignedShortTy; 1069 break; 1070 case 32: 1071 if (!IntegerMode) 1072 NewTy = S.Context.FloatTy; 1073 else if (OldTy->isSignedIntegerType()) 1074 NewTy = S.Context.IntTy; 1075 else 1076 NewTy = S.Context.UnsignedIntTy; 1077 break; 1078 case 64: 1079 if (!IntegerMode) 1080 NewTy = S.Context.DoubleTy; 1081 else if (OldTy->isSignedIntegerType()) 1082 NewTy = S.Context.LongLongTy; 1083 else 1084 NewTy = S.Context.UnsignedLongLongTy; 1085 break; 1086 } 1087 1088 if (!OldTy->getAsBuiltinType()) 1089 S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); 1090 else if (!(IntegerMode && OldTy->isIntegerType()) && 1091 !(!IntegerMode && OldTy->isFloatingType())) { 1092 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); 1093 } 1094 1095 // Install the new type. 1096 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) 1097 TD->setUnderlyingType(NewTy); 1098 else 1099 cast<ValueDecl>(D)->setType(NewTy); 1100} 1101 1102//===----------------------------------------------------------------------===// 1103// Top Level Sema Entry Points 1104//===----------------------------------------------------------------------===// 1105 1106/// HandleDeclAttribute - Apply the specific attribute to the specified decl if 1107/// the attribute applies to decls. If the attribute is a type attribute, just 1108/// silently ignore it. 1109static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) { 1110 switch (Attr.getKind()) { 1111 case AttributeList::AT_IBOutlet: HandleIBOutletAttr (D, Attr, S); break; 1112 case AttributeList::AT_address_space: 1113 // Ignore this, this is a type attribute, handled by ProcessTypeAttributes. 1114 break; 1115 case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break; 1116 case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break; 1117 case AttributeList::AT_always_inline: 1118 HandleAlwaysInlineAttr (D, Attr, S); break; 1119 case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break; 1120 case AttributeList::AT_constructor: HandleConstructorAttr(D, Attr, S); break; 1121 case AttributeList::AT_deprecated: HandleDeprecatedAttr(D, Attr, S); break; 1122 case AttributeList::AT_destructor: HandleDestructorAttr(D, Attr, S); break; 1123 case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break; 1124 case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break; 1125 case AttributeList::AT_ext_vector_type: 1126 HandleExtVectorTypeAttr(D, Attr, S); 1127 break; 1128 case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break; 1129 case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break; 1130 case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break; 1131 case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break; 1132 case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break; 1133 case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break; 1134 case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; 1135 case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break; 1136 case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break; 1137 case AttributeList::AT_vector_size: HandleVectorSizeAttr(D, Attr, S); break; 1138 case AttributeList::AT_visibility: HandleVisibilityAttr(D, Attr, S); break; 1139 case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break; 1140 case AttributeList::AT_transparent_union: 1141 HandleTransparentUnionAttr(D, Attr, S); 1142 break; 1143 case AttributeList::AT_objc_gc: HandleObjCGCAttr (D, Attr, S); break; 1144 case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break; 1145 case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break; 1146 case AttributeList::AT_const: HandleConstAttr (D, Attr, S); break; 1147 case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break; 1148 default: 1149#if 0 1150 // TODO: when we have the full set of attributes, warn about unknown ones. 1151 S.Diag(Attr->getLoc(), diag::warn_attribute_ignored) 1152 << Attr->getName()->getName(); 1153#endif 1154 break; 1155 } 1156} 1157 1158/// ProcessDeclAttributeList - Apply all the decl attributes in the specified 1159/// attribute list to the specified decl, ignoring any type attributes. 1160void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) { 1161 while (AttrList) { 1162 ProcessDeclAttribute(D, *AttrList, *this); 1163 AttrList = AttrList->getNext(); 1164 } 1165} 1166 1167 1168/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in 1169/// it, apply them to D. This is a bit tricky because PD can have attributes 1170/// specified in many different places, and we need to find and apply them all. 1171void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) { 1172 // Apply decl attributes from the DeclSpec if present. 1173 if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes()) 1174 ProcessDeclAttributeList(D, Attrs); 1175 1176 // Walk the declarator structure, applying decl attributes that were in a type 1177 // position to the decl itself. This handles cases like: 1178 // int *__attr__(x)** D; 1179 // when X is a decl attribute. 1180 for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) 1181 if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) 1182 ProcessDeclAttributeList(D, Attrs); 1183 1184 // Finally, apply any attributes on the decl itself. 1185 if (const AttributeList *Attrs = PD.getAttributes()) 1186 ProcessDeclAttributeList(D, Attrs); 1187} 1188 1189