1193326Sed//===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// This file implements decl-related attribute processing. 11193326Sed// 12193326Sed//===----------------------------------------------------------------------===// 13193326Sed 14212904Sdim#include "clang/Sema/SemaInternal.h" 15202379Srdivacky#include "TargetAttributesSema.h" 16193326Sed#include "clang/AST/ASTContext.h" 17245431Sdim#include "clang/AST/CXXInheritance.h" 18212904Sdim#include "clang/AST/DeclCXX.h" 19252723Sdim#include "clang/AST/DeclObjC.h" 20226890Sdim#include "clang/AST/DeclTemplate.h" 21193326Sed#include "clang/AST/Expr.h" 22252723Sdim#include "clang/AST/Mangle.h" 23252723Sdim#include "clang/Basic/CharInfo.h" 24224145Sdim#include "clang/Basic/SourceManager.h" 25193326Sed#include "clang/Basic/TargetInfo.h" 26263509Sdim#include "clang/Lex/Preprocessor.h" 27212904Sdim#include "clang/Sema/DeclSpec.h" 28212904Sdim#include "clang/Sema/DelayedDiagnostic.h" 29226890Sdim#include "clang/Sema/Lookup.h" 30252723Sdim#include "clang/Sema/Scope.h" 31198092Srdivacky#include "llvm/ADT/StringExtras.h" 32193326Sedusing namespace clang; 33212904Sdimusing namespace sema; 34193326Sed 35221345Sdim/// These constants match the enumerated choices of 36221345Sdim/// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type. 37226890Sdimenum AttributeDeclKind { 38221345Sdim ExpectedFunction, 39221345Sdim ExpectedUnion, 40221345Sdim ExpectedVariableOrFunction, 41221345Sdim ExpectedFunctionOrMethod, 42221345Sdim ExpectedParameter, 43221345Sdim ExpectedFunctionMethodOrBlock, 44252723Sdim ExpectedFunctionMethodOrClass, 45221345Sdim ExpectedFunctionMethodOrParameter, 46221345Sdim ExpectedClass, 47221345Sdim ExpectedVariable, 48221345Sdim ExpectedMethod, 49226890Sdim ExpectedVariableFunctionOrLabel, 50235633Sdim ExpectedFieldOrGlobalVar, 51245431Sdim ExpectedStruct, 52252723Sdim ExpectedVariableFunctionOrTag, 53252723Sdim ExpectedTLSVar, 54252723Sdim ExpectedVariableOrField, 55252723Sdim ExpectedVariableFieldOrTag, 56263509Sdim ExpectedTypeOrNamespace, 57263509Sdim ExpectedObjectiveCInterface, 58263509Sdim ExpectedMethodOrProperty, 59263509Sdim ExpectedStructOrUnion, 60263509Sdim ExpectedStructOrUnionOrClass 61221345Sdim}; 62221345Sdim 63193326Sed//===----------------------------------------------------------------------===// 64193326Sed// Helper functions 65193326Sed//===----------------------------------------------------------------------===// 66193326Sed 67224145Sdimstatic const FunctionType *getFunctionType(const Decl *D, 68198092Srdivacky bool blocksToo = true) { 69193326Sed QualType Ty; 70224145Sdim if (const ValueDecl *decl = dyn_cast<ValueDecl>(D)) 71193326Sed Ty = decl->getType(); 72224145Sdim else if (const FieldDecl *decl = dyn_cast<FieldDecl>(D)) 73193326Sed Ty = decl->getType(); 74224145Sdim else if (const TypedefNameDecl* decl = dyn_cast<TypedefNameDecl>(D)) 75193326Sed Ty = decl->getUnderlyingType(); 76193326Sed else 77193326Sed return 0; 78198092Srdivacky 79193326Sed if (Ty->isFunctionPointerType()) 80198092Srdivacky Ty = Ty->getAs<PointerType>()->getPointeeType(); 81193326Sed else if (blocksToo && Ty->isBlockPointerType()) 82198092Srdivacky Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); 83193326Sed 84198092Srdivacky return Ty->getAs<FunctionType>(); 85193326Sed} 86193326Sed 87193326Sed// FIXME: We should provide an abstraction around a method or function 88193326Sed// to provide the following bits of information. 89193326Sed 90201361Srdivacky/// isFunction - Return true if the given decl has function 91198092Srdivacky/// type (function or function-typed variable). 92224145Sdimstatic bool isFunction(const Decl *D) { 93224145Sdim return getFunctionType(D, false) != NULL; 94198092Srdivacky} 95198092Srdivacky 96198092Srdivacky/// isFunctionOrMethod - Return true if the given decl has function 97193326Sed/// type (function or function-typed variable) or an Objective-C 98193326Sed/// method. 99224145Sdimstatic bool isFunctionOrMethod(const Decl *D) { 100245431Sdim return isFunction(D) || isa<ObjCMethodDecl>(D); 101193326Sed} 102193326Sed 103193326Sed/// isFunctionOrMethodOrBlock - Return true if the given decl has function 104193326Sed/// type (function or function-typed variable) or an Objective-C 105193326Sed/// method or a block. 106224145Sdimstatic bool isFunctionOrMethodOrBlock(const Decl *D) { 107224145Sdim if (isFunctionOrMethod(D)) 108193326Sed return true; 109193326Sed // check for block is more involved. 110224145Sdim if (const VarDecl *V = dyn_cast<VarDecl>(D)) { 111193326Sed QualType Ty = V->getType(); 112193326Sed return Ty->isBlockPointerType(); 113193326Sed } 114224145Sdim return isa<BlockDecl>(D); 115193326Sed} 116193326Sed 117218893Sdim/// Return true if the given decl has a declarator that should have 118218893Sdim/// been processed by Sema::GetTypeForDeclarator. 119224145Sdimstatic bool hasDeclarator(const Decl *D) { 120224145Sdim // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl. 121224145Sdim return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) || isa<TypedefNameDecl>(D) || 122224145Sdim isa<ObjCPropertyDecl>(D); 123218893Sdim} 124218893Sdim 125193326Sed/// hasFunctionProto - Return true if the given decl has a argument 126193326Sed/// information. This decl should have already passed 127193326Sed/// isFunctionOrMethod or isFunctionOrMethodOrBlock. 128224145Sdimstatic bool hasFunctionProto(const Decl *D) { 129224145Sdim if (const FunctionType *FnTy = getFunctionType(D)) 130193326Sed return isa<FunctionProtoType>(FnTy); 131193326Sed else { 132224145Sdim assert(isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D)); 133193326Sed return true; 134193326Sed } 135193326Sed} 136193326Sed 137193326Sed/// getFunctionOrMethodNumArgs - Return number of function or method 138193326Sed/// arguments. It is an error to call this on a K&R function (use 139193326Sed/// hasFunctionProto first). 140224145Sdimstatic unsigned getFunctionOrMethodNumArgs(const Decl *D) { 141224145Sdim if (const FunctionType *FnTy = getFunctionType(D)) 142193326Sed return cast<FunctionProtoType>(FnTy)->getNumArgs(); 143224145Sdim if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) 144193326Sed return BD->getNumParams(); 145224145Sdim return cast<ObjCMethodDecl>(D)->param_size(); 146193326Sed} 147193326Sed 148224145Sdimstatic QualType getFunctionOrMethodArgType(const Decl *D, unsigned Idx) { 149224145Sdim if (const FunctionType *FnTy = getFunctionType(D)) 150193326Sed return cast<FunctionProtoType>(FnTy)->getArgType(Idx); 151224145Sdim if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) 152193326Sed return BD->getParamDecl(Idx)->getType(); 153198092Srdivacky 154224145Sdim return cast<ObjCMethodDecl>(D)->param_begin()[Idx]->getType(); 155193326Sed} 156193326Sed 157224145Sdimstatic QualType getFunctionOrMethodResultType(const Decl *D) { 158224145Sdim if (const FunctionType *FnTy = getFunctionType(D)) 159193326Sed return cast<FunctionProtoType>(FnTy)->getResultType(); 160224145Sdim return cast<ObjCMethodDecl>(D)->getResultType(); 161193326Sed} 162193326Sed 163224145Sdimstatic bool isFunctionOrMethodVariadic(const Decl *D) { 164224145Sdim if (const FunctionType *FnTy = getFunctionType(D)) { 165193326Sed const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy); 166193326Sed return proto->isVariadic(); 167224145Sdim } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) 168207619Srdivacky return BD->isVariadic(); 169193326Sed else { 170224145Sdim return cast<ObjCMethodDecl>(D)->isVariadic(); 171193326Sed } 172193326Sed} 173193326Sed 174224145Sdimstatic bool isInstanceMethod(const Decl *D) { 175224145Sdim if (const CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) 176218893Sdim return MethodDecl->isInstance(); 177218893Sdim return false; 178218893Sdim} 179218893Sdim 180193326Sedstatic inline bool isNSStringType(QualType T, ASTContext &Ctx) { 181198092Srdivacky const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>(); 182193326Sed if (!PT) 183193326Sed return false; 184198092Srdivacky 185208600Srdivacky ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface(); 186208600Srdivacky if (!Cls) 187193326Sed return false; 188198092Srdivacky 189208600Srdivacky IdentifierInfo* ClsName = Cls->getIdentifier(); 190198092Srdivacky 191193326Sed // FIXME: Should we walk the chain of classes? 192193326Sed return ClsName == &Ctx.Idents.get("NSString") || 193193326Sed ClsName == &Ctx.Idents.get("NSMutableString"); 194193326Sed} 195193326Sed 196193326Sedstatic inline bool isCFStringType(QualType T, ASTContext &Ctx) { 197198092Srdivacky const PointerType *PT = T->getAs<PointerType>(); 198193326Sed if (!PT) 199193326Sed return false; 200193326Sed 201198092Srdivacky const RecordType *RT = PT->getPointeeType()->getAs<RecordType>(); 202193326Sed if (!RT) 203193326Sed return false; 204198092Srdivacky 205193326Sed const RecordDecl *RD = RT->getDecl(); 206208600Srdivacky if (RD->getTagKind() != TTK_Struct) 207193326Sed return false; 208193326Sed 209193326Sed return RD->getIdentifier() == &Ctx.Idents.get("__CFString"); 210193326Sed} 211193326Sed 212263509Sdimstatic unsigned getNumAttributeArgs(const AttributeList &Attr) { 213263509Sdim // FIXME: Include the type in the argument list. 214263509Sdim return Attr.getNumArgs() + Attr.hasParsedType(); 215263509Sdim} 216263509Sdim 217226890Sdim/// \brief Check if the attribute has exactly as many args as Num. May 218226890Sdim/// output an error. 219224145Sdimstatic bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr, 220263509Sdim unsigned Num) { 221263509Sdim if (getNumAttributeArgs(Attr) != Num) { 222263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 223263509Sdim << Attr.getName() << Num; 224224145Sdim return false; 225224145Sdim } 226224145Sdim 227224145Sdim return true; 228224145Sdim} 229224145Sdim 230226890Sdim 231226890Sdim/// \brief Check if the attribute has at least as many args as Num. May 232226890Sdim/// output an error. 233226890Sdimstatic bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr, 234263509Sdim unsigned Num) { 235263509Sdim if (getNumAttributeArgs(Attr) < Num) { 236226890Sdim S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments) << Num; 237226890Sdim return false; 238226890Sdim } 239226890Sdim 240226890Sdim return true; 241226890Sdim} 242226890Sdim 243245431Sdim/// \brief Check if IdxExpr is a valid argument index for a function or 244245431Sdim/// instance method D. May output an error. 245226890Sdim/// 246245431Sdim/// \returns true if IdxExpr is a valid index. 247245431Sdimstatic bool checkFunctionOrMethodArgumentIndex(Sema &S, const Decl *D, 248245431Sdim StringRef AttrName, 249245431Sdim SourceLocation AttrLoc, 250245431Sdim unsigned AttrArgNum, 251245431Sdim const Expr *IdxExpr, 252245431Sdim uint64_t &Idx) 253245431Sdim{ 254263509Sdim assert(isFunctionOrMethod(D)); 255245431Sdim 256245431Sdim // In C++ the implicit 'this' function parameter also counts. 257245431Sdim // Parameters are counted from one. 258263509Sdim bool HP = hasFunctionProto(D); 259263509Sdim bool HasImplicitThisParam = isInstanceMethod(D); 260263509Sdim bool IV = HP && isFunctionOrMethodVariadic(D); 261263509Sdim unsigned NumArgs = (HP ? getFunctionOrMethodNumArgs(D) : 0) + 262263509Sdim HasImplicitThisParam; 263245431Sdim 264245431Sdim llvm::APSInt IdxInt; 265245431Sdim if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || 266245431Sdim !IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) { 267263509Sdim std::string Name = std::string("'") + AttrName.str() + std::string("'"); 268263509Sdim S.Diag(AttrLoc, diag::err_attribute_argument_n_type) << Name.c_str() 269263509Sdim << AttrArgNum << AANT_ArgumentIntegerConstant << IdxExpr->getSourceRange(); 270245431Sdim return false; 271245431Sdim } 272245431Sdim 273245431Sdim Idx = IdxInt.getLimitedValue(); 274263509Sdim if (Idx < 1 || (!IV && Idx > NumArgs)) { 275245431Sdim S.Diag(AttrLoc, diag::err_attribute_argument_out_of_bounds) 276245431Sdim << AttrName << AttrArgNum << IdxExpr->getSourceRange(); 277245431Sdim return false; 278245431Sdim } 279245431Sdim Idx--; // Convert to zero-based. 280245431Sdim if (HasImplicitThisParam) { 281245431Sdim if (Idx == 0) { 282245431Sdim S.Diag(AttrLoc, 283245431Sdim diag::err_attribute_invalid_implicit_this_argument) 284245431Sdim << AttrName << IdxExpr->getSourceRange(); 285245431Sdim return false; 286245431Sdim } 287245431Sdim --Idx; 288245431Sdim } 289245431Sdim 290245431Sdim return true; 291245431Sdim} 292245431Sdim 293263509Sdim/// \brief Check if the argument \p ArgNum of \p Attr is a ASCII string literal. 294263509Sdim/// If not emit an error and return false. If the argument is an identifier it 295263509Sdim/// will emit an error with a fixit hint and treat it as if it was a string 296263509Sdim/// literal. 297263509Sdimbool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr, 298263509Sdim unsigned ArgNum, StringRef &Str, 299263509Sdim SourceLocation *ArgLocation) { 300263509Sdim // Look for identifiers. If we have one emit a hint to fix it to a literal. 301263509Sdim if (Attr.isArgIdent(ArgNum)) { 302263509Sdim IdentifierLoc *Loc = Attr.getArgAsIdent(ArgNum); 303263509Sdim Diag(Loc->Loc, diag::err_attribute_argument_type) 304263509Sdim << Attr.getName() << AANT_ArgumentString 305263509Sdim << FixItHint::CreateInsertion(Loc->Loc, "\"") 306263509Sdim << FixItHint::CreateInsertion(PP.getLocForEndOfToken(Loc->Loc), "\""); 307263509Sdim Str = Loc->Ident->getName(); 308263509Sdim if (ArgLocation) 309263509Sdim *ArgLocation = Loc->Loc; 310263509Sdim return true; 311263509Sdim } 312263509Sdim 313263509Sdim // Now check for an actual string literal. 314263509Sdim Expr *ArgExpr = Attr.getArgAsExpr(ArgNum); 315263509Sdim StringLiteral *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts()); 316263509Sdim if (ArgLocation) 317263509Sdim *ArgLocation = ArgExpr->getLocStart(); 318263509Sdim 319263509Sdim if (!Literal || !Literal->isAscii()) { 320263509Sdim Diag(ArgExpr->getLocStart(), diag::err_attribute_argument_type) 321263509Sdim << Attr.getName() << AANT_ArgumentString; 322263509Sdim return false; 323263509Sdim } 324263509Sdim 325263509Sdim Str = Literal->getString(); 326263509Sdim return true; 327263509Sdim} 328263509Sdim 329245431Sdim/// 330226890Sdim/// \brief Check if passed in Decl is a field or potentially shared global var 331226890Sdim/// \return true if the Decl is a field or potentially shared global variable 332226890Sdim/// 333226890Sdimstatic bool mayBeSharedVariable(const Decl *D) { 334226890Sdim if (isa<FieldDecl>(D)) 335226890Sdim return true; 336226890Sdim if (const VarDecl *vd = dyn_cast<VarDecl>(D)) 337252723Sdim return vd->hasGlobalStorage() && !vd->getTLSKind(); 338226890Sdim 339226890Sdim return false; 340226890Sdim} 341226890Sdim 342226890Sdim/// \brief Check if the passed-in expression is of type int or bool. 343226890Sdimstatic bool isIntOrBool(Expr *Exp) { 344226890Sdim QualType QT = Exp->getType(); 345226890Sdim return QT->isBooleanType() || QT->isIntegerType(); 346226890Sdim} 347226890Sdim 348245431Sdim 349245431Sdim// Check to see if the type is a smart pointer of some kind. We assume 350245431Sdim// it's a smart pointer if it defines both operator-> and operator*. 351245431Sdimstatic bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) { 352245431Sdim DeclContextLookupConstResult Res1 = RT->getDecl()->lookup( 353245431Sdim S.Context.DeclarationNames.getCXXOperatorName(OO_Star)); 354252723Sdim if (Res1.empty()) 355245431Sdim return false; 356245431Sdim 357245431Sdim DeclContextLookupConstResult Res2 = RT->getDecl()->lookup( 358245431Sdim S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow)); 359252723Sdim if (Res2.empty()) 360245431Sdim return false; 361245431Sdim 362245431Sdim return true; 363245431Sdim} 364245431Sdim 365226890Sdim/// \brief Check if passed in Decl is a pointer type. 366226890Sdim/// Note that this function may produce an error message. 367226890Sdim/// \return true if the Decl is a pointer type; false otherwise 368245431Sdimstatic bool threadSafetyCheckIsPointer(Sema &S, const Decl *D, 369245431Sdim const AttributeList &Attr) { 370226890Sdim if (const ValueDecl *vd = dyn_cast<ValueDecl>(D)) { 371226890Sdim QualType QT = vd->getType(); 372226890Sdim if (QT->isAnyPointerType()) 373226890Sdim return true; 374245431Sdim 375245431Sdim if (const RecordType *RT = QT->getAs<RecordType>()) { 376245431Sdim // If it's an incomplete type, it could be a smart pointer; skip it. 377245431Sdim // (We don't want to force template instantiation if we can avoid it, 378245431Sdim // since that would alter the order in which templates are instantiated.) 379245431Sdim if (RT->isIncompleteType()) 380245431Sdim return true; 381245431Sdim 382245431Sdim if (threadSafetyCheckIsSmartPointer(S, RT)) 383245431Sdim return true; 384245431Sdim } 385245431Sdim 386245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_pointer) 387226890Sdim << Attr.getName()->getName() << QT; 388226890Sdim } else { 389226890Sdim S.Diag(Attr.getLoc(), diag::err_attribute_can_be_applied_only_to_value_decl) 390226890Sdim << Attr.getName(); 391226890Sdim } 392226890Sdim return false; 393226890Sdim} 394226890Sdim 395226890Sdim/// \brief Checks that the passed in QualType either is of RecordType or points 396226890Sdim/// to RecordType. Returns the relevant RecordType, null if it does not exit. 397226890Sdimstatic const RecordType *getRecordType(QualType QT) { 398226890Sdim if (const RecordType *RT = QT->getAs<RecordType>()) 399226890Sdim return RT; 400226890Sdim 401226890Sdim // Now check if we point to record type. 402226890Sdim if (const PointerType *PT = QT->getAs<PointerType>()) 403226890Sdim return PT->getPointeeType()->getAs<RecordType>(); 404226890Sdim 405226890Sdim return 0; 406226890Sdim} 407226890Sdim 408245431Sdim 409245431Sdimstatic bool checkBaseClassIsLockableCallback(const CXXBaseSpecifier *Specifier, 410245431Sdim CXXBasePath &Path, void *Unused) { 411245431Sdim const RecordType *RT = Specifier->getType()->getAs<RecordType>(); 412245431Sdim if (RT->getDecl()->getAttr<LockableAttr>()) 413245431Sdim return true; 414245431Sdim return false; 415245431Sdim} 416245431Sdim 417245431Sdim 418226890Sdim/// \brief Thread Safety Analysis: Checks that the passed in RecordType 419245431Sdim/// resolves to a lockable object. 420235633Sdimstatic void checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr, 421235633Sdim QualType Ty) { 422235633Sdim const RecordType *RT = getRecordType(Ty); 423245431Sdim 424235633Sdim // Warn if could not get record type for this argument. 425226890Sdim if (!RT) { 426245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_class) 427235633Sdim << Attr.getName() << Ty.getAsString(); 428235633Sdim return; 429226890Sdim } 430245431Sdim 431245431Sdim // Don't check for lockable if the class hasn't been defined yet. 432235633Sdim if (RT->isIncompleteType()) 433235633Sdim return; 434245431Sdim 435245431Sdim // Allow smart pointers to be used as lockable objects. 436245431Sdim // FIXME -- Check the type that the smart pointer points to. 437245431Sdim if (threadSafetyCheckIsSmartPointer(S, RT)) 438235633Sdim return; 439245431Sdim 440245431Sdim // Check if the type is lockable. 441245431Sdim RecordDecl *RD = RT->getDecl(); 442245431Sdim if (RD->getAttr<LockableAttr>()) 443245431Sdim return; 444245431Sdim 445245431Sdim // Else check if any base classes are lockable. 446245431Sdim if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) { 447245431Sdim CXXBasePaths BPaths(false, false); 448245431Sdim if (CRD->lookupInBases(checkBaseClassIsLockableCallback, 0, BPaths)) 449245431Sdim return; 450226890Sdim } 451245431Sdim 452245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_lockable) 453245431Sdim << Attr.getName() << Ty.getAsString(); 454226890Sdim} 455226890Sdim 456226890Sdim/// \brief Thread Safety Analysis: Checks that all attribute arguments, starting 457245431Sdim/// from Sidx, resolve to a lockable object. 458226890Sdim/// \param Sidx The attribute argument index to start checking with. 459226890Sdim/// \param ParamIdxOk Whether an argument can be indexing into a function 460226890Sdim/// parameter list. 461245431Sdimstatic void checkAttrArgsAreLockableObjs(Sema &S, Decl *D, 462226890Sdim const AttributeList &Attr, 463226890Sdim SmallVectorImpl<Expr*> &Args, 464226890Sdim int Sidx = 0, 465226890Sdim bool ParamIdxOk = false) { 466226890Sdim for(unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) { 467263509Sdim Expr *ArgExp = Attr.getArgAsExpr(Idx); 468226890Sdim 469226890Sdim if (ArgExp->isTypeDependent()) { 470245431Sdim // FIXME -- need to check this again on template instantiation 471226890Sdim Args.push_back(ArgExp); 472226890Sdim continue; 473226890Sdim } 474226890Sdim 475245431Sdim if (StringLiteral *StrLit = dyn_cast<StringLiteral>(ArgExp)) { 476245431Sdim if (StrLit->getLength() == 0 || 477263509Sdim (StrLit->isAscii() && StrLit->getString() == StringRef("*"))) { 478245431Sdim // Pass empty strings to the analyzer without warnings. 479245431Sdim // Treat "*" as the universal lock. 480245431Sdim Args.push_back(ArgExp); 481245431Sdim continue; 482245431Sdim } 483245431Sdim 484245431Sdim // We allow constant strings to be used as a placeholder for expressions 485245431Sdim // that are not valid C++ syntax, but warn that they are ignored. 486245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_ignored) << 487245431Sdim Attr.getName(); 488245431Sdim Args.push_back(ArgExp); 489245431Sdim continue; 490245431Sdim } 491245431Sdim 492226890Sdim QualType ArgTy = ArgExp->getType(); 493226890Sdim 494245431Sdim // A pointer to member expression of the form &MyClass::mu is treated 495245431Sdim // specially -- we need to look at the type of the member. 496245431Sdim if (UnaryOperator *UOp = dyn_cast<UnaryOperator>(ArgExp)) 497245431Sdim if (UOp->getOpcode() == UO_AddrOf) 498245431Sdim if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(UOp->getSubExpr())) 499245431Sdim if (DRE->getDecl()->isCXXInstanceMember()) 500245431Sdim ArgTy = DRE->getDecl()->getType(); 501245431Sdim 502226890Sdim // First see if we can just cast to record type, or point to record type. 503226890Sdim const RecordType *RT = getRecordType(ArgTy); 504226890Sdim 505226890Sdim // Now check if we index into a record type function param. 506226890Sdim if(!RT && ParamIdxOk) { 507226890Sdim FunctionDecl *FD = dyn_cast<FunctionDecl>(D); 508226890Sdim IntegerLiteral *IL = dyn_cast<IntegerLiteral>(ArgExp); 509226890Sdim if(FD && IL) { 510226890Sdim unsigned int NumParams = FD->getNumParams(); 511226890Sdim llvm::APInt ArgValue = IL->getValue(); 512226890Sdim uint64_t ParamIdxFromOne = ArgValue.getZExtValue(); 513226890Sdim uint64_t ParamIdxFromZero = ParamIdxFromOne - 1; 514226890Sdim if(!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) { 515226890Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_range) 516226890Sdim << Attr.getName() << Idx + 1 << NumParams; 517245431Sdim continue; 518226890Sdim } 519226890Sdim ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType(); 520226890Sdim } 521226890Sdim } 522226890Sdim 523235633Sdim checkForLockableRecord(S, D, Attr, ArgTy); 524226890Sdim 525226890Sdim Args.push_back(ArgExp); 526226890Sdim } 527226890Sdim} 528226890Sdim 529193326Sed//===----------------------------------------------------------------------===// 530193326Sed// Attribute Implementations 531193326Sed//===----------------------------------------------------------------------===// 532193326Sed 533193326Sed// FIXME: All this manual attribute parsing code is gross. At the 534193326Sed// least add some helper functions to check most argument patterns (# 535193326Sed// and types of args). 536193326Sed 537245431Sdimenum ThreadAttributeDeclKind { 538245431Sdim ThreadExpectedFieldOrGlobalVar, 539245431Sdim ThreadExpectedFunctionOrMethod, 540245431Sdim ThreadExpectedClassOrStruct 541245431Sdim}; 542245431Sdim 543245431Sdimstatic bool checkGuardedVarAttrCommon(Sema &S, Decl *D, 544245431Sdim const AttributeList &Attr) { 545226890Sdim // D must be either a member field or global (potentially shared) variable. 546226890Sdim if (!mayBeSharedVariable(D)) { 547245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 548245431Sdim << Attr.getName() << ThreadExpectedFieldOrGlobalVar; 549245431Sdim return false; 550226890Sdim } 551226890Sdim 552245431Sdim return true; 553245431Sdim} 554245431Sdim 555245431Sdimstatic void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr) { 556245431Sdim if (!checkGuardedVarAttrCommon(S, D, Attr)) 557226890Sdim return; 558226890Sdim 559252723Sdim D->addAttr(::new (S.Context) 560252723Sdim GuardedVarAttr(Attr.getRange(), S.Context, 561252723Sdim Attr.getAttributeSpellingListIndex())); 562226890Sdim} 563226890Sdim 564245431Sdimstatic void handlePtGuardedVarAttr(Sema &S, Decl *D, 565252723Sdim const AttributeList &Attr) { 566245431Sdim if (!checkGuardedVarAttrCommon(S, D, Attr)) 567245431Sdim return; 568245431Sdim 569245431Sdim if (!threadSafetyCheckIsPointer(S, D, Attr)) 570245431Sdim return; 571245431Sdim 572252723Sdim D->addAttr(::new (S.Context) 573252723Sdim PtGuardedVarAttr(Attr.getRange(), S.Context, 574252723Sdim Attr.getAttributeSpellingListIndex())); 575245431Sdim} 576245431Sdim 577245431Sdimstatic bool checkGuardedByAttrCommon(Sema &S, Decl *D, 578245431Sdim const AttributeList &Attr, 579245431Sdim Expr* &Arg) { 580226890Sdim // D must be either a member field or global (potentially shared) variable. 581226890Sdim if (!mayBeSharedVariable(D)) { 582245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 583245431Sdim << Attr.getName() << ThreadExpectedFieldOrGlobalVar; 584245431Sdim return false; 585226890Sdim } 586226890Sdim 587245431Sdim SmallVector<Expr*, 1> Args; 588245431Sdim // check that all arguments are lockable objects 589245431Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args); 590245431Sdim unsigned Size = Args.size(); 591245431Sdim if (Size != 1) 592245431Sdim return false; 593245431Sdim 594245431Sdim Arg = Args[0]; 595245431Sdim 596245431Sdim return true; 597245431Sdim} 598245431Sdim 599245431Sdimstatic void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr) { 600245431Sdim Expr *Arg = 0; 601245431Sdim if (!checkGuardedByAttrCommon(S, D, Attr, Arg)) 602226890Sdim return; 603226890Sdim 604245431Sdim D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg)); 605245431Sdim} 606226890Sdim 607245431Sdimstatic void handlePtGuardedByAttr(Sema &S, Decl *D, 608245431Sdim const AttributeList &Attr) { 609245431Sdim Expr *Arg = 0; 610245431Sdim if (!checkGuardedByAttrCommon(S, D, Attr, Arg)) 611245431Sdim return; 612245431Sdim 613245431Sdim if (!threadSafetyCheckIsPointer(S, D, Attr)) 614245431Sdim return; 615245431Sdim 616245431Sdim D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(), 617245431Sdim S.Context, Arg)); 618226890Sdim} 619226890Sdim 620245431Sdimstatic bool checkLockableAttrCommon(Sema &S, Decl *D, 621245431Sdim const AttributeList &Attr) { 622226890Sdim // FIXME: Lockable structs for C code. 623263509Sdim if (!isa<RecordDecl>(D)) { 624245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 625245431Sdim << Attr.getName() << ThreadExpectedClassOrStruct; 626245431Sdim return false; 627226890Sdim } 628226890Sdim 629245431Sdim return true; 630226890Sdim} 631226890Sdim 632245431Sdimstatic void handleLockableAttr(Sema &S, Decl *D, const AttributeList &Attr) { 633245431Sdim if (!checkLockableAttrCommon(S, D, Attr)) 634245431Sdim return; 635245431Sdim 636245431Sdim D->addAttr(::new (S.Context) LockableAttr(Attr.getRange(), S.Context)); 637245431Sdim} 638245431Sdim 639245431Sdimstatic void handleScopedLockableAttr(Sema &S, Decl *D, 640245431Sdim const AttributeList &Attr) { 641245431Sdim if (!checkLockableAttrCommon(S, D, Attr)) 642245431Sdim return; 643245431Sdim 644252723Sdim D->addAttr(::new (S.Context) 645252723Sdim ScopedLockableAttr(Attr.getRange(), S.Context, 646252723Sdim Attr.getAttributeSpellingListIndex())); 647245431Sdim} 648245431Sdim 649252723Sdimstatic void handleNoThreadSafetyAnalysis(Sema &S, Decl *D, 650252723Sdim const AttributeList &Attr) { 651226890Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 652245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 653245431Sdim << Attr.getName() << ThreadExpectedFunctionOrMethod; 654226890Sdim return; 655226890Sdim } 656226890Sdim 657226890Sdim D->addAttr(::new (S.Context) NoThreadSafetyAnalysisAttr(Attr.getRange(), 658226890Sdim S.Context)); 659226890Sdim} 660226890Sdim 661252723Sdimstatic void handleNoSanitizeAddressAttr(Sema &S, Decl *D, 662245431Sdim const AttributeList &Attr) { 663235633Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 664252723Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 665235633Sdim << Attr.getName() << ExpectedFunctionOrMethod; 666235633Sdim return; 667235633Sdim } 668235633Sdim 669252723Sdim D->addAttr(::new (S.Context) 670252723Sdim NoSanitizeAddressAttr(Attr.getRange(), S.Context, 671252723Sdim Attr.getAttributeSpellingListIndex())); 672235633Sdim} 673235633Sdim 674252723Sdimstatic void handleNoSanitizeMemory(Sema &S, Decl *D, 675252723Sdim const AttributeList &Attr) { 676252723Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 677252723Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 678252723Sdim << Attr.getName() << ExpectedFunctionOrMethod; 679252723Sdim return; 680252723Sdim } 681252723Sdim 682252723Sdim D->addAttr(::new (S.Context) NoSanitizeMemoryAttr(Attr.getRange(), 683252723Sdim S.Context)); 684252723Sdim} 685252723Sdim 686252723Sdimstatic void handleNoSanitizeThread(Sema &S, Decl *D, 687252723Sdim const AttributeList &Attr) { 688252723Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 689252723Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 690252723Sdim << Attr.getName() << ExpectedFunctionOrMethod; 691252723Sdim return; 692252723Sdim } 693252723Sdim 694252723Sdim D->addAttr(::new (S.Context) NoSanitizeThreadAttr(Attr.getRange(), 695252723Sdim S.Context)); 696252723Sdim} 697252723Sdim 698245431Sdimstatic bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, 699245431Sdim const AttributeList &Attr, 700263509Sdim SmallVectorImpl<Expr *> &Args) { 701226890Sdim if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) 702245431Sdim return false; 703226890Sdim 704226890Sdim // D must be either a member field or global (potentially shared) variable. 705226890Sdim ValueDecl *VD = dyn_cast<ValueDecl>(D); 706226890Sdim if (!VD || !mayBeSharedVariable(D)) { 707245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 708245431Sdim << Attr.getName() << ThreadExpectedFieldOrGlobalVar; 709245431Sdim return false; 710226890Sdim } 711226890Sdim 712245431Sdim // Check that this attribute only applies to lockable types. 713226890Sdim QualType QT = VD->getType(); 714226890Sdim if (!QT->isDependentType()) { 715226890Sdim const RecordType *RT = getRecordType(QT); 716226890Sdim if (!RT || !RT->getDecl()->getAttr<LockableAttr>()) { 717245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable) 718245431Sdim << Attr.getName(); 719245431Sdim return false; 720226890Sdim } 721226890Sdim } 722226890Sdim 723245431Sdim // Check that all arguments are lockable objects. 724245431Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args); 725252723Sdim if (Args.empty()) 726245431Sdim return false; 727245431Sdim 728245431Sdim return true; 729245431Sdim} 730245431Sdim 731245431Sdimstatic void handleAcquiredAfterAttr(Sema &S, Decl *D, 732245431Sdim const AttributeList &Attr) { 733226890Sdim SmallVector<Expr*, 1> Args; 734245431Sdim if (!checkAcquireOrderAttrCommon(S, D, Attr, Args)) 735226890Sdim return; 736226890Sdim 737245431Sdim Expr **StartArg = &Args[0]; 738252723Sdim D->addAttr(::new (S.Context) 739252723Sdim AcquiredAfterAttr(Attr.getRange(), S.Context, 740252723Sdim StartArg, Args.size(), 741252723Sdim Attr.getAttributeSpellingListIndex())); 742245431Sdim} 743226890Sdim 744245431Sdimstatic void handleAcquiredBeforeAttr(Sema &S, Decl *D, 745245431Sdim const AttributeList &Attr) { 746245431Sdim SmallVector<Expr*, 1> Args; 747245431Sdim if (!checkAcquireOrderAttrCommon(S, D, Attr, Args)) 748245431Sdim return; 749245431Sdim 750245431Sdim Expr **StartArg = &Args[0]; 751252723Sdim D->addAttr(::new (S.Context) 752252723Sdim AcquiredBeforeAttr(Attr.getRange(), S.Context, 753252723Sdim StartArg, Args.size(), 754252723Sdim Attr.getAttributeSpellingListIndex())); 755226890Sdim} 756226890Sdim 757245431Sdimstatic bool checkLockFunAttrCommon(Sema &S, Decl *D, 758245431Sdim const AttributeList &Attr, 759263509Sdim SmallVectorImpl<Expr *> &Args) { 760226890Sdim // zero or more arguments ok 761226890Sdim 762226890Sdim // check that the attribute is applied to a function 763226890Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 764245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 765245431Sdim << Attr.getName() << ThreadExpectedFunctionOrMethod; 766245431Sdim return false; 767226890Sdim } 768226890Sdim 769226890Sdim // check that all arguments are lockable objects 770245431Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true); 771245431Sdim 772245431Sdim return true; 773245431Sdim} 774245431Sdim 775245431Sdimstatic void handleSharedLockFunctionAttr(Sema &S, Decl *D, 776245431Sdim const AttributeList &Attr) { 777226890Sdim SmallVector<Expr*, 1> Args; 778245431Sdim if (!checkLockFunAttrCommon(S, D, Attr, Args)) 779226890Sdim return; 780226890Sdim 781226890Sdim unsigned Size = Args.size(); 782226890Sdim Expr **StartArg = Size == 0 ? 0 : &Args[0]; 783252723Sdim D->addAttr(::new (S.Context) 784252723Sdim SharedLockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size, 785252723Sdim Attr.getAttributeSpellingListIndex())); 786245431Sdim} 787226890Sdim 788245431Sdimstatic void handleExclusiveLockFunctionAttr(Sema &S, Decl *D, 789245431Sdim const AttributeList &Attr) { 790245431Sdim SmallVector<Expr*, 1> Args; 791245431Sdim if (!checkLockFunAttrCommon(S, D, Attr, Args)) 792245431Sdim return; 793245431Sdim 794245431Sdim unsigned Size = Args.size(); 795245431Sdim Expr **StartArg = Size == 0 ? 0 : &Args[0]; 796252723Sdim D->addAttr(::new (S.Context) 797252723Sdim ExclusiveLockFunctionAttr(Attr.getRange(), S.Context, 798252723Sdim StartArg, Size, 799252723Sdim Attr.getAttributeSpellingListIndex())); 800226890Sdim} 801226890Sdim 802263509Sdimstatic void handleAssertSharedLockAttr(Sema &S, Decl *D, 803263509Sdim const AttributeList &Attr) { 804263509Sdim SmallVector<Expr*, 1> Args; 805263509Sdim if (!checkLockFunAttrCommon(S, D, Attr, Args)) 806263509Sdim return; 807263509Sdim 808263509Sdim unsigned Size = Args.size(); 809263509Sdim Expr **StartArg = Size == 0 ? 0 : &Args[0]; 810263509Sdim D->addAttr(::new (S.Context) 811263509Sdim AssertSharedLockAttr(Attr.getRange(), S.Context, StartArg, Size, 812263509Sdim Attr.getAttributeSpellingListIndex())); 813263509Sdim} 814263509Sdim 815263509Sdimstatic void handleAssertExclusiveLockAttr(Sema &S, Decl *D, 816263509Sdim const AttributeList &Attr) { 817263509Sdim SmallVector<Expr*, 1> Args; 818263509Sdim if (!checkLockFunAttrCommon(S, D, Attr, Args)) 819263509Sdim return; 820263509Sdim 821263509Sdim unsigned Size = Args.size(); 822263509Sdim Expr **StartArg = Size == 0 ? 0 : &Args[0]; 823263509Sdim D->addAttr(::new (S.Context) 824263509Sdim AssertExclusiveLockAttr(Attr.getRange(), S.Context, 825263509Sdim StartArg, Size, 826263509Sdim Attr.getAttributeSpellingListIndex())); 827263509Sdim} 828263509Sdim 829263509Sdim 830245431Sdimstatic bool checkTryLockFunAttrCommon(Sema &S, Decl *D, 831245431Sdim const AttributeList &Attr, 832263509Sdim SmallVectorImpl<Expr *> &Args) { 833226890Sdim if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) 834245431Sdim return false; 835226890Sdim 836226890Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 837245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 838245431Sdim << Attr.getName() << ThreadExpectedFunctionOrMethod; 839245431Sdim return false; 840226890Sdim } 841226890Sdim 842263509Sdim if (!isIntOrBool(Attr.getArgAsExpr(0))) { 843263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 844263509Sdim << Attr.getName() << 1 << AANT_ArgumentIntOrBool; 845245431Sdim return false; 846226890Sdim } 847226890Sdim 848245431Sdim // check that all arguments are lockable objects 849245431Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args, 1); 850245431Sdim 851245431Sdim return true; 852245431Sdim} 853245431Sdim 854245431Sdimstatic void handleSharedTrylockFunctionAttr(Sema &S, Decl *D, 855245431Sdim const AttributeList &Attr) { 856226890Sdim SmallVector<Expr*, 2> Args; 857245431Sdim if (!checkTryLockFunAttrCommon(S, D, Attr, Args)) 858226890Sdim return; 859226890Sdim 860252723Sdim D->addAttr(::new (S.Context) 861252723Sdim SharedTrylockFunctionAttr(Attr.getRange(), S.Context, 862263509Sdim Attr.getArgAsExpr(0), 863263509Sdim Args.data(), Args.size(), 864252723Sdim Attr.getAttributeSpellingListIndex())); 865245431Sdim} 866226890Sdim 867245431Sdimstatic void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, 868245431Sdim const AttributeList &Attr) { 869245431Sdim SmallVector<Expr*, 2> Args; 870245431Sdim if (!checkTryLockFunAttrCommon(S, D, Attr, Args)) 871245431Sdim return; 872245431Sdim 873252723Sdim D->addAttr(::new (S.Context) 874252723Sdim ExclusiveTrylockFunctionAttr(Attr.getRange(), S.Context, 875263509Sdim Attr.getArgAsExpr(0), 876263509Sdim Args.data(), Args.size(), 877252723Sdim Attr.getAttributeSpellingListIndex())); 878226890Sdim} 879226890Sdim 880245431Sdimstatic bool checkLocksRequiredCommon(Sema &S, Decl *D, 881245431Sdim const AttributeList &Attr, 882263509Sdim SmallVectorImpl<Expr *> &Args) { 883226890Sdim if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) 884245431Sdim return false; 885226890Sdim 886226890Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 887245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 888245431Sdim << Attr.getName() << ThreadExpectedFunctionOrMethod; 889245431Sdim return false; 890226890Sdim } 891226890Sdim 892226890Sdim // check that all arguments are lockable objects 893245431Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args); 894252723Sdim if (Args.empty()) 895245431Sdim return false; 896245431Sdim 897245431Sdim return true; 898245431Sdim} 899245431Sdim 900245431Sdimstatic void handleExclusiveLocksRequiredAttr(Sema &S, Decl *D, 901245431Sdim const AttributeList &Attr) { 902226890Sdim SmallVector<Expr*, 1> Args; 903245431Sdim if (!checkLocksRequiredCommon(S, D, Attr, Args)) 904226890Sdim return; 905226890Sdim 906245431Sdim Expr **StartArg = &Args[0]; 907252723Sdim D->addAttr(::new (S.Context) 908252723Sdim ExclusiveLocksRequiredAttr(Attr.getRange(), S.Context, 909252723Sdim StartArg, Args.size(), 910252723Sdim Attr.getAttributeSpellingListIndex())); 911245431Sdim} 912226890Sdim 913245431Sdimstatic void handleSharedLocksRequiredAttr(Sema &S, Decl *D, 914245431Sdim const AttributeList &Attr) { 915245431Sdim SmallVector<Expr*, 1> Args; 916245431Sdim if (!checkLocksRequiredCommon(S, D, Attr, Args)) 917245431Sdim return; 918245431Sdim 919245431Sdim Expr **StartArg = &Args[0]; 920252723Sdim D->addAttr(::new (S.Context) 921252723Sdim SharedLocksRequiredAttr(Attr.getRange(), S.Context, 922252723Sdim StartArg, Args.size(), 923252723Sdim Attr.getAttributeSpellingListIndex())); 924226890Sdim} 925226890Sdim 926226890Sdimstatic void handleUnlockFunAttr(Sema &S, Decl *D, 927226890Sdim const AttributeList &Attr) { 928226890Sdim // zero or more arguments ok 929226890Sdim 930226890Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 931245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 932245431Sdim << Attr.getName() << ThreadExpectedFunctionOrMethod; 933226890Sdim return; 934226890Sdim } 935226890Sdim 936226890Sdim // check that all arguments are lockable objects 937226890Sdim SmallVector<Expr*, 1> Args; 938245431Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true); 939226890Sdim unsigned Size = Args.size(); 940226890Sdim Expr **StartArg = Size == 0 ? 0 : &Args[0]; 941226890Sdim 942252723Sdim D->addAttr(::new (S.Context) 943252723Sdim UnlockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size, 944252723Sdim Attr.getAttributeSpellingListIndex())); 945226890Sdim} 946226890Sdim 947226890Sdimstatic void handleLockReturnedAttr(Sema &S, Decl *D, 948226890Sdim const AttributeList &Attr) { 949226890Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 950245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 951245431Sdim << Attr.getName() << ThreadExpectedFunctionOrMethod; 952226890Sdim return; 953226890Sdim } 954226890Sdim 955245431Sdim // check that the argument is lockable object 956245431Sdim SmallVector<Expr*, 1> Args; 957245431Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args); 958245431Sdim unsigned Size = Args.size(); 959245431Sdim if (Size == 0) 960226890Sdim return; 961226890Sdim 962252723Sdim D->addAttr(::new (S.Context) 963252723Sdim LockReturnedAttr(Attr.getRange(), S.Context, Args[0], 964252723Sdim Attr.getAttributeSpellingListIndex())); 965226890Sdim} 966226890Sdim 967226890Sdimstatic void handleLocksExcludedAttr(Sema &S, Decl *D, 968226890Sdim const AttributeList &Attr) { 969226890Sdim if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) 970226890Sdim return; 971226890Sdim 972226890Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 973245431Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 974245431Sdim << Attr.getName() << ThreadExpectedFunctionOrMethod; 975226890Sdim return; 976226890Sdim } 977226890Sdim 978226890Sdim // check that all arguments are lockable objects 979226890Sdim SmallVector<Expr*, 1> Args; 980245431Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args); 981245431Sdim unsigned Size = Args.size(); 982245431Sdim if (Size == 0) 983226890Sdim return; 984245431Sdim Expr **StartArg = &Args[0]; 985226890Sdim 986252723Sdim D->addAttr(::new (S.Context) 987252723Sdim LocksExcludedAttr(Attr.getRange(), S.Context, StartArg, Size, 988252723Sdim Attr.getAttributeSpellingListIndex())); 989226890Sdim} 990226890Sdim 991263509Sdimstatic void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) { 992263509Sdim ConsumableAttr::ConsumedState DefaultState; 993226890Sdim 994263509Sdim if (Attr.isArgIdent(0)) { 995263509Sdim IdentifierLoc *IL = Attr.getArgAsIdent(0); 996263509Sdim if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(), 997263509Sdim DefaultState)) { 998263509Sdim S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) 999263509Sdim << Attr.getName() << IL->Ident; 1000263509Sdim return; 1001263509Sdim } 1002263509Sdim } else { 1003263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) 1004263509Sdim << Attr.getName() << AANT_ArgumentIdentifier; 1005263509Sdim return; 1006263509Sdim } 1007263509Sdim 1008263509Sdim if (!isa<CXXRecordDecl>(D)) { 1009263509Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << 1010263509Sdim Attr.getName() << ExpectedClass; 1011263509Sdim return; 1012263509Sdim } 1013263509Sdim 1014263509Sdim D->addAttr(::new (S.Context) 1015263509Sdim ConsumableAttr(Attr.getRange(), S.Context, DefaultState, 1016263509Sdim Attr.getAttributeSpellingListIndex())); 1017263509Sdim} 1018263509Sdim 1019263509Sdimstatic bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, 1020263509Sdim const AttributeList &Attr) { 1021263509Sdim ASTContext &CurrContext = S.getASTContext(); 1022263509Sdim QualType ThisType = MD->getThisType(CurrContext)->getPointeeType(); 1023263509Sdim 1024263509Sdim if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) { 1025263509Sdim if (!RD->hasAttr<ConsumableAttr>()) { 1026263509Sdim S.Diag(Attr.getLoc(), diag::warn_attr_on_unconsumable_class) << 1027263509Sdim RD->getNameAsString(); 1028263509Sdim 1029263509Sdim return false; 1030263509Sdim } 1031263509Sdim } 1032263509Sdim 1033263509Sdim return true; 1034263509Sdim} 1035263509Sdim 1036263509Sdim 1037263509Sdimstatic void handleCallableWhenAttr(Sema &S, Decl *D, 1038263509Sdim const AttributeList &Attr) { 1039263509Sdim if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) 1040263509Sdim return; 1041263509Sdim 1042263509Sdim if (!isa<CXXMethodDecl>(D)) { 1043263509Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << 1044263509Sdim Attr.getName() << ExpectedMethod; 1045263509Sdim return; 1046263509Sdim } 1047263509Sdim 1048263509Sdim if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) 1049263509Sdim return; 1050263509Sdim 1051263509Sdim SmallVector<CallableWhenAttr::ConsumedState, 3> States; 1052263509Sdim for (unsigned ArgIndex = 0; ArgIndex < Attr.getNumArgs(); ++ArgIndex) { 1053263509Sdim CallableWhenAttr::ConsumedState CallableState; 1054263509Sdim 1055263509Sdim StringRef StateString; 1056263509Sdim SourceLocation Loc; 1057263509Sdim if (!S.checkStringLiteralArgumentAttr(Attr, ArgIndex, StateString, &Loc)) 1058263509Sdim return; 1059263509Sdim 1060263509Sdim if (!CallableWhenAttr::ConvertStrToConsumedState(StateString, 1061263509Sdim CallableState)) { 1062263509Sdim S.Diag(Loc, diag::warn_attribute_type_not_supported) 1063263509Sdim << Attr.getName() << StateString; 1064263509Sdim return; 1065263509Sdim } 1066263509Sdim 1067263509Sdim States.push_back(CallableState); 1068263509Sdim } 1069263509Sdim 1070263509Sdim D->addAttr(::new (S.Context) 1071263509Sdim CallableWhenAttr(Attr.getRange(), S.Context, States.data(), 1072263509Sdim States.size(), Attr.getAttributeSpellingListIndex())); 1073263509Sdim} 1074263509Sdim 1075263509Sdim 1076263509Sdimstatic void handleParamTypestateAttr(Sema &S, Decl *D, 1077263509Sdim const AttributeList &Attr) { 1078263509Sdim if (!checkAttributeNumArgs(S, Attr, 1)) return; 1079263509Sdim 1080263509Sdim if (!isa<ParmVarDecl>(D)) { 1081263509Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << 1082263509Sdim Attr.getName() << ExpectedParameter; 1083263509Sdim return; 1084263509Sdim } 1085263509Sdim 1086263509Sdim ParamTypestateAttr::ConsumedState ParamState; 1087263509Sdim 1088263509Sdim if (Attr.isArgIdent(0)) { 1089263509Sdim IdentifierLoc *Ident = Attr.getArgAsIdent(0); 1090263509Sdim StringRef StateString = Ident->Ident->getName(); 1091263509Sdim 1092263509Sdim if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString, 1093263509Sdim ParamState)) { 1094263509Sdim S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) 1095263509Sdim << Attr.getName() << StateString; 1096263509Sdim return; 1097263509Sdim } 1098263509Sdim } else { 1099263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << 1100263509Sdim Attr.getName() << AANT_ArgumentIdentifier; 1101263509Sdim return; 1102263509Sdim } 1103263509Sdim 1104263509Sdim // FIXME: This check is currently being done in the analysis. It can be 1105263509Sdim // enabled here only after the parser propagates attributes at 1106263509Sdim // template specialization definition, not declaration. 1107263509Sdim //QualType ReturnType = cast<ParmVarDecl>(D)->getType(); 1108263509Sdim //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); 1109263509Sdim // 1110263509Sdim //if (!RD || !RD->hasAttr<ConsumableAttr>()) { 1111263509Sdim // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) << 1112263509Sdim // ReturnType.getAsString(); 1113263509Sdim // return; 1114263509Sdim //} 1115263509Sdim 1116263509Sdim D->addAttr(::new (S.Context) 1117263509Sdim ParamTypestateAttr(Attr.getRange(), S.Context, ParamState, 1118263509Sdim Attr.getAttributeSpellingListIndex())); 1119263509Sdim} 1120263509Sdim 1121263509Sdim 1122263509Sdimstatic void handleReturnTypestateAttr(Sema &S, Decl *D, 1123263509Sdim const AttributeList &Attr) { 1124263509Sdim if (!checkAttributeNumArgs(S, Attr, 1)) return; 1125263509Sdim 1126263509Sdim if (!(isa<FunctionDecl>(D) || isa<ParmVarDecl>(D))) { 1127263509Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << 1128263509Sdim Attr.getName() << ExpectedFunctionMethodOrParameter; 1129263509Sdim return; 1130263509Sdim } 1131263509Sdim 1132263509Sdim ReturnTypestateAttr::ConsumedState ReturnState; 1133263509Sdim 1134263509Sdim if (Attr.isArgIdent(0)) { 1135263509Sdim IdentifierLoc *IL = Attr.getArgAsIdent(0); 1136263509Sdim if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(), 1137263509Sdim ReturnState)) { 1138263509Sdim S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) 1139263509Sdim << Attr.getName() << IL->Ident; 1140263509Sdim return; 1141263509Sdim } 1142263509Sdim } else { 1143263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << 1144263509Sdim Attr.getName() << AANT_ArgumentIdentifier; 1145263509Sdim return; 1146263509Sdim } 1147263509Sdim 1148263509Sdim // FIXME: This check is currently being done in the analysis. It can be 1149263509Sdim // enabled here only after the parser propagates attributes at 1150263509Sdim // template specialization definition, not declaration. 1151263509Sdim //QualType ReturnType; 1152263509Sdim // 1153263509Sdim //if (const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D)) { 1154263509Sdim // ReturnType = Param->getType(); 1155263509Sdim // 1156263509Sdim //} else if (const CXXConstructorDecl *Constructor = 1157263509Sdim // dyn_cast<CXXConstructorDecl>(D)) { 1158263509Sdim // ReturnType = Constructor->getThisType(S.getASTContext())->getPointeeType(); 1159263509Sdim // 1160263509Sdim //} else { 1161263509Sdim // 1162263509Sdim // ReturnType = cast<FunctionDecl>(D)->getCallResultType(); 1163263509Sdim //} 1164263509Sdim // 1165263509Sdim //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); 1166263509Sdim // 1167263509Sdim //if (!RD || !RD->hasAttr<ConsumableAttr>()) { 1168263509Sdim // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) << 1169263509Sdim // ReturnType.getAsString(); 1170263509Sdim // return; 1171263509Sdim //} 1172263509Sdim 1173263509Sdim D->addAttr(::new (S.Context) 1174263509Sdim ReturnTypestateAttr(Attr.getRange(), S.Context, ReturnState, 1175263509Sdim Attr.getAttributeSpellingListIndex())); 1176263509Sdim} 1177263509Sdim 1178263509Sdim 1179263509Sdimstatic void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1180263509Sdim if (!checkAttributeNumArgs(S, Attr, 1)) 1181263509Sdim return; 1182263509Sdim 1183263509Sdim if (!isa<CXXMethodDecl>(D)) { 1184263509Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << 1185263509Sdim Attr.getName() << ExpectedMethod; 1186263509Sdim return; 1187263509Sdim } 1188263509Sdim 1189263509Sdim if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) 1190263509Sdim return; 1191263509Sdim 1192263509Sdim SetTypestateAttr::ConsumedState NewState; 1193263509Sdim if (Attr.isArgIdent(0)) { 1194263509Sdim IdentifierLoc *Ident = Attr.getArgAsIdent(0); 1195263509Sdim StringRef Param = Ident->Ident->getName(); 1196263509Sdim if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) { 1197263509Sdim S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) 1198263509Sdim << Attr.getName() << Param; 1199263509Sdim return; 1200263509Sdim } 1201263509Sdim } else { 1202263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << 1203263509Sdim Attr.getName() << AANT_ArgumentIdentifier; 1204263509Sdim return; 1205263509Sdim } 1206263509Sdim 1207263509Sdim D->addAttr(::new (S.Context) 1208263509Sdim SetTypestateAttr(Attr.getRange(), S.Context, NewState, 1209263509Sdim Attr.getAttributeSpellingListIndex())); 1210263509Sdim} 1211263509Sdim 1212263509Sdimstatic void handleTestTypestateAttr(Sema &S, Decl *D, 1213263509Sdim const AttributeList &Attr) { 1214263509Sdim if (!checkAttributeNumArgs(S, Attr, 1)) 1215263509Sdim return; 1216263509Sdim 1217263509Sdim if (!isa<CXXMethodDecl>(D)) { 1218263509Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << 1219263509Sdim Attr.getName() << ExpectedMethod; 1220263509Sdim return; 1221263509Sdim } 1222263509Sdim 1223263509Sdim if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) 1224263509Sdim return; 1225263509Sdim 1226263509Sdim TestTypestateAttr::ConsumedState TestState; 1227263509Sdim if (Attr.isArgIdent(0)) { 1228263509Sdim IdentifierLoc *Ident = Attr.getArgAsIdent(0); 1229263509Sdim StringRef Param = Ident->Ident->getName(); 1230263509Sdim if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) { 1231263509Sdim S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) 1232263509Sdim << Attr.getName() << Param; 1233263509Sdim return; 1234263509Sdim } 1235263509Sdim } else { 1236263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << 1237263509Sdim Attr.getName() << AANT_ArgumentIdentifier; 1238263509Sdim return; 1239263509Sdim } 1240263509Sdim 1241263509Sdim D->addAttr(::new (S.Context) 1242263509Sdim TestTypestateAttr(Attr.getRange(), S.Context, TestState, 1243263509Sdim Attr.getAttributeSpellingListIndex())); 1244263509Sdim} 1245263509Sdim 1246224145Sdimstatic void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D, 1247224145Sdim const AttributeList &Attr) { 1248252723Sdim TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); 1249252723Sdim if (TD == 0) { 1250252723Sdim // __attribute__((ext_vector_type(N))) can only be applied to typedefs 1251252723Sdim // and type-ids. 1252193326Sed S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); 1253193326Sed return; 1254193326Sed } 1255198092Srdivacky 1256252723Sdim // Remember this typedef decl, we will need it later for diagnostics. 1257252723Sdim S.ExtVectorDecls.push_back(TD); 1258193326Sed} 1259193326Sed 1260224145Sdimstatic void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1261224145Sdim if (TagDecl *TD = dyn_cast<TagDecl>(D)) 1262226890Sdim TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context)); 1263224145Sdim else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { 1264193326Sed // If the alignment is less than or equal to 8 bits, the packed attribute 1265193326Sed // has no effect. 1266245431Sdim if (!FD->getType()->isDependentType() && 1267245431Sdim !FD->getType()->isIncompleteType() && 1268193326Sed S.Context.getTypeAlign(FD->getType()) <= 8) 1269193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) 1270193326Sed << Attr.getName() << FD->getType(); 1271193326Sed else 1272252723Sdim FD->addAttr(::new (S.Context) 1273252723Sdim PackedAttr(Attr.getRange(), S.Context, 1274252723Sdim Attr.getAttributeSpellingListIndex())); 1275193326Sed } else 1276193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 1277193326Sed} 1278193326Sed 1279224145Sdimstatic void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1280245431Sdim if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) 1281252723Sdim RD->addAttr(::new (S.Context) 1282252723Sdim MsStructAttr(Attr.getRange(), S.Context, 1283252723Sdim Attr.getAttributeSpellingListIndex())); 1284221345Sdim else 1285221345Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 1286221345Sdim} 1287221345Sdim 1288224145Sdimstatic void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) { 1289204643Srdivacky // The IBAction attributes only apply to instance methods. 1290224145Sdim if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 1291204643Srdivacky if (MD->isInstanceMethod()) { 1292252723Sdim D->addAttr(::new (S.Context) 1293252723Sdim IBActionAttr(Attr.getRange(), S.Context, 1294252723Sdim Attr.getAttributeSpellingListIndex())); 1295204643Srdivacky return; 1296204643Srdivacky } 1297204643Srdivacky 1298218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ibaction) << Attr.getName(); 1299204643Srdivacky} 1300204643Srdivacky 1301226890Sdimstatic bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) { 1302226890Sdim // The IBOutlet/IBOutletCollection attributes only apply to instance 1303226890Sdim // variables or properties of Objective-C classes. The outlet must also 1304226890Sdim // have an object reference type. 1305226890Sdim if (const ObjCIvarDecl *VD = dyn_cast<ObjCIvarDecl>(D)) { 1306226890Sdim if (!VD->getType()->getAs<ObjCObjectPointerType>()) { 1307235633Sdim S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type) 1308226890Sdim << Attr.getName() << VD->getType() << 0; 1309226890Sdim return false; 1310226890Sdim } 1311226890Sdim } 1312226890Sdim else if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) { 1313226890Sdim if (!PD->getType()->getAs<ObjCObjectPointerType>()) { 1314235633Sdim S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type) 1315226890Sdim << Attr.getName() << PD->getType() << 1; 1316226890Sdim return false; 1317226890Sdim } 1318226890Sdim } 1319226890Sdim else { 1320226890Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName(); 1321226890Sdim return false; 1322226890Sdim } 1323235633Sdim 1324226890Sdim return true; 1325226890Sdim} 1326226890Sdim 1327224145Sdimstatic void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) { 1328226890Sdim if (!checkIBOutletCommon(S, D, Attr)) 1329204643Srdivacky return; 1330204643Srdivacky 1331252723Sdim D->addAttr(::new (S.Context) 1332252723Sdim IBOutletAttr(Attr.getRange(), S.Context, 1333252723Sdim Attr.getAttributeSpellingListIndex())); 1334193326Sed} 1335193326Sed 1336224145Sdimstatic void handleIBOutletCollection(Sema &S, Decl *D, 1337224145Sdim const AttributeList &Attr) { 1338208600Srdivacky 1339208600Srdivacky // The iboutletcollection attribute can have zero or one arguments. 1340263509Sdim if (Attr.getNumArgs() > 1) { 1341263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 1342263509Sdim << Attr.getName() << 1; 1343208600Srdivacky return; 1344208600Srdivacky } 1345208600Srdivacky 1346226890Sdim if (!checkIBOutletCommon(S, D, Attr)) 1347208600Srdivacky return; 1348226890Sdim 1349263509Sdim ParsedType PT; 1350263509Sdim 1351263509Sdim if (Attr.hasParsedType()) 1352263509Sdim PT = Attr.getTypeArg(); 1353263509Sdim else { 1354263509Sdim PT = S.getTypeName(S.Context.Idents.get("NSObject"), Attr.getLoc(), 1355263509Sdim S.getScopeForContext(D->getDeclContext()->getParent())); 1356263509Sdim if (!PT) { 1357263509Sdim S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << "NSObject"; 1358263509Sdim return; 1359263509Sdim } 1360212904Sdim } 1361263509Sdim 1362263509Sdim TypeSourceInfo *QTLoc = 0; 1363263509Sdim QualType QT = S.GetTypeFromParser(PT, &QTLoc); 1364263509Sdim if (!QTLoc) 1365263509Sdim QTLoc = S.Context.getTrivialTypeSourceInfo(QT, Attr.getLoc()); 1366263509Sdim 1367212904Sdim // Diagnose use of non-object type in iboutletcollection attribute. 1368212904Sdim // FIXME. Gnu attribute extension ignores use of builtin types in 1369212904Sdim // attributes. So, __attribute__((iboutletcollection(char))) will be 1370212904Sdim // treated as __attribute__((iboutletcollection())). 1371235633Sdim if (!QT->isObjCIdType() && !QT->isObjCObjectType()) { 1372263509Sdim S.Diag(Attr.getLoc(), 1373263509Sdim QT->isBuiltinType() ? diag::err_iboutletcollection_builtintype 1374263509Sdim : diag::err_iboutletcollection_type) << QT; 1375212904Sdim return; 1376212904Sdim } 1377263509Sdim 1378252723Sdim D->addAttr(::new (S.Context) 1379263509Sdim IBOutletCollectionAttr(Attr.getRange(), S.Context, QTLoc, 1380252723Sdim Attr.getAttributeSpellingListIndex())); 1381208600Srdivacky} 1382208600Srdivacky 1383224145Sdimstatic void possibleTransparentUnionPointerType(QualType &T) { 1384224145Sdim if (const RecordType *UT = T->getAsUnionType()) 1385224145Sdim if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) { 1386224145Sdim RecordDecl *UD = UT->getDecl(); 1387224145Sdim for (RecordDecl::field_iterator it = UD->field_begin(), 1388224145Sdim itend = UD->field_end(); it != itend; ++it) { 1389224145Sdim QualType QT = it->getType(); 1390224145Sdim if (QT->isAnyPointerType() || QT->isBlockPointerType()) { 1391224145Sdim T = QT; 1392224145Sdim return; 1393224145Sdim } 1394224145Sdim } 1395224145Sdim } 1396224145Sdim} 1397224145Sdim 1398245431Sdimstatic void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1399245431Sdim if (!isFunctionOrMethod(D)) { 1400245431Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1401263509Sdim << Attr.getName() << ExpectedFunctionOrMethod; 1402245431Sdim return; 1403245431Sdim } 1404245431Sdim 1405245431Sdim if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) 1406245431Sdim return; 1407245431Sdim 1408245431Sdim SmallVector<unsigned, 8> SizeArgs; 1409263509Sdim for (unsigned i = 0; i < Attr.getNumArgs(); ++i) { 1410263509Sdim Expr *Ex = Attr.getArgAsExpr(i); 1411263509Sdim uint64_t Idx; 1412263509Sdim if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(), 1413263509Sdim Attr.getLoc(), i + 1, Ex, Idx)) 1414245431Sdim return; 1415245431Sdim 1416245431Sdim // check if the function argument is of an integer type 1417263509Sdim QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType(); 1418245431Sdim if (!T->isIntegerType()) { 1419263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) 1420263509Sdim << Attr.getName() << AANT_ArgumentIntegerConstant 1421263509Sdim << Ex->getSourceRange(); 1422245431Sdim return; 1423245431Sdim } 1424263509Sdim SizeArgs.push_back(Idx); 1425245431Sdim } 1426245431Sdim 1427245431Sdim // check if the function returns a pointer 1428245431Sdim if (!getFunctionType(D)->getResultType()->isAnyPointerType()) { 1429245431Sdim S.Diag(Attr.getLoc(), diag::warn_ns_attribute_wrong_return_type) 1430263509Sdim << Attr.getName() << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange(); 1431245431Sdim } 1432245431Sdim 1433252723Sdim D->addAttr(::new (S.Context) 1434252723Sdim AllocSizeAttr(Attr.getRange(), S.Context, 1435252723Sdim SizeArgs.data(), SizeArgs.size(), 1436252723Sdim Attr.getAttributeSpellingListIndex())); 1437245431Sdim} 1438245431Sdim 1439224145Sdimstatic void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1440198092Srdivacky // GCC ignores the nonnull attribute on K&R style function prototypes, so we 1441198092Srdivacky // ignore it as well 1442224145Sdim if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { 1443193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1444221345Sdim << Attr.getName() << ExpectedFunction; 1445193326Sed return; 1446193326Sed } 1447198092Srdivacky 1448263509Sdim SmallVector<unsigned, 8> NonNullArgs; 1449263509Sdim for (unsigned i = 0; i < Attr.getNumArgs(); ++i) { 1450263509Sdim Expr *Ex = Attr.getArgAsExpr(i); 1451263509Sdim uint64_t Idx; 1452263509Sdim if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(), 1453263509Sdim Attr.getLoc(), i + 1, Ex, Idx)) 1454193326Sed return; 1455198092Srdivacky 1456193326Sed // Is the function argument a pointer type? 1457263509Sdim QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType(); 1458224145Sdim possibleTransparentUnionPointerType(T); 1459224145Sdim 1460198092Srdivacky if (!T->isAnyPointerType() && !T->isBlockPointerType()) { 1461193326Sed // FIXME: Should also highlight argument in decl. 1462212904Sdim S.Diag(Attr.getLoc(), diag::warn_nonnull_pointers_only) 1463193326Sed << "nonnull" << Ex->getSourceRange(); 1464193326Sed continue; 1465193326Sed } 1466198092Srdivacky 1467263509Sdim NonNullArgs.push_back(Idx); 1468193326Sed } 1469198092Srdivacky 1470198092Srdivacky // If no arguments were specified to __attribute__((nonnull)) then all pointer 1471198092Srdivacky // arguments have a nonnull attribute. 1472193326Sed if (NonNullArgs.empty()) { 1473252723Sdim for (unsigned i = 0, e = getFunctionOrMethodNumArgs(D); i != e; ++i) { 1474252723Sdim QualType T = getFunctionOrMethodArgType(D, i).getNonReferenceType(); 1475224145Sdim possibleTransparentUnionPointerType(T); 1476198092Srdivacky if (T->isAnyPointerType() || T->isBlockPointerType()) 1477252723Sdim NonNullArgs.push_back(i); 1478193326Sed } 1479198092Srdivacky 1480218893Sdim // No pointer arguments? 1481193326Sed if (NonNullArgs.empty()) { 1482218893Sdim // Warn the trivial case only if attribute is not coming from a 1483218893Sdim // macro instantiation. 1484218893Sdim if (Attr.getLoc().isFileID()) 1485218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers); 1486193326Sed return; 1487193326Sed } 1488193326Sed } 1489193326Sed 1490252723Sdim unsigned *start = &NonNullArgs[0]; 1491193326Sed unsigned size = NonNullArgs.size(); 1492212904Sdim llvm::array_pod_sort(start, start + size); 1493252723Sdim D->addAttr(::new (S.Context) 1494252723Sdim NonNullAttr(Attr.getRange(), S.Context, start, size, 1495252723Sdim Attr.getAttributeSpellingListIndex())); 1496193326Sed} 1497193326Sed 1498263509Sdimstatic const char *ownershipKindToDiagName(OwnershipAttr::OwnershipKind K) { 1499263509Sdim switch (K) { 1500263509Sdim case OwnershipAttr::Holds: return "'ownership_holds'"; 1501263509Sdim case OwnershipAttr::Takes: return "'ownership_takes'"; 1502263509Sdim case OwnershipAttr::Returns: return "'ownership_returns'"; 1503263509Sdim } 1504263509Sdim llvm_unreachable("unknown ownership"); 1505263509Sdim} 1506263509Sdim 1507224145Sdimstatic void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { 1508263509Sdim // This attribute must be applied to a function declaration. The first 1509263509Sdim // argument to the attribute must be an identifier, the name of the resource, 1510263509Sdim // for example: malloc. The following arguments must be argument indexes, the 1511263509Sdim // arguments must be of integer type for Returns, otherwise of pointer type. 1512212904Sdim // The difference between Holds and Takes is that a pointer may still be used 1513263509Sdim // after being held. free() should be __attribute((ownership_takes)), whereas 1514212904Sdim // a list append function may well be __attribute((ownership_holds)). 1515212904Sdim 1516263509Sdim if (!AL.isArgIdent(0)) { 1517263509Sdim S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 1518263509Sdim << AL.getName() << 1 << AANT_ArgumentIdentifier; 1519212904Sdim return; 1520212904Sdim } 1521263509Sdim 1522212904Sdim // Figure out our Kind, and check arguments while we're at it. 1523212904Sdim OwnershipAttr::OwnershipKind K; 1524212904Sdim switch (AL.getKind()) { 1525212904Sdim case AttributeList::AT_ownership_takes: 1526212904Sdim K = OwnershipAttr::Takes; 1527263509Sdim if (AL.getNumArgs() < 2) { 1528263509Sdim S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << 2; 1529212904Sdim return; 1530212904Sdim } 1531212904Sdim break; 1532212904Sdim case AttributeList::AT_ownership_holds: 1533212904Sdim K = OwnershipAttr::Holds; 1534263509Sdim if (AL.getNumArgs() < 2) { 1535263509Sdim S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << 2; 1536212904Sdim return; 1537212904Sdim } 1538212904Sdim break; 1539212904Sdim case AttributeList::AT_ownership_returns: 1540212904Sdim K = OwnershipAttr::Returns; 1541263509Sdim 1542263509Sdim if (AL.getNumArgs() > 2) { 1543263509Sdim S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << 1; 1544212904Sdim return; 1545212904Sdim } 1546212904Sdim break; 1547212904Sdim default: 1548212904Sdim // This should never happen given how we are called. 1549212904Sdim llvm_unreachable("Unknown ownership attribute"); 1550212904Sdim } 1551212904Sdim 1552224145Sdim if (!isFunction(D) || !hasFunctionProto(D)) { 1553221345Sdim S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) 1554221345Sdim << AL.getName() << ExpectedFunction; 1555212904Sdim return; 1556212904Sdim } 1557212904Sdim 1558263509Sdim StringRef Module = AL.getArgAsIdent(0)->Ident->getName(); 1559212904Sdim 1560212904Sdim // Normalize the argument, __foo__ becomes foo. 1561212904Sdim if (Module.startswith("__") && Module.endswith("__")) 1562212904Sdim Module = Module.substr(2, Module.size() - 4); 1563212904Sdim 1564263509Sdim SmallVector<unsigned, 8> OwnershipArgs; 1565263509Sdim for (unsigned i = 1; i < AL.getNumArgs(); ++i) { 1566263509Sdim Expr *Ex = AL.getArgAsExpr(i); 1567263509Sdim uint64_t Idx; 1568263509Sdim if (!checkFunctionOrMethodArgumentIndex(S, D, AL.getName()->getName(), 1569263509Sdim AL.getLoc(), i, Ex, Idx)) 1570263509Sdim return; 1571212904Sdim 1572263509Sdim // Is the function argument a pointer type? 1573263509Sdim QualType T = getFunctionOrMethodArgType(D, Idx); 1574263509Sdim int Err = -1; // No error 1575212904Sdim switch (K) { 1576263509Sdim case OwnershipAttr::Takes: 1577263509Sdim case OwnershipAttr::Holds: 1578263509Sdim if (!T->isAnyPointerType() && !T->isBlockPointerType()) 1579263509Sdim Err = 0; 1580263509Sdim break; 1581263509Sdim case OwnershipAttr::Returns: 1582263509Sdim if (!T->isIntegerType()) 1583263509Sdim Err = 1; 1584263509Sdim break; 1585212904Sdim } 1586263509Sdim if (-1 != Err) { 1587263509Sdim S.Diag(AL.getLoc(), diag::err_ownership_type) << AL.getName() << Err 1588263509Sdim << Ex->getSourceRange(); 1589263509Sdim return; 1590212904Sdim } 1591212904Sdim 1592212904Sdim // Check we don't have a conflict with another ownership attribute. 1593212904Sdim for (specific_attr_iterator<OwnershipAttr> 1594263509Sdim i = D->specific_attr_begin<OwnershipAttr>(), 1595263509Sdim e = D->specific_attr_end<OwnershipAttr>(); i != e; ++i) { 1596263509Sdim if ((*i)->getOwnKind() != K && (*i)->args_end() != 1597263509Sdim std::find((*i)->args_begin(), (*i)->args_end(), Idx)) { 1598263509Sdim S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) 1599263509Sdim << AL.getName() << ownershipKindToDiagName((*i)->getOwnKind()); 1600263509Sdim return; 1601212904Sdim } 1602212904Sdim } 1603263509Sdim OwnershipArgs.push_back(Idx); 1604212904Sdim } 1605212904Sdim 1606212904Sdim unsigned* start = OwnershipArgs.data(); 1607212904Sdim unsigned size = OwnershipArgs.size(); 1608212904Sdim llvm::array_pod_sort(start, start + size); 1609212904Sdim 1610252723Sdim D->addAttr(::new (S.Context) 1611252723Sdim OwnershipAttr(AL.getLoc(), S.Context, K, Module, start, size, 1612252723Sdim AL.getAttributeSpellingListIndex())); 1613212904Sdim} 1614212904Sdim 1615224145Sdimstatic void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1616204643Srdivacky // Check the attribute arguments. 1617204643Srdivacky if (Attr.getNumArgs() > 1) { 1618263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 1619263509Sdim << Attr.getName() << 1; 1620204643Srdivacky return; 1621204643Srdivacky } 1622204643Srdivacky 1623224145Sdim if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) { 1624218893Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 1625221345Sdim << Attr.getName() << ExpectedVariableOrFunction; 1626218893Sdim return; 1627218893Sdim } 1628218893Sdim 1629224145Sdim NamedDecl *nd = cast<NamedDecl>(D); 1630218893Sdim 1631204643Srdivacky // gcc rejects 1632204643Srdivacky // class c { 1633204643Srdivacky // static int a __attribute__((weakref ("v2"))); 1634204643Srdivacky // static int b() __attribute__((weakref ("f3"))); 1635204643Srdivacky // }; 1636204643Srdivacky // and ignores the attributes of 1637204643Srdivacky // void f(void) { 1638204643Srdivacky // static int a __attribute__((weakref ("v2"))); 1639204643Srdivacky // } 1640204643Srdivacky // we reject them 1641224145Sdim const DeclContext *Ctx = D->getDeclContext()->getRedeclContext(); 1642212904Sdim if (!Ctx->isFileContext()) { 1643212904Sdim S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) << 1644218893Sdim nd->getNameAsString(); 1645212904Sdim return; 1646204643Srdivacky } 1647204643Srdivacky 1648204643Srdivacky // The GCC manual says 1649204643Srdivacky // 1650204643Srdivacky // At present, a declaration to which `weakref' is attached can only 1651204643Srdivacky // be `static'. 1652204643Srdivacky // 1653204643Srdivacky // It also says 1654204643Srdivacky // 1655204643Srdivacky // Without a TARGET, 1656204643Srdivacky // given as an argument to `weakref' or to `alias', `weakref' is 1657204643Srdivacky // equivalent to `weak'. 1658204643Srdivacky // 1659204643Srdivacky // gcc 4.4.1 will accept 1660204643Srdivacky // int a7 __attribute__((weakref)); 1661204643Srdivacky // as 1662204643Srdivacky // int a7 __attribute__((weak)); 1663204643Srdivacky // This looks like a bug in gcc. We reject that for now. We should revisit 1664204643Srdivacky // it if this behaviour is actually used. 1665204643Srdivacky 1666204643Srdivacky // GCC rejects 1667204643Srdivacky // static ((alias ("y"), weakref)). 1668204643Srdivacky // Should we? How to check that weakref is before or after alias? 1669204643Srdivacky 1670263509Sdim // FIXME: it would be good for us to keep the WeakRefAttr as-written instead 1671263509Sdim // of transforming it into an AliasAttr. The WeakRefAttr never uses the 1672263509Sdim // StringRef parameter it was given anyway. 1673263509Sdim StringRef Str; 1674263509Sdim if (Attr.getNumArgs() && S.checkStringLiteralArgumentAttr(Attr, 0, Str)) 1675204643Srdivacky // GCC will accept anything as the argument of weakref. Should we 1676204643Srdivacky // check for an existing decl? 1677263509Sdim D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str, 1678263509Sdim Attr.getAttributeSpellingListIndex())); 1679204643Srdivacky 1680252723Sdim D->addAttr(::new (S.Context) 1681252723Sdim WeakRefAttr(Attr.getRange(), S.Context, 1682252723Sdim Attr.getAttributeSpellingListIndex())); 1683204643Srdivacky} 1684204643Srdivacky 1685224145Sdimstatic void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1686263509Sdim StringRef Str; 1687263509Sdim if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str)) 1688193326Sed return; 1689198092Srdivacky 1690226890Sdim if (S.Context.getTargetInfo().getTriple().isOSDarwin()) { 1691218893Sdim S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin); 1692218893Sdim return; 1693218893Sdim } 1694218893Sdim 1695193326Sed // FIXME: check if target symbol exists in current file 1696198092Srdivacky 1697263509Sdim D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str, 1698252723Sdim Attr.getAttributeSpellingListIndex())); 1699193326Sed} 1700193326Sed 1701245431Sdimstatic void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1702245431Sdim if (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D)) { 1703245431Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 1704245431Sdim << Attr.getName() << ExpectedFunctionOrMethod; 1705245431Sdim return; 1706245431Sdim } 1707245431Sdim 1708252723Sdim D->addAttr(::new (S.Context) 1709252723Sdim MinSizeAttr(Attr.getRange(), S.Context, 1710252723Sdim Attr.getAttributeSpellingListIndex())); 1711245431Sdim} 1712245431Sdim 1713245431Sdimstatic void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1714245431Sdim if (!isa<FunctionDecl>(D)) { 1715245431Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1716245431Sdim << Attr.getName() << ExpectedFunction; 1717245431Sdim return; 1718245431Sdim } 1719245431Sdim 1720245431Sdim if (D->hasAttr<HotAttr>()) { 1721245431Sdim S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) 1722245431Sdim << Attr.getName() << "hot"; 1723245431Sdim return; 1724245431Sdim } 1725245431Sdim 1726252723Sdim D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context, 1727252723Sdim Attr.getAttributeSpellingListIndex())); 1728245431Sdim} 1729245431Sdim 1730245431Sdimstatic void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1731245431Sdim if (!isa<FunctionDecl>(D)) { 1732245431Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1733245431Sdim << Attr.getName() << ExpectedFunction; 1734245431Sdim return; 1735245431Sdim } 1736245431Sdim 1737245431Sdim if (D->hasAttr<ColdAttr>()) { 1738245431Sdim S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) 1739245431Sdim << Attr.getName() << "cold"; 1740245431Sdim return; 1741245431Sdim } 1742245431Sdim 1743252723Sdim D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context, 1744252723Sdim Attr.getAttributeSpellingListIndex())); 1745245431Sdim} 1746245431Sdim 1747224145Sdimstatic void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1748224145Sdim if (!isa<FunctionDecl>(D)) { 1749218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1750221345Sdim << Attr.getName() << ExpectedFunction; 1751218893Sdim return; 1752218893Sdim } 1753218893Sdim 1754252723Sdim D->addAttr(::new (S.Context) 1755252723Sdim NakedAttr(Attr.getRange(), S.Context, 1756252723Sdim Attr.getAttributeSpellingListIndex())); 1757218893Sdim} 1758218893Sdim 1759224145Sdimstatic void handleAlwaysInlineAttr(Sema &S, Decl *D, 1760224145Sdim const AttributeList &Attr) { 1761224145Sdim if (!isa<FunctionDecl>(D)) { 1762193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1763221345Sdim << Attr.getName() << ExpectedFunction; 1764193326Sed return; 1765193326Sed } 1766198092Srdivacky 1767252723Sdim D->addAttr(::new (S.Context) 1768252723Sdim AlwaysInlineAttr(Attr.getRange(), S.Context, 1769252723Sdim Attr.getAttributeSpellingListIndex())); 1770193326Sed} 1771193326Sed 1772245431Sdimstatic void handleTLSModelAttr(Sema &S, Decl *D, 1773245431Sdim const AttributeList &Attr) { 1774263509Sdim StringRef Model; 1775263509Sdim SourceLocation LiteralLoc; 1776245431Sdim // Check that it is a string. 1777263509Sdim if (!S.checkStringLiteralArgumentAttr(Attr, 0, Model, &LiteralLoc)) 1778245431Sdim return; 1779245431Sdim 1780252723Sdim if (!isa<VarDecl>(D) || !cast<VarDecl>(D)->getTLSKind()) { 1781245431Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 1782245431Sdim << Attr.getName() << ExpectedTLSVar; 1783245431Sdim return; 1784245431Sdim } 1785245431Sdim 1786245431Sdim // Check that the value. 1787245431Sdim if (Model != "global-dynamic" && Model != "local-dynamic" 1788245431Sdim && Model != "initial-exec" && Model != "local-exec") { 1789263509Sdim S.Diag(LiteralLoc, diag::err_attr_tlsmodel_arg); 1790245431Sdim return; 1791245431Sdim } 1792245431Sdim 1793252723Sdim D->addAttr(::new (S.Context) 1794252723Sdim TLSModelAttr(Attr.getRange(), S.Context, Model, 1795252723Sdim Attr.getAttributeSpellingListIndex())); 1796245431Sdim} 1797245431Sdim 1798224145Sdimstatic void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1799224145Sdim if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 1800198092Srdivacky QualType RetTy = FD->getResultType(); 1801198092Srdivacky if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) { 1802252723Sdim D->addAttr(::new (S.Context) 1803252723Sdim MallocAttr(Attr.getRange(), S.Context, 1804252723Sdim Attr.getAttributeSpellingListIndex())); 1805198092Srdivacky return; 1806198092Srdivacky } 1807198092Srdivacky } 1808198092Srdivacky 1809198092Srdivacky S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only); 1810198092Srdivacky} 1811198092Srdivacky 1812224145Sdimstatic void handleMayAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1813252723Sdim D->addAttr(::new (S.Context) 1814252723Sdim MayAliasAttr(Attr.getRange(), S.Context, 1815252723Sdim Attr.getAttributeSpellingListIndex())); 1816218893Sdim} 1817218893Sdim 1818224145Sdimstatic void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1819224145Sdim if (isa<VarDecl>(D)) 1820252723Sdim D->addAttr(::new (S.Context) 1821252723Sdim NoCommonAttr(Attr.getRange(), S.Context, 1822252723Sdim Attr.getAttributeSpellingListIndex())); 1823218893Sdim else 1824218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1825221345Sdim << Attr.getName() << ExpectedVariable; 1826212904Sdim} 1827212904Sdim 1828224145Sdimstatic void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1829263509Sdim if (S.LangOpts.CPlusPlus) { 1830263509Sdim S.Diag(Attr.getLoc(), diag::err_common_not_supported_cplusplus); 1831263509Sdim return; 1832263509Sdim } 1833263509Sdim 1834224145Sdim if (isa<VarDecl>(D)) 1835252723Sdim D->addAttr(::new (S.Context) 1836252723Sdim CommonAttr(Attr.getRange(), S.Context, 1837252723Sdim Attr.getAttributeSpellingListIndex())); 1838218893Sdim else 1839218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1840221345Sdim << Attr.getName() << ExpectedVariable; 1841218893Sdim} 1842218893Sdim 1843224145Sdimstatic void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) { 1844224145Sdim if (hasDeclarator(D)) return; 1845218893Sdim 1846218893Sdim if (S.CheckNoReturnAttr(attr)) return; 1847218893Sdim 1848224145Sdim if (!isa<ObjCMethodDecl>(D)) { 1849218893Sdim S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1850221345Sdim << attr.getName() << ExpectedFunctionOrMethod; 1851218893Sdim return; 1852218893Sdim } 1853218893Sdim 1854252723Sdim D->addAttr(::new (S.Context) 1855252723Sdim NoReturnAttr(attr.getRange(), S.Context, 1856252723Sdim attr.getAttributeSpellingListIndex())); 1857218893Sdim} 1858218893Sdim 1859218893Sdimbool Sema::CheckNoReturnAttr(const AttributeList &attr) { 1860263509Sdim if (!checkAttributeNumArgs(*this, attr, 0)) { 1861218893Sdim attr.setInvalid(); 1862218893Sdim return true; 1863218893Sdim } 1864218893Sdim 1865218893Sdim return false; 1866218893Sdim} 1867218893Sdim 1868224145Sdimstatic void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, 1869224145Sdim const AttributeList &Attr) { 1870212904Sdim 1871212904Sdim // The checking path for 'noreturn' and 'analyzer_noreturn' are different 1872212904Sdim // because 'analyzer_noreturn' does not impact the type. 1873224145Sdim if (!isFunctionOrMethod(D) && !isa<BlockDecl>(D)) { 1874224145Sdim ValueDecl *VD = dyn_cast<ValueDecl>(D); 1875200583Srdivacky if (VD == 0 || (!VD->getType()->isBlockPointerType() 1876200583Srdivacky && !VD->getType()->isFunctionPointerType())) { 1877199990Srdivacky S.Diag(Attr.getLoc(), 1878252723Sdim Attr.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type 1879212904Sdim : diag::warn_attribute_wrong_decl_type) 1880221345Sdim << Attr.getName() << ExpectedFunctionMethodOrBlock; 1881212904Sdim return; 1882193326Sed } 1883193326Sed } 1884212904Sdim 1885252723Sdim D->addAttr(::new (S.Context) 1886252723Sdim AnalyzerNoReturnAttr(Attr.getRange(), S.Context, 1887252723Sdim Attr.getAttributeSpellingListIndex())); 1888193326Sed} 1889193326Sed 1890252723Sdimstatic void handleCXX11NoReturnAttr(Sema &S, Decl *D, 1891252723Sdim const AttributeList &Attr) { 1892252723Sdim // C++11 [dcl.attr.noreturn]p1: 1893252723Sdim // The attribute may be applied to the declarator-id in a function 1894252723Sdim // declaration. 1895252723Sdim FunctionDecl *FD = dyn_cast<FunctionDecl>(D); 1896252723Sdim if (!FD) { 1897252723Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 1898252723Sdim << Attr.getName() << ExpectedFunctionOrMethod; 1899252723Sdim return; 1900252723Sdim } 1901252723Sdim 1902252723Sdim D->addAttr(::new (S.Context) 1903252723Sdim CXX11NoReturnAttr(Attr.getRange(), S.Context, 1904252723Sdim Attr.getAttributeSpellingListIndex())); 1905252723Sdim} 1906252723Sdim 1907212904Sdim// PS3 PPU-specific. 1908224145Sdimstatic void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1909212904Sdim/* 1910212904Sdim Returning a Vector Class in Registers 1911212904Sdim 1912218893Sdim According to the PPU ABI specifications, a class with a single member of 1913218893Sdim vector type is returned in memory when used as the return value of a function. 1914218893Sdim This results in inefficient code when implementing vector classes. To return 1915218893Sdim the value in a single vector register, add the vecreturn attribute to the 1916218893Sdim class definition. This attribute is also applicable to struct types. 1917212904Sdim 1918212904Sdim Example: 1919212904Sdim 1920212904Sdim struct Vector 1921212904Sdim { 1922212904Sdim __vector float xyzw; 1923212904Sdim } __attribute__((vecreturn)); 1924212904Sdim 1925212904Sdim Vector Add(Vector lhs, Vector rhs) 1926212904Sdim { 1927212904Sdim Vector result; 1928212904Sdim result.xyzw = vec_add(lhs.xyzw, rhs.xyzw); 1929212904Sdim return result; // This will be returned in a register 1930212904Sdim } 1931212904Sdim*/ 1932224145Sdim if (!isa<RecordDecl>(D)) { 1933212904Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 1934221345Sdim << Attr.getName() << ExpectedClass; 1935212904Sdim return; 1936212904Sdim } 1937193326Sed 1938224145Sdim if (D->getAttr<VecReturnAttr>()) { 1939212904Sdim S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn"; 1940212904Sdim return; 1941212904Sdim } 1942212904Sdim 1943224145Sdim RecordDecl *record = cast<RecordDecl>(D); 1944218893Sdim int count = 0; 1945218893Sdim 1946218893Sdim if (!isa<CXXRecordDecl>(record)) { 1947218893Sdim S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member); 1948218893Sdim return; 1949218893Sdim } 1950218893Sdim 1951218893Sdim if (!cast<CXXRecordDecl>(record)->isPOD()) { 1952218893Sdim S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_pod_record); 1953218893Sdim return; 1954218893Sdim } 1955218893Sdim 1956218893Sdim for (RecordDecl::field_iterator iter = record->field_begin(); 1957218893Sdim iter != record->field_end(); iter++) { 1958218893Sdim if ((count == 1) || !iter->getType()->isVectorType()) { 1959218893Sdim S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member); 1960218893Sdim return; 1961218893Sdim } 1962218893Sdim count++; 1963218893Sdim } 1964218893Sdim 1965252723Sdim D->addAttr(::new (S.Context) 1966252723Sdim VecReturnAttr(Attr.getRange(), S.Context, 1967252723Sdim Attr.getAttributeSpellingListIndex())); 1968193326Sed} 1969193326Sed 1970252723Sdimstatic void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, 1971252723Sdim const AttributeList &Attr) { 1972252723Sdim if (isa<ParmVarDecl>(D)) { 1973252723Sdim // [[carries_dependency]] can only be applied to a parameter if it is a 1974252723Sdim // parameter of a function declaration or lambda. 1975252723Sdim if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) { 1976252723Sdim S.Diag(Attr.getLoc(), 1977252723Sdim diag::err_carries_dependency_param_not_function_decl); 1978252723Sdim return; 1979252723Sdim } 1980252723Sdim } else if (!isa<FunctionDecl>(D)) { 1981199990Srdivacky S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 1982221345Sdim << Attr.getName() << ExpectedFunctionMethodOrParameter; 1983199990Srdivacky return; 1984199990Srdivacky } 1985252723Sdim 1986252723Sdim D->addAttr(::new (S.Context) CarriesDependencyAttr( 1987252723Sdim Attr.getRange(), S.Context, 1988252723Sdim Attr.getAttributeSpellingListIndex())); 1989199990Srdivacky} 1990199990Srdivacky 1991224145Sdimstatic void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1992224145Sdim if (!isa<VarDecl>(D) && !isa<ObjCIvarDecl>(D) && !isFunctionOrMethod(D) && 1993245431Sdim !isa<TypeDecl>(D) && !isa<LabelDecl>(D) && !isa<FieldDecl>(D)) { 1994193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1995221345Sdim << Attr.getName() << ExpectedVariableFunctionOrLabel; 1996193326Sed return; 1997193326Sed } 1998198092Srdivacky 1999252723Sdim D->addAttr(::new (S.Context) 2000252723Sdim UnusedAttr(Attr.getRange(), S.Context, 2001252723Sdim Attr.getAttributeSpellingListIndex())); 2002193326Sed} 2003193326Sed 2004226890Sdimstatic void handleReturnsTwiceAttr(Sema &S, Decl *D, 2005226890Sdim const AttributeList &Attr) { 2006226890Sdim if (!isa<FunctionDecl>(D)) { 2007226890Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2008226890Sdim << Attr.getName() << ExpectedFunction; 2009226890Sdim return; 2010226890Sdim } 2011226890Sdim 2012252723Sdim D->addAttr(::new (S.Context) 2013252723Sdim ReturnsTwiceAttr(Attr.getRange(), S.Context, 2014252723Sdim Attr.getAttributeSpellingListIndex())); 2015226890Sdim} 2016226890Sdim 2017224145Sdimstatic void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2018224145Sdim if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { 2019263509Sdim if (VD->hasLocalStorage()) { 2020193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used"; 2021193326Sed return; 2022193326Sed } 2023224145Sdim } else if (!isFunctionOrMethod(D)) { 2024193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2025221345Sdim << Attr.getName() << ExpectedVariableOrFunction; 2026193326Sed return; 2027193326Sed } 2028198092Srdivacky 2029252723Sdim D->addAttr(::new (S.Context) 2030252723Sdim UsedAttr(Attr.getRange(), S.Context, 2031252723Sdim Attr.getAttributeSpellingListIndex())); 2032193326Sed} 2033193326Sed 2034224145Sdimstatic void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2035193326Sed // check the attribute arguments. 2036221345Sdim if (Attr.getNumArgs() > 1) { 2037221345Sdim S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; 2038193326Sed return; 2039198092Srdivacky } 2040193326Sed 2041193326Sed int priority = 65535; // FIXME: Do not hardcode such constants. 2042193326Sed if (Attr.getNumArgs() > 0) { 2043263509Sdim Expr *E = Attr.getArgAsExpr(0); 2044193326Sed llvm::APSInt Idx(32); 2045208600Srdivacky if (E->isTypeDependent() || E->isValueDependent() || 2046208600Srdivacky !E->isIntegerConstantExpr(Idx, S.Context)) { 2047263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 2048263509Sdim << Attr.getName() << 1 << AANT_ArgumentIntegerConstant 2049263509Sdim << E->getSourceRange(); 2050193326Sed return; 2051193326Sed } 2052193326Sed priority = Idx.getZExtValue(); 2053193326Sed } 2054198092Srdivacky 2055224145Sdim if (!isa<FunctionDecl>(D)) { 2056193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2057221345Sdim << Attr.getName() << ExpectedFunction; 2058193326Sed return; 2059193326Sed } 2060193326Sed 2061252723Sdim D->addAttr(::new (S.Context) 2062252723Sdim ConstructorAttr(Attr.getRange(), S.Context, priority, 2063252723Sdim Attr.getAttributeSpellingListIndex())); 2064193326Sed} 2065193326Sed 2066224145Sdimstatic void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2067193326Sed // check the attribute arguments. 2068221345Sdim if (Attr.getNumArgs() > 1) { 2069221345Sdim S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; 2070193326Sed return; 2071198092Srdivacky } 2072193326Sed 2073193326Sed int priority = 65535; // FIXME: Do not hardcode such constants. 2074193326Sed if (Attr.getNumArgs() > 0) { 2075263509Sdim Expr *E = Attr.getArgAsExpr(0); 2076193326Sed llvm::APSInt Idx(32); 2077208600Srdivacky if (E->isTypeDependent() || E->isValueDependent() || 2078208600Srdivacky !E->isIntegerConstantExpr(Idx, S.Context)) { 2079263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 2080263509Sdim << Attr.getName() << 1 << AANT_ArgumentIntegerConstant 2081263509Sdim << E->getSourceRange(); 2082193326Sed return; 2083193326Sed } 2084193326Sed priority = Idx.getZExtValue(); 2085193326Sed } 2086198092Srdivacky 2087224145Sdim if (!isa<FunctionDecl>(D)) { 2088193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2089221345Sdim << Attr.getName() << ExpectedFunction; 2090193326Sed return; 2091193326Sed } 2092193326Sed 2093252723Sdim D->addAttr(::new (S.Context) 2094252723Sdim DestructorAttr(Attr.getRange(), S.Context, priority, 2095252723Sdim Attr.getAttributeSpellingListIndex())); 2096193326Sed} 2097193326Sed 2098245431Sdimtemplate <typename AttrTy> 2099263509Sdimstatic void handleAttrWithMessage(Sema &S, Decl *D, 2100263509Sdim const AttributeList &Attr) { 2101219077Sdim unsigned NumArgs = Attr.getNumArgs(); 2102219077Sdim if (NumArgs > 1) { 2103221345Sdim S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; 2104193326Sed return; 2105193326Sed } 2106245431Sdim 2107245431Sdim // Handle the case where the attribute has a text message. 2108226890Sdim StringRef Str; 2109263509Sdim if (NumArgs == 1 && !S.checkStringLiteralArgumentAttr(Attr, 0, Str)) 2110263509Sdim return; 2111198092Srdivacky 2112252723Sdim D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str, 2113252723Sdim Attr.getAttributeSpellingListIndex())); 2114193326Sed} 2115193326Sed 2116224145Sdimstatic void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D, 2117224145Sdim const AttributeList &Attr) { 2118252723Sdim D->addAttr(::new (S.Context) 2119252723Sdim ArcWeakrefUnavailableAttr(Attr.getRange(), S.Context, 2120252723Sdim Attr.getAttributeSpellingListIndex())); 2121224145Sdim} 2122224145Sdim 2123235633Sdimstatic void handleObjCRootClassAttr(Sema &S, Decl *D, 2124235633Sdim const AttributeList &Attr) { 2125235633Sdim if (!isa<ObjCInterfaceDecl>(D)) { 2126263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 2127263509Sdim << Attr.getName() << ExpectedObjectiveCInterface; 2128235633Sdim return; 2129235633Sdim } 2130235633Sdim 2131252723Sdim D->addAttr(::new (S.Context) 2132252723Sdim ObjCRootClassAttr(Attr.getRange(), S.Context, 2133252723Sdim Attr.getAttributeSpellingListIndex())); 2134235633Sdim} 2135235633Sdim 2136252723Sdimstatic void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D, 2137252723Sdim const AttributeList &Attr) { 2138235633Sdim if (!isa<ObjCInterfaceDecl>(D)) { 2139235633Sdim S.Diag(Attr.getLoc(), diag::err_suppress_autosynthesis); 2140235633Sdim return; 2141235633Sdim } 2142235633Sdim 2143252723Sdim D->addAttr(::new (S.Context) 2144252723Sdim ObjCRequiresPropertyDefsAttr(Attr.getRange(), S.Context, 2145252723Sdim Attr.getAttributeSpellingListIndex())); 2146235633Sdim} 2147235633Sdim 2148245431Sdimstatic bool checkAvailabilityAttr(Sema &S, SourceRange Range, 2149245431Sdim IdentifierInfo *Platform, 2150245431Sdim VersionTuple Introduced, 2151245431Sdim VersionTuple Deprecated, 2152245431Sdim VersionTuple Obsoleted) { 2153245431Sdim StringRef PlatformName 2154245431Sdim = AvailabilityAttr::getPrettyPlatformName(Platform->getName()); 2155245431Sdim if (PlatformName.empty()) 2156245431Sdim PlatformName = Platform->getName(); 2157245431Sdim 2158245431Sdim // Ensure that Introduced <= Deprecated <= Obsoleted (although not all 2159245431Sdim // of these steps are needed). 2160245431Sdim if (!Introduced.empty() && !Deprecated.empty() && 2161245431Sdim !(Introduced <= Deprecated)) { 2162245431Sdim S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) 2163245431Sdim << 1 << PlatformName << Deprecated.getAsString() 2164245431Sdim << 0 << Introduced.getAsString(); 2165245431Sdim return true; 2166245431Sdim } 2167245431Sdim 2168245431Sdim if (!Introduced.empty() && !Obsoleted.empty() && 2169245431Sdim !(Introduced <= Obsoleted)) { 2170245431Sdim S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) 2171245431Sdim << 2 << PlatformName << Obsoleted.getAsString() 2172245431Sdim << 0 << Introduced.getAsString(); 2173245431Sdim return true; 2174245431Sdim } 2175245431Sdim 2176245431Sdim if (!Deprecated.empty() && !Obsoleted.empty() && 2177245431Sdim !(Deprecated <= Obsoleted)) { 2178245431Sdim S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) 2179245431Sdim << 2 << PlatformName << Obsoleted.getAsString() 2180245431Sdim << 1 << Deprecated.getAsString(); 2181245431Sdim return true; 2182245431Sdim } 2183245431Sdim 2184245431Sdim return false; 2185245431Sdim} 2186245431Sdim 2187252723Sdim/// \brief Check whether the two versions match. 2188252723Sdim/// 2189252723Sdim/// If either version tuple is empty, then they are assumed to match. If 2190252723Sdim/// \p BeforeIsOkay is true, then \p X can be less than or equal to \p Y. 2191252723Sdimstatic bool versionsMatch(const VersionTuple &X, const VersionTuple &Y, 2192252723Sdim bool BeforeIsOkay) { 2193252723Sdim if (X.empty() || Y.empty()) 2194252723Sdim return true; 2195252723Sdim 2196252723Sdim if (X == Y) 2197252723Sdim return true; 2198252723Sdim 2199252723Sdim if (BeforeIsOkay && X < Y) 2200252723Sdim return true; 2201252723Sdim 2202252723Sdim return false; 2203252723Sdim} 2204252723Sdim 2205252723SdimAvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, 2206245431Sdim IdentifierInfo *Platform, 2207245431Sdim VersionTuple Introduced, 2208245431Sdim VersionTuple Deprecated, 2209245431Sdim VersionTuple Obsoleted, 2210245431Sdim bool IsUnavailable, 2211252723Sdim StringRef Message, 2212252723Sdim bool Override, 2213252723Sdim unsigned AttrSpellingListIndex) { 2214245431Sdim VersionTuple MergedIntroduced = Introduced; 2215245431Sdim VersionTuple MergedDeprecated = Deprecated; 2216245431Sdim VersionTuple MergedObsoleted = Obsoleted; 2217245431Sdim bool FoundAny = false; 2218245431Sdim 2219245431Sdim if (D->hasAttrs()) { 2220245431Sdim AttrVec &Attrs = D->getAttrs(); 2221245431Sdim for (unsigned i = 0, e = Attrs.size(); i != e;) { 2222245431Sdim const AvailabilityAttr *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]); 2223245431Sdim if (!OldAA) { 2224245431Sdim ++i; 2225245431Sdim continue; 2226245431Sdim } 2227245431Sdim 2228245431Sdim IdentifierInfo *OldPlatform = OldAA->getPlatform(); 2229245431Sdim if (OldPlatform != Platform) { 2230245431Sdim ++i; 2231245431Sdim continue; 2232245431Sdim } 2233245431Sdim 2234245431Sdim FoundAny = true; 2235245431Sdim VersionTuple OldIntroduced = OldAA->getIntroduced(); 2236245431Sdim VersionTuple OldDeprecated = OldAA->getDeprecated(); 2237245431Sdim VersionTuple OldObsoleted = OldAA->getObsoleted(); 2238245431Sdim bool OldIsUnavailable = OldAA->getUnavailable(); 2239245431Sdim 2240252723Sdim if (!versionsMatch(OldIntroduced, Introduced, Override) || 2241252723Sdim !versionsMatch(Deprecated, OldDeprecated, Override) || 2242252723Sdim !versionsMatch(Obsoleted, OldObsoleted, Override) || 2243252723Sdim !(OldIsUnavailable == IsUnavailable || 2244252723Sdim (Override && !OldIsUnavailable && IsUnavailable))) { 2245252723Sdim if (Override) { 2246252723Sdim int Which = -1; 2247252723Sdim VersionTuple FirstVersion; 2248252723Sdim VersionTuple SecondVersion; 2249252723Sdim if (!versionsMatch(OldIntroduced, Introduced, Override)) { 2250252723Sdim Which = 0; 2251252723Sdim FirstVersion = OldIntroduced; 2252252723Sdim SecondVersion = Introduced; 2253252723Sdim } else if (!versionsMatch(Deprecated, OldDeprecated, Override)) { 2254252723Sdim Which = 1; 2255252723Sdim FirstVersion = Deprecated; 2256252723Sdim SecondVersion = OldDeprecated; 2257252723Sdim } else if (!versionsMatch(Obsoleted, OldObsoleted, Override)) { 2258252723Sdim Which = 2; 2259252723Sdim FirstVersion = Obsoleted; 2260252723Sdim SecondVersion = OldObsoleted; 2261252723Sdim } 2262252723Sdim 2263252723Sdim if (Which == -1) { 2264252723Sdim Diag(OldAA->getLocation(), 2265252723Sdim diag::warn_mismatched_availability_override_unavail) 2266252723Sdim << AvailabilityAttr::getPrettyPlatformName(Platform->getName()); 2267252723Sdim } else { 2268252723Sdim Diag(OldAA->getLocation(), 2269252723Sdim diag::warn_mismatched_availability_override) 2270252723Sdim << Which 2271252723Sdim << AvailabilityAttr::getPrettyPlatformName(Platform->getName()) 2272252723Sdim << FirstVersion.getAsString() << SecondVersion.getAsString(); 2273252723Sdim } 2274252723Sdim Diag(Range.getBegin(), diag::note_overridden_method); 2275252723Sdim } else { 2276252723Sdim Diag(OldAA->getLocation(), diag::warn_mismatched_availability); 2277252723Sdim Diag(Range.getBegin(), diag::note_previous_attribute); 2278252723Sdim } 2279252723Sdim 2280245431Sdim Attrs.erase(Attrs.begin() + i); 2281245431Sdim --e; 2282245431Sdim continue; 2283245431Sdim } 2284245431Sdim 2285245431Sdim VersionTuple MergedIntroduced2 = MergedIntroduced; 2286245431Sdim VersionTuple MergedDeprecated2 = MergedDeprecated; 2287245431Sdim VersionTuple MergedObsoleted2 = MergedObsoleted; 2288245431Sdim 2289245431Sdim if (MergedIntroduced2.empty()) 2290245431Sdim MergedIntroduced2 = OldIntroduced; 2291245431Sdim if (MergedDeprecated2.empty()) 2292245431Sdim MergedDeprecated2 = OldDeprecated; 2293245431Sdim if (MergedObsoleted2.empty()) 2294245431Sdim MergedObsoleted2 = OldObsoleted; 2295245431Sdim 2296245431Sdim if (checkAvailabilityAttr(*this, OldAA->getRange(), Platform, 2297245431Sdim MergedIntroduced2, MergedDeprecated2, 2298245431Sdim MergedObsoleted2)) { 2299245431Sdim Attrs.erase(Attrs.begin() + i); 2300245431Sdim --e; 2301245431Sdim continue; 2302245431Sdim } 2303245431Sdim 2304245431Sdim MergedIntroduced = MergedIntroduced2; 2305245431Sdim MergedDeprecated = MergedDeprecated2; 2306245431Sdim MergedObsoleted = MergedObsoleted2; 2307245431Sdim ++i; 2308245431Sdim } 2309245431Sdim } 2310245431Sdim 2311245431Sdim if (FoundAny && 2312245431Sdim MergedIntroduced == Introduced && 2313245431Sdim MergedDeprecated == Deprecated && 2314245431Sdim MergedObsoleted == Obsoleted) 2315245431Sdim return NULL; 2316245431Sdim 2317252723Sdim // Only create a new attribute if !Override, but we want to do 2318252723Sdim // the checking. 2319245431Sdim if (!checkAvailabilityAttr(*this, Range, Platform, MergedIntroduced, 2320252723Sdim MergedDeprecated, MergedObsoleted) && 2321252723Sdim !Override) { 2322245431Sdim return ::new (Context) AvailabilityAttr(Range, Context, Platform, 2323245431Sdim Introduced, Deprecated, 2324252723Sdim Obsoleted, IsUnavailable, Message, 2325252723Sdim AttrSpellingListIndex); 2326245431Sdim } 2327245431Sdim return NULL; 2328245431Sdim} 2329245431Sdim 2330224145Sdimstatic void handleAvailabilityAttr(Sema &S, Decl *D, 2331224145Sdim const AttributeList &Attr) { 2332263509Sdim if (!checkAttributeNumArgs(S, Attr, 1)) 2333263509Sdim return; 2334263509Sdim IdentifierLoc *Platform = Attr.getArgAsIdent(0); 2335252723Sdim unsigned Index = Attr.getAttributeSpellingListIndex(); 2336252723Sdim 2337263509Sdim IdentifierInfo *II = Platform->Ident; 2338263509Sdim if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty()) 2339263509Sdim S.Diag(Platform->Loc, diag::warn_availability_unknown_platform) 2340263509Sdim << Platform->Ident; 2341221345Sdim 2342252723Sdim NamedDecl *ND = dyn_cast<NamedDecl>(D); 2343252723Sdim if (!ND) { 2344252723Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 2345252723Sdim return; 2346252723Sdim } 2347252723Sdim 2348221345Sdim AvailabilityChange Introduced = Attr.getAvailabilityIntroduced(); 2349221345Sdim AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated(); 2350221345Sdim AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted(); 2351221345Sdim bool IsUnavailable = Attr.getUnavailableLoc().isValid(); 2352235633Sdim StringRef Str; 2353263509Sdim if (const StringLiteral *SE = 2354263509Sdim dyn_cast_or_null<StringLiteral>(Attr.getMessageExpr())) 2355235633Sdim Str = SE->getString(); 2356245431Sdim 2357263509Sdim AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), II, 2358245431Sdim Introduced.Version, 2359245431Sdim Deprecated.Version, 2360245431Sdim Obsoleted.Version, 2361252723Sdim IsUnavailable, Str, 2362252723Sdim /*Override=*/false, 2363252723Sdim Index); 2364245431Sdim if (NewAttr) 2365245431Sdim D->addAttr(NewAttr); 2366221345Sdim} 2367221345Sdim 2368252723Sdimtemplate <class T> 2369252723Sdimstatic T *mergeVisibilityAttr(Sema &S, Decl *D, SourceRange range, 2370252723Sdim typename T::VisibilityType value, 2371252723Sdim unsigned attrSpellingListIndex) { 2372252723Sdim T *existingAttr = D->getAttr<T>(); 2373252723Sdim if (existingAttr) { 2374252723Sdim typename T::VisibilityType existingValue = existingAttr->getVisibility(); 2375252723Sdim if (existingValue == value) 2376252723Sdim return NULL; 2377252723Sdim S.Diag(existingAttr->getLocation(), diag::err_mismatched_visibility); 2378252723Sdim S.Diag(range.getBegin(), diag::note_previous_attribute); 2379252723Sdim D->dropAttr<T>(); 2380252723Sdim } 2381252723Sdim return ::new (S.Context) T(range, S.Context, value, attrSpellingListIndex); 2382252723Sdim} 2383252723Sdim 2384245431SdimVisibilityAttr *Sema::mergeVisibilityAttr(Decl *D, SourceRange Range, 2385252723Sdim VisibilityAttr::VisibilityType Vis, 2386252723Sdim unsigned AttrSpellingListIndex) { 2387252723Sdim return ::mergeVisibilityAttr<VisibilityAttr>(*this, D, Range, Vis, 2388252723Sdim AttrSpellingListIndex); 2389252723Sdim} 2390252723Sdim 2391252723SdimTypeVisibilityAttr *Sema::mergeTypeVisibilityAttr(Decl *D, SourceRange Range, 2392252723Sdim TypeVisibilityAttr::VisibilityType Vis, 2393252723Sdim unsigned AttrSpellingListIndex) { 2394252723Sdim return ::mergeVisibilityAttr<TypeVisibilityAttr>(*this, D, Range, Vis, 2395252723Sdim AttrSpellingListIndex); 2396252723Sdim} 2397252723Sdim 2398252723Sdimstatic void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr, 2399252723Sdim bool isTypeVisibility) { 2400252723Sdim // Visibility attributes don't mean anything on a typedef. 2401245431Sdim if (isa<TypedefNameDecl>(D)) { 2402252723Sdim S.Diag(Attr.getRange().getBegin(), diag::warn_attribute_ignored) 2403252723Sdim << Attr.getName(); 2404252723Sdim return; 2405245431Sdim } 2406252723Sdim 2407252723Sdim // 'type_visibility' can only go on a type or namespace. 2408252723Sdim if (isTypeVisibility && 2409252723Sdim !(isa<TagDecl>(D) || 2410252723Sdim isa<ObjCInterfaceDecl>(D) || 2411252723Sdim isa<NamespaceDecl>(D))) { 2412252723Sdim S.Diag(Attr.getRange().getBegin(), diag::err_attribute_wrong_decl_type) 2413252723Sdim << Attr.getName() << ExpectedTypeOrNamespace; 2414252723Sdim return; 2415245431Sdim } 2416245431Sdim 2417263509Sdim // Check that the argument is a string literal. 2418263509Sdim StringRef TypeStr; 2419263509Sdim SourceLocation LiteralLoc; 2420263509Sdim if (!S.checkStringLiteralArgumentAttr(Attr, 0, TypeStr, &LiteralLoc)) 2421193326Sed return; 2422198092Srdivacky 2423263509Sdim VisibilityAttr::VisibilityType type; 2424263509Sdim if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) { 2425263509Sdim S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) 2426263509Sdim << Attr.getName() << TypeStr; 2427193326Sed return; 2428193326Sed } 2429252723Sdim 2430263509Sdim // Complain about attempts to use protected visibility on targets 2431263509Sdim // (like Darwin) that don't support it. 2432263509Sdim if (type == VisibilityAttr::Protected && 2433263509Sdim !S.Context.getTargetInfo().hasProtectedVisibility()) { 2434263509Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility); 2435212904Sdim type = VisibilityAttr::Default; 2436193326Sed } 2437198092Srdivacky 2438252723Sdim unsigned Index = Attr.getAttributeSpellingListIndex(); 2439252723Sdim clang::Attr *newAttr; 2440252723Sdim if (isTypeVisibility) { 2441252723Sdim newAttr = S.mergeTypeVisibilityAttr(D, Attr.getRange(), 2442252723Sdim (TypeVisibilityAttr::VisibilityType) type, 2443252723Sdim Index); 2444252723Sdim } else { 2445252723Sdim newAttr = S.mergeVisibilityAttr(D, Attr.getRange(), type, Index); 2446252723Sdim } 2447252723Sdim if (newAttr) 2448252723Sdim D->addAttr(newAttr); 2449193326Sed} 2450193326Sed 2451224145Sdimstatic void handleObjCMethodFamilyAttr(Sema &S, Decl *decl, 2452224145Sdim const AttributeList &Attr) { 2453221345Sdim ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(decl); 2454221345Sdim if (!method) { 2455224145Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 2456221345Sdim << ExpectedMethod; 2457221345Sdim return; 2458221345Sdim } 2459221345Sdim 2460263509Sdim if (!Attr.isArgIdent(0)) { 2461263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 2462263509Sdim << Attr.getName() << 1 << AANT_ArgumentIdentifier; 2463221345Sdim return; 2464221345Sdim } 2465221345Sdim 2466263509Sdim IdentifierLoc *IL = Attr.getArgAsIdent(0); 2467263509Sdim ObjCMethodFamilyAttr::FamilyKind F; 2468263509Sdim if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) { 2469263509Sdim S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << Attr.getName() 2470263509Sdim << IL->Ident; 2471221345Sdim return; 2472221345Sdim } 2473221345Sdim 2474263509Sdim if (F == ObjCMethodFamilyAttr::OMF_init && 2475224145Sdim !method->getResultType()->isObjCObjectPointerType()) { 2476224145Sdim S.Diag(method->getLocation(), diag::err_init_method_bad_return_type) 2477224145Sdim << method->getResultType(); 2478224145Sdim // Ignore the attribute. 2479224145Sdim return; 2480224145Sdim } 2481224145Sdim 2482226890Sdim method->addAttr(new (S.Context) ObjCMethodFamilyAttr(Attr.getRange(), 2483263509Sdim S.Context, F)); 2484221345Sdim} 2485221345Sdim 2486224145Sdimstatic void handleObjCExceptionAttr(Sema &S, Decl *D, 2487224145Sdim const AttributeList &Attr) { 2488193326Sed ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D); 2489193326Sed if (OCI == 0) { 2490263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 2491263509Sdim << Attr.getName() << ExpectedObjectiveCInterface; 2492193326Sed return; 2493193326Sed } 2494198092Srdivacky 2495252723Sdim D->addAttr(::new (S.Context) 2496252723Sdim ObjCExceptionAttr(Attr.getRange(), S.Context, 2497252723Sdim Attr.getAttributeSpellingListIndex())); 2498193326Sed} 2499193326Sed 2500224145Sdimstatic void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) { 2501221345Sdim if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { 2502193326Sed QualType T = TD->getUnderlyingType(); 2503245431Sdim if (!T->isCARCBridgableType()) { 2504193326Sed S.Diag(TD->getLocation(), diag::err_nsobject_attribute); 2505193326Sed return; 2506193326Sed } 2507193326Sed } 2508245431Sdim else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) { 2509245431Sdim QualType T = PD->getType(); 2510245431Sdim if (!T->isCARCBridgableType()) { 2511245431Sdim S.Diag(PD->getLocation(), diag::err_nsobject_attribute); 2512245431Sdim return; 2513245431Sdim } 2514245431Sdim } 2515245431Sdim else { 2516235633Sdim // It is okay to include this attribute on properties, e.g.: 2517235633Sdim // 2518235633Sdim // @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject)); 2519235633Sdim // 2520235633Sdim // In this case it follows tradition and suppresses an error in the above 2521235633Sdim // case. 2522235633Sdim S.Diag(D->getLocation(), diag::warn_nsobject_attribute); 2523235633Sdim } 2524252723Sdim D->addAttr(::new (S.Context) 2525252723Sdim ObjCNSObjectAttr(Attr.getRange(), S.Context, 2526252723Sdim Attr.getAttributeSpellingListIndex())); 2527193326Sed} 2528193326Sed 2529198092Srdivackystatic void 2530224145SdimhandleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2531193326Sed if (!isa<FunctionDecl>(D)) { 2532193326Sed S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function); 2533193326Sed return; 2534193326Sed } 2535193326Sed 2536252723Sdim D->addAttr(::new (S.Context) 2537252723Sdim OverloadableAttr(Attr.getRange(), S.Context, 2538252723Sdim Attr.getAttributeSpellingListIndex())); 2539193326Sed} 2540193326Sed 2541224145Sdimstatic void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2542263509Sdim if (!Attr.isArgIdent(0)) { 2543263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 2544263509Sdim << Attr.getName() << 1 << AANT_ArgumentIdentifier; 2545193326Sed return; 2546193326Sed } 2547198092Srdivacky 2548263509Sdim IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident; 2549212904Sdim BlocksAttr::BlockType type; 2550263509Sdim if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) { 2551193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) 2552263509Sdim << Attr.getName() << II; 2553193326Sed return; 2554193326Sed } 2555198092Srdivacky 2556252723Sdim D->addAttr(::new (S.Context) 2557252723Sdim BlocksAttr(Attr.getRange(), S.Context, type, 2558252723Sdim Attr.getAttributeSpellingListIndex())); 2559193326Sed} 2560193326Sed 2561224145Sdimstatic void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2562193326Sed // check the attribute arguments. 2563193326Sed if (Attr.getNumArgs() > 2) { 2564221345Sdim S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2; 2565193326Sed return; 2566198092Srdivacky } 2567198092Srdivacky 2568226890Sdim unsigned sentinel = 0; 2569193326Sed if (Attr.getNumArgs() > 0) { 2570263509Sdim Expr *E = Attr.getArgAsExpr(0); 2571193326Sed llvm::APSInt Idx(32); 2572208600Srdivacky if (E->isTypeDependent() || E->isValueDependent() || 2573208600Srdivacky !E->isIntegerConstantExpr(Idx, S.Context)) { 2574263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 2575263509Sdim << Attr.getName() << 1 << AANT_ArgumentIntegerConstant 2576263509Sdim << E->getSourceRange(); 2577193326Sed return; 2578193326Sed } 2579198092Srdivacky 2580226890Sdim if (Idx.isSigned() && Idx.isNegative()) { 2581193326Sed S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero) 2582193326Sed << E->getSourceRange(); 2583193326Sed return; 2584193326Sed } 2585226890Sdim 2586226890Sdim sentinel = Idx.getZExtValue(); 2587193326Sed } 2588193326Sed 2589226890Sdim unsigned nullPos = 0; 2590193326Sed if (Attr.getNumArgs() > 1) { 2591263509Sdim Expr *E = Attr.getArgAsExpr(1); 2592193326Sed llvm::APSInt Idx(32); 2593208600Srdivacky if (E->isTypeDependent() || E->isValueDependent() || 2594208600Srdivacky !E->isIntegerConstantExpr(Idx, S.Context)) { 2595263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 2596263509Sdim << Attr.getName() << 2 << AANT_ArgumentIntegerConstant 2597263509Sdim << E->getSourceRange(); 2598193326Sed return; 2599193326Sed } 2600193326Sed nullPos = Idx.getZExtValue(); 2601198092Srdivacky 2602226890Sdim if ((Idx.isSigned() && Idx.isNegative()) || nullPos > 1) { 2603193326Sed // FIXME: This error message could be improved, it would be nice 2604193326Sed // to say what the bounds actually are. 2605193326Sed S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one) 2606193326Sed << E->getSourceRange(); 2607193326Sed return; 2608193326Sed } 2609193326Sed } 2610193326Sed 2611224145Sdim if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 2612226890Sdim const FunctionType *FT = FD->getType()->castAs<FunctionType>(); 2613193326Sed if (isa<FunctionNoProtoType>(FT)) { 2614193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_named_arguments); 2615193326Sed return; 2616193326Sed } 2617198092Srdivacky 2618193326Sed if (!cast<FunctionProtoType>(FT)->isVariadic()) { 2619193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; 2620193326Sed return; 2621198092Srdivacky } 2622224145Sdim } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 2623193326Sed if (!MD->isVariadic()) { 2624193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; 2625193326Sed return; 2626193326Sed } 2627235633Sdim } else if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) { 2628235633Sdim if (!BD->isVariadic()) { 2629235633Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; 2630235633Sdim return; 2631235633Sdim } 2632224145Sdim } else if (const VarDecl *V = dyn_cast<VarDecl>(D)) { 2633193326Sed QualType Ty = V->getType(); 2634193326Sed if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) { 2635224145Sdim const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(D) 2636218893Sdim : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>(); 2637193326Sed if (!cast<FunctionProtoType>(FT)->isVariadic()) { 2638193326Sed int m = Ty->isFunctionPointerType() ? 0 : 1; 2639193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m; 2640193326Sed return; 2641193326Sed } 2642198092Srdivacky } else { 2643193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2644221345Sdim << Attr.getName() << ExpectedFunctionMethodOrBlock; 2645193326Sed return; 2646193326Sed } 2647193326Sed } else { 2648193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2649221345Sdim << Attr.getName() << ExpectedFunctionMethodOrBlock; 2650193326Sed return; 2651193326Sed } 2652252723Sdim D->addAttr(::new (S.Context) 2653252723Sdim SentinelAttr(Attr.getRange(), S.Context, sentinel, nullPos, 2654252723Sdim Attr.getAttributeSpellingListIndex())); 2655193326Sed} 2656193326Sed 2657263509Sdimstatic void handleWarnUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2658263509Sdim if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) 2659263509Sdim RD->addAttr(::new (S.Context) WarnUnusedAttr(Attr.getRange(), S.Context)); 2660263509Sdim else 2661263509Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 2662263509Sdim} 2663263509Sdim 2664224145Sdimstatic void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) { 2665252723Sdim if (!isFunction(D) && !isa<ObjCMethodDecl>(D) && !isa<CXXRecordDecl>(D)) { 2666193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2667252723Sdim << Attr.getName() << ExpectedFunctionMethodOrClass; 2668193326Sed return; 2669193326Sed } 2670198092Srdivacky 2671206084Srdivacky if (isFunction(D) && getFunctionType(D)->getResultType()->isVoidType()) { 2672206084Srdivacky S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method) 2673206084Srdivacky << Attr.getName() << 0; 2674201361Srdivacky return; 2675201361Srdivacky } 2676206084Srdivacky if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 2677206084Srdivacky if (MD->getResultType()->isVoidType()) { 2678206084Srdivacky S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method) 2679206084Srdivacky << Attr.getName() << 1; 2680206084Srdivacky return; 2681206084Srdivacky } 2682206084Srdivacky 2683252723Sdim D->addAttr(::new (S.Context) 2684252723Sdim WarnUnusedResultAttr(Attr.getRange(), S.Context, 2685252723Sdim Attr.getAttributeSpellingListIndex())); 2686193326Sed} 2687193326Sed 2688224145Sdimstatic void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2689224145Sdim if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) { 2690235633Sdim if (isa<CXXRecordDecl>(D)) { 2691235633Sdim D->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context)); 2692235633Sdim return; 2693235633Sdim } 2694224145Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2695224145Sdim << Attr.getName() << ExpectedVariableOrFunction; 2696198092Srdivacky return; 2697198092Srdivacky } 2698198092Srdivacky 2699224145Sdim NamedDecl *nd = cast<NamedDecl>(D); 2700218893Sdim 2701252723Sdim nd->addAttr(::new (S.Context) 2702252723Sdim WeakAttr(Attr.getRange(), S.Context, 2703252723Sdim Attr.getAttributeSpellingListIndex())); 2704193326Sed} 2705193326Sed 2706224145Sdimstatic void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2707193326Sed // weak_import only applies to variable & function declarations. 2708193326Sed bool isDef = false; 2709221345Sdim if (!D->canBeWeakImported(isDef)) { 2710221345Sdim if (isDef) 2711263509Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_invalid_on_definition) 2712263509Sdim << "weak_import"; 2713221345Sdim else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) || 2714226890Sdim (S.Context.getTargetInfo().getTriple().isOSDarwin() && 2715235633Sdim (isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) { 2716221345Sdim // Nothing to warn about here. 2717221345Sdim } else 2718207619Srdivacky S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2719221345Sdim << Attr.getName() << ExpectedVariableOrFunction; 2720193326Sed 2721193326Sed return; 2722193326Sed } 2723193326Sed 2724252723Sdim D->addAttr(::new (S.Context) 2725252723Sdim WeakImportAttr(Attr.getRange(), S.Context, 2726252723Sdim Attr.getAttributeSpellingListIndex())); 2727193326Sed} 2728193326Sed 2729245431Sdim// Handles reqd_work_group_size and work_group_size_hint. 2730245431Sdimstatic void handleWorkGroupSize(Sema &S, Decl *D, 2731245431Sdim const AttributeList &Attr) { 2732195099Sed unsigned WGSize[3]; 2733195099Sed for (unsigned i = 0; i < 3; ++i) { 2734263509Sdim Expr *E = Attr.getArgAsExpr(i); 2735195099Sed llvm::APSInt ArgNum(32); 2736208600Srdivacky if (E->isTypeDependent() || E->isValueDependent() || 2737208600Srdivacky !E->isIntegerConstantExpr(ArgNum, S.Context)) { 2738263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) 2739263509Sdim << Attr.getName() << AANT_ArgumentIntegerConstant 2740263509Sdim << E->getSourceRange(); 2741195099Sed return; 2742195099Sed } 2743195099Sed WGSize[i] = (unsigned) ArgNum.getZExtValue(); 2744195099Sed } 2745245431Sdim 2746245431Sdim if (Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize 2747245431Sdim && D->hasAttr<ReqdWorkGroupSizeAttr>()) { 2748245431Sdim ReqdWorkGroupSizeAttr *A = D->getAttr<ReqdWorkGroupSizeAttr>(); 2749245431Sdim if (!(A->getXDim() == WGSize[0] && 2750245431Sdim A->getYDim() == WGSize[1] && 2751245431Sdim A->getZDim() == WGSize[2])) { 2752245431Sdim S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << 2753245431Sdim Attr.getName(); 2754245431Sdim } 2755245431Sdim } 2756245431Sdim 2757245431Sdim if (Attr.getKind() == AttributeList::AT_WorkGroupSizeHint 2758245431Sdim && D->hasAttr<WorkGroupSizeHintAttr>()) { 2759245431Sdim WorkGroupSizeHintAttr *A = D->getAttr<WorkGroupSizeHintAttr>(); 2760245431Sdim if (!(A->getXDim() == WGSize[0] && 2761245431Sdim A->getYDim() == WGSize[1] && 2762245431Sdim A->getZDim() == WGSize[2])) { 2763245431Sdim S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << 2764245431Sdim Attr.getName(); 2765245431Sdim } 2766245431Sdim } 2767245431Sdim 2768245431Sdim if (Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize) 2769245431Sdim D->addAttr(::new (S.Context) 2770245431Sdim ReqdWorkGroupSizeAttr(Attr.getRange(), S.Context, 2771252723Sdim WGSize[0], WGSize[1], WGSize[2], 2772252723Sdim Attr.getAttributeSpellingListIndex())); 2773245431Sdim else 2774245431Sdim D->addAttr(::new (S.Context) 2775245431Sdim WorkGroupSizeHintAttr(Attr.getRange(), S.Context, 2776252723Sdim WGSize[0], WGSize[1], WGSize[2], 2777252723Sdim Attr.getAttributeSpellingListIndex())); 2778195099Sed} 2779195099Sed 2780252723Sdimstatic void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) { 2781252723Sdim assert(Attr.getKind() == AttributeList::AT_VecTypeHint); 2782252723Sdim 2783263509Sdim if (!Attr.hasParsedType()) { 2784263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 2785263509Sdim << Attr.getName() << 1; 2786252723Sdim return; 2787263509Sdim } 2788252723Sdim 2789263509Sdim TypeSourceInfo *ParmTSI = 0; 2790263509Sdim QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg(), &ParmTSI); 2791263509Sdim assert(ParmTSI && "no type source info for attribute argument"); 2792252723Sdim 2793252723Sdim if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() && 2794252723Sdim (ParmType->isBooleanType() || 2795252723Sdim !ParmType->isIntegralType(S.getASTContext()))) { 2796252723Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_vec_type_hint) 2797252723Sdim << ParmType; 2798252723Sdim return; 2799252723Sdim } 2800252723Sdim 2801252723Sdim if (Attr.getKind() == AttributeList::AT_VecTypeHint && 2802252723Sdim D->hasAttr<VecTypeHintAttr>()) { 2803252723Sdim VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>(); 2804263509Sdim if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) { 2805252723Sdim S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName(); 2806252723Sdim return; 2807252723Sdim } 2808252723Sdim } 2809252723Sdim 2810252723Sdim D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context, 2811263509Sdim ParmTSI)); 2812252723Sdim} 2813252723Sdim 2814245431SdimSectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range, 2815252723Sdim StringRef Name, 2816252723Sdim unsigned AttrSpellingListIndex) { 2817245431Sdim if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) { 2818245431Sdim if (ExistingAttr->getName() == Name) 2819245431Sdim return NULL; 2820245431Sdim Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section); 2821245431Sdim Diag(Range.getBegin(), diag::note_previous_attribute); 2822245431Sdim return NULL; 2823245431Sdim } 2824252723Sdim return ::new (Context) SectionAttr(Range, Context, Name, 2825252723Sdim AttrSpellingListIndex); 2826245431Sdim} 2827245431Sdim 2828224145Sdimstatic void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2829193326Sed // Make sure that there is a string literal as the sections's single 2830193326Sed // argument. 2831263509Sdim StringRef Str; 2832263509Sdim SourceLocation LiteralLoc; 2833263509Sdim if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc)) 2834193326Sed return; 2835198092Srdivacky 2836198092Srdivacky // If the target wants to validate the section specifier, make it happen. 2837263509Sdim std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(Str); 2838202379Srdivacky if (!Error.empty()) { 2839263509Sdim S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) 2840202379Srdivacky << Error; 2841198092Srdivacky return; 2842198092Srdivacky } 2843198092Srdivacky 2844202379Srdivacky // This attribute cannot be applied to local variables. 2845202379Srdivacky if (isa<VarDecl>(D) && cast<VarDecl>(D)->hasLocalStorage()) { 2846263509Sdim S.Diag(LiteralLoc, diag::err_attribute_section_local_variable); 2847202379Srdivacky return; 2848202379Srdivacky } 2849252723Sdim 2850252723Sdim unsigned Index = Attr.getAttributeSpellingListIndex(); 2851263509Sdim SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), Str, Index); 2852245431Sdim if (NewAttr) 2853245431Sdim D->addAttr(NewAttr); 2854193326Sed} 2855193326Sed 2856199482Srdivacky 2857224145Sdimstatic void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2858224145Sdim if (NoThrowAttr *Existing = D->getAttr<NoThrowAttr>()) { 2859224145Sdim if (Existing->getLocation().isInvalid()) 2860226890Sdim Existing->setRange(Attr.getRange()); 2861224145Sdim } else { 2862252723Sdim D->addAttr(::new (S.Context) 2863252723Sdim NoThrowAttr(Attr.getRange(), S.Context, 2864252723Sdim Attr.getAttributeSpellingListIndex())); 2865224145Sdim } 2866193326Sed} 2867193326Sed 2868224145Sdimstatic void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2869224145Sdim if (ConstAttr *Existing = D->getAttr<ConstAttr>()) { 2870224145Sdim if (Existing->getLocation().isInvalid()) 2871226890Sdim Existing->setRange(Attr.getRange()); 2872224145Sdim } else { 2873252723Sdim D->addAttr(::new (S.Context) 2874252723Sdim ConstAttr(Attr.getRange(), S.Context, 2875252723Sdim Attr.getAttributeSpellingListIndex() )); 2876224145Sdim } 2877193326Sed} 2878193326Sed 2879224145Sdimstatic void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2880252723Sdim D->addAttr(::new (S.Context) 2881252723Sdim PureAttr(Attr.getRange(), S.Context, 2882252723Sdim Attr.getAttributeSpellingListIndex())); 2883193326Sed} 2884193326Sed 2885224145Sdimstatic void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2886224145Sdim VarDecl *VD = dyn_cast<VarDecl>(D); 2887193326Sed if (!VD || !VD->hasLocalStorage()) { 2888263509Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 2889193326Sed return; 2890193326Sed } 2891198092Srdivacky 2892263509Sdim Expr *E = Attr.getArgAsExpr(0); 2893263509Sdim SourceLocation Loc = E->getExprLoc(); 2894263509Sdim FunctionDecl *FD = 0; 2895263509Sdim DeclarationNameInfo NI; 2896198092Srdivacky 2897263509Sdim // gcc only allows for simple identifiers. Since we support more than gcc, we 2898263509Sdim // will warn the user. 2899263509Sdim if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { 2900263509Sdim if (DRE->hasQualifier()) 2901263509Sdim S.Diag(Loc, diag::warn_cleanup_ext); 2902263509Sdim FD = dyn_cast<FunctionDecl>(DRE->getDecl()); 2903263509Sdim NI = DRE->getNameInfo(); 2904263509Sdim if (!FD) { 2905263509Sdim S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 1 2906263509Sdim << NI.getName(); 2907263509Sdim return; 2908263509Sdim } 2909263509Sdim } else if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) { 2910263509Sdim if (ULE->hasExplicitTemplateArgs()) 2911263509Sdim S.Diag(Loc, diag::warn_cleanup_ext); 2912263509Sdim FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true); 2913263509Sdim NI = ULE->getNameInfo(); 2914263509Sdim if (!FD) { 2915263509Sdim S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2 2916263509Sdim << NI.getName(); 2917263509Sdim if (ULE->getType() == S.Context.OverloadTy) 2918263509Sdim S.NoteAllOverloadCandidates(ULE); 2919263509Sdim return; 2920263509Sdim } 2921263509Sdim } else { 2922263509Sdim S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 0; 2923193326Sed return; 2924193326Sed } 2925193326Sed 2926193326Sed if (FD->getNumParams() != 1) { 2927263509Sdim S.Diag(Loc, diag::err_attribute_cleanup_func_must_take_one_arg) 2928263509Sdim << NI.getName(); 2929193326Sed return; 2930193326Sed } 2931198092Srdivacky 2932193326Sed // We're currently more strict than GCC about what function types we accept. 2933193326Sed // If this ever proves to be a problem it should be easy to fix. 2934193326Sed QualType Ty = S.Context.getPointerType(VD->getType()); 2935193326Sed QualType ParamTy = FD->getParamDecl(0)->getType(); 2936218893Sdim if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(), 2937218893Sdim ParamTy, Ty) != Sema::Compatible) { 2938263509Sdim S.Diag(Loc, diag::err_attribute_cleanup_func_arg_incompatible_type) 2939263509Sdim << NI.getName() << ParamTy << Ty; 2940193326Sed return; 2941193326Sed } 2942198092Srdivacky 2943252723Sdim D->addAttr(::new (S.Context) 2944252723Sdim CleanupAttr(Attr.getRange(), S.Context, FD, 2945252723Sdim Attr.getAttributeSpellingListIndex())); 2946193326Sed} 2947193326Sed 2948198092Srdivacky/// Handle __attribute__((format_arg((idx)))) attribute based on 2949198092Srdivacky/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html 2950224145Sdimstatic void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2951224145Sdim if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { 2952193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2953221345Sdim << Attr.getName() << ExpectedFunction; 2954193326Sed return; 2955193326Sed } 2956218893Sdim 2957263509Sdim Expr *IdxExpr = Attr.getArgAsExpr(0); 2958263509Sdim uint64_t ArgIdx; 2959263509Sdim if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(), 2960263509Sdim Attr.getLoc(), 1, IdxExpr, ArgIdx)) 2961193326Sed return; 2962198092Srdivacky 2963193326Sed // make sure the format string is really a string 2964224145Sdim QualType Ty = getFunctionOrMethodArgType(D, ArgIdx); 2965198092Srdivacky 2966193326Sed bool not_nsstring_type = !isNSStringType(Ty, S.Context); 2967193326Sed if (not_nsstring_type && 2968193326Sed !isCFStringType(Ty, S.Context) && 2969193326Sed (!Ty->isPointerType() || 2970198092Srdivacky !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) { 2971193326Sed // FIXME: Should highlight the actual expression that has the wrong type. 2972193326Sed S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 2973198092Srdivacky << (not_nsstring_type ? "a string type" : "an NSString") 2974193326Sed << IdxExpr->getSourceRange(); 2975193326Sed return; 2976198092Srdivacky } 2977224145Sdim Ty = getFunctionOrMethodResultType(D); 2978193326Sed if (!isNSStringType(Ty, S.Context) && 2979193326Sed !isCFStringType(Ty, S.Context) && 2980193326Sed (!Ty->isPointerType() || 2981198092Srdivacky !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) { 2982193326Sed // FIXME: Should highlight the actual expression that has the wrong type. 2983193326Sed S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not) 2984198092Srdivacky << (not_nsstring_type ? "string type" : "NSString") 2985193326Sed << IdxExpr->getSourceRange(); 2986193326Sed return; 2987198092Srdivacky } 2988198092Srdivacky 2989263509Sdim // We cannot use the ArgIdx returned from checkFunctionOrMethodArgumentIndex 2990263509Sdim // because that has corrected for the implicit this parameter, and is zero- 2991263509Sdim // based. The attribute expects what the user wrote explicitly. 2992263509Sdim llvm::APSInt Val; 2993263509Sdim IdxExpr->EvaluateAsInt(Val, S.Context); 2994263509Sdim 2995252723Sdim D->addAttr(::new (S.Context) 2996263509Sdim FormatArgAttr(Attr.getRange(), S.Context, Val.getZExtValue(), 2997252723Sdim Attr.getAttributeSpellingListIndex())); 2998193326Sed} 2999193326Sed 3000198398Srdivackyenum FormatAttrKind { 3001198398Srdivacky CFStringFormat, 3002198398Srdivacky NSStringFormat, 3003198398Srdivacky StrftimeFormat, 3004198398Srdivacky SupportedFormat, 3005206084Srdivacky IgnoredFormat, 3006198398Srdivacky InvalidFormat 3007198398Srdivacky}; 3008198398Srdivacky 3009198398Srdivacky/// getFormatAttrKind - Map from format attribute names to supported format 3010198398Srdivacky/// types. 3011226890Sdimstatic FormatAttrKind getFormatAttrKind(StringRef Format) { 3012245431Sdim return llvm::StringSwitch<FormatAttrKind>(Format) 3013245431Sdim // Check for formats that get handled specially. 3014245431Sdim .Case("NSString", NSStringFormat) 3015245431Sdim .Case("CFString", CFStringFormat) 3016245431Sdim .Case("strftime", StrftimeFormat) 3017198398Srdivacky 3018245431Sdim // Otherwise, check for supported formats. 3019245431Sdim .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat) 3020245431Sdim .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat) 3021245431Sdim .Case("kprintf", SupportedFormat) // OpenBSD. 3022198398Srdivacky 3023245431Sdim .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat) 3024245431Sdim .Default(InvalidFormat); 3025198398Srdivacky} 3026198398Srdivacky 3027210299Sed/// Handle __attribute__((init_priority(priority))) attributes based on 3028210299Sed/// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html 3029224145Sdimstatic void handleInitPriorityAttr(Sema &S, Decl *D, 3030224145Sdim const AttributeList &Attr) { 3031235633Sdim if (!S.getLangOpts().CPlusPlus) { 3032210299Sed S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 3033210299Sed return; 3034210299Sed } 3035210299Sed 3036224145Sdim if (!isa<VarDecl>(D) || S.getCurFunctionOrMethodDecl()) { 3037210299Sed S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr); 3038210299Sed Attr.setInvalid(); 3039210299Sed return; 3040210299Sed } 3041224145Sdim QualType T = dyn_cast<VarDecl>(D)->getType(); 3042210299Sed if (S.Context.getAsArrayType(T)) 3043210299Sed T = S.Context.getBaseElementType(T); 3044210299Sed if (!T->getAs<RecordType>()) { 3045210299Sed S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr); 3046210299Sed Attr.setInvalid(); 3047210299Sed return; 3048210299Sed } 3049210299Sed 3050263509Sdim Expr *priorityExpr = Attr.getArgAsExpr(0); 3051210299Sed 3052210299Sed llvm::APSInt priority(32); 3053210299Sed if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() || 3054210299Sed !priorityExpr->isIntegerConstantExpr(priority, S.Context)) { 3055263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) 3056263509Sdim << Attr.getName() << AANT_ArgumentIntegerConstant 3057263509Sdim << priorityExpr->getSourceRange(); 3058210299Sed Attr.setInvalid(); 3059210299Sed return; 3060210299Sed } 3061210299Sed unsigned prioritynum = priority.getZExtValue(); 3062210299Sed if (prioritynum < 101 || prioritynum > 65535) { 3063210299Sed S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range) 3064210299Sed << priorityExpr->getSourceRange(); 3065210299Sed Attr.setInvalid(); 3066210299Sed return; 3067210299Sed } 3068252723Sdim D->addAttr(::new (S.Context) 3069252723Sdim InitPriorityAttr(Attr.getRange(), S.Context, prioritynum, 3070252723Sdim Attr.getAttributeSpellingListIndex())); 3071210299Sed} 3072210299Sed 3073263509SdimFormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, 3074263509Sdim IdentifierInfo *Format, int FormatIdx, 3075263509Sdim int FirstArg, 3076252723Sdim unsigned AttrSpellingListIndex) { 3077245431Sdim // Check whether we already have an equivalent format attribute. 3078245431Sdim for (specific_attr_iterator<FormatAttr> 3079245431Sdim i = D->specific_attr_begin<FormatAttr>(), 3080245431Sdim e = D->specific_attr_end<FormatAttr>(); 3081245431Sdim i != e ; ++i) { 3082245431Sdim FormatAttr *f = *i; 3083245431Sdim if (f->getType() == Format && 3084245431Sdim f->getFormatIdx() == FormatIdx && 3085245431Sdim f->getFirstArg() == FirstArg) { 3086245431Sdim // If we don't have a valid location for this attribute, adopt the 3087245431Sdim // location. 3088245431Sdim if (f->getLocation().isInvalid()) 3089245431Sdim f->setRange(Range); 3090245431Sdim return NULL; 3091245431Sdim } 3092245431Sdim } 3093245431Sdim 3094263509Sdim return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx, 3095263509Sdim FirstArg, AttrSpellingListIndex); 3096245431Sdim} 3097245431Sdim 3098198092Srdivacky/// Handle __attribute__((format(type,idx,firstarg))) attributes based on 3099198092Srdivacky/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html 3100224145Sdimstatic void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3101263509Sdim if (!Attr.isArgIdent(0)) { 3102263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 3103263509Sdim << Attr.getName() << 1 << AANT_ArgumentIdentifier; 3104193326Sed return; 3105193326Sed } 3106193326Sed 3107224145Sdim if (!isFunctionOrMethodOrBlock(D) || !hasFunctionProto(D)) { 3108193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3109221345Sdim << Attr.getName() << ExpectedFunction; 3110193326Sed return; 3111193326Sed } 3112193326Sed 3113218893Sdim // In C++ the implicit 'this' function parameter also counts, and they are 3114218893Sdim // counted from one. 3115224145Sdim bool HasImplicitThisParam = isInstanceMethod(D); 3116224145Sdim unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; 3117193326Sed unsigned FirstIdx = 1; 3118193326Sed 3119263509Sdim IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident; 3120263509Sdim StringRef Format = II->getName(); 3121193326Sed 3122193326Sed // Normalize the argument, __foo__ becomes foo. 3123263509Sdim if (Format.startswith("__") && Format.endswith("__")) { 3124198398Srdivacky Format = Format.substr(2, Format.size() - 4); 3125263509Sdim // If we've modified the string name, we need a new identifier for it. 3126263509Sdim II = &S.Context.Idents.get(Format); 3127263509Sdim } 3128193326Sed 3129198398Srdivacky // Check for supported formats. 3130198398Srdivacky FormatAttrKind Kind = getFormatAttrKind(Format); 3131206084Srdivacky 3132206084Srdivacky if (Kind == IgnoredFormat) 3133206084Srdivacky return; 3134206084Srdivacky 3135198398Srdivacky if (Kind == InvalidFormat) { 3136193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) 3137263509Sdim << "format" << II->getName(); 3138193326Sed return; 3139193326Sed } 3140193326Sed 3141193326Sed // checks for the 2nd argument 3142263509Sdim Expr *IdxExpr = Attr.getArgAsExpr(1); 3143193326Sed llvm::APSInt Idx(32); 3144208600Srdivacky if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || 3145208600Srdivacky !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { 3146263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 3147263509Sdim << Attr.getName() << 2 << AANT_ArgumentIntegerConstant 3148263509Sdim << IdxExpr->getSourceRange(); 3149193326Sed return; 3150193326Sed } 3151193326Sed 3152193326Sed if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { 3153193326Sed S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 3154193326Sed << "format" << 2 << IdxExpr->getSourceRange(); 3155193326Sed return; 3156193326Sed } 3157193326Sed 3158193326Sed // FIXME: Do we need to bounds check? 3159193326Sed unsigned ArgIdx = Idx.getZExtValue() - 1; 3160198092Srdivacky 3161199482Srdivacky if (HasImplicitThisParam) { 3162199482Srdivacky if (ArgIdx == 0) { 3163218893Sdim S.Diag(Attr.getLoc(), 3164218893Sdim diag::err_format_attribute_implicit_this_format_string) 3165218893Sdim << IdxExpr->getSourceRange(); 3166199482Srdivacky return; 3167199482Srdivacky } 3168199482Srdivacky ArgIdx--; 3169199482Srdivacky } 3170198092Srdivacky 3171193326Sed // make sure the format string is really a string 3172224145Sdim QualType Ty = getFunctionOrMethodArgType(D, ArgIdx); 3173193326Sed 3174198398Srdivacky if (Kind == CFStringFormat) { 3175193326Sed if (!isCFStringType(Ty, S.Context)) { 3176193326Sed S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 3177193326Sed << "a CFString" << IdxExpr->getSourceRange(); 3178193326Sed return; 3179193326Sed } 3180198398Srdivacky } else if (Kind == NSStringFormat) { 3181193326Sed // FIXME: do we need to check if the type is NSString*? What are the 3182193326Sed // semantics? 3183193326Sed if (!isNSStringType(Ty, S.Context)) { 3184193326Sed // FIXME: Should highlight the actual expression that has the wrong type. 3185193326Sed S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 3186193326Sed << "an NSString" << IdxExpr->getSourceRange(); 3187193326Sed return; 3188198092Srdivacky } 3189193326Sed } else if (!Ty->isPointerType() || 3190198092Srdivacky !Ty->getAs<PointerType>()->getPointeeType()->isCharType()) { 3191193326Sed // FIXME: Should highlight the actual expression that has the wrong type. 3192193326Sed S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 3193193326Sed << "a string type" << IdxExpr->getSourceRange(); 3194193326Sed return; 3195193326Sed } 3196193326Sed 3197193326Sed // check the 3rd argument 3198263509Sdim Expr *FirstArgExpr = Attr.getArgAsExpr(2); 3199193326Sed llvm::APSInt FirstArg(32); 3200208600Srdivacky if (FirstArgExpr->isTypeDependent() || FirstArgExpr->isValueDependent() || 3201208600Srdivacky !FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) { 3202263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 3203263509Sdim << Attr.getName() << 3 << AANT_ArgumentIntegerConstant 3204263509Sdim << FirstArgExpr->getSourceRange(); 3205193326Sed return; 3206193326Sed } 3207193326Sed 3208193326Sed // check if the function is variadic if the 3rd argument non-zero 3209193326Sed if (FirstArg != 0) { 3210224145Sdim if (isFunctionOrMethodVariadic(D)) { 3211193326Sed ++NumArgs; // +1 for ... 3212193326Sed } else { 3213224145Sdim S.Diag(D->getLocation(), diag::err_format_attribute_requires_variadic); 3214193326Sed return; 3215193326Sed } 3216193326Sed } 3217193326Sed 3218193326Sed // strftime requires FirstArg to be 0 because it doesn't read from any 3219193326Sed // variable the input is just the current time + the format string. 3220198398Srdivacky if (Kind == StrftimeFormat) { 3221193326Sed if (FirstArg != 0) { 3222193326Sed S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter) 3223193326Sed << FirstArgExpr->getSourceRange(); 3224193326Sed return; 3225193326Sed } 3226193326Sed // if 0 it disables parameter checking (to use with e.g. va_list) 3227193326Sed } else if (FirstArg != 0 && FirstArg != NumArgs) { 3228193326Sed S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 3229193326Sed << "format" << 3 << FirstArgExpr->getSourceRange(); 3230193326Sed return; 3231193326Sed } 3232193326Sed 3233263509Sdim FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), II, 3234212904Sdim Idx.getZExtValue(), 3235252723Sdim FirstArg.getZExtValue(), 3236252723Sdim Attr.getAttributeSpellingListIndex()); 3237245431Sdim if (NewAttr) 3238245431Sdim D->addAttr(NewAttr); 3239193326Sed} 3240193326Sed 3241224145Sdimstatic void handleTransparentUnionAttr(Sema &S, Decl *D, 3242224145Sdim const AttributeList &Attr) { 3243193326Sed // Try to find the underlying union declaration. 3244193326Sed RecordDecl *RD = 0; 3245224145Sdim TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); 3246193326Sed if (TD && TD->getUnderlyingType()->isUnionType()) 3247193326Sed RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); 3248193326Sed else 3249224145Sdim RD = dyn_cast<RecordDecl>(D); 3250193326Sed 3251193326Sed if (!RD || !RD->isUnion()) { 3252193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3253221345Sdim << Attr.getName() << ExpectedUnion; 3254193326Sed return; 3255193326Sed } 3256193326Sed 3257226890Sdim if (!RD->isCompleteDefinition()) { 3258198092Srdivacky S.Diag(Attr.getLoc(), 3259193326Sed diag::warn_transparent_union_attribute_not_definition); 3260193326Sed return; 3261193326Sed } 3262193326Sed 3263195341Sed RecordDecl::field_iterator Field = RD->field_begin(), 3264195341Sed FieldEnd = RD->field_end(); 3265193326Sed if (Field == FieldEnd) { 3266193326Sed S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields); 3267193326Sed return; 3268193326Sed } 3269193326Sed 3270193326Sed FieldDecl *FirstField = *Field; 3271193326Sed QualType FirstType = FirstField->getType(); 3272210299Sed if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) { 3273198092Srdivacky S.Diag(FirstField->getLocation(), 3274210299Sed diag::warn_transparent_union_attribute_floating) 3275210299Sed << FirstType->isVectorType() << FirstType; 3276193326Sed return; 3277193326Sed } 3278193326Sed 3279193326Sed uint64_t FirstSize = S.Context.getTypeSize(FirstType); 3280193326Sed uint64_t FirstAlign = S.Context.getTypeAlign(FirstType); 3281193326Sed for (; Field != FieldEnd; ++Field) { 3282193326Sed QualType FieldType = Field->getType(); 3283193326Sed if (S.Context.getTypeSize(FieldType) != FirstSize || 3284193326Sed S.Context.getTypeAlign(FieldType) != FirstAlign) { 3285193326Sed // Warn if we drop the attribute. 3286193326Sed bool isSize = S.Context.getTypeSize(FieldType) != FirstSize; 3287198092Srdivacky unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType) 3288193326Sed : S.Context.getTypeAlign(FieldType); 3289198092Srdivacky S.Diag(Field->getLocation(), 3290193326Sed diag::warn_transparent_union_attribute_field_size_align) 3291193326Sed << isSize << Field->getDeclName() << FieldBits; 3292193326Sed unsigned FirstBits = isSize? FirstSize : FirstAlign; 3293198092Srdivacky S.Diag(FirstField->getLocation(), 3294193326Sed diag::note_transparent_union_first_field_size_align) 3295193326Sed << isSize << FirstBits; 3296193326Sed return; 3297193326Sed } 3298193326Sed } 3299193326Sed 3300252723Sdim RD->addAttr(::new (S.Context) 3301252723Sdim TransparentUnionAttr(Attr.getRange(), S.Context, 3302252723Sdim Attr.getAttributeSpellingListIndex())); 3303193326Sed} 3304193326Sed 3305224145Sdimstatic void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3306193326Sed // Make sure that there is a string literal as the annotation's single 3307193326Sed // argument. 3308263509Sdim StringRef Str; 3309263509Sdim if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str)) 3310193326Sed return; 3311226890Sdim 3312226890Sdim // Don't duplicate annotations that are already set. 3313226890Sdim for (specific_attr_iterator<AnnotateAttr> 3314226890Sdim i = D->specific_attr_begin<AnnotateAttr>(), 3315226890Sdim e = D->specific_attr_end<AnnotateAttr>(); i != e; ++i) { 3316263509Sdim if ((*i)->getAnnotation() == Str) 3317263509Sdim return; 3318226890Sdim } 3319252723Sdim 3320252723Sdim D->addAttr(::new (S.Context) 3321263509Sdim AnnotateAttr(Attr.getRange(), S.Context, Str, 3322252723Sdim Attr.getAttributeSpellingListIndex())); 3323193326Sed} 3324193326Sed 3325224145Sdimstatic void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3326193326Sed // check the attribute arguments. 3327193326Sed if (Attr.getNumArgs() > 1) { 3328263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 3329263509Sdim << Attr.getName() << 1; 3330193326Sed return; 3331193326Sed } 3332245431Sdim 3333193326Sed if (Attr.getNumArgs() == 0) { 3334252723Sdim D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context, 3335252723Sdim true, 0, Attr.getAttributeSpellingListIndex())); 3336193326Sed return; 3337193326Sed } 3338198092Srdivacky 3339263509Sdim Expr *E = Attr.getArgAsExpr(0); 3340252723Sdim if (Attr.isPackExpansion() && !E->containsUnexpandedParameterPack()) { 3341252723Sdim S.Diag(Attr.getEllipsisLoc(), 3342252723Sdim diag::err_pack_expansion_without_parameter_packs); 3343252723Sdim return; 3344252723Sdim } 3345210299Sed 3346252723Sdim if (!Attr.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E)) 3347235633Sdim return; 3348235633Sdim 3349252723Sdim S.AddAlignedAttr(Attr.getRange(), D, E, Attr.getAttributeSpellingListIndex(), 3350252723Sdim Attr.isPackExpansion()); 3351252723Sdim} 3352252723Sdim 3353252723Sdimvoid Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, 3354252723Sdim unsigned SpellingListIndex, bool IsPackExpansion) { 3355252723Sdim AlignedAttr TmpAttr(AttrRange, Context, true, E, SpellingListIndex); 3356252723Sdim SourceLocation AttrLoc = AttrRange.getBegin(); 3357252723Sdim 3358252723Sdim // C++11 alignas(...) and C11 _Alignas(...) have additional requirements. 3359252723Sdim if (TmpAttr.isAlignas()) { 3360252723Sdim // C++11 [dcl.align]p1: 3361252723Sdim // An alignment-specifier may be applied to a variable or to a class 3362252723Sdim // data member, but it shall not be applied to a bit-field, a function 3363252723Sdim // parameter, the formal parameter of a catch clause, or a variable 3364252723Sdim // declared with the register storage class specifier. An 3365252723Sdim // alignment-specifier may also be applied to the declaration of a class 3366252723Sdim // or enumeration type. 3367252723Sdim // C11 6.7.5/2: 3368252723Sdim // An alignment attribute shall not be specified in a declaration of 3369252723Sdim // a typedef, or a bit-field, or a function, or a parameter, or an 3370252723Sdim // object declared with the register storage-class specifier. 3371252723Sdim int DiagKind = -1; 3372252723Sdim if (isa<ParmVarDecl>(D)) { 3373252723Sdim DiagKind = 0; 3374252723Sdim } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { 3375252723Sdim if (VD->getStorageClass() == SC_Register) 3376252723Sdim DiagKind = 1; 3377252723Sdim if (VD->isExceptionVariable()) 3378252723Sdim DiagKind = 2; 3379252723Sdim } else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { 3380252723Sdim if (FD->isBitField()) 3381252723Sdim DiagKind = 3; 3382252723Sdim } else if (!isa<TagDecl>(D)) { 3383252723Sdim Diag(AttrLoc, diag::err_attribute_wrong_decl_type) 3384252723Sdim << (TmpAttr.isC11() ? "'_Alignas'" : "'alignas'") 3385252723Sdim << (TmpAttr.isC11() ? ExpectedVariableOrField 3386252723Sdim : ExpectedVariableFieldOrTag); 3387252723Sdim return; 3388252723Sdim } 3389252723Sdim if (DiagKind != -1) { 3390252723Sdim Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type) 3391252723Sdim << TmpAttr.isC11() << DiagKind; 3392252723Sdim return; 3393252723Sdim } 3394252723Sdim } 3395252723Sdim 3396210299Sed if (E->isTypeDependent() || E->isValueDependent()) { 3397210299Sed // Save dependent expressions in the AST to be instantiated. 3398252723Sdim AlignedAttr *AA = ::new (Context) AlignedAttr(TmpAttr); 3399252723Sdim AA->setPackExpansion(IsPackExpansion); 3400252723Sdim D->addAttr(AA); 3401210299Sed return; 3402210299Sed } 3403252723Sdim 3404212904Sdim // FIXME: Cache the number on the Attr object? 3405193326Sed llvm::APSInt Alignment(32); 3406245431Sdim ExprResult ICE 3407245431Sdim = VerifyIntegerConstantExpression(E, &Alignment, 3408245431Sdim diag::err_aligned_attribute_argument_not_int, 3409245431Sdim /*AllowFold*/ false); 3410235633Sdim if (ICE.isInvalid()) 3411193326Sed return; 3412252723Sdim 3413252723Sdim // C++11 [dcl.align]p2: 3414252723Sdim // -- if the constant expression evaluates to zero, the alignment 3415252723Sdim // specifier shall have no effect 3416252723Sdim // C11 6.7.5p6: 3417252723Sdim // An alignment specification of zero has no effect. 3418252723Sdim if (!(TmpAttr.isAlignas() && !Alignment) && 3419252723Sdim !llvm::isPowerOf2_64(Alignment.getZExtValue())) { 3420210299Sed Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two) 3421210299Sed << E->getSourceRange(); 3422193326Sed return; 3423193326Sed } 3424252723Sdim 3425252723Sdim if (TmpAttr.isDeclspec()) { 3426245431Sdim // We've already verified it's a power of 2, now let's make sure it's 3427245431Sdim // 8192 or less. 3428245431Sdim if (Alignment.getZExtValue() > 8192) { 3429252723Sdim Diag(AttrLoc, diag::err_attribute_aligned_greater_than_8192) 3430245431Sdim << E->getSourceRange(); 3431245431Sdim return; 3432245431Sdim } 3433245431Sdim } 3434193326Sed 3435252723Sdim AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, true, 3436252723Sdim ICE.take(), SpellingListIndex); 3437252723Sdim AA->setPackExpansion(IsPackExpansion); 3438252723Sdim D->addAttr(AA); 3439193326Sed} 3440193326Sed 3441252723Sdimvoid Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS, 3442252723Sdim unsigned SpellingListIndex, bool IsPackExpansion) { 3443212904Sdim // FIXME: Cache the number on the Attr object if non-dependent? 3444212904Sdim // FIXME: Perform checking of type validity 3445252723Sdim AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, false, TS, 3446252723Sdim SpellingListIndex); 3447252723Sdim AA->setPackExpansion(IsPackExpansion); 3448252723Sdim D->addAttr(AA); 3449212904Sdim} 3450212904Sdim 3451252723Sdimvoid Sema::CheckAlignasUnderalignment(Decl *D) { 3452252723Sdim assert(D->hasAttrs() && "no attributes on decl"); 3453252723Sdim 3454252723Sdim QualType Ty; 3455252723Sdim if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 3456252723Sdim Ty = VD->getType(); 3457252723Sdim else 3458252723Sdim Ty = Context.getTagDeclType(cast<TagDecl>(D)); 3459252723Sdim if (Ty->isDependentType() || Ty->isIncompleteType()) 3460252723Sdim return; 3461252723Sdim 3462252723Sdim // C++11 [dcl.align]p5, C11 6.7.5/4: 3463252723Sdim // The combined effect of all alignment attributes in a declaration shall 3464252723Sdim // not specify an alignment that is less strict than the alignment that 3465252723Sdim // would otherwise be required for the entity being declared. 3466252723Sdim AlignedAttr *AlignasAttr = 0; 3467252723Sdim unsigned Align = 0; 3468252723Sdim for (specific_attr_iterator<AlignedAttr> 3469252723Sdim I = D->specific_attr_begin<AlignedAttr>(), 3470252723Sdim E = D->specific_attr_end<AlignedAttr>(); I != E; ++I) { 3471252723Sdim if (I->isAlignmentDependent()) 3472252723Sdim return; 3473252723Sdim if (I->isAlignas()) 3474252723Sdim AlignasAttr = *I; 3475252723Sdim Align = std::max(Align, I->getAlignment(Context)); 3476252723Sdim } 3477252723Sdim 3478252723Sdim if (AlignasAttr && Align) { 3479252723Sdim CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align); 3480252723Sdim CharUnits NaturalAlign = Context.getTypeAlignInChars(Ty); 3481252723Sdim if (NaturalAlign > RequestedAlign) 3482252723Sdim Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned) 3483252723Sdim << Ty << (unsigned)NaturalAlign.getQuantity(); 3484252723Sdim } 3485252723Sdim} 3486252723Sdim 3487224145Sdim/// handleModeAttr - This attribute modifies the width of a decl with primitive 3488198092Srdivacky/// type. 3489193326Sed/// 3490198092Srdivacky/// Despite what would be logical, the mode attribute is a decl attribute, not a 3491198092Srdivacky/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be 3492198092Srdivacky/// HImode, not an intermediate pointer. 3493224145Sdimstatic void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3494193326Sed // This attribute isn't documented, but glibc uses it. It changes 3495193326Sed // the width of an int or unsigned int to the specified size. 3496263509Sdim if (!Attr.isArgIdent(0)) { 3497263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName() 3498263509Sdim << AANT_ArgumentIdentifier; 3499193326Sed return; 3500193326Sed } 3501263509Sdim 3502263509Sdim IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident; 3503263509Sdim StringRef Str = Name->getName(); 3504193326Sed 3505193326Sed // Normalize the attribute name, __foo__ becomes foo. 3506198398Srdivacky if (Str.startswith("__") && Str.endswith("__")) 3507198398Srdivacky Str = Str.substr(2, Str.size() - 4); 3508193326Sed 3509193326Sed unsigned DestWidth = 0; 3510193326Sed bool IntegerMode = true; 3511193326Sed bool ComplexMode = false; 3512198398Srdivacky switch (Str.size()) { 3513193326Sed case 2: 3514193326Sed switch (Str[0]) { 3515193326Sed case 'Q': DestWidth = 8; break; 3516193326Sed case 'H': DestWidth = 16; break; 3517193326Sed case 'S': DestWidth = 32; break; 3518193326Sed case 'D': DestWidth = 64; break; 3519193326Sed case 'X': DestWidth = 96; break; 3520193326Sed case 'T': DestWidth = 128; break; 3521193326Sed } 3522193326Sed if (Str[1] == 'F') { 3523193326Sed IntegerMode = false; 3524193326Sed } else if (Str[1] == 'C') { 3525193326Sed IntegerMode = false; 3526193326Sed ComplexMode = true; 3527193326Sed } else if (Str[1] != 'I') { 3528193326Sed DestWidth = 0; 3529193326Sed } 3530193326Sed break; 3531193326Sed case 4: 3532193326Sed // FIXME: glibc uses 'word' to define register_t; this is narrower than a 3533193326Sed // pointer on PIC16 and other embedded platforms. 3534198398Srdivacky if (Str == "word") 3535226890Sdim DestWidth = S.Context.getTargetInfo().getPointerWidth(0); 3536198398Srdivacky else if (Str == "byte") 3537226890Sdim DestWidth = S.Context.getTargetInfo().getCharWidth(); 3538193326Sed break; 3539193326Sed case 7: 3540198398Srdivacky if (Str == "pointer") 3541226890Sdim DestWidth = S.Context.getTargetInfo().getPointerWidth(0); 3542193326Sed break; 3543252723Sdim case 11: 3544252723Sdim if (Str == "unwind_word") 3545252723Sdim DestWidth = S.Context.getTargetInfo().getUnwindWordWidth(); 3546252723Sdim break; 3547193326Sed } 3548193326Sed 3549193326Sed QualType OldTy; 3550221345Sdim if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) 3551193326Sed OldTy = TD->getUnderlyingType(); 3552193326Sed else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 3553193326Sed OldTy = VD->getType(); 3554193326Sed else { 3555193326Sed S.Diag(D->getLocation(), diag::err_attr_wrong_decl) 3556226890Sdim << "mode" << Attr.getRange(); 3557193326Sed return; 3558193326Sed } 3559193326Sed 3560198092Srdivacky if (!OldTy->getAs<BuiltinType>() && !OldTy->isComplexType()) 3561193326Sed S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); 3562193326Sed else if (IntegerMode) { 3563210299Sed if (!OldTy->isIntegralOrEnumerationType()) 3564193326Sed S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); 3565193326Sed } else if (ComplexMode) { 3566193326Sed if (!OldTy->isComplexType()) 3567193326Sed S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); 3568193326Sed } else { 3569193326Sed if (!OldTy->isFloatingType()) 3570193326Sed S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); 3571193326Sed } 3572193326Sed 3573193326Sed // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t 3574193326Sed // and friends, at least with glibc. 3575193326Sed // FIXME: Make sure floating-point mappings are accurate 3576193326Sed // FIXME: Support XF and TF types 3577263509Sdim if (!DestWidth) { 3578193326Sed S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name; 3579193326Sed return; 3580263509Sdim } 3581263509Sdim 3582263509Sdim QualType NewTy; 3583263509Sdim 3584263509Sdim if (IntegerMode) 3585263509Sdim NewTy = S.Context.getIntTypeForBitwidth(DestWidth, 3586263509Sdim OldTy->isSignedIntegerType()); 3587263509Sdim else 3588263509Sdim NewTy = S.Context.getRealTypeForBitwidth(DestWidth); 3589263509Sdim 3590263509Sdim if (NewTy.isNull()) { 3591193326Sed S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; 3592193326Sed return; 3593193326Sed } 3594193326Sed 3595193326Sed if (ComplexMode) { 3596193326Sed NewTy = S.Context.getComplexType(NewTy); 3597193326Sed } 3598193326Sed 3599193326Sed // Install the new type. 3600263509Sdim if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) 3601263509Sdim TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy); 3602263509Sdim else 3603193326Sed cast<ValueDecl>(D)->setType(NewTy); 3604263509Sdim 3605263509Sdim D->addAttr(::new (S.Context) 3606263509Sdim ModeAttr(Attr.getRange(), S.Context, Name, 3607263509Sdim Attr.getAttributeSpellingListIndex())); 3608193326Sed} 3609193326Sed 3610224145Sdimstatic void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3611245431Sdim if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { 3612245431Sdim if (!VD->hasGlobalStorage()) 3613245431Sdim S.Diag(Attr.getLoc(), 3614245431Sdim diag::warn_attribute_requires_functions_or_static_globals) 3615245431Sdim << Attr.getName(); 3616245431Sdim } else if (!isFunctionOrMethod(D)) { 3617245431Sdim S.Diag(Attr.getLoc(), 3618245431Sdim diag::warn_attribute_requires_functions_or_static_globals) 3619245431Sdim << Attr.getName(); 3620193326Sed return; 3621193326Sed } 3622198092Srdivacky 3623252723Sdim D->addAttr(::new (S.Context) 3624252723Sdim NoDebugAttr(Attr.getRange(), S.Context, 3625252723Sdim Attr.getAttributeSpellingListIndex())); 3626193326Sed} 3627193326Sed 3628224145Sdimstatic void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3629224145Sdim if (!isa<FunctionDecl>(D)) { 3630193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3631221345Sdim << Attr.getName() << ExpectedFunction; 3632193326Sed return; 3633193326Sed } 3634198092Srdivacky 3635252723Sdim D->addAttr(::new (S.Context) 3636252723Sdim NoInlineAttr(Attr.getRange(), S.Context, 3637252723Sdim Attr.getAttributeSpellingListIndex())); 3638193326Sed} 3639193326Sed 3640224145Sdimstatic void handleNoInstrumentFunctionAttr(Sema &S, Decl *D, 3641224145Sdim const AttributeList &Attr) { 3642224145Sdim if (!isa<FunctionDecl>(D)) { 3643210299Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3644221345Sdim << Attr.getName() << ExpectedFunction; 3645210299Sed return; 3646210299Sed } 3647210299Sed 3648252723Sdim D->addAttr(::new (S.Context) 3649252723Sdim NoInstrumentFunctionAttr(Attr.getRange(), S.Context, 3650252723Sdim Attr.getAttributeSpellingListIndex())); 3651210299Sed} 3652210299Sed 3653224145Sdimstatic void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3654218893Sdim if (S.LangOpts.CUDA) { 3655224145Sdim if (!isa<VarDecl>(D)) { 3656218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3657221345Sdim << Attr.getName() << ExpectedVariable; 3658218893Sdim return; 3659218893Sdim } 3660218893Sdim 3661252723Sdim D->addAttr(::new (S.Context) 3662252723Sdim CUDAConstantAttr(Attr.getRange(), S.Context, 3663252723Sdim Attr.getAttributeSpellingListIndex())); 3664218893Sdim } else { 3665218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "constant"; 3666218893Sdim } 3667218893Sdim} 3668218893Sdim 3669224145Sdimstatic void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3670218893Sdim if (S.LangOpts.CUDA) { 3671218893Sdim // check the attribute arguments. 3672218893Sdim if (Attr.getNumArgs() != 0) { 3673263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 3674263509Sdim << Attr.getName() << 0; 3675218893Sdim return; 3676218893Sdim } 3677218893Sdim 3678224145Sdim if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D)) { 3679218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3680221345Sdim << Attr.getName() << ExpectedVariableOrFunction; 3681218893Sdim return; 3682218893Sdim } 3683218893Sdim 3684252723Sdim D->addAttr(::new (S.Context) 3685252723Sdim CUDADeviceAttr(Attr.getRange(), S.Context, 3686252723Sdim Attr.getAttributeSpellingListIndex())); 3687218893Sdim } else { 3688218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "device"; 3689218893Sdim } 3690218893Sdim} 3691218893Sdim 3692224145Sdimstatic void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3693218893Sdim if (S.LangOpts.CUDA) { 3694224145Sdim if (!isa<FunctionDecl>(D)) { 3695218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3696221345Sdim << Attr.getName() << ExpectedFunction; 3697218893Sdim return; 3698218893Sdim } 3699218893Sdim 3700224145Sdim FunctionDecl *FD = cast<FunctionDecl>(D); 3701218893Sdim if (!FD->getResultType()->isVoidType()) { 3702218893Sdim TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens(); 3703252723Sdim if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { 3704218893Sdim S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) 3705218893Sdim << FD->getType() 3706252723Sdim << FixItHint::CreateReplacement(FTL.getResultLoc().getSourceRange(), 3707218893Sdim "void"); 3708218893Sdim } else { 3709218893Sdim S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) 3710218893Sdim << FD->getType(); 3711218893Sdim } 3712218893Sdim return; 3713218893Sdim } 3714218893Sdim 3715252723Sdim D->addAttr(::new (S.Context) 3716252723Sdim CUDAGlobalAttr(Attr.getRange(), S.Context, 3717252723Sdim Attr.getAttributeSpellingListIndex())); 3718218893Sdim } else { 3719218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "global"; 3720218893Sdim } 3721218893Sdim} 3722218893Sdim 3723224145Sdimstatic void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3724218893Sdim if (S.LangOpts.CUDA) { 3725224145Sdim if (!isa<FunctionDecl>(D)) { 3726218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3727221345Sdim << Attr.getName() << ExpectedFunction; 3728218893Sdim return; 3729218893Sdim } 3730218893Sdim 3731252723Sdim D->addAttr(::new (S.Context) 3732252723Sdim CUDAHostAttr(Attr.getRange(), S.Context, 3733252723Sdim Attr.getAttributeSpellingListIndex())); 3734218893Sdim } else { 3735218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "host"; 3736218893Sdim } 3737218893Sdim} 3738218893Sdim 3739224145Sdimstatic void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3740218893Sdim if (S.LangOpts.CUDA) { 3741224145Sdim if (!isa<VarDecl>(D)) { 3742218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3743221345Sdim << Attr.getName() << ExpectedVariable; 3744218893Sdim return; 3745218893Sdim } 3746218893Sdim 3747252723Sdim D->addAttr(::new (S.Context) 3748252723Sdim CUDASharedAttr(Attr.getRange(), S.Context, 3749252723Sdim Attr.getAttributeSpellingListIndex())); 3750218893Sdim } else { 3751218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "shared"; 3752218893Sdim } 3753218893Sdim} 3754218893Sdim 3755224145Sdimstatic void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3756224145Sdim FunctionDecl *Fn = dyn_cast<FunctionDecl>(D); 3757193326Sed if (Fn == 0) { 3758193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3759221345Sdim << Attr.getName() << ExpectedFunction; 3760193326Sed return; 3761193326Sed } 3762198092Srdivacky 3763198893Srdivacky if (!Fn->isInlineSpecified()) { 3764193326Sed S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline); 3765193326Sed return; 3766193326Sed } 3767198092Srdivacky 3768252723Sdim D->addAttr(::new (S.Context) 3769252723Sdim GNUInlineAttr(Attr.getRange(), S.Context, 3770252723Sdim Attr.getAttributeSpellingListIndex())); 3771193326Sed} 3772193326Sed 3773224145Sdimstatic void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3774224145Sdim if (hasDeclarator(D)) return; 3775218893Sdim 3776252723Sdim const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); 3777224145Sdim // Diagnostic is emitted elsewhere: here we store the (valid) Attr 3778207619Srdivacky // in the Decl node for syntactic reasoning, e.g., pretty-printing. 3779218893Sdim CallingConv CC; 3780252723Sdim if (S.CheckCallingConvAttr(Attr, CC, FD)) 3781218893Sdim return; 3782207619Srdivacky 3783224145Sdim if (!isa<ObjCMethodDecl>(D)) { 3784224145Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3785224145Sdim << Attr.getName() << ExpectedFunctionOrMethod; 3786218893Sdim return; 3787218893Sdim } 3788218893Sdim 3789224145Sdim switch (Attr.getKind()) { 3790245431Sdim case AttributeList::AT_FastCall: 3791252723Sdim D->addAttr(::new (S.Context) 3792252723Sdim FastCallAttr(Attr.getRange(), S.Context, 3793252723Sdim Attr.getAttributeSpellingListIndex())); 3794207619Srdivacky return; 3795245431Sdim case AttributeList::AT_StdCall: 3796252723Sdim D->addAttr(::new (S.Context) 3797252723Sdim StdCallAttr(Attr.getRange(), S.Context, 3798252723Sdim Attr.getAttributeSpellingListIndex())); 3799207619Srdivacky return; 3800245431Sdim case AttributeList::AT_ThisCall: 3801252723Sdim D->addAttr(::new (S.Context) 3802252723Sdim ThisCallAttr(Attr.getRange(), S.Context, 3803252723Sdim Attr.getAttributeSpellingListIndex())); 3804212904Sdim return; 3805245431Sdim case AttributeList::AT_CDecl: 3806252723Sdim D->addAttr(::new (S.Context) 3807252723Sdim CDeclAttr(Attr.getRange(), S.Context, 3808252723Sdim Attr.getAttributeSpellingListIndex())); 3809207619Srdivacky return; 3810245431Sdim case AttributeList::AT_Pascal: 3811252723Sdim D->addAttr(::new (S.Context) 3812252723Sdim PascalAttr(Attr.getRange(), S.Context, 3813252723Sdim Attr.getAttributeSpellingListIndex())); 3814212904Sdim return; 3815256382Sdim case AttributeList::AT_MSABI: 3816256382Sdim D->addAttr(::new (S.Context) 3817256382Sdim MSABIAttr(Attr.getRange(), S.Context, 3818256382Sdim Attr.getAttributeSpellingListIndex())); 3819256382Sdim return; 3820256382Sdim case AttributeList::AT_SysVABI: 3821256382Sdim D->addAttr(::new (S.Context) 3822256382Sdim SysVABIAttr(Attr.getRange(), S.Context, 3823256382Sdim Attr.getAttributeSpellingListIndex())); 3824256382Sdim return; 3825245431Sdim case AttributeList::AT_Pcs: { 3826221345Sdim PcsAttr::PCSType PCS; 3827245431Sdim switch (CC) { 3828245431Sdim case CC_AAPCS: 3829221345Sdim PCS = PcsAttr::AAPCS; 3830245431Sdim break; 3831245431Sdim case CC_AAPCS_VFP: 3832221345Sdim PCS = PcsAttr::AAPCS_VFP; 3833245431Sdim break; 3834245431Sdim default: 3835245431Sdim llvm_unreachable("unexpected calling convention in pcs attribute"); 3836221345Sdim } 3837221345Sdim 3838252723Sdim D->addAttr(::new (S.Context) 3839252723Sdim PcsAttr(Attr.getRange(), S.Context, PCS, 3840252723Sdim Attr.getAttributeSpellingListIndex())); 3841245431Sdim return; 3842221345Sdim } 3843245431Sdim case AttributeList::AT_PnaclCall: 3844252723Sdim D->addAttr(::new (S.Context) 3845252723Sdim PnaclCallAttr(Attr.getRange(), S.Context, 3846252723Sdim Attr.getAttributeSpellingListIndex())); 3847245431Sdim return; 3848252723Sdim case AttributeList::AT_IntelOclBicc: 3849252723Sdim D->addAttr(::new (S.Context) 3850252723Sdim IntelOclBiccAttr(Attr.getRange(), S.Context, 3851252723Sdim Attr.getAttributeSpellingListIndex())); 3852252723Sdim return; 3853245431Sdim 3854207619Srdivacky default: 3855207619Srdivacky llvm_unreachable("unexpected attribute kind"); 3856207619Srdivacky } 3857207619Srdivacky} 3858207619Srdivacky 3859224145Sdimstatic void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){ 3860226890Sdim D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getRange(), S.Context)); 3861218893Sdim} 3862218893Sdim 3863252723Sdimstatic void handleOpenCLImageAccessAttr(Sema &S, Decl *D, const AttributeList &Attr){ 3864263509Sdim Expr *E = Attr.getArgAsExpr(0); 3865252723Sdim llvm::APSInt ArgNum(32); 3866252723Sdim if (E->isTypeDependent() || E->isValueDependent() || 3867252723Sdim !E->isIntegerConstantExpr(ArgNum, S.Context)) { 3868263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) 3869263509Sdim << Attr.getName() << AANT_ArgumentIntegerConstant 3870263509Sdim << E->getSourceRange(); 3871252723Sdim return; 3872252723Sdim } 3873252723Sdim 3874252723Sdim D->addAttr(::new (S.Context) OpenCLImageAccessAttr( 3875252723Sdim Attr.getRange(), S.Context, ArgNum.getZExtValue())); 3876252723Sdim} 3877252723Sdim 3878252723Sdimbool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, 3879252723Sdim const FunctionDecl *FD) { 3880218893Sdim if (attr.isInvalid()) 3881218893Sdim return true; 3882218893Sdim 3883245431Sdim unsigned ReqArgs = attr.getKind() == AttributeList::AT_Pcs ? 1 : 0; 3884263509Sdim if (!checkAttributeNumArgs(*this, attr, ReqArgs)) { 3885218893Sdim attr.setInvalid(); 3886218893Sdim return true; 3887193326Sed } 3888193326Sed 3889221345Sdim // TODO: diagnose uses of these conventions on the wrong target. Or, better 3890221345Sdim // move to TargetAttributesSema one day. 3891218893Sdim switch (attr.getKind()) { 3892245431Sdim case AttributeList::AT_CDecl: CC = CC_C; break; 3893245431Sdim case AttributeList::AT_FastCall: CC = CC_X86FastCall; break; 3894245431Sdim case AttributeList::AT_StdCall: CC = CC_X86StdCall; break; 3895245431Sdim case AttributeList::AT_ThisCall: CC = CC_X86ThisCall; break; 3896245431Sdim case AttributeList::AT_Pascal: CC = CC_X86Pascal; break; 3897256382Sdim case AttributeList::AT_MSABI: 3898256382Sdim CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C : 3899256382Sdim CC_X86_64Win64; 3900256382Sdim break; 3901256382Sdim case AttributeList::AT_SysVABI: 3902256382Sdim CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV : 3903256382Sdim CC_C; 3904256382Sdim break; 3905245431Sdim case AttributeList::AT_Pcs: { 3906263509Sdim StringRef StrRef; 3907263509Sdim if (!checkStringLiteralArgumentAttr(attr, 0, StrRef)) { 3908221345Sdim attr.setInvalid(); 3909221345Sdim return true; 3910221345Sdim } 3911221345Sdim if (StrRef == "aapcs") { 3912221345Sdim CC = CC_AAPCS; 3913221345Sdim break; 3914221345Sdim } else if (StrRef == "aapcs-vfp") { 3915221345Sdim CC = CC_AAPCS_VFP; 3916221345Sdim break; 3917221345Sdim } 3918245431Sdim 3919245431Sdim attr.setInvalid(); 3920245431Sdim Diag(attr.getLoc(), diag::err_invalid_pcs); 3921245431Sdim return true; 3922221345Sdim } 3923245431Sdim case AttributeList::AT_PnaclCall: CC = CC_PnaclCall; break; 3924252723Sdim case AttributeList::AT_IntelOclBicc: CC = CC_IntelOclBicc; break; 3925235633Sdim default: llvm_unreachable("unexpected attribute kind"); 3926218893Sdim } 3927218893Sdim 3928245431Sdim const TargetInfo &TI = Context.getTargetInfo(); 3929245431Sdim TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC); 3930245431Sdim if (A == TargetInfo::CCCR_Warning) { 3931245431Sdim Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName(); 3932252723Sdim 3933252723Sdim TargetInfo::CallingConvMethodType MT = TargetInfo::CCMT_Unknown; 3934252723Sdim if (FD) 3935252723Sdim MT = FD->isCXXInstanceMember() ? TargetInfo::CCMT_Member : 3936252723Sdim TargetInfo::CCMT_NonMember; 3937252723Sdim CC = TI.getDefaultCallingConv(MT); 3938245431Sdim } 3939245431Sdim 3940218893Sdim return false; 3941218893Sdim} 3942218893Sdim 3943224145Sdimstatic void handleRegparmAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3944224145Sdim if (hasDeclarator(D)) return; 3945218893Sdim 3946218893Sdim unsigned numParams; 3947224145Sdim if (S.CheckRegparmAttr(Attr, numParams)) 3948193326Sed return; 3949218893Sdim 3950224145Sdim if (!isa<ObjCMethodDecl>(D)) { 3951224145Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3952224145Sdim << Attr.getName() << ExpectedFunctionOrMethod; 3953218893Sdim return; 3954193326Sed } 3955193326Sed 3956252723Sdim D->addAttr(::new (S.Context) 3957252723Sdim RegparmAttr(Attr.getRange(), S.Context, numParams, 3958252723Sdim Attr.getAttributeSpellingListIndex())); 3959218893Sdim} 3960218893Sdim 3961218893Sdim/// Checks a regparm attribute, returning true if it is ill-formed and 3962218893Sdim/// otherwise setting numParams to the appropriate value. 3963224145Sdimbool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) { 3964224145Sdim if (Attr.isInvalid()) 3965218893Sdim return true; 3966218893Sdim 3967263509Sdim if (!checkAttributeNumArgs(*this, Attr, 1)) { 3968224145Sdim Attr.setInvalid(); 3969218893Sdim return true; 3970218893Sdim } 3971218893Sdim 3972263509Sdim Expr *NumParamsExpr = Attr.getArgAsExpr(0); 3973193326Sed llvm::APSInt NumParams(32); 3974208600Srdivacky if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() || 3975218893Sdim !NumParamsExpr->isIntegerConstantExpr(NumParams, Context)) { 3976263509Sdim Diag(Attr.getLoc(), diag::err_attribute_argument_type) 3977263509Sdim << Attr.getName() << AANT_ArgumentIntegerConstant 3978263509Sdim << NumParamsExpr->getSourceRange(); 3979224145Sdim Attr.setInvalid(); 3980218893Sdim return true; 3981193326Sed } 3982193326Sed 3983226890Sdim if (Context.getTargetInfo().getRegParmMax() == 0) { 3984224145Sdim Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform) 3985193326Sed << NumParamsExpr->getSourceRange(); 3986224145Sdim Attr.setInvalid(); 3987218893Sdim return true; 3988193326Sed } 3989193326Sed 3990218893Sdim numParams = NumParams.getZExtValue(); 3991226890Sdim if (numParams > Context.getTargetInfo().getRegParmMax()) { 3992224145Sdim Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number) 3993226890Sdim << Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange(); 3994224145Sdim Attr.setInvalid(); 3995218893Sdim return true; 3996193326Sed } 3997193326Sed 3998218893Sdim return false; 3999193326Sed} 4000193326Sed 4001224145Sdimstatic void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){ 4002218893Sdim if (S.LangOpts.CUDA) { 4003218893Sdim // check the attribute arguments. 4004218893Sdim if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) { 4005221345Sdim // FIXME: 0 is not okay. 4006221345Sdim S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2; 4007218893Sdim return; 4008218893Sdim } 4009199990Srdivacky 4010224145Sdim if (!isFunctionOrMethod(D)) { 4011218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 4012221345Sdim << Attr.getName() << ExpectedFunctionOrMethod; 4013218893Sdim return; 4014218893Sdim } 4015218893Sdim 4016263509Sdim Expr *MaxThreadsExpr = Attr.getArgAsExpr(0); 4017218893Sdim llvm::APSInt MaxThreads(32); 4018218893Sdim if (MaxThreadsExpr->isTypeDependent() || 4019218893Sdim MaxThreadsExpr->isValueDependent() || 4020218893Sdim !MaxThreadsExpr->isIntegerConstantExpr(MaxThreads, S.Context)) { 4021263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 4022263509Sdim << Attr.getName() << 1 << AANT_ArgumentIntegerConstant 4023263509Sdim << MaxThreadsExpr->getSourceRange(); 4024218893Sdim return; 4025218893Sdim } 4026218893Sdim 4027218893Sdim llvm::APSInt MinBlocks(32); 4028218893Sdim if (Attr.getNumArgs() > 1) { 4029263509Sdim Expr *MinBlocksExpr = Attr.getArgAsExpr(1); 4030218893Sdim if (MinBlocksExpr->isTypeDependent() || 4031218893Sdim MinBlocksExpr->isValueDependent() || 4032218893Sdim !MinBlocksExpr->isIntegerConstantExpr(MinBlocks, S.Context)) { 4033263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 4034263509Sdim << Attr.getName() << 2 << AANT_ArgumentIntegerConstant 4035263509Sdim << MinBlocksExpr->getSourceRange(); 4036218893Sdim return; 4037218893Sdim } 4038218893Sdim } 4039218893Sdim 4040252723Sdim D->addAttr(::new (S.Context) 4041252723Sdim CUDALaunchBoundsAttr(Attr.getRange(), S.Context, 4042252723Sdim MaxThreads.getZExtValue(), 4043252723Sdim MinBlocks.getZExtValue(), 4044252723Sdim Attr.getAttributeSpellingListIndex())); 4045218893Sdim } else { 4046218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "launch_bounds"; 4047199990Srdivacky } 4048199990Srdivacky} 4049199990Srdivacky 4050245431Sdimstatic void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, 4051245431Sdim const AttributeList &Attr) { 4052263509Sdim if (!Attr.isArgIdent(0)) { 4053263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 4054263509Sdim << Attr.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier; 4055245431Sdim return; 4056245431Sdim } 4057263509Sdim 4058263509Sdim if (!checkAttributeNumArgs(S, Attr, 3)) 4059245431Sdim return; 4060245431Sdim 4061263509Sdim StringRef AttrName = Attr.getName()->getName(); 4062263509Sdim IdentifierInfo *ArgumentKind = Attr.getArgAsIdent(0)->Ident; 4063245431Sdim 4064245431Sdim if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { 4065245431Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 4066245431Sdim << Attr.getName() << ExpectedFunctionOrMethod; 4067245431Sdim return; 4068245431Sdim } 4069245431Sdim 4070245431Sdim uint64_t ArgumentIdx; 4071245431Sdim if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName, 4072245431Sdim Attr.getLoc(), 2, 4073263509Sdim Attr.getArgAsExpr(1), ArgumentIdx)) 4074245431Sdim return; 4075245431Sdim 4076245431Sdim uint64_t TypeTagIdx; 4077245431Sdim if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName, 4078245431Sdim Attr.getLoc(), 3, 4079263509Sdim Attr.getArgAsExpr(2), TypeTagIdx)) 4080245431Sdim return; 4081245431Sdim 4082245431Sdim bool IsPointer = (AttrName == "pointer_with_type_tag"); 4083245431Sdim if (IsPointer) { 4084245431Sdim // Ensure that buffer has a pointer type. 4085245431Sdim QualType BufferTy = getFunctionOrMethodArgType(D, ArgumentIdx); 4086245431Sdim if (!BufferTy->isPointerType()) { 4087245431Sdim S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only) 4088263509Sdim << Attr.getName(); 4089245431Sdim } 4090245431Sdim } 4091245431Sdim 4092252723Sdim D->addAttr(::new (S.Context) 4093252723Sdim ArgumentWithTypeTagAttr(Attr.getRange(), S.Context, ArgumentKind, 4094252723Sdim ArgumentIdx, TypeTagIdx, IsPointer, 4095252723Sdim Attr.getAttributeSpellingListIndex())); 4096245431Sdim} 4097245431Sdim 4098245431Sdimstatic void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, 4099245431Sdim const AttributeList &Attr) { 4100263509Sdim if (!Attr.isArgIdent(0)) { 4101263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 4102263509Sdim << Attr.getName() << 1 << AANT_ArgumentIdentifier; 4103245431Sdim return; 4104245431Sdim } 4105263509Sdim 4106263509Sdim if (!checkAttributeNumArgs(S, Attr, 1)) 4107263509Sdim return; 4108245431Sdim 4109263509Sdim IdentifierInfo *PointerKind = Attr.getArgAsIdent(0)->Ident; 4110263509Sdim TypeSourceInfo *MatchingCTypeLoc = 0; 4111263509Sdim S.GetTypeFromParser(Attr.getMatchingCType(), &MatchingCTypeLoc); 4112263509Sdim assert(MatchingCTypeLoc && "no type source info for attribute argument"); 4113245431Sdim 4114252723Sdim D->addAttr(::new (S.Context) 4115252723Sdim TypeTagForDatatypeAttr(Attr.getRange(), S.Context, PointerKind, 4116263509Sdim MatchingCTypeLoc, 4117252723Sdim Attr.getLayoutCompatible(), 4118252723Sdim Attr.getMustBeNull(), 4119252723Sdim Attr.getAttributeSpellingListIndex())); 4120245431Sdim} 4121245431Sdim 4122193326Sed//===----------------------------------------------------------------------===// 4123218893Sdim// Checker-specific attribute handlers. 4124199990Srdivacky//===----------------------------------------------------------------------===// 4125199990Srdivacky 4126218893Sdimstatic bool isValidSubjectOfNSAttribute(Sema &S, QualType type) { 4127226890Sdim return type->isDependentType() || 4128226890Sdim type->isObjCObjectPointerType() || 4129226890Sdim S.Context.isObjCNSObjectType(type); 4130199990Srdivacky} 4131218893Sdimstatic bool isValidSubjectOfCFAttribute(Sema &S, QualType type) { 4132226890Sdim return type->isDependentType() || 4133226890Sdim type->isPointerType() || 4134226890Sdim isValidSubjectOfNSAttribute(S, type); 4135218893Sdim} 4136199990Srdivacky 4137224145Sdimstatic void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 4138224145Sdim ParmVarDecl *param = dyn_cast<ParmVarDecl>(D); 4139218893Sdim if (!param) { 4140224145Sdim S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) 4141226890Sdim << Attr.getRange() << Attr.getName() << ExpectedParameter; 4142199990Srdivacky return; 4143199990Srdivacky } 4144199990Srdivacky 4145218893Sdim bool typeOK, cf; 4146245431Sdim if (Attr.getKind() == AttributeList::AT_NSConsumed) { 4147218893Sdim typeOK = isValidSubjectOfNSAttribute(S, param->getType()); 4148218893Sdim cf = false; 4149218893Sdim } else { 4150218893Sdim typeOK = isValidSubjectOfCFAttribute(S, param->getType()); 4151218893Sdim cf = true; 4152199990Srdivacky } 4153199990Srdivacky 4154218893Sdim if (!typeOK) { 4155224145Sdim S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type) 4156226890Sdim << Attr.getRange() << Attr.getName() << cf; 4157199990Srdivacky return; 4158199990Srdivacky } 4159199990Srdivacky 4160218893Sdim if (cf) 4161252723Sdim param->addAttr(::new (S.Context) 4162252723Sdim CFConsumedAttr(Attr.getRange(), S.Context, 4163252723Sdim Attr.getAttributeSpellingListIndex())); 4164218893Sdim else 4165252723Sdim param->addAttr(::new (S.Context) 4166252723Sdim NSConsumedAttr(Attr.getRange(), S.Context, 4167252723Sdim Attr.getAttributeSpellingListIndex())); 4168199990Srdivacky} 4169199990Srdivacky 4170224145Sdimstatic void handleNSConsumesSelfAttr(Sema &S, Decl *D, 4171224145Sdim const AttributeList &Attr) { 4172224145Sdim if (!isa<ObjCMethodDecl>(D)) { 4173224145Sdim S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) 4174226890Sdim << Attr.getRange() << Attr.getName() << ExpectedMethod; 4175199990Srdivacky return; 4176199990Srdivacky } 4177199990Srdivacky 4178252723Sdim D->addAttr(::new (S.Context) 4179252723Sdim NSConsumesSelfAttr(Attr.getRange(), S.Context, 4180252723Sdim Attr.getAttributeSpellingListIndex())); 4181199990Srdivacky} 4182199990Srdivacky 4183224145Sdimstatic void handleNSReturnsRetainedAttr(Sema &S, Decl *D, 4184224145Sdim const AttributeList &Attr) { 4185193326Sed 4186218893Sdim QualType returnType; 4187198092Srdivacky 4188224145Sdim if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 4189218893Sdim returnType = MD->getResultType(); 4190245431Sdim else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) && 4191245431Sdim (Attr.getKind() == AttributeList::AT_NSReturnsRetained)) 4192245431Sdim return; // ignore: was handled as a type attribute 4193224145Sdim else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) 4194224145Sdim returnType = PD->getType(); 4195224145Sdim else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 4196218893Sdim returnType = FD->getResultType(); 4197193326Sed else { 4198224145Sdim S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) 4199226890Sdim << Attr.getRange() << Attr.getName() 4200221345Sdim << ExpectedFunctionOrMethod; 4201193326Sed return; 4202193326Sed } 4203198092Srdivacky 4204218893Sdim bool typeOK; 4205218893Sdim bool cf; 4206224145Sdim switch (Attr.getKind()) { 4207235633Sdim default: llvm_unreachable("invalid ownership attribute"); 4208245431Sdim case AttributeList::AT_NSReturnsAutoreleased: 4209245431Sdim case AttributeList::AT_NSReturnsRetained: 4210245431Sdim case AttributeList::AT_NSReturnsNotRetained: 4211218893Sdim typeOK = isValidSubjectOfNSAttribute(S, returnType); 4212218893Sdim cf = false; 4213218893Sdim break; 4214218893Sdim 4215245431Sdim case AttributeList::AT_CFReturnsRetained: 4216245431Sdim case AttributeList::AT_CFReturnsNotRetained: 4217218893Sdim typeOK = isValidSubjectOfCFAttribute(S, returnType); 4218218893Sdim cf = true; 4219218893Sdim break; 4220218893Sdim } 4221218893Sdim 4222218893Sdim if (!typeOK) { 4223224145Sdim S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type) 4224226890Sdim << Attr.getRange() << Attr.getName() << isa<ObjCMethodDecl>(D) << cf; 4225198092Srdivacky return; 4226193326Sed } 4227198092Srdivacky 4228224145Sdim switch (Attr.getKind()) { 4229193326Sed default: 4230226890Sdim llvm_unreachable("invalid ownership attribute"); 4231245431Sdim case AttributeList::AT_NSReturnsAutoreleased: 4232252723Sdim D->addAttr(::new (S.Context) 4233252723Sdim NSReturnsAutoreleasedAttr(Attr.getRange(), S.Context, 4234252723Sdim Attr.getAttributeSpellingListIndex())); 4235218893Sdim return; 4236245431Sdim case AttributeList::AT_CFReturnsNotRetained: 4237252723Sdim D->addAttr(::new (S.Context) 4238252723Sdim CFReturnsNotRetainedAttr(Attr.getRange(), S.Context, 4239252723Sdim Attr.getAttributeSpellingListIndex())); 4240204643Srdivacky return; 4241245431Sdim case AttributeList::AT_NSReturnsNotRetained: 4242252723Sdim D->addAttr(::new (S.Context) 4243252723Sdim NSReturnsNotRetainedAttr(Attr.getRange(), S.Context, 4244252723Sdim Attr.getAttributeSpellingListIndex())); 4245204643Srdivacky return; 4246245431Sdim case AttributeList::AT_CFReturnsRetained: 4247252723Sdim D->addAttr(::new (S.Context) 4248252723Sdim CFReturnsRetainedAttr(Attr.getRange(), S.Context, 4249252723Sdim Attr.getAttributeSpellingListIndex())); 4250193326Sed return; 4251245431Sdim case AttributeList::AT_NSReturnsRetained: 4252252723Sdim D->addAttr(::new (S.Context) 4253252723Sdim NSReturnsRetainedAttr(Attr.getRange(), S.Context, 4254252723Sdim Attr.getAttributeSpellingListIndex())); 4255193326Sed return; 4256193326Sed }; 4257193326Sed} 4258193326Sed 4259226890Sdimstatic void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, 4260226890Sdim const AttributeList &attr) { 4261263509Sdim const int EP_ObjCMethod = 1; 4262263509Sdim const int EP_ObjCProperty = 2; 4263263509Sdim 4264226890Sdim SourceLocation loc = attr.getLoc(); 4265263509Sdim QualType resultType; 4266263509Sdim 4267226890Sdim ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D); 4268226890Sdim 4269245431Sdim if (!method) { 4270263509Sdim ObjCPropertyDecl *property = dyn_cast<ObjCPropertyDecl>(D); 4271263509Sdim if (!property) { 4272263509Sdim S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) 4273263509Sdim << SourceRange(loc, loc) << attr.getName() << ExpectedMethodOrProperty; 4274263509Sdim return; 4275263509Sdim } 4276263509Sdim resultType = property->getType(); 4277226890Sdim } 4278263509Sdim else 4279263509Sdim // Check that the method returns a normal pointer. 4280263509Sdim resultType = method->getResultType(); 4281226890Sdim 4282226890Sdim if (!resultType->isReferenceType() && 4283226890Sdim (!resultType->isPointerType() || resultType->isObjCRetainableType())) { 4284263509Sdim S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type) 4285226890Sdim << SourceRange(loc) 4286263509Sdim << attr.getName() << (method ? EP_ObjCMethod : EP_ObjCProperty) 4287263509Sdim << /*non-retainable pointer*/ 2; 4288226890Sdim 4289226890Sdim // Drop the attribute. 4290226890Sdim return; 4291226890Sdim } 4292226890Sdim 4293263509Sdim D->addAttr(::new (S.Context) 4294252723Sdim ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context, 4295252723Sdim attr.getAttributeSpellingListIndex())); 4296226890Sdim} 4297226890Sdim 4298245431Sdimstatic void handleObjCRequiresSuperAttr(Sema &S, Decl *D, 4299245431Sdim const AttributeList &attr) { 4300245431Sdim SourceLocation loc = attr.getLoc(); 4301245431Sdim ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D); 4302245431Sdim 4303245431Sdim if (!method) { 4304245431Sdim S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) 4305245431Sdim << SourceRange(loc, loc) << attr.getName() << ExpectedMethod; 4306245431Sdim return; 4307245431Sdim } 4308245431Sdim DeclContext *DC = method->getDeclContext(); 4309245431Sdim if (const ObjCProtocolDecl *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) { 4310245431Sdim S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol) 4311245431Sdim << attr.getName() << 0; 4312245431Sdim S.Diag(PDecl->getLocation(), diag::note_protocol_decl); 4313245431Sdim return; 4314245431Sdim } 4315245431Sdim if (method->getMethodFamily() == OMF_dealloc) { 4316245431Sdim S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol) 4317245431Sdim << attr.getName() << 1; 4318245431Sdim return; 4319245431Sdim } 4320245431Sdim 4321252723Sdim method->addAttr(::new (S.Context) 4322252723Sdim ObjCRequiresSuperAttr(attr.getRange(), S.Context, 4323252723Sdim attr.getAttributeSpellingListIndex())); 4324245431Sdim} 4325245431Sdim 4326226890Sdim/// Handle cf_audited_transfer and cf_unknown_transfer. 4327226890Sdimstatic void handleCFTransferAttr(Sema &S, Decl *D, const AttributeList &A) { 4328226890Sdim if (!isa<FunctionDecl>(D)) { 4329226890Sdim S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) 4330235633Sdim << A.getRange() << A.getName() << ExpectedFunction; 4331226890Sdim return; 4332226890Sdim } 4333226890Sdim 4334245431Sdim bool IsAudited = (A.getKind() == AttributeList::AT_CFAuditedTransfer); 4335226890Sdim 4336226890Sdim // Check whether there's a conflicting attribute already present. 4337226890Sdim Attr *Existing; 4338226890Sdim if (IsAudited) { 4339226890Sdim Existing = D->getAttr<CFUnknownTransferAttr>(); 4340226890Sdim } else { 4341226890Sdim Existing = D->getAttr<CFAuditedTransferAttr>(); 4342226890Sdim } 4343226890Sdim if (Existing) { 4344226890Sdim S.Diag(D->getLocStart(), diag::err_attributes_are_not_compatible) 4345226890Sdim << A.getName() 4346226890Sdim << (IsAudited ? "cf_unknown_transfer" : "cf_audited_transfer") 4347226890Sdim << A.getRange() << Existing->getRange(); 4348226890Sdim return; 4349226890Sdim } 4350226890Sdim 4351226890Sdim // All clear; add the attribute. 4352226890Sdim if (IsAudited) { 4353252723Sdim D->addAttr(::new (S.Context) 4354252723Sdim CFAuditedTransferAttr(A.getRange(), S.Context, 4355252723Sdim A.getAttributeSpellingListIndex())); 4356226890Sdim } else { 4357252723Sdim D->addAttr(::new (S.Context) 4358252723Sdim CFUnknownTransferAttr(A.getRange(), S.Context, 4359252723Sdim A.getAttributeSpellingListIndex())); 4360226890Sdim } 4361226890Sdim} 4362226890Sdim 4363226890Sdimstatic void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D, 4364226890Sdim const AttributeList &Attr) { 4365226890Sdim RecordDecl *RD = dyn_cast<RecordDecl>(D); 4366226890Sdim if (!RD || RD->isUnion()) { 4367226890Sdim S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) 4368235633Sdim << Attr.getRange() << Attr.getName() << ExpectedStruct; 4369226890Sdim } 4370226890Sdim 4371263509Sdim IdentifierLoc *Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0; 4372226890Sdim 4373226890Sdim // In Objective-C, verify that the type names an Objective-C type. 4374226890Sdim // We don't want to check this outside of ObjC because people sometimes 4375226890Sdim // do crazy C declarations of Objective-C types. 4376263509Sdim if (Parm && S.getLangOpts().ObjC1) { 4377226890Sdim // Check for an existing type with this name. 4378263509Sdim LookupResult R(S, DeclarationName(Parm->Ident), Parm->Loc, 4379226890Sdim Sema::LookupOrdinaryName); 4380226890Sdim if (S.LookupName(R, Sc)) { 4381226890Sdim NamedDecl *Target = R.getFoundDecl(); 4382226890Sdim if (Target && !isa<ObjCInterfaceDecl>(Target)) { 4383226890Sdim S.Diag(D->getLocStart(), diag::err_ns_bridged_not_interface); 4384226890Sdim S.Diag(Target->getLocStart(), diag::note_declared_at); 4385226890Sdim } 4386226890Sdim } 4387226890Sdim } 4388226890Sdim 4389252723Sdim D->addAttr(::new (S.Context) 4390263509Sdim NSBridgedAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0, 4391252723Sdim Attr.getAttributeSpellingListIndex())); 4392226890Sdim} 4393226890Sdim 4394263509Sdimstatic void handleObjCBridgeAttr(Sema &S, Scope *Sc, Decl *D, 4395263509Sdim const AttributeList &Attr) { 4396263509Sdim if (!isa<RecordDecl>(D)) { 4397263509Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 4398263509Sdim << Attr.getName() 4399263509Sdim << (S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass 4400263509Sdim : ExpectedStructOrUnion); 4401263509Sdim return; 4402263509Sdim } 4403263509Sdim 4404263509Sdim if (Attr.getNumArgs() != 1) { 4405263509Sdim S.Diag(D->getLocStart(), diag::err_objc_bridge_not_id); 4406263509Sdim return; 4407263509Sdim } 4408263509Sdim IdentifierLoc *Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0; 4409263509Sdim if (!Parm) { 4410263509Sdim S.Diag(D->getLocStart(), diag::err_objc_bridge_not_id); 4411263509Sdim return; 4412263509Sdim } 4413263509Sdim 4414263509Sdim D->addAttr(::new (S.Context) 4415263509Sdim ObjCBridgeAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0, 4416263509Sdim Attr.getAttributeSpellingListIndex())); 4417263509Sdim} 4418263509Sdim 4419224145Sdimstatic void handleObjCOwnershipAttr(Sema &S, Decl *D, 4420224145Sdim const AttributeList &Attr) { 4421224145Sdim if (hasDeclarator(D)) return; 4422224145Sdim 4423224145Sdim S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) 4424235633Sdim << Attr.getRange() << Attr.getName() << ExpectedVariable; 4425224145Sdim} 4426224145Sdim 4427224145Sdimstatic void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, 4428224145Sdim const AttributeList &Attr) { 4429224145Sdim if (!isa<VarDecl>(D) && !isa<FieldDecl>(D)) { 4430224145Sdim S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) 4431235633Sdim << Attr.getRange() << Attr.getName() << ExpectedVariable; 4432224145Sdim return; 4433224145Sdim } 4434224145Sdim 4435224145Sdim ValueDecl *vd = cast<ValueDecl>(D); 4436224145Sdim QualType type = vd->getType(); 4437224145Sdim 4438224145Sdim if (!type->isDependentType() && 4439224145Sdim !type->isObjCLifetimeType()) { 4440224145Sdim S.Diag(Attr.getLoc(), diag::err_objc_precise_lifetime_bad_type) 4441224145Sdim << type; 4442224145Sdim return; 4443224145Sdim } 4444224145Sdim 4445224145Sdim Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime(); 4446224145Sdim 4447224145Sdim // If we have no lifetime yet, check the lifetime we're presumably 4448224145Sdim // going to infer. 4449224145Sdim if (lifetime == Qualifiers::OCL_None && !type->isDependentType()) 4450224145Sdim lifetime = type->getObjCARCImplicitLifetime(); 4451224145Sdim 4452224145Sdim switch (lifetime) { 4453224145Sdim case Qualifiers::OCL_None: 4454224145Sdim assert(type->isDependentType() && 4455224145Sdim "didn't infer lifetime for non-dependent type?"); 4456224145Sdim break; 4457224145Sdim 4458224145Sdim case Qualifiers::OCL_Weak: // meaningful 4459224145Sdim case Qualifiers::OCL_Strong: // meaningful 4460224145Sdim break; 4461224145Sdim 4462224145Sdim case Qualifiers::OCL_ExplicitNone: 4463224145Sdim case Qualifiers::OCL_Autoreleasing: 4464224145Sdim S.Diag(Attr.getLoc(), diag::warn_objc_precise_lifetime_meaningless) 4465224145Sdim << (lifetime == Qualifiers::OCL_Autoreleasing); 4466224145Sdim break; 4467224145Sdim } 4468224145Sdim 4469224145Sdim D->addAttr(::new (S.Context) 4470252723Sdim ObjCPreciseLifetimeAttr(Attr.getRange(), S.Context, 4471252723Sdim Attr.getAttributeSpellingListIndex())); 4472224145Sdim} 4473224145Sdim 4474193326Sed//===----------------------------------------------------------------------===// 4475218893Sdim// Microsoft specific attribute handlers. 4476218893Sdim//===----------------------------------------------------------------------===// 4477218893Sdim 4478263509Sdim// Check if MS extensions or some other language extensions are enabled. If 4479263509Sdim// not, issue a diagnostic that the given attribute is unused. 4480263509Sdimstatic bool checkMicrosoftExt(Sema &S, const AttributeList &Attr, 4481263509Sdim bool OtherExtension = false) { 4482263509Sdim if (S.LangOpts.MicrosoftExt || OtherExtension) 4483263509Sdim return true; 4484263509Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 4485263509Sdim return false; 4486263509Sdim} 4487263509Sdim 4488224145Sdimstatic void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { 4489263509Sdim if (!checkMicrosoftExt(S, Attr, S.LangOpts.Borland)) 4490263509Sdim return; 4491224145Sdim 4492263509Sdim StringRef StrRef; 4493263509Sdim SourceLocation LiteralLoc; 4494263509Sdim if (!S.checkStringLiteralArgumentAttr(Attr, 0, StrRef, &LiteralLoc)) 4495263509Sdim return; 4496218893Sdim 4497263509Sdim // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or 4498263509Sdim // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}", normalize to the former. 4499263509Sdim if (StrRef.size() == 38 && StrRef.front() == '{' && StrRef.back() == '}') 4500263509Sdim StrRef = StrRef.drop_front().drop_back(); 4501218893Sdim 4502263509Sdim // Validate GUID length. 4503263509Sdim if (StrRef.size() != 36) { 4504263509Sdim S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); 4505263509Sdim return; 4506263509Sdim } 4507235633Sdim 4508263509Sdim for (unsigned i = 0; i < 36; ++i) { 4509263509Sdim if (i == 8 || i == 13 || i == 18 || i == 23) { 4510263509Sdim if (StrRef[i] != '-') { 4511263509Sdim S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); 4512218893Sdim return; 4513218893Sdim } 4514263509Sdim } else if (!isHexDigit(StrRef[i])) { 4515263509Sdim S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); 4516263509Sdim return; 4517218893Sdim } 4518263509Sdim } 4519218893Sdim 4520263509Sdim D->addAttr(::new (S.Context) UuidAttr(Attr.getRange(), S.Context, StrRef, 4521263509Sdim Attr.getAttributeSpellingListIndex())); 4522218893Sdim} 4523218893Sdim 4524245431Sdimstatic void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) { 4525263509Sdim if (!checkMicrosoftExt(S, Attr)) 4526245431Sdim return; 4527245431Sdim 4528245431Sdim AttributeList::Kind Kind = Attr.getKind(); 4529245431Sdim if (Kind == AttributeList::AT_SingleInheritance) 4530245431Sdim D->addAttr( 4531252723Sdim ::new (S.Context) 4532252723Sdim SingleInheritanceAttr(Attr.getRange(), S.Context, 4533252723Sdim Attr.getAttributeSpellingListIndex())); 4534245431Sdim else if (Kind == AttributeList::AT_MultipleInheritance) 4535245431Sdim D->addAttr( 4536252723Sdim ::new (S.Context) 4537252723Sdim MultipleInheritanceAttr(Attr.getRange(), S.Context, 4538252723Sdim Attr.getAttributeSpellingListIndex())); 4539245431Sdim else if (Kind == AttributeList::AT_VirtualInheritance) 4540245431Sdim D->addAttr( 4541252723Sdim ::new (S.Context) 4542252723Sdim VirtualInheritanceAttr(Attr.getRange(), S.Context, 4543252723Sdim Attr.getAttributeSpellingListIndex())); 4544245431Sdim} 4545245431Sdim 4546245431Sdimstatic void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { 4547263509Sdim if (!checkMicrosoftExt(S, Attr)) 4548263509Sdim return; 4549263509Sdim 4550263509Sdim AttributeList::Kind Kind = Attr.getKind(); 4551263509Sdim if (Kind == AttributeList::AT_Win64) 4552263509Sdim D->addAttr( 4553263509Sdim ::new (S.Context) Win64Attr(Attr.getRange(), S.Context, 4554263509Sdim Attr.getAttributeSpellingListIndex())); 4555245431Sdim} 4556245431Sdim 4557245431Sdimstatic void handleForceInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { 4558263509Sdim if (!checkMicrosoftExt(S, Attr)) 4559263509Sdim return; 4560263509Sdim D->addAttr(::new (S.Context) 4561263509Sdim ForceInlineAttr(Attr.getRange(), S.Context, 4562263509Sdim Attr.getAttributeSpellingListIndex())); 4563245431Sdim} 4564245431Sdim 4565263509Sdimstatic void handleSelectAnyAttr(Sema &S, Decl *D, const AttributeList &Attr) { 4566263509Sdim if (!checkMicrosoftExt(S, Attr)) 4567263509Sdim return; 4568263509Sdim // Check linkage after possibly merging declaratinos. See 4569263509Sdim // checkAttributesAfterMerging(). 4570263509Sdim D->addAttr(::new (S.Context) 4571263509Sdim SelectAnyAttr(Attr.getRange(), S.Context, 4572263509Sdim Attr.getAttributeSpellingListIndex())); 4573263509Sdim} 4574263509Sdim 4575263509Sdim/// Handles semantic checking for features that are common to all attributes, 4576263509Sdim/// such as checking whether a parameter was properly specified, or the correct 4577263509Sdim/// number of arguments were passed, etc. 4578263509Sdimstatic bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D, 4579263509Sdim const AttributeList &Attr) { 4580263509Sdim // Several attributes carry different semantics than the parsing requires, so 4581263509Sdim // those are opted out of the common handling. 4582263509Sdim // 4583263509Sdim // We also bail on unknown and ignored attributes because those are handled 4584263509Sdim // as part of the target-specific handling logic. 4585263509Sdim if (Attr.hasCustomParsing() || 4586263509Sdim Attr.getKind() == AttributeList::UnknownAttribute || 4587263509Sdim Attr.getKind() == AttributeList::IgnoredAttribute) 4588263509Sdim return false; 4589263509Sdim 4590263509Sdim // If there are no optional arguments, then checking for the argument count 4591263509Sdim // is trivial. 4592263509Sdim if (Attr.getMinArgs() == Attr.getMaxArgs() && 4593263509Sdim !checkAttributeNumArgs(S, Attr, Attr.getMinArgs())) 4594263509Sdim return true; 4595263509Sdim return false; 4596263509Sdim} 4597263509Sdim 4598218893Sdim//===----------------------------------------------------------------------===// 4599193326Sed// Top Level Sema Entry Points 4600193326Sed//===----------------------------------------------------------------------===// 4601193326Sed 4602263509Sdim/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if 4603263509Sdim/// the attribute applies to decls. If the attribute is a type attribute, just 4604263509Sdim/// silently ignore it if a GNU attribute. 4605263509Sdimstatic void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, 4606263509Sdim const AttributeList &Attr, 4607263509Sdim bool IncludeCXX11Attributes) { 4608263509Sdim if (Attr.isInvalid()) 4609263509Sdim return; 4610207619Srdivacky 4611263509Sdim // Ignore C++11 attributes on declarator chunks: they appertain to the type 4612263509Sdim // instead. 4613263509Sdim if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes) 4614263509Sdim return; 4615263509Sdim 4616263509Sdim if (handleCommonAttributeFeatures(S, scope, D, Attr)) 4617263509Sdim return; 4618263509Sdim 4619193326Sed switch (Attr.getKind()) { 4620252723Sdim case AttributeList::AT_IBAction: handleIBAction(S, D, Attr); break; 4621252723Sdim case AttributeList::AT_IBOutlet: handleIBOutlet(S, D, Attr); break; 4622252723Sdim case AttributeList::AT_IBOutletCollection: 4623252723Sdim handleIBOutletCollection(S, D, Attr); break; 4624245431Sdim case AttributeList::AT_AddressSpace: 4625245431Sdim case AttributeList::AT_ObjCGC: 4626245431Sdim case AttributeList::AT_VectorSize: 4627245431Sdim case AttributeList::AT_NeonVectorType: 4628245431Sdim case AttributeList::AT_NeonPolyVectorType: 4629263509Sdim case AttributeList::AT_Ptr32: 4630263509Sdim case AttributeList::AT_Ptr64: 4631263509Sdim case AttributeList::AT_SPtr: 4632263509Sdim case AttributeList::AT_UPtr: 4633198092Srdivacky // Ignore these, these are type attributes, handled by 4634198092Srdivacky // ProcessTypeAttributes. 4635193326Sed break; 4636245431Sdim case AttributeList::AT_Alias: handleAliasAttr (S, D, Attr); break; 4637245431Sdim case AttributeList::AT_Aligned: handleAlignedAttr (S, D, Attr); break; 4638245431Sdim case AttributeList::AT_AllocSize: handleAllocSizeAttr (S, D, Attr); break; 4639245431Sdim case AttributeList::AT_AlwaysInline: 4640224145Sdim handleAlwaysInlineAttr (S, D, Attr); break; 4641245431Sdim case AttributeList::AT_AnalyzerNoReturn: 4642224145Sdim handleAnalyzerNoReturnAttr (S, D, Attr); break; 4643245431Sdim case AttributeList::AT_TLSModel: handleTLSModelAttr (S, D, Attr); break; 4644245431Sdim case AttributeList::AT_Annotate: handleAnnotateAttr (S, D, Attr); break; 4645245431Sdim case AttributeList::AT_Availability:handleAvailabilityAttr(S, D, Attr); break; 4646245431Sdim case AttributeList::AT_CarriesDependency: 4647252723Sdim handleDependencyAttr(S, scope, D, Attr); 4648252723Sdim break; 4649245431Sdim case AttributeList::AT_Common: handleCommonAttr (S, D, Attr); break; 4650245431Sdim case AttributeList::AT_CUDAConstant:handleConstantAttr (S, D, Attr); break; 4651245431Sdim case AttributeList::AT_Constructor: handleConstructorAttr (S, D, Attr); break; 4652252723Sdim case AttributeList::AT_CXX11NoReturn: 4653252723Sdim handleCXX11NoReturnAttr(S, D, Attr); 4654252723Sdim break; 4655245431Sdim case AttributeList::AT_Deprecated: 4656263509Sdim handleAttrWithMessage<DeprecatedAttr>(S, D, Attr); 4657245431Sdim break; 4658245431Sdim case AttributeList::AT_Destructor: handleDestructorAttr (S, D, Attr); break; 4659245431Sdim case AttributeList::AT_ExtVectorType: 4660224145Sdim handleExtVectorTypeAttr(S, scope, D, Attr); 4661193326Sed break; 4662245431Sdim case AttributeList::AT_MinSize: 4663245431Sdim handleMinSizeAttr(S, D, Attr); 4664245431Sdim break; 4665245431Sdim case AttributeList::AT_Format: handleFormatAttr (S, D, Attr); break; 4666245431Sdim case AttributeList::AT_FormatArg: handleFormatArgAttr (S, D, Attr); break; 4667245431Sdim case AttributeList::AT_CUDAGlobal: handleGlobalAttr (S, D, Attr); break; 4668263509Sdim case AttributeList::AT_CUDADevice: handleDeviceAttr (S, D, Attr); break; 4669263509Sdim case AttributeList::AT_CUDAHost: handleHostAttr (S, D, Attr); break; 4670245431Sdim case AttributeList::AT_GNUInline: handleGNUInlineAttr (S, D, Attr); break; 4671245431Sdim case AttributeList::AT_CUDALaunchBounds: 4672224145Sdim handleLaunchBoundsAttr(S, D, Attr); 4673218893Sdim break; 4674245431Sdim case AttributeList::AT_Malloc: handleMallocAttr (S, D, Attr); break; 4675245431Sdim case AttributeList::AT_MayAlias: handleMayAliasAttr (S, D, Attr); break; 4676263509Sdim case AttributeList::AT_Mode: handleModeAttr (S, D, Attr); break; 4677245431Sdim case AttributeList::AT_NoCommon: handleNoCommonAttr (S, D, Attr); break; 4678245431Sdim case AttributeList::AT_NonNull: handleNonNullAttr (S, D, Attr); break; 4679263509Sdim case AttributeList::AT_Overloadable:handleOverloadableAttr(S, D, Attr); break; 4680212904Sdim case AttributeList::AT_ownership_returns: 4681212904Sdim case AttributeList::AT_ownership_takes: 4682212904Sdim case AttributeList::AT_ownership_holds: 4683224145Sdim handleOwnershipAttr (S, D, Attr); break; 4684245431Sdim case AttributeList::AT_Cold: handleColdAttr (S, D, Attr); break; 4685245431Sdim case AttributeList::AT_Hot: handleHotAttr (S, D, Attr); break; 4686245431Sdim case AttributeList::AT_Naked: handleNakedAttr (S, D, Attr); break; 4687245431Sdim case AttributeList::AT_NoReturn: handleNoReturnAttr (S, D, Attr); break; 4688245431Sdim case AttributeList::AT_NoThrow: handleNothrowAttr (S, D, Attr); break; 4689245431Sdim case AttributeList::AT_CUDAShared: handleSharedAttr (S, D, Attr); break; 4690245431Sdim case AttributeList::AT_VecReturn: handleVecReturnAttr (S, D, Attr); break; 4691193326Sed 4692245431Sdim case AttributeList::AT_ObjCOwnership: 4693224145Sdim handleObjCOwnershipAttr(S, D, Attr); break; 4694245431Sdim case AttributeList::AT_ObjCPreciseLifetime: 4695224145Sdim handleObjCPreciseLifetimeAttr(S, D, Attr); break; 4696224145Sdim 4697245431Sdim case AttributeList::AT_ObjCReturnsInnerPointer: 4698226890Sdim handleObjCReturnsInnerPointerAttr(S, D, Attr); break; 4699226890Sdim 4700245431Sdim case AttributeList::AT_ObjCRequiresSuper: 4701245431Sdim handleObjCRequiresSuperAttr(S, D, Attr); break; 4702245431Sdim 4703245431Sdim case AttributeList::AT_NSBridged: 4704226890Sdim handleNSBridgedAttr(S, scope, D, Attr); break; 4705263509Sdim 4706263509Sdim case AttributeList::AT_ObjCBridge: 4707263509Sdim handleObjCBridgeAttr(S, scope, D, Attr); break; 4708226890Sdim 4709245431Sdim case AttributeList::AT_CFAuditedTransfer: 4710245431Sdim case AttributeList::AT_CFUnknownTransfer: 4711226890Sdim handleCFTransferAttr(S, D, Attr); break; 4712226890Sdim 4713193326Sed // Checker-specific. 4714245431Sdim case AttributeList::AT_CFConsumed: 4715245431Sdim case AttributeList::AT_NSConsumed: handleNSConsumedAttr (S, D, Attr); break; 4716245431Sdim case AttributeList::AT_NSConsumesSelf: 4717224145Sdim handleNSConsumesSelfAttr(S, D, Attr); break; 4718218893Sdim 4719245431Sdim case AttributeList::AT_NSReturnsAutoreleased: 4720245431Sdim case AttributeList::AT_NSReturnsNotRetained: 4721245431Sdim case AttributeList::AT_CFReturnsNotRetained: 4722245431Sdim case AttributeList::AT_NSReturnsRetained: 4723245431Sdim case AttributeList::AT_CFReturnsRetained: 4724224145Sdim handleNSReturnsRetainedAttr(S, D, Attr); break; 4725193326Sed 4726245431Sdim case AttributeList::AT_WorkGroupSizeHint: 4727245431Sdim case AttributeList::AT_ReqdWorkGroupSize: 4728245431Sdim handleWorkGroupSize(S, D, Attr); break; 4729195099Sed 4730252723Sdim case AttributeList::AT_VecTypeHint: 4731252723Sdim handleVecTypeHint(S, D, Attr); break; 4732252723Sdim 4733245431Sdim case AttributeList::AT_InitPriority: 4734224145Sdim handleInitPriorityAttr(S, D, Attr); break; 4735210299Sed 4736245431Sdim case AttributeList::AT_Packed: handlePackedAttr (S, D, Attr); break; 4737245431Sdim case AttributeList::AT_Section: handleSectionAttr (S, D, Attr); break; 4738245431Sdim case AttributeList::AT_Unavailable: 4739263509Sdim handleAttrWithMessage<UnavailableAttr>(S, D, Attr); 4740245431Sdim break; 4741245431Sdim case AttributeList::AT_ArcWeakrefUnavailable: 4742224145Sdim handleArcWeakrefUnavailableAttr (S, D, Attr); 4743193326Sed break; 4744245431Sdim case AttributeList::AT_ObjCRootClass: 4745235633Sdim handleObjCRootClassAttr(S, D, Attr); 4746235633Sdim break; 4747245431Sdim case AttributeList::AT_ObjCRequiresPropertyDefs: 4748235633Sdim handleObjCRequiresPropertyDefsAttr (S, D, Attr); 4749235633Sdim break; 4750245431Sdim case AttributeList::AT_Unused: handleUnusedAttr (S, D, Attr); break; 4751245431Sdim case AttributeList::AT_ReturnsTwice: 4752226890Sdim handleReturnsTwiceAttr(S, D, Attr); 4753226890Sdim break; 4754245431Sdim case AttributeList::AT_Used: handleUsedAttr (S, D, Attr); break; 4755252723Sdim case AttributeList::AT_Visibility: 4756252723Sdim handleVisibilityAttr(S, D, Attr, false); 4757252723Sdim break; 4758252723Sdim case AttributeList::AT_TypeVisibility: 4759252723Sdim handleVisibilityAttr(S, D, Attr, true); 4760252723Sdim break; 4761263509Sdim case AttributeList::AT_WarnUnused: 4762263509Sdim handleWarnUnusedAttr(S, D, Attr); 4763263509Sdim break; 4764245431Sdim case AttributeList::AT_WarnUnusedResult: handleWarnUnusedResult(S, D, Attr); 4765224145Sdim break; 4766245431Sdim case AttributeList::AT_Weak: handleWeakAttr (S, D, Attr); break; 4767245431Sdim case AttributeList::AT_WeakRef: handleWeakRefAttr (S, D, Attr); break; 4768245431Sdim case AttributeList::AT_WeakImport: handleWeakImportAttr (S, D, Attr); break; 4769245431Sdim case AttributeList::AT_TransparentUnion: 4770224145Sdim handleTransparentUnionAttr(S, D, Attr); 4771193326Sed break; 4772245431Sdim case AttributeList::AT_ObjCException: 4773224145Sdim handleObjCExceptionAttr(S, D, Attr); 4774193326Sed break; 4775245431Sdim case AttributeList::AT_ObjCMethodFamily: 4776224145Sdim handleObjCMethodFamilyAttr(S, D, Attr); 4777221345Sdim break; 4778245431Sdim case AttributeList::AT_ObjCNSObject:handleObjCNSObject (S, D, Attr); break; 4779245431Sdim case AttributeList::AT_Blocks: handleBlocksAttr (S, D, Attr); break; 4780245431Sdim case AttributeList::AT_Sentinel: handleSentinelAttr (S, D, Attr); break; 4781245431Sdim case AttributeList::AT_Const: handleConstAttr (S, D, Attr); break; 4782245431Sdim case AttributeList::AT_Pure: handlePureAttr (S, D, Attr); break; 4783245431Sdim case AttributeList::AT_Cleanup: handleCleanupAttr (S, D, Attr); break; 4784245431Sdim case AttributeList::AT_NoDebug: handleNoDebugAttr (S, D, Attr); break; 4785245431Sdim case AttributeList::AT_NoInline: handleNoInlineAttr (S, D, Attr); break; 4786245431Sdim case AttributeList::AT_Regparm: handleRegparmAttr (S, D, Attr); break; 4787198092Srdivacky case AttributeList::IgnoredAttribute: 4788193326Sed // Just ignore 4789193326Sed break; 4790245431Sdim case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg. 4791224145Sdim handleNoInstrumentFunctionAttr(S, D, Attr); 4792210299Sed break; 4793245431Sdim case AttributeList::AT_StdCall: 4794245431Sdim case AttributeList::AT_CDecl: 4795245431Sdim case AttributeList::AT_FastCall: 4796245431Sdim case AttributeList::AT_ThisCall: 4797245431Sdim case AttributeList::AT_Pascal: 4798256382Sdim case AttributeList::AT_MSABI: 4799256382Sdim case AttributeList::AT_SysVABI: 4800245431Sdim case AttributeList::AT_Pcs: 4801245431Sdim case AttributeList::AT_PnaclCall: 4802252723Sdim case AttributeList::AT_IntelOclBicc: 4803224145Sdim handleCallConvAttr(S, D, Attr); 4804203955Srdivacky break; 4805245431Sdim case AttributeList::AT_OpenCLKernel: 4806224145Sdim handleOpenCLKernelAttr(S, D, Attr); 4807218893Sdim break; 4808252723Sdim case AttributeList::AT_OpenCLImageAccess: 4809252723Sdim handleOpenCLImageAccessAttr(S, D, Attr); 4810252723Sdim break; 4811245431Sdim 4812245431Sdim // Microsoft attributes: 4813245431Sdim case AttributeList::AT_MsStruct: 4814245431Sdim handleMsStructAttr(S, D, Attr); 4815245431Sdim break; 4816245431Sdim case AttributeList::AT_Uuid: 4817224145Sdim handleUuidAttr(S, D, Attr); 4818218893Sdim break; 4819245431Sdim case AttributeList::AT_SingleInheritance: 4820245431Sdim case AttributeList::AT_MultipleInheritance: 4821245431Sdim case AttributeList::AT_VirtualInheritance: 4822245431Sdim handleInheritanceAttr(S, D, Attr); 4823245431Sdim break; 4824245431Sdim case AttributeList::AT_Win64: 4825245431Sdim handlePortabilityAttr(S, D, Attr); 4826245431Sdim break; 4827245431Sdim case AttributeList::AT_ForceInline: 4828245431Sdim handleForceInlineAttr(S, D, Attr); 4829245431Sdim break; 4830263509Sdim case AttributeList::AT_SelectAny: 4831263509Sdim handleSelectAnyAttr(S, D, Attr); 4832263509Sdim break; 4833226890Sdim 4834226890Sdim // Thread safety attributes: 4835263509Sdim case AttributeList::AT_AssertExclusiveLock: 4836263509Sdim handleAssertExclusiveLockAttr(S, D, Attr); 4837263509Sdim break; 4838263509Sdim case AttributeList::AT_AssertSharedLock: 4839263509Sdim handleAssertSharedLockAttr(S, D, Attr); 4840263509Sdim break; 4841245431Sdim case AttributeList::AT_GuardedVar: 4842226890Sdim handleGuardedVarAttr(S, D, Attr); 4843226890Sdim break; 4844245431Sdim case AttributeList::AT_PtGuardedVar: 4845245431Sdim handlePtGuardedVarAttr(S, D, Attr); 4846226890Sdim break; 4847245431Sdim case AttributeList::AT_ScopedLockable: 4848245431Sdim handleScopedLockableAttr(S, D, Attr); 4849226890Sdim break; 4850252723Sdim case AttributeList::AT_NoSanitizeAddress: 4851252723Sdim handleNoSanitizeAddressAttr(S, D, Attr); 4852235633Sdim break; 4853245431Sdim case AttributeList::AT_NoThreadSafetyAnalysis: 4854252723Sdim handleNoThreadSafetyAnalysis(S, D, Attr); 4855226890Sdim break; 4856252723Sdim case AttributeList::AT_NoSanitizeThread: 4857252723Sdim handleNoSanitizeThread(S, D, Attr); 4858252723Sdim break; 4859252723Sdim case AttributeList::AT_NoSanitizeMemory: 4860252723Sdim handleNoSanitizeMemory(S, D, Attr); 4861252723Sdim break; 4862245431Sdim case AttributeList::AT_Lockable: 4863226890Sdim handleLockableAttr(S, D, Attr); 4864226890Sdim break; 4865245431Sdim case AttributeList::AT_GuardedBy: 4866226890Sdim handleGuardedByAttr(S, D, Attr); 4867226890Sdim break; 4868245431Sdim case AttributeList::AT_PtGuardedBy: 4869245431Sdim handlePtGuardedByAttr(S, D, Attr); 4870226890Sdim break; 4871245431Sdim case AttributeList::AT_ExclusiveLockFunction: 4872245431Sdim handleExclusiveLockFunctionAttr(S, D, Attr); 4873226890Sdim break; 4874245431Sdim case AttributeList::AT_ExclusiveLocksRequired: 4875245431Sdim handleExclusiveLocksRequiredAttr(S, D, Attr); 4876226890Sdim break; 4877245431Sdim case AttributeList::AT_ExclusiveTrylockFunction: 4878245431Sdim handleExclusiveTrylockFunctionAttr(S, D, Attr); 4879226890Sdim break; 4880245431Sdim case AttributeList::AT_LockReturned: 4881226890Sdim handleLockReturnedAttr(S, D, Attr); 4882226890Sdim break; 4883245431Sdim case AttributeList::AT_LocksExcluded: 4884226890Sdim handleLocksExcludedAttr(S, D, Attr); 4885226890Sdim break; 4886245431Sdim case AttributeList::AT_SharedLockFunction: 4887245431Sdim handleSharedLockFunctionAttr(S, D, Attr); 4888226890Sdim break; 4889245431Sdim case AttributeList::AT_SharedLocksRequired: 4890245431Sdim handleSharedLocksRequiredAttr(S, D, Attr); 4891226890Sdim break; 4892245431Sdim case AttributeList::AT_SharedTrylockFunction: 4893245431Sdim handleSharedTrylockFunctionAttr(S, D, Attr); 4894226890Sdim break; 4895245431Sdim case AttributeList::AT_UnlockFunction: 4896226890Sdim handleUnlockFunAttr(S, D, Attr); 4897226890Sdim break; 4898245431Sdim case AttributeList::AT_AcquiredBefore: 4899245431Sdim handleAcquiredBeforeAttr(S, D, Attr); 4900226890Sdim break; 4901245431Sdim case AttributeList::AT_AcquiredAfter: 4902245431Sdim handleAcquiredAfterAttr(S, D, Attr); 4903226890Sdim break; 4904226890Sdim 4905263509Sdim // Consumed analysis attributes. 4906263509Sdim case AttributeList::AT_Consumable: 4907263509Sdim handleConsumableAttr(S, D, Attr); 4908263509Sdim break; 4909263509Sdim case AttributeList::AT_CallableWhen: 4910263509Sdim handleCallableWhenAttr(S, D, Attr); 4911263509Sdim break; 4912263509Sdim case AttributeList::AT_ParamTypestate: 4913263509Sdim handleParamTypestateAttr(S, D, Attr); 4914263509Sdim break; 4915263509Sdim case AttributeList::AT_ReturnTypestate: 4916263509Sdim handleReturnTypestateAttr(S, D, Attr); 4917263509Sdim break; 4918263509Sdim case AttributeList::AT_SetTypestate: 4919263509Sdim handleSetTypestateAttr(S, D, Attr); 4920263509Sdim break; 4921263509Sdim case AttributeList::AT_TestTypestate: 4922263509Sdim handleTestTypestateAttr(S, D, Attr); 4923263509Sdim break; 4924263509Sdim 4925245431Sdim // Type safety attributes. 4926245431Sdim case AttributeList::AT_ArgumentWithTypeTag: 4927245431Sdim handleArgumentWithTypeTagAttr(S, D, Attr); 4928245431Sdim break; 4929245431Sdim case AttributeList::AT_TypeTagForDatatype: 4930245431Sdim handleTypeTagForDatatypeAttr(S, D, Attr); 4931245431Sdim break; 4932245431Sdim 4933193326Sed default: 4934202379Srdivacky // Ask target about the attribute. 4935202379Srdivacky const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema(); 4936202379Srdivacky if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S)) 4937245431Sdim S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute() ? 4938245431Sdim diag::warn_unhandled_ms_attribute_ignored : 4939245431Sdim diag::warn_unknown_attribute_ignored) << Attr.getName(); 4940193326Sed break; 4941193326Sed } 4942193326Sed} 4943193326Sed 4944193326Sed/// ProcessDeclAttributeList - Apply all the decl attributes in the specified 4945193326Sed/// attribute list to the specified decl, ignoring any type attributes. 4946218893Sdimvoid Sema::ProcessDeclAttributeList(Scope *S, Decl *D, 4947218893Sdim const AttributeList *AttrList, 4948252723Sdim bool IncludeCXX11Attributes) { 4949252723Sdim for (const AttributeList* l = AttrList; l; l = l->getNext()) 4950263509Sdim ProcessDeclAttribute(*this, S, D, *l, IncludeCXX11Attributes); 4951204643Srdivacky 4952204643Srdivacky // GCC accepts 4953204643Srdivacky // static int a9 __attribute__((weakref)); 4954204643Srdivacky // but that looks really pointless. We reject it. 4955263509Sdim if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) { 4956204643Srdivacky Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) << 4957252723Sdim cast<NamedDecl>(D)->getNameAsString(); 4958252723Sdim D->dropAttr<WeakRefAttr>(); 4959204643Srdivacky return; 4960204643Srdivacky } 4961193326Sed} 4962193326Sed 4963226890Sdim// Annotation attributes are the only attributes allowed after an access 4964226890Sdim// specifier. 4965226890Sdimbool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, 4966226890Sdim const AttributeList *AttrList) { 4967226890Sdim for (const AttributeList* l = AttrList; l; l = l->getNext()) { 4968245431Sdim if (l->getKind() == AttributeList::AT_Annotate) { 4969226890Sdim handleAnnotateAttr(*this, ASDecl, *l); 4970226890Sdim } else { 4971226890Sdim Diag(l->getLoc(), diag::err_only_annotate_after_access_spec); 4972226890Sdim return true; 4973226890Sdim } 4974226890Sdim } 4975226890Sdim 4976226890Sdim return false; 4977226890Sdim} 4978226890Sdim 4979226890Sdim/// checkUnusedDeclAttributes - Check a list of attributes to see if it 4980226890Sdim/// contains any decl attributes that we should warn about. 4981226890Sdimstatic void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) { 4982226890Sdim for ( ; A; A = A->getNext()) { 4983226890Sdim // Only warn if the attribute is an unignored, non-type attribute. 4984252723Sdim if (A->isUsedAsTypeAttr() || A->isInvalid()) continue; 4985226890Sdim if (A->getKind() == AttributeList::IgnoredAttribute) continue; 4986226890Sdim 4987226890Sdim if (A->getKind() == AttributeList::UnknownAttribute) { 4988226890Sdim S.Diag(A->getLoc(), diag::warn_unknown_attribute_ignored) 4989226890Sdim << A->getName() << A->getRange(); 4990226890Sdim } else { 4991226890Sdim S.Diag(A->getLoc(), diag::warn_attribute_not_on_decl) 4992226890Sdim << A->getName() << A->getRange(); 4993226890Sdim } 4994226890Sdim } 4995226890Sdim} 4996226890Sdim 4997226890Sdim/// checkUnusedDeclAttributes - Given a declarator which is not being 4998226890Sdim/// used to build a declaration, complain about any decl attributes 4999226890Sdim/// which might be lying around on it. 5000226890Sdimvoid Sema::checkUnusedDeclAttributes(Declarator &D) { 5001226890Sdim ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes().getList()); 5002226890Sdim ::checkUnusedDeclAttributes(*this, D.getAttributes()); 5003226890Sdim for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) 5004226890Sdim ::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs()); 5005226890Sdim} 5006226890Sdim 5007198092Srdivacky/// DeclClonePragmaWeak - clone existing decl (maybe definition), 5008245431Sdim/// \#pragma weak needs a non-definition decl and source may not have one. 5009226890SdimNamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, 5010226890Sdim SourceLocation Loc) { 5011198092Srdivacky assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND)); 5012198092Srdivacky NamedDecl *NewD = 0; 5013198092Srdivacky if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { 5014226890Sdim FunctionDecl *NewFD; 5015226890Sdim // FIXME: Missing call to CheckFunctionDeclaration(). 5016226890Sdim // FIXME: Mangling? 5017226890Sdim // FIXME: Is the qualifier info correct? 5018226890Sdim // FIXME: Is the DeclContext correct? 5019226890Sdim NewFD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(), 5020226890Sdim Loc, Loc, DeclarationName(II), 5021226890Sdim FD->getType(), FD->getTypeSourceInfo(), 5022252723Sdim SC_None, false/*isInlineSpecified*/, 5023226890Sdim FD->hasPrototype(), 5024226890Sdim false/*isConstexprSpecified*/); 5025226890Sdim NewD = NewFD; 5026226890Sdim 5027226890Sdim if (FD->getQualifier()) 5028219077Sdim NewFD->setQualifierInfo(FD->getQualifierLoc()); 5029226890Sdim 5030226890Sdim // Fake up parameter variables; they are declared as if this were 5031226890Sdim // a typedef. 5032226890Sdim QualType FDTy = FD->getType(); 5033226890Sdim if (const FunctionProtoType *FT = FDTy->getAs<FunctionProtoType>()) { 5034226890Sdim SmallVector<ParmVarDecl*, 16> Params; 5035226890Sdim for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(), 5036226890Sdim AE = FT->arg_type_end(); AI != AE; ++AI) { 5037226890Sdim ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, *AI); 5038226890Sdim Param->setScopeInfo(0, Params.size()); 5039226890Sdim Params.push_back(Param); 5040226890Sdim } 5041226890Sdim NewFD->setParams(Params); 5042205219Srdivacky } 5043198092Srdivacky } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) { 5044198092Srdivacky NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(), 5045221345Sdim VD->getInnerLocStart(), VD->getLocation(), II, 5046200583Srdivacky VD->getType(), VD->getTypeSourceInfo(), 5047252723Sdim VD->getStorageClass()); 5048205219Srdivacky if (VD->getQualifier()) { 5049205219Srdivacky VarDecl *NewVD = cast<VarDecl>(NewD); 5050219077Sdim NewVD->setQualifierInfo(VD->getQualifierLoc()); 5051205219Srdivacky } 5052198092Srdivacky } 5053198092Srdivacky return NewD; 5054198092Srdivacky} 5055198092Srdivacky 5056245431Sdim/// DeclApplyPragmaWeak - A declaration (maybe definition) needs \#pragma weak 5057198092Srdivacky/// applied to it, possibly with an alias. 5058198092Srdivackyvoid Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) { 5059198092Srdivacky if (W.getUsed()) return; // only do this once 5060198092Srdivacky W.setUsed(true); 5061198092Srdivacky if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...)) 5062198092Srdivacky IdentifierInfo *NDId = ND->getIdentifier(); 5063226890Sdim NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation()); 5064212904Sdim NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context, 5065212904Sdim NDId->getName())); 5066212904Sdim NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context)); 5067198092Srdivacky WeakTopLevelDecl.push_back(NewD); 5068198092Srdivacky // FIXME: "hideous" code from Sema::LazilyCreateBuiltin 5069198092Srdivacky // to insert Decl at TU scope, sorry. 5070198092Srdivacky DeclContext *SavedContext = CurContext; 5071198092Srdivacky CurContext = Context.getTranslationUnitDecl(); 5072198092Srdivacky PushOnScopeChains(NewD, S); 5073198092Srdivacky CurContext = SavedContext; 5074198092Srdivacky } else { // just add weak to existing 5075212904Sdim ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context)); 5076198092Srdivacky } 5077198092Srdivacky} 5078198092Srdivacky 5079252723Sdimvoid Sema::ProcessPragmaWeak(Scope *S, Decl *D) { 5080218893Sdim // It's valid to "forward-declare" #pragma weak, in which case we 5081218893Sdim // have to do this. 5082252723Sdim LoadExternalWeakUndeclaredIdentifiers(); 5083252723Sdim if (!WeakUndeclaredIdentifiers.empty()) { 5084252723Sdim NamedDecl *ND = NULL; 5085252723Sdim if (VarDecl *VD = dyn_cast<VarDecl>(D)) 5086252723Sdim if (VD->isExternC()) 5087252723Sdim ND = VD; 5088252723Sdim if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 5089252723Sdim if (FD->isExternC()) 5090252723Sdim ND = FD; 5091252723Sdim if (ND) { 5092252723Sdim if (IdentifierInfo *Id = ND->getIdentifier()) { 5093252723Sdim llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I 5094252723Sdim = WeakUndeclaredIdentifiers.find(Id); 5095252723Sdim if (I != WeakUndeclaredIdentifiers.end()) { 5096252723Sdim WeakInfo W = I->second; 5097252723Sdim DeclApplyPragmaWeak(S, ND, W); 5098252723Sdim WeakUndeclaredIdentifiers[Id] = W; 5099218893Sdim } 5100198092Srdivacky } 5101198092Srdivacky } 5102198092Srdivacky } 5103252723Sdim} 5104198092Srdivacky 5105252723Sdim/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in 5106252723Sdim/// it, apply them to D. This is a bit tricky because PD can have attributes 5107252723Sdim/// specified in many different places, and we need to find and apply them all. 5108263509Sdimvoid Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { 5109193326Sed // Apply decl attributes from the DeclSpec if present. 5110218893Sdim if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList()) 5111263509Sdim ProcessDeclAttributeList(S, D, Attrs); 5112198092Srdivacky 5113193326Sed // Walk the declarator structure, applying decl attributes that were in a type 5114193326Sed // position to the decl itself. This handles cases like: 5115193326Sed // int *__attr__(x)** D; 5116193326Sed // when X is a decl attribute. 5117193326Sed for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) 5118193326Sed if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) 5119263509Sdim ProcessDeclAttributeList(S, D, Attrs, /*IncludeCXX11Attributes=*/false); 5120198092Srdivacky 5121193326Sed // Finally, apply any attributes on the decl itself. 5122193326Sed if (const AttributeList *Attrs = PD.getAttributes()) 5123263509Sdim ProcessDeclAttributeList(S, D, Attrs); 5124193326Sed} 5125198893Srdivacky 5126224145Sdim/// Is the given declaration allowed to use a forbidden type? 5127224145Sdimstatic bool isForbiddenTypeAllowed(Sema &S, Decl *decl) { 5128224145Sdim // Private ivars are always okay. Unfortunately, people don't 5129224145Sdim // always properly make their ivars private, even in system headers. 5130224145Sdim // Plus we need to make fields okay, too. 5131226890Sdim // Function declarations in sys headers will be marked unavailable. 5132226890Sdim if (!isa<FieldDecl>(decl) && !isa<ObjCPropertyDecl>(decl) && 5133226890Sdim !isa<FunctionDecl>(decl)) 5134224145Sdim return false; 5135224145Sdim 5136224145Sdim // Require it to be declared in a system header. 5137224145Sdim return S.Context.getSourceManager().isInSystemHeader(decl->getLocation()); 5138224145Sdim} 5139224145Sdim 5140224145Sdim/// Handle a delayed forbidden-type diagnostic. 5141224145Sdimstatic void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag, 5142224145Sdim Decl *decl) { 5143224145Sdim if (decl && isForbiddenTypeAllowed(S, decl)) { 5144224145Sdim decl->addAttr(new (S.Context) UnavailableAttr(diag.Loc, S.Context, 5145224145Sdim "this system declaration uses an unsupported type")); 5146224145Sdim return; 5147224145Sdim } 5148235633Sdim if (S.getLangOpts().ObjCAutoRefCount) 5149226890Sdim if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(decl)) { 5150245431Sdim // FIXME: we may want to suppress diagnostics for all 5151226890Sdim // kind of forbidden type messages on unavailable functions. 5152226890Sdim if (FD->hasAttr<UnavailableAttr>() && 5153226890Sdim diag.getForbiddenTypeDiagnostic() == 5154226890Sdim diag::err_arc_array_param_no_ownership) { 5155226890Sdim diag.Triggered = true; 5156226890Sdim return; 5157226890Sdim } 5158226890Sdim } 5159224145Sdim 5160224145Sdim S.Diag(diag.Loc, diag.getForbiddenTypeDiagnostic()) 5161224145Sdim << diag.getForbiddenTypeOperand() << diag.getForbiddenTypeArgument(); 5162224145Sdim diag.Triggered = true; 5163224145Sdim} 5164224145Sdim 5165245431Sdimvoid Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) { 5166245431Sdim assert(DelayedDiagnostics.getCurrentPool()); 5167245431Sdim DelayedDiagnosticPool &poppedPool = *DelayedDiagnostics.getCurrentPool(); 5168245431Sdim DelayedDiagnostics.popWithoutEmitting(state); 5169218893Sdim 5170245431Sdim // When delaying diagnostics to run in the context of a parsed 5171245431Sdim // declaration, we only want to actually emit anything if parsing 5172245431Sdim // succeeds. 5173245431Sdim if (!decl) return; 5174218893Sdim 5175245431Sdim // We emit all the active diagnostics in this pool or any of its 5176245431Sdim // parents. In general, we'll get one pool for the decl spec 5177245431Sdim // and a child pool for each declarator; in a decl group like: 5178245431Sdim // deprecated_typedef foo, *bar, baz(); 5179245431Sdim // only the declarator pops will be passed decls. This is correct; 5180245431Sdim // we really do need to consider delayed diagnostics from the decl spec 5181245431Sdim // for each of the different declarations. 5182245431Sdim const DelayedDiagnosticPool *pool = &poppedPool; 5183245431Sdim do { 5184245431Sdim for (DelayedDiagnosticPool::pool_iterator 5185245431Sdim i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) { 5186245431Sdim // This const_cast is a bit lame. Really, Triggered should be mutable. 5187245431Sdim DelayedDiagnostic &diag = const_cast<DelayedDiagnostic&>(*i); 5188218893Sdim if (diag.Triggered) 5189203955Srdivacky continue; 5190198893Srdivacky 5191218893Sdim switch (diag.Kind) { 5192203955Srdivacky case DelayedDiagnostic::Deprecation: 5193235633Sdim // Don't bother giving deprecation diagnostics if the decl is invalid. 5194235633Sdim if (!decl->isInvalidDecl()) 5195245431Sdim HandleDelayedDeprecationCheck(diag, decl); 5196203955Srdivacky break; 5197203955Srdivacky 5198203955Srdivacky case DelayedDiagnostic::Access: 5199245431Sdim HandleDelayedAccessCheck(diag, decl); 5200203955Srdivacky break; 5201224145Sdim 5202224145Sdim case DelayedDiagnostic::ForbiddenType: 5203245431Sdim handleDelayedForbiddenType(*this, diag, decl); 5204224145Sdim break; 5205198893Srdivacky } 5206198893Srdivacky } 5207245431Sdim } while ((pool = pool->getParent())); 5208245431Sdim} 5209198893Srdivacky 5210245431Sdim/// Given a set of delayed diagnostics, re-emit them as if they had 5211245431Sdim/// been delayed in the current context instead of in the given pool. 5212245431Sdim/// Essentially, this just moves them to the current pool. 5213245431Sdimvoid Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) { 5214245431Sdim DelayedDiagnosticPool *curPool = DelayedDiagnostics.getCurrentPool(); 5215245431Sdim assert(curPool && "re-emitting in undelayed context not supported"); 5216245431Sdim curPool->steal(pool); 5217198893Srdivacky} 5218198893Srdivacky 5219203955Srdivackystatic bool isDeclDeprecated(Decl *D) { 5220203955Srdivacky do { 5221221345Sdim if (D->isDeprecated()) 5222203955Srdivacky return true; 5223226890Sdim // A category implicitly has the availability of the interface. 5224226890Sdim if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D)) 5225226890Sdim return CatD->getClassInterface()->isDeprecated(); 5226203955Srdivacky } while ((D = cast_or_null<Decl>(D->getDeclContext()))); 5227203955Srdivacky return false; 5228203955Srdivacky} 5229203955Srdivacky 5230245431Sdimstatic void 5231245431SdimDoEmitDeprecationWarning(Sema &S, const NamedDecl *D, StringRef Message, 5232245431Sdim SourceLocation Loc, 5233245431Sdim const ObjCInterfaceDecl *UnknownObjCClass, 5234245431Sdim const ObjCPropertyDecl *ObjCPropery) { 5235245431Sdim DeclarationName Name = D->getDeclName(); 5236245431Sdim if (!Message.empty()) { 5237245431Sdim S.Diag(Loc, diag::warn_deprecated_message) << Name << Message; 5238245431Sdim S.Diag(D->getLocation(), 5239245431Sdim isa<ObjCMethodDecl>(D) ? diag::note_method_declared_at 5240245431Sdim : diag::note_previous_decl) << Name; 5241245431Sdim if (ObjCPropery) 5242245431Sdim S.Diag(ObjCPropery->getLocation(), diag::note_property_attribute) 5243245431Sdim << ObjCPropery->getDeclName() << 0; 5244245431Sdim } else if (!UnknownObjCClass) { 5245245431Sdim S.Diag(Loc, diag::warn_deprecated) << D->getDeclName(); 5246245431Sdim S.Diag(D->getLocation(), 5247245431Sdim isa<ObjCMethodDecl>(D) ? diag::note_method_declared_at 5248245431Sdim : diag::note_previous_decl) << Name; 5249245431Sdim if (ObjCPropery) 5250245431Sdim S.Diag(ObjCPropery->getLocation(), diag::note_property_attribute) 5251245431Sdim << ObjCPropery->getDeclName() << 0; 5252245431Sdim } else { 5253245431Sdim S.Diag(Loc, diag::warn_deprecated_fwdclass_message) << Name; 5254245431Sdim S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); 5255245431Sdim } 5256245431Sdim} 5257245431Sdim 5258212904Sdimvoid Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, 5259203955Srdivacky Decl *Ctx) { 5260203955Srdivacky if (isDeclDeprecated(Ctx)) 5261203955Srdivacky return; 5262203955Srdivacky 5263203955Srdivacky DD.Triggered = true; 5264245431Sdim DoEmitDeprecationWarning(*this, DD.getDeprecationDecl(), 5265245431Sdim DD.getDeprecationMessage(), DD.Loc, 5266245431Sdim DD.getUnknownObjCClass(), 5267245431Sdim DD.getObjCProperty()); 5268203955Srdivacky} 5269203955Srdivacky 5270226890Sdimvoid Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message, 5271218893Sdim SourceLocation Loc, 5272245431Sdim const ObjCInterfaceDecl *UnknownObjCClass, 5273245431Sdim const ObjCPropertyDecl *ObjCProperty) { 5274198893Srdivacky // Delay if we're currently parsing a declaration. 5275218893Sdim if (DelayedDiagnostics.shouldDelayDiagnostics()) { 5276235633Sdim DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, 5277235633Sdim UnknownObjCClass, 5278245431Sdim ObjCProperty, 5279235633Sdim Message)); 5280198893Srdivacky return; 5281198893Srdivacky } 5282198893Srdivacky 5283198893Srdivacky // Otherwise, don't warn if our current context is deprecated. 5284226890Sdim if (isDeclDeprecated(cast<Decl>(getCurLexicalContext()))) 5285198893Srdivacky return; 5286245431Sdim DoEmitDeprecationWarning(*this, D, Message, Loc, UnknownObjCClass, ObjCProperty); 5287198893Srdivacky} 5288