| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1 | //===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===// | 
 | 2 | // | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
 | 5 | // This file is distributed under the University of Illinois Open Source | 
 | 6 | // License. See LICENSE.TXT for details. | 
 | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
 | 10 | //  This file implements decl-related attribute processing. | 
 | 11 | // | 
 | 12 | //===----------------------------------------------------------------------===// | 
 | 13 |  | 
| John McCall | 2d88708 | 2010-08-25 22:03:47 +0000 | [diff] [blame] | 14 | #include "clang/Sema/SemaInternal.h" | 
| Anton Korobeynikov | 82d0a41 | 2010-01-10 12:58:08 +0000 | [diff] [blame] | 15 | #include "TargetAttributesSema.h" | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 16 | #include "clang/AST/ASTContext.h" | 
| DeLesley Hutchins | bbba25f | 2012-05-04 16:28:38 +0000 | [diff] [blame] | 17 | #include "clang/AST/CXXInheritance.h" | 
| John McCall | 384aff8 | 2010-08-25 07:42:41 +0000 | [diff] [blame] | 18 | #include "clang/AST/DeclCXX.h" | 
| Daniel Dunbar | acc5f3e | 2008-08-11 06:23:49 +0000 | [diff] [blame] | 19 | #include "clang/AST/DeclObjC.h" | 
| Chandler Carruth | 55fc873 | 2012-12-04 09:13:33 +0000 | [diff] [blame] | 20 | #include "clang/AST/DeclTemplate.h" | 
| Daniel Dunbar | acc5f3e | 2008-08-11 06:23:49 +0000 | [diff] [blame] | 21 | #include "clang/AST/Expr.h" | 
| Rafael Espindola | d7a60ad | 2013-02-26 19:13:56 +0000 | [diff] [blame] | 22 | #include "clang/AST/Mangle.h" | 
| Jordan Rose | 3f6f51e | 2013-02-08 22:30:41 +0000 | [diff] [blame] | 23 | #include "clang/Basic/CharInfo.h" | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 24 | #include "clang/Basic/SourceManager.h" | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 25 | #include "clang/Basic/TargetInfo.h" | 
| John McCall | 1951085 | 2010-08-20 18:27:03 +0000 | [diff] [blame] | 26 | #include "clang/Sema/DeclSpec.h" | 
| John McCall | 9c3087b | 2010-08-26 02:13:20 +0000 | [diff] [blame] | 27 | #include "clang/Sema/DelayedDiagnostic.h" | 
| John McCall | fe98da0 | 2011-09-29 07:17:38 +0000 | [diff] [blame] | 28 | #include "clang/Sema/Lookup.h" | 
| Richard Smith | 3a2b7a1 | 2013-01-28 22:42:45 +0000 | [diff] [blame] | 29 | #include "clang/Sema/Scope.h" | 
| Chris Lattner | 797c3c4 | 2009-08-10 19:03:04 +0000 | [diff] [blame] | 30 | #include "llvm/ADT/StringExtras.h" | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 31 | using namespace clang; | 
| John McCall | 9c3087b | 2010-08-26 02:13:20 +0000 | [diff] [blame] | 32 | using namespace sema; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 33 |  | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 34 | /// These constants match the enumerated choices of | 
 | 35 | /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type. | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 36 | enum AttributeDeclKind { | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 37 |   ExpectedFunction, | 
 | 38 |   ExpectedUnion, | 
 | 39 |   ExpectedVariableOrFunction, | 
 | 40 |   ExpectedFunctionOrMethod, | 
 | 41 |   ExpectedParameter, | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 42 |   ExpectedFunctionMethodOrBlock, | 
| Kaelyn Uhrain | 51ceb7b | 2012-11-12 23:48:05 +0000 | [diff] [blame] | 43 |   ExpectedFunctionMethodOrClass, | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 44 |   ExpectedFunctionMethodOrParameter, | 
 | 45 |   ExpectedClass, | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 46 |   ExpectedVariable, | 
 | 47 |   ExpectedMethod, | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 48 |   ExpectedVariableFunctionOrLabel, | 
| Douglas Gregor | f6b8b58 | 2012-03-14 16:55:17 +0000 | [diff] [blame] | 49 |   ExpectedFieldOrGlobalVar, | 
| Hans Wennborg | 5e2d5de | 2012-06-23 11:51:46 +0000 | [diff] [blame] | 50 |   ExpectedStruct, | 
| Kaelyn Uhrain | 51ceb7b | 2012-11-12 23:48:05 +0000 | [diff] [blame] | 51 |   ExpectedVariableFunctionOrTag, | 
| Richard Smith | 5f838aa | 2013-02-01 08:25:07 +0000 | [diff] [blame] | 52 |   ExpectedTLSVar, | 
 | 53 |   ExpectedVariableOrField, | 
| John McCall | d4c3d66 | 2013-02-20 01:54:26 +0000 | [diff] [blame] | 54 |   ExpectedVariableFieldOrTag, | 
 | 55 |   ExpectedTypeOrNamespace | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 56 | }; | 
 | 57 |  | 
| Chris Lattner | e5c5ee1 | 2008-06-29 00:16:31 +0000 | [diff] [blame] | 58 | //===----------------------------------------------------------------------===// | 
 | 59 | //  Helper functions | 
 | 60 | //===----------------------------------------------------------------------===// | 
 | 61 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 62 | static const FunctionType *getFunctionType(const Decl *D, | 
| Ted Kremenek | a18d7d8 | 2009-08-14 20:49:40 +0000 | [diff] [blame] | 63 |                                            bool blocksToo = true) { | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 64 |   QualType Ty; | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 65 |   if (const ValueDecl *decl = dyn_cast<ValueDecl>(D)) | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 66 |     Ty = decl->getType(); | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 67 |   else if (const FieldDecl *decl = dyn_cast<FieldDecl>(D)) | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 68 |     Ty = decl->getType(); | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 69 |   else if (const TypedefNameDecl* decl = dyn_cast<TypedefNameDecl>(D)) | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 70 |     Ty = decl->getUnderlyingType(); | 
 | 71 |   else | 
 | 72 |     return 0; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 73 |  | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 74 |   if (Ty->isFunctionPointerType()) | 
| Ted Kremenek | 6217b80 | 2009-07-29 21:53:49 +0000 | [diff] [blame] | 75 |     Ty = Ty->getAs<PointerType>()->getPointeeType(); | 
| Fariborz Jahanian | 755f9d2 | 2009-05-18 17:39:25 +0000 | [diff] [blame] | 76 |   else if (blocksToo && Ty->isBlockPointerType()) | 
| Ted Kremenek | 6217b80 | 2009-07-29 21:53:49 +0000 | [diff] [blame] | 77 |     Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); | 
| Daniel Dunbar | d3f2c10 | 2008-10-19 02:04:16 +0000 | [diff] [blame] | 78 |  | 
| John McCall | 183700f | 2009-09-21 23:43:11 +0000 | [diff] [blame] | 79 |   return Ty->getAs<FunctionType>(); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 80 | } | 
 | 81 |  | 
| Daniel Dunbar | 3568249 | 2008-09-26 04:12:28 +0000 | [diff] [blame] | 82 | // FIXME: We should provide an abstraction around a method or function | 
 | 83 | // to provide the following bits of information. | 
 | 84 |  | 
| Nuno Lopes | d20254f | 2009-12-20 23:11:08 +0000 | [diff] [blame] | 85 | /// isFunction - Return true if the given decl has function | 
| Ted Kremenek | a18d7d8 | 2009-08-14 20:49:40 +0000 | [diff] [blame] | 86 | /// type (function or function-typed variable). | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 87 | static bool isFunction(const Decl *D) { | 
 | 88 |   return getFunctionType(D, false) != NULL; | 
| Ted Kremenek | a18d7d8 | 2009-08-14 20:49:40 +0000 | [diff] [blame] | 89 | } | 
 | 90 |  | 
 | 91 | /// isFunctionOrMethod - Return true if the given decl has function | 
| Daniel Dunbar | d3f2c10 | 2008-10-19 02:04:16 +0000 | [diff] [blame] | 92 | /// type (function or function-typed variable) or an Objective-C | 
 | 93 | /// method. | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 94 | static bool isFunctionOrMethod(const Decl *D) { | 
| Nick Lewycky | 4ae89bc | 2012-07-24 01:31:55 +0000 | [diff] [blame] | 95 |   return isFunction(D) || isa<ObjCMethodDecl>(D); | 
| Daniel Dunbar | 3568249 | 2008-09-26 04:12:28 +0000 | [diff] [blame] | 96 | } | 
 | 97 |  | 
| Fariborz Jahanian | 620d89c | 2009-05-15 23:15:03 +0000 | [diff] [blame] | 98 | /// isFunctionOrMethodOrBlock - Return true if the given decl has function | 
 | 99 | /// type (function or function-typed variable) or an Objective-C | 
 | 100 | /// method or a block. | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 101 | static bool isFunctionOrMethodOrBlock(const Decl *D) { | 
 | 102 |   if (isFunctionOrMethod(D)) | 
| Fariborz Jahanian | 620d89c | 2009-05-15 23:15:03 +0000 | [diff] [blame] | 103 |     return true; | 
 | 104 |   // check for block is more involved. | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 105 |   if (const VarDecl *V = dyn_cast<VarDecl>(D)) { | 
| Fariborz Jahanian | 620d89c | 2009-05-15 23:15:03 +0000 | [diff] [blame] | 106 |     QualType Ty = V->getType(); | 
 | 107 |     return Ty->isBlockPointerType(); | 
 | 108 |   } | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 109 |   return isa<BlockDecl>(D); | 
| Fariborz Jahanian | 620d89c | 2009-05-15 23:15:03 +0000 | [diff] [blame] | 110 | } | 
 | 111 |  | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 112 | /// Return true if the given decl has a declarator that should have | 
 | 113 | /// been processed by Sema::GetTypeForDeclarator. | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 114 | static bool hasDeclarator(const Decl *D) { | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 115 |   // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl. | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 116 |   return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) || isa<TypedefNameDecl>(D) || | 
 | 117 |          isa<ObjCPropertyDecl>(D); | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 118 | } | 
 | 119 |  | 
| Daniel Dunbar | d3f2c10 | 2008-10-19 02:04:16 +0000 | [diff] [blame] | 120 | /// hasFunctionProto - Return true if the given decl has a argument | 
 | 121 | /// information. This decl should have already passed | 
| Fariborz Jahanian | 620d89c | 2009-05-15 23:15:03 +0000 | [diff] [blame] | 122 | /// isFunctionOrMethod or isFunctionOrMethodOrBlock. | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 123 | static bool hasFunctionProto(const Decl *D) { | 
 | 124 |   if (const FunctionType *FnTy = getFunctionType(D)) | 
| Douglas Gregor | 72564e7 | 2009-02-26 23:50:07 +0000 | [diff] [blame] | 125 |     return isa<FunctionProtoType>(FnTy); | 
| Fariborz Jahanian | 620d89c | 2009-05-15 23:15:03 +0000 | [diff] [blame] | 126 |   else { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 127 |     assert(isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D)); | 
| Daniel Dunbar | d3f2c10 | 2008-10-19 02:04:16 +0000 | [diff] [blame] | 128 |     return true; | 
 | 129 |   } | 
 | 130 | } | 
 | 131 |  | 
 | 132 | /// getFunctionOrMethodNumArgs - Return number of function or method | 
 | 133 | /// arguments. It is an error to call this on a K&R function (use | 
 | 134 | /// hasFunctionProto first). | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 135 | static unsigned getFunctionOrMethodNumArgs(const Decl *D) { | 
 | 136 |   if (const FunctionType *FnTy = getFunctionType(D)) | 
| Douglas Gregor | 72564e7 | 2009-02-26 23:50:07 +0000 | [diff] [blame] | 137 |     return cast<FunctionProtoType>(FnTy)->getNumArgs(); | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 138 |   if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) | 
| Fariborz Jahanian | d66f22d | 2009-05-19 17:08:59 +0000 | [diff] [blame] | 139 |     return BD->getNumParams(); | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 140 |   return cast<ObjCMethodDecl>(D)->param_size(); | 
| Daniel Dunbar | 3568249 | 2008-09-26 04:12:28 +0000 | [diff] [blame] | 141 | } | 
 | 142 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 143 | static QualType getFunctionOrMethodArgType(const Decl *D, unsigned Idx) { | 
 | 144 |   if (const FunctionType *FnTy = getFunctionType(D)) | 
| Douglas Gregor | 72564e7 | 2009-02-26 23:50:07 +0000 | [diff] [blame] | 145 |     return cast<FunctionProtoType>(FnTy)->getArgType(Idx); | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 146 |   if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) | 
| Fariborz Jahanian | d66f22d | 2009-05-19 17:08:59 +0000 | [diff] [blame] | 147 |     return BD->getParamDecl(Idx)->getType(); | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 148 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 149 |   return cast<ObjCMethodDecl>(D)->param_begin()[Idx]->getType(); | 
| Daniel Dunbar | 3568249 | 2008-09-26 04:12:28 +0000 | [diff] [blame] | 150 | } | 
 | 151 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 152 | static QualType getFunctionOrMethodResultType(const Decl *D) { | 
 | 153 |   if (const FunctionType *FnTy = getFunctionType(D)) | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 154 |     return cast<FunctionProtoType>(FnTy)->getResultType(); | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 155 |   return cast<ObjCMethodDecl>(D)->getResultType(); | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 156 | } | 
 | 157 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 158 | static bool isFunctionOrMethodVariadic(const Decl *D) { | 
 | 159 |   if (const FunctionType *FnTy = getFunctionType(D)) { | 
| Douglas Gregor | 72564e7 | 2009-02-26 23:50:07 +0000 | [diff] [blame] | 160 |     const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy); | 
| Daniel Dunbar | 3568249 | 2008-09-26 04:12:28 +0000 | [diff] [blame] | 161 |     return proto->isVariadic(); | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 162 |   } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) | 
| Ted Kremenek | db9a0ae | 2010-04-29 16:48:58 +0000 | [diff] [blame] | 163 |     return BD->isVariadic(); | 
| Fariborz Jahanian | d66f22d | 2009-05-19 17:08:59 +0000 | [diff] [blame] | 164 |   else { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 165 |     return cast<ObjCMethodDecl>(D)->isVariadic(); | 
| Daniel Dunbar | 3568249 | 2008-09-26 04:12:28 +0000 | [diff] [blame] | 166 |   } | 
 | 167 | } | 
 | 168 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 169 | static bool isInstanceMethod(const Decl *D) { | 
 | 170 |   if (const CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) | 
| Chandler Carruth | 07d7e7a | 2010-11-16 08:35:43 +0000 | [diff] [blame] | 171 |     return MethodDecl->isInstance(); | 
 | 172 |   return false; | 
 | 173 | } | 
 | 174 |  | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 175 | static inline bool isNSStringType(QualType T, ASTContext &Ctx) { | 
| John McCall | 183700f | 2009-09-21 23:43:11 +0000 | [diff] [blame] | 176 |   const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>(); | 
| Chris Lattner | b77792e | 2008-07-26 22:17:49 +0000 | [diff] [blame] | 177 |   if (!PT) | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 178 |     return false; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 179 |  | 
| John McCall | 506b57e | 2010-05-17 21:00:27 +0000 | [diff] [blame] | 180 |   ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface(); | 
 | 181 |   if (!Cls) | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 182 |     return false; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 183 |  | 
| John McCall | 506b57e | 2010-05-17 21:00:27 +0000 | [diff] [blame] | 184 |   IdentifierInfo* ClsName = Cls->getIdentifier(); | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 185 |  | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 186 |   // FIXME: Should we walk the chain of classes? | 
 | 187 |   return ClsName == &Ctx.Idents.get("NSString") || | 
 | 188 |          ClsName == &Ctx.Idents.get("NSMutableString"); | 
 | 189 | } | 
 | 190 |  | 
| Daniel Dunbar | 085e8f7 | 2008-09-26 03:32:58 +0000 | [diff] [blame] | 191 | static inline bool isCFStringType(QualType T, ASTContext &Ctx) { | 
| Ted Kremenek | 6217b80 | 2009-07-29 21:53:49 +0000 | [diff] [blame] | 192 |   const PointerType *PT = T->getAs<PointerType>(); | 
| Daniel Dunbar | 085e8f7 | 2008-09-26 03:32:58 +0000 | [diff] [blame] | 193 |   if (!PT) | 
 | 194 |     return false; | 
 | 195 |  | 
| Ted Kremenek | 6217b80 | 2009-07-29 21:53:49 +0000 | [diff] [blame] | 196 |   const RecordType *RT = PT->getPointeeType()->getAs<RecordType>(); | 
| Daniel Dunbar | 085e8f7 | 2008-09-26 03:32:58 +0000 | [diff] [blame] | 197 |   if (!RT) | 
 | 198 |     return false; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 199 |  | 
| Daniel Dunbar | 085e8f7 | 2008-09-26 03:32:58 +0000 | [diff] [blame] | 200 |   const RecordDecl *RD = RT->getDecl(); | 
| Abramo Bagnara | 465d41b | 2010-05-11 21:36:43 +0000 | [diff] [blame] | 201 |   if (RD->getTagKind() != TTK_Struct) | 
| Daniel Dunbar | 085e8f7 | 2008-09-26 03:32:58 +0000 | [diff] [blame] | 202 |     return false; | 
 | 203 |  | 
 | 204 |   return RD->getIdentifier() == &Ctx.Idents.get("__CFString"); | 
 | 205 | } | 
 | 206 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 207 | /// \brief Check if the attribute has exactly as many args as Num. May | 
 | 208 | /// output an error. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 209 | static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr, | 
 | 210 |                                   unsigned int Num) { | 
 | 211 |   if (Attr.getNumArgs() != Num) { | 
 | 212 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Num; | 
 | 213 |     return false; | 
 | 214 |   } | 
 | 215 |  | 
 | 216 |   return true; | 
 | 217 | } | 
 | 218 |  | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 219 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 220 | /// \brief Check if the attribute has at least as many args as Num. May | 
 | 221 | /// output an error. | 
 | 222 | static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr, | 
 | 223 |                                   unsigned int Num) { | 
 | 224 |   if (Attr.getNumArgs() < Num) { | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 225 |     S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments) << Num; | 
 | 226 |     return false; | 
 | 227 |   } | 
 | 228 |  | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 229 |   return true; | 
 | 230 | } | 
 | 231 |  | 
| Dmitri Gribenko | 0d5a069 | 2012-08-17 00:08:38 +0000 | [diff] [blame] | 232 | /// \brief Check if IdxExpr is a valid argument index for a function or | 
 | 233 | /// instance method D.  May output an error. | 
 | 234 | /// | 
 | 235 | /// \returns true if IdxExpr is a valid index. | 
 | 236 | static bool checkFunctionOrMethodArgumentIndex(Sema &S, const Decl *D, | 
 | 237 |                                                StringRef AttrName, | 
 | 238 |                                                SourceLocation AttrLoc, | 
 | 239 |                                                unsigned AttrArgNum, | 
 | 240 |                                                const Expr *IdxExpr, | 
 | 241 |                                                uint64_t &Idx) | 
 | 242 | { | 
 | 243 |   assert(isFunctionOrMethod(D) && hasFunctionProto(D)); | 
 | 244 |  | 
 | 245 |   // In C++ the implicit 'this' function parameter also counts. | 
 | 246 |   // Parameters are counted from one. | 
 | 247 |   const bool HasImplicitThisParam = isInstanceMethod(D); | 
 | 248 |   const unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; | 
 | 249 |   const unsigned FirstIdx = 1; | 
 | 250 |  | 
 | 251 |   llvm::APSInt IdxInt; | 
 | 252 |   if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || | 
 | 253 |       !IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) { | 
 | 254 |     S.Diag(AttrLoc, diag::err_attribute_argument_n_not_int) | 
 | 255 |       << AttrName << AttrArgNum << IdxExpr->getSourceRange(); | 
 | 256 |     return false; | 
 | 257 |   } | 
 | 258 |  | 
 | 259 |   Idx = IdxInt.getLimitedValue(); | 
 | 260 |   if (Idx < FirstIdx || (!isFunctionOrMethodVariadic(D) && Idx > NumArgs)) { | 
 | 261 |     S.Diag(AttrLoc, diag::err_attribute_argument_out_of_bounds) | 
 | 262 |       << AttrName << AttrArgNum << IdxExpr->getSourceRange(); | 
 | 263 |     return false; | 
 | 264 |   } | 
 | 265 |   Idx--; // Convert to zero-based. | 
 | 266 |   if (HasImplicitThisParam) { | 
 | 267 |     if (Idx == 0) { | 
 | 268 |       S.Diag(AttrLoc, | 
 | 269 |              diag::err_attribute_invalid_implicit_this_argument) | 
 | 270 |         << AttrName << IdxExpr->getSourceRange(); | 
 | 271 |       return false; | 
 | 272 |     } | 
 | 273 |     --Idx; | 
 | 274 |   } | 
 | 275 |  | 
 | 276 |   return true; | 
 | 277 | } | 
 | 278 |  | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 279 | /// | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 280 | /// \brief Check if passed in Decl is a field or potentially shared global var | 
 | 281 | /// \return true if the Decl is a field or potentially shared global variable | 
 | 282 | /// | 
| Benjamin Kramer | 39997fc | 2011-08-02 04:50:49 +0000 | [diff] [blame] | 283 | static bool mayBeSharedVariable(const Decl *D) { | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 284 |   if (isa<FieldDecl>(D)) | 
 | 285 |     return true; | 
| Benjamin Kramer | 39997fc | 2011-08-02 04:50:49 +0000 | [diff] [blame] | 286 |   if (const VarDecl *vd = dyn_cast<VarDecl>(D)) | 
| Richard Smith | 38afbc7 | 2013-04-13 02:43:54 +0000 | [diff] [blame] | 287 |     return vd->hasGlobalStorage() && !vd->getTLSKind(); | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 288 |  | 
 | 289 |   return false; | 
 | 290 | } | 
 | 291 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 292 | /// \brief Check if the passed-in expression is of type int or bool. | 
 | 293 | static bool isIntOrBool(Expr *Exp) { | 
 | 294 |   QualType QT = Exp->getType(); | 
 | 295 |   return QT->isBooleanType() || QT->isIntegerType(); | 
 | 296 | } | 
 | 297 |  | 
| DeLesley Hutchins | aed9ea3 | 2012-04-23 18:39:55 +0000 | [diff] [blame] | 298 |  | 
 | 299 | // Check to see if the type is a smart pointer of some kind.  We assume | 
 | 300 | // it's a smart pointer if it defines both operator-> and operator*. | 
| DeLesley Hutchins | 60f2024 | 2012-05-02 22:18:42 +0000 | [diff] [blame] | 301 | static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) { | 
 | 302 |   DeclContextLookupConstResult Res1 = RT->getDecl()->lookup( | 
 | 303 |     S.Context.DeclarationNames.getCXXOperatorName(OO_Star)); | 
| David Blaikie | 3bc93e3 | 2012-12-19 00:45:41 +0000 | [diff] [blame] | 304 |   if (Res1.empty()) | 
| DeLesley Hutchins | 60f2024 | 2012-05-02 22:18:42 +0000 | [diff] [blame] | 305 |     return false; | 
| DeLesley Hutchins | aed9ea3 | 2012-04-23 18:39:55 +0000 | [diff] [blame] | 306 |  | 
| DeLesley Hutchins | 60f2024 | 2012-05-02 22:18:42 +0000 | [diff] [blame] | 307 |   DeclContextLookupConstResult Res2 = RT->getDecl()->lookup( | 
 | 308 |     S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow)); | 
| David Blaikie | 3bc93e3 | 2012-12-19 00:45:41 +0000 | [diff] [blame] | 309 |   if (Res2.empty()) | 
| DeLesley Hutchins | 60f2024 | 2012-05-02 22:18:42 +0000 | [diff] [blame] | 310 |     return false; | 
 | 311 |  | 
 | 312 |   return true; | 
| DeLesley Hutchins | aed9ea3 | 2012-04-23 18:39:55 +0000 | [diff] [blame] | 313 | } | 
 | 314 |  | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 315 | /// \brief Check if passed in Decl is a pointer type. | 
 | 316 | /// Note that this function may produce an error message. | 
 | 317 | /// \return true if the Decl is a pointer type; false otherwise | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 318 | static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D, | 
 | 319 |                                        const AttributeList &Attr) { | 
| Benjamin Kramer | 39997fc | 2011-08-02 04:50:49 +0000 | [diff] [blame] | 320 |   if (const ValueDecl *vd = dyn_cast<ValueDecl>(D)) { | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 321 |     QualType QT = vd->getType(); | 
| Benjamin Kramer | 39997fc | 2011-08-02 04:50:49 +0000 | [diff] [blame] | 322 |     if (QT->isAnyPointerType()) | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 323 |       return true; | 
| DeLesley Hutchins | aed9ea3 | 2012-04-23 18:39:55 +0000 | [diff] [blame] | 324 |  | 
| DeLesley Hutchins | 60f2024 | 2012-05-02 22:18:42 +0000 | [diff] [blame] | 325 |     if (const RecordType *RT = QT->getAs<RecordType>()) { | 
 | 326 |       // If it's an incomplete type, it could be a smart pointer; skip it. | 
 | 327 |       // (We don't want to force template instantiation if we can avoid it, | 
 | 328 |       // since that would alter the order in which templates are instantiated.) | 
 | 329 |       if (RT->isIncompleteType()) | 
 | 330 |         return true; | 
 | 331 |  | 
 | 332 |       if (threadSafetyCheckIsSmartPointer(S, RT)) | 
 | 333 |         return true; | 
 | 334 |     } | 
| DeLesley Hutchins | aed9ea3 | 2012-04-23 18:39:55 +0000 | [diff] [blame] | 335 |  | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 336 |     S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_pointer) | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 337 |       << Attr.getName()->getName() << QT; | 
 | 338 |   } else { | 
 | 339 |     S.Diag(Attr.getLoc(), diag::err_attribute_can_be_applied_only_to_value_decl) | 
 | 340 |       << Attr.getName(); | 
 | 341 |   } | 
 | 342 |   return false; | 
 | 343 | } | 
 | 344 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 345 | /// \brief Checks that the passed in QualType either is of RecordType or points | 
 | 346 | /// to RecordType. Returns the relevant RecordType, null if it does not exit. | 
| Benjamin Kramer | 7d23b4a | 2011-08-19 04:18:11 +0000 | [diff] [blame] | 347 | static const RecordType *getRecordType(QualType QT) { | 
 | 348 |   if (const RecordType *RT = QT->getAs<RecordType>()) | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 349 |     return RT; | 
| Benjamin Kramer | 7d23b4a | 2011-08-19 04:18:11 +0000 | [diff] [blame] | 350 |  | 
 | 351 |   // Now check if we point to record type. | 
 | 352 |   if (const PointerType *PT = QT->getAs<PointerType>()) | 
 | 353 |     return PT->getPointeeType()->getAs<RecordType>(); | 
 | 354 |  | 
 | 355 |   return 0; | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 356 | } | 
 | 357 |  | 
| DeLesley Hutchins | bbba25f | 2012-05-04 16:28:38 +0000 | [diff] [blame] | 358 |  | 
| Jordy Rose | fad5de9 | 2012-05-08 03:27:22 +0000 | [diff] [blame] | 359 | static bool checkBaseClassIsLockableCallback(const CXXBaseSpecifier *Specifier, | 
 | 360 |                                              CXXBasePath &Path, void *Unused) { | 
| DeLesley Hutchins | bbba25f | 2012-05-04 16:28:38 +0000 | [diff] [blame] | 361 |   const RecordType *RT = Specifier->getType()->getAs<RecordType>(); | 
 | 362 |   if (RT->getDecl()->getAttr<LockableAttr>()) | 
 | 363 |     return true; | 
 | 364 |   return false; | 
 | 365 | } | 
 | 366 |  | 
 | 367 |  | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 368 | /// \brief Thread Safety Analysis: Checks that the passed in RecordType | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 369 | /// resolves to a lockable object. | 
| DeLesley Hutchins | 83cad45 | 2012-04-06 20:02:30 +0000 | [diff] [blame] | 370 | static void checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr, | 
 | 371 |                                    QualType Ty) { | 
 | 372 |   const RecordType *RT = getRecordType(Ty); | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 373 |  | 
| DeLesley Hutchins | 83cad45 | 2012-04-06 20:02:30 +0000 | [diff] [blame] | 374 |   // Warn if could not get record type for this argument. | 
| Benjamin Kramer | d77ba89 | 2011-09-03 03:30:59 +0000 | [diff] [blame] | 375 |   if (!RT) { | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 376 |     S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_class) | 
| DeLesley Hutchins | 83cad45 | 2012-04-06 20:02:30 +0000 | [diff] [blame] | 377 |       << Attr.getName() << Ty.getAsString(); | 
 | 378 |     return; | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 379 |   } | 
| DeLesley Hutchins | 60f2024 | 2012-05-02 22:18:42 +0000 | [diff] [blame] | 380 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 381 |   // Don't check for lockable if the class hasn't been defined yet. | 
| DeLesley Hutchins | 634b293 | 2012-02-16 17:15:51 +0000 | [diff] [blame] | 382 |   if (RT->isIncompleteType()) | 
| DeLesley Hutchins | 83cad45 | 2012-04-06 20:02:30 +0000 | [diff] [blame] | 383 |     return; | 
| DeLesley Hutchins | 60f2024 | 2012-05-02 22:18:42 +0000 | [diff] [blame] | 384 |  | 
 | 385 |   // Allow smart pointers to be used as lockable objects. | 
 | 386 |   // FIXME -- Check the type that the smart pointer points to. | 
 | 387 |   if (threadSafetyCheckIsSmartPointer(S, RT)) | 
 | 388 |     return; | 
 | 389 |  | 
| DeLesley Hutchins | bbba25f | 2012-05-04 16:28:38 +0000 | [diff] [blame] | 390 |   // Check if the type is lockable. | 
 | 391 |   RecordDecl *RD = RT->getDecl(); | 
 | 392 |   if (RD->getAttr<LockableAttr>()) | 
| DeLesley Hutchins | 83cad45 | 2012-04-06 20:02:30 +0000 | [diff] [blame] | 393 |     return; | 
| DeLesley Hutchins | bbba25f | 2012-05-04 16:28:38 +0000 | [diff] [blame] | 394 |  | 
 | 395 |   // Else check if any base classes are lockable. | 
 | 396 |   if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) { | 
 | 397 |     CXXBasePaths BPaths(false, false); | 
 | 398 |     if (CRD->lookupInBases(checkBaseClassIsLockableCallback, 0, BPaths)) | 
 | 399 |       return; | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 400 |   } | 
| DeLesley Hutchins | bbba25f | 2012-05-04 16:28:38 +0000 | [diff] [blame] | 401 |  | 
 | 402 |   S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_lockable) | 
 | 403 |     << Attr.getName() << Ty.getAsString(); | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 404 | } | 
 | 405 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 406 | /// \brief Thread Safety Analysis: Checks that all attribute arguments, starting | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 407 | /// from Sidx, resolve to a lockable object. | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 408 | /// \param Sidx The attribute argument index to start checking with. | 
 | 409 | /// \param ParamIdxOk Whether an argument can be indexing into a function | 
 | 410 | /// parameter list. | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 411 | static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D, | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 412 |                                          const AttributeList &Attr, | 
 | 413 |                                          SmallVectorImpl<Expr*> &Args, | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 414 |                                          int Sidx = 0, | 
 | 415 |                                          bool ParamIdxOk = false) { | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 416 |   for(unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) { | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 417 |     Expr *ArgExp = Attr.getArg(Idx); | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 418 |  | 
| Caitlin Sadowski | ed9d84a | 2011-09-08 17:42:31 +0000 | [diff] [blame] | 419 |     if (ArgExp->isTypeDependent()) { | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 420 |       // FIXME -- need to check this again on template instantiation | 
| Caitlin Sadowski | ed9d84a | 2011-09-08 17:42:31 +0000 | [diff] [blame] | 421 |       Args.push_back(ArgExp); | 
 | 422 |       continue; | 
 | 423 |     } | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 424 |  | 
| DeLesley Hutchins | 79747e0 | 2012-04-23 16:45:01 +0000 | [diff] [blame] | 425 |     if (StringLiteral *StrLit = dyn_cast<StringLiteral>(ArgExp)) { | 
| DeLesley Hutchins | 0b4db3e | 2012-09-07 17:34:53 +0000 | [diff] [blame] | 426 |       if (StrLit->getLength() == 0 || | 
 | 427 |           StrLit->getString() == StringRef("*")) { | 
| DeLesley Hutchins | 4e4c157 | 2012-08-31 21:57:32 +0000 | [diff] [blame] | 428 |         // Pass empty strings to the analyzer without warnings. | 
| DeLesley Hutchins | 0b4db3e | 2012-09-07 17:34:53 +0000 | [diff] [blame] | 429 |         // Treat "*" as the universal lock. | 
| DeLesley Hutchins | 4e4c157 | 2012-08-31 21:57:32 +0000 | [diff] [blame] | 430 |         Args.push_back(ArgExp); | 
| DeLesley Hutchins | 79747e0 | 2012-04-23 16:45:01 +0000 | [diff] [blame] | 431 |         continue; | 
| DeLesley Hutchins | 4e4c157 | 2012-08-31 21:57:32 +0000 | [diff] [blame] | 432 |       } | 
| DeLesley Hutchins | 79747e0 | 2012-04-23 16:45:01 +0000 | [diff] [blame] | 433 |  | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 434 |       // We allow constant strings to be used as a placeholder for expressions | 
 | 435 |       // that are not valid C++ syntax, but warn that they are ignored. | 
 | 436 |       S.Diag(Attr.getLoc(), diag::warn_thread_attribute_ignored) << | 
 | 437 |         Attr.getName(); | 
| DeLesley Hutchins | 4e4c157 | 2012-08-31 21:57:32 +0000 | [diff] [blame] | 438 |       Args.push_back(ArgExp); | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 439 |       continue; | 
 | 440 |     } | 
 | 441 |  | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 442 |     QualType ArgTy = ArgExp->getType(); | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 443 |  | 
| DeLesley Hutchins | 79747e0 | 2012-04-23 16:45:01 +0000 | [diff] [blame] | 444 |     // A pointer to member expression of the form  &MyClass::mu is treated | 
 | 445 |     // specially -- we need to look at the type of the member. | 
 | 446 |     if (UnaryOperator *UOp = dyn_cast<UnaryOperator>(ArgExp)) | 
 | 447 |       if (UOp->getOpcode() == UO_AddrOf) | 
 | 448 |         if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(UOp->getSubExpr())) | 
 | 449 |           if (DRE->getDecl()->isCXXInstanceMember()) | 
 | 450 |             ArgTy = DRE->getDecl()->getType(); | 
 | 451 |  | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 452 |     // First see if we can just cast to record type, or point to record type. | 
 | 453 |     const RecordType *RT = getRecordType(ArgTy); | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 454 |  | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 455 |     // Now check if we index into a record type function param. | 
 | 456 |     if(!RT && ParamIdxOk) { | 
 | 457 |       FunctionDecl *FD = dyn_cast<FunctionDecl>(D); | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 458 |       IntegerLiteral *IL = dyn_cast<IntegerLiteral>(ArgExp); | 
 | 459 |       if(FD && IL) { | 
 | 460 |         unsigned int NumParams = FD->getNumParams(); | 
 | 461 |         llvm::APInt ArgValue = IL->getValue(); | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 462 |         uint64_t ParamIdxFromOne = ArgValue.getZExtValue(); | 
 | 463 |         uint64_t ParamIdxFromZero = ParamIdxFromOne - 1; | 
 | 464 |         if(!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) { | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 465 |           S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_range) | 
 | 466 |             << Attr.getName() << Idx + 1 << NumParams; | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 467 |           continue; | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 468 |         } | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 469 |         ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType(); | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 470 |       } | 
 | 471 |     } | 
 | 472 |  | 
| DeLesley Hutchins | 83cad45 | 2012-04-06 20:02:30 +0000 | [diff] [blame] | 473 |     checkForLockableRecord(S, D, Attr, ArgTy); | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 474 |  | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 475 |     Args.push_back(ArgExp); | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 476 |   } | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 477 | } | 
 | 478 |  | 
| Chris Lattner | e5c5ee1 | 2008-06-29 00:16:31 +0000 | [diff] [blame] | 479 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | e5c5ee1 | 2008-06-29 00:16:31 +0000 | [diff] [blame] | 480 | // Attribute Implementations | 
 | 481 | //===----------------------------------------------------------------------===// | 
 | 482 |  | 
| Daniel Dunbar | 3068ae0 | 2008-07-31 22:40:48 +0000 | [diff] [blame] | 483 | // FIXME: All this manual attribute parsing code is gross. At the | 
 | 484 | // least add some helper functions to check most argument patterns (# | 
 | 485 | // and types of args). | 
 | 486 |  | 
| DeLesley Hutchins | 0aa52aa | 2012-06-19 23:25:19 +0000 | [diff] [blame] | 487 | enum ThreadAttributeDeclKind { | 
 | 488 |   ThreadExpectedFieldOrGlobalVar, | 
 | 489 |   ThreadExpectedFunctionOrMethod, | 
 | 490 |   ThreadExpectedClassOrStruct | 
 | 491 | }; | 
 | 492 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 493 | static bool checkGuardedVarAttrCommon(Sema &S, Decl *D, | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 494 |                                       const AttributeList &Attr) { | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 495 |   assert(!Attr.isInvalid()); | 
 | 496 |  | 
 | 497 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 498 |     return false; | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 499 |  | 
 | 500 |   // D must be either a member field or global (potentially shared) variable. | 
 | 501 |   if (!mayBeSharedVariable(D)) { | 
| DeLesley Hutchins | 0aa52aa | 2012-06-19 23:25:19 +0000 | [diff] [blame] | 502 |     S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) | 
 | 503 |       << Attr.getName() << ThreadExpectedFieldOrGlobalVar; | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 504 |     return false; | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 505 |   } | 
 | 506 |  | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 507 |   return true; | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 508 | } | 
 | 509 |  | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 510 | static void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
 | 511 |   if (!checkGuardedVarAttrCommon(S, D, Attr)) | 
 | 512 |     return; | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 513 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 514 |   D->addAttr(::new (S.Context) | 
 | 515 |              GuardedVarAttr(Attr.getRange(), S.Context, | 
 | 516 |                             Attr.getAttributeSpellingListIndex())); | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 517 | } | 
 | 518 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 519 | static void handlePtGuardedVarAttr(Sema &S, Decl *D, | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 520 |                                    const AttributeList &Attr) { | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 521 |   if (!checkGuardedVarAttrCommon(S, D, Attr)) | 
 | 522 |     return; | 
 | 523 |  | 
 | 524 |   if (!threadSafetyCheckIsPointer(S, D, Attr)) | 
 | 525 |     return; | 
 | 526 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 527 |   D->addAttr(::new (S.Context) | 
 | 528 |              PtGuardedVarAttr(Attr.getRange(), S.Context, | 
 | 529 |                               Attr.getAttributeSpellingListIndex())); | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 530 | } | 
 | 531 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 532 | static bool checkGuardedByAttrCommon(Sema &S, Decl *D, | 
 | 533 |                                      const AttributeList &Attr, | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 534 |                                      Expr* &Arg) { | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 535 |   assert(!Attr.isInvalid()); | 
 | 536 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 537 |   if (!checkAttributeNumArgs(S, Attr, 1)) | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 538 |     return false; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 539 |  | 
 | 540 |   // D must be either a member field or global (potentially shared) variable. | 
 | 541 |   if (!mayBeSharedVariable(D)) { | 
| DeLesley Hutchins | 0aa52aa | 2012-06-19 23:25:19 +0000 | [diff] [blame] | 542 |     S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) | 
 | 543 |       << Attr.getName() << ThreadExpectedFieldOrGlobalVar; | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 544 |     return false; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 545 |   } | 
 | 546 |  | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 547 |   SmallVector<Expr*, 1> Args; | 
 | 548 |   // check that all arguments are lockable objects | 
 | 549 |   checkAttrArgsAreLockableObjs(S, D, Attr, Args); | 
 | 550 |   unsigned Size = Args.size(); | 
 | 551 |   if (Size != 1) | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 552 |     return false; | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 553 |  | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 554 |   Arg = Args[0]; | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 555 |  | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 556 |   return true; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 557 | } | 
 | 558 |  | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 559 | static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
 | 560 |   Expr *Arg = 0; | 
 | 561 |   if (!checkGuardedByAttrCommon(S, D, Attr, Arg)) | 
 | 562 |     return; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 563 |  | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 564 |   D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg)); | 
 | 565 | } | 
 | 566 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 567 | static void handlePtGuardedByAttr(Sema &S, Decl *D, | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 568 |                                   const AttributeList &Attr) { | 
 | 569 |   Expr *Arg = 0; | 
 | 570 |   if (!checkGuardedByAttrCommon(S, D, Attr, Arg)) | 
 | 571 |     return; | 
 | 572 |  | 
 | 573 |   if (!threadSafetyCheckIsPointer(S, D, Attr)) | 
 | 574 |     return; | 
 | 575 |  | 
 | 576 |   D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(), | 
 | 577 |                                                S.Context, Arg)); | 
 | 578 | } | 
 | 579 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 580 | static bool checkLockableAttrCommon(Sema &S, Decl *D, | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 581 |                                     const AttributeList &Attr) { | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 582 |   assert(!Attr.isInvalid()); | 
 | 583 |  | 
 | 584 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 585 |     return false; | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 586 |  | 
| Caitlin Sadowski | 1748b12 | 2011-09-16 00:35:54 +0000 | [diff] [blame] | 587 |   // FIXME: Lockable structs for C code. | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 588 |   if (!isa<CXXRecordDecl>(D)) { | 
| DeLesley Hutchins | 0aa52aa | 2012-06-19 23:25:19 +0000 | [diff] [blame] | 589 |     S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) | 
 | 590 |       << Attr.getName() << ThreadExpectedClassOrStruct; | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 591 |     return false; | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 592 |   } | 
 | 593 |  | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 594 |   return true; | 
 | 595 | } | 
 | 596 |  | 
 | 597 | static void handleLockableAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
 | 598 |   if (!checkLockableAttrCommon(S, D, Attr)) | 
 | 599 |     return; | 
 | 600 |  | 
 | 601 |   D->addAttr(::new (S.Context) LockableAttr(Attr.getRange(), S.Context)); | 
 | 602 | } | 
 | 603 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 604 | static void handleScopedLockableAttr(Sema &S, Decl *D, | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 605 |                              const AttributeList &Attr) { | 
 | 606 |   if (!checkLockableAttrCommon(S, D, Attr)) | 
 | 607 |     return; | 
 | 608 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 609 |   D->addAttr(::new (S.Context) | 
 | 610 |              ScopedLockableAttr(Attr.getRange(), S.Context, | 
 | 611 |                                 Attr.getAttributeSpellingListIndex())); | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 612 | } | 
 | 613 |  | 
| Kostya Serebryany | 85aee96 | 2013-02-26 06:58:27 +0000 | [diff] [blame] | 614 | static void handleNoThreadSafetyAnalysis(Sema &S, Decl *D, | 
 | 615 |                                          const AttributeList &Attr) { | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 616 |   assert(!Attr.isInvalid()); | 
 | 617 |  | 
 | 618 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
 | 619 |     return; | 
 | 620 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 621 |   if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { | 
| DeLesley Hutchins | 0aa52aa | 2012-06-19 23:25:19 +0000 | [diff] [blame] | 622 |     S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) | 
 | 623 |       << Attr.getName() << ThreadExpectedFunctionOrMethod; | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 624 |     return; | 
 | 625 |   } | 
 | 626 |  | 
| Argyrios Kyrtzidis | 768d6ca | 2011-09-13 16:05:58 +0000 | [diff] [blame] | 627 |   D->addAttr(::new (S.Context) NoThreadSafetyAnalysisAttr(Attr.getRange(), | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 628 |                                                           S.Context)); | 
 | 629 | } | 
 | 630 |  | 
| Kostya Serebryany | 85aee96 | 2013-02-26 06:58:27 +0000 | [diff] [blame] | 631 | static void handleNoSanitizeAddressAttr(Sema &S, Decl *D, | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 632 |                                       const AttributeList &Attr) { | 
| Kostya Serebryany | 71efba0 | 2012-01-24 19:25:38 +0000 | [diff] [blame] | 633 |   assert(!Attr.isInvalid()); | 
 | 634 |  | 
 | 635 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
 | 636 |     return; | 
 | 637 |  | 
 | 638 |   if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { | 
| Kostya Serebryany | 85aee96 | 2013-02-26 06:58:27 +0000 | [diff] [blame] | 639 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) | 
| Kostya Serebryany | 71efba0 | 2012-01-24 19:25:38 +0000 | [diff] [blame] | 640 |       << Attr.getName() << ExpectedFunctionOrMethod; | 
 | 641 |     return; | 
 | 642 |   } | 
 | 643 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 644 |   D->addAttr(::new (S.Context) | 
| Kostya Serebryany | 85aee96 | 2013-02-26 06:58:27 +0000 | [diff] [blame] | 645 |              NoSanitizeAddressAttr(Attr.getRange(), S.Context, | 
 | 646 |                                    Attr.getAttributeSpellingListIndex())); | 
 | 647 | } | 
 | 648 |  | 
 | 649 | static void handleNoSanitizeMemory(Sema &S, Decl *D, | 
 | 650 |                                    const AttributeList &Attr) { | 
 | 651 |   assert(!Attr.isInvalid()); | 
 | 652 |  | 
 | 653 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
 | 654 |     return; | 
 | 655 |  | 
 | 656 |   if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { | 
 | 657 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) | 
 | 658 |       << Attr.getName() << ExpectedFunctionOrMethod; | 
 | 659 |     return; | 
 | 660 |   } | 
 | 661 |  | 
 | 662 |   D->addAttr(::new (S.Context) NoSanitizeMemoryAttr(Attr.getRange(), | 
 | 663 |                                                          S.Context)); | 
 | 664 | } | 
 | 665 |  | 
 | 666 | static void handleNoSanitizeThread(Sema &S, Decl *D, | 
 | 667 |                                    const AttributeList &Attr) { | 
 | 668 |   assert(!Attr.isInvalid()); | 
 | 669 |  | 
 | 670 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
 | 671 |     return; | 
 | 672 |  | 
 | 673 |   if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { | 
 | 674 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) | 
 | 675 |       << Attr.getName() << ExpectedFunctionOrMethod; | 
 | 676 |     return; | 
 | 677 |   } | 
 | 678 |  | 
 | 679 |   D->addAttr(::new (S.Context) NoSanitizeThreadAttr(Attr.getRange(), | 
 | 680 |                                                     S.Context)); | 
| Kostya Serebryany | 71efba0 | 2012-01-24 19:25:38 +0000 | [diff] [blame] | 681 | } | 
 | 682 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 683 | static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, | 
 | 684 |                                         const AttributeList &Attr, | 
| Craig Topper | 6b9240e | 2013-07-05 19:34:19 +0000 | [diff] [blame] | 685 |                                         SmallVectorImpl<Expr *> &Args) { | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 686 |   assert(!Attr.isInvalid()); | 
 | 687 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 688 |   if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 689 |     return false; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 690 |  | 
 | 691 |   // D must be either a member field or global (potentially shared) variable. | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 692 |   ValueDecl *VD = dyn_cast<ValueDecl>(D); | 
 | 693 |   if (!VD || !mayBeSharedVariable(D)) { | 
| DeLesley Hutchins | 0aa52aa | 2012-06-19 23:25:19 +0000 | [diff] [blame] | 694 |     S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) | 
 | 695 |       << Attr.getName() << ThreadExpectedFieldOrGlobalVar; | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 696 |     return false; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 697 |   } | 
 | 698 |  | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 699 |   // Check that this attribute only applies to lockable types. | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 700 |   QualType QT = VD->getType(); | 
 | 701 |   if (!QT->isDependentType()) { | 
 | 702 |     const RecordType *RT = getRecordType(QT); | 
 | 703 |     if (!RT || !RT->getDecl()->getAttr<LockableAttr>()) { | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 704 |       S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable) | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 705 |         << Attr.getName(); | 
 | 706 |       return false; | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 707 |     } | 
 | 708 |   } | 
 | 709 |  | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 710 |   // Check that all arguments are lockable objects. | 
 | 711 |   checkAttrArgsAreLockableObjs(S, D, Attr, Args); | 
| Dmitri Gribenko | 1f78a50 | 2013-05-03 15:05:50 +0000 | [diff] [blame] | 712 |   if (Args.empty()) | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 713 |     return false; | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 714 |  | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 715 |   return true; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 716 | } | 
 | 717 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 718 | static void handleAcquiredAfterAttr(Sema &S, Decl *D, | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 719 |                                     const AttributeList &Attr) { | 
 | 720 |   SmallVector<Expr*, 1> Args; | 
 | 721 |   if (!checkAcquireOrderAttrCommon(S, D, Attr, Args)) | 
 | 722 |     return; | 
 | 723 |  | 
 | 724 |   Expr **StartArg = &Args[0]; | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 725 |   D->addAttr(::new (S.Context) | 
 | 726 |              AcquiredAfterAttr(Attr.getRange(), S.Context, | 
 | 727 |                                StartArg, Args.size(), | 
 | 728 |                                Attr.getAttributeSpellingListIndex())); | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 729 | } | 
 | 730 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 731 | static void handleAcquiredBeforeAttr(Sema &S, Decl *D, | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 732 |                                      const AttributeList &Attr) { | 
 | 733 |   SmallVector<Expr*, 1> Args; | 
 | 734 |   if (!checkAcquireOrderAttrCommon(S, D, Attr, Args)) | 
 | 735 |     return; | 
 | 736 |  | 
 | 737 |   Expr **StartArg = &Args[0]; | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 738 |   D->addAttr(::new (S.Context) | 
 | 739 |              AcquiredBeforeAttr(Attr.getRange(), S.Context, | 
 | 740 |                                 StartArg, Args.size(), | 
 | 741 |                                 Attr.getAttributeSpellingListIndex())); | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 742 | } | 
 | 743 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 744 | static bool checkLockFunAttrCommon(Sema &S, Decl *D, | 
 | 745 |                                    const AttributeList &Attr, | 
| Craig Topper | 6b9240e | 2013-07-05 19:34:19 +0000 | [diff] [blame] | 746 |                                    SmallVectorImpl<Expr *> &Args) { | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 747 |   assert(!Attr.isInvalid()); | 
 | 748 |  | 
 | 749 |   // zero or more arguments ok | 
 | 750 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 751 |   // check that the attribute is applied to a function | 
 | 752 |   if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { | 
| DeLesley Hutchins | 0aa52aa | 2012-06-19 23:25:19 +0000 | [diff] [blame] | 753 |     S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) | 
 | 754 |       << Attr.getName() << ThreadExpectedFunctionOrMethod; | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 755 |     return false; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 756 |   } | 
 | 757 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 758 |   // check that all arguments are lockable objects | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 759 |   checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true); | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 760 |  | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 761 |   return true; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 762 | } | 
 | 763 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 764 | static void handleSharedLockFunctionAttr(Sema &S, Decl *D, | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 765 |                                          const AttributeList &Attr) { | 
 | 766 |   SmallVector<Expr*, 1> Args; | 
 | 767 |   if (!checkLockFunAttrCommon(S, D, Attr, Args)) | 
 | 768 |     return; | 
 | 769 |  | 
 | 770 |   unsigned Size = Args.size(); | 
 | 771 |   Expr **StartArg = Size == 0 ? 0 : &Args[0]; | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 772 |   D->addAttr(::new (S.Context) | 
 | 773 |              SharedLockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size, | 
 | 774 |                                     Attr.getAttributeSpellingListIndex())); | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 775 | } | 
 | 776 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 777 | static void handleExclusiveLockFunctionAttr(Sema &S, Decl *D, | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 778 |                                             const AttributeList &Attr) { | 
 | 779 |   SmallVector<Expr*, 1> Args; | 
 | 780 |   if (!checkLockFunAttrCommon(S, D, Attr, Args)) | 
 | 781 |     return; | 
 | 782 |  | 
 | 783 |   unsigned Size = Args.size(); | 
 | 784 |   Expr **StartArg = Size == 0 ? 0 : &Args[0]; | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 785 |   D->addAttr(::new (S.Context) | 
 | 786 |              ExclusiveLockFunctionAttr(Attr.getRange(), S.Context, | 
 | 787 |                                        StartArg, Size, | 
 | 788 |                                        Attr.getAttributeSpellingListIndex())); | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 789 | } | 
 | 790 |  | 
| DeLesley Hutchins | 5c6134f | 2013-05-17 23:02:59 +0000 | [diff] [blame] | 791 | static void handleAssertSharedLockAttr(Sema &S, Decl *D, | 
 | 792 |                                        const AttributeList &Attr) { | 
 | 793 |   SmallVector<Expr*, 1> Args; | 
 | 794 |   if (!checkLockFunAttrCommon(S, D, Attr, Args)) | 
 | 795 |     return; | 
 | 796 |  | 
 | 797 |   unsigned Size = Args.size(); | 
 | 798 |   Expr **StartArg = Size == 0 ? 0 : &Args[0]; | 
 | 799 |   D->addAttr(::new (S.Context) | 
 | 800 |              AssertSharedLockAttr(Attr.getRange(), S.Context, StartArg, Size, | 
 | 801 |                                   Attr.getAttributeSpellingListIndex())); | 
 | 802 | } | 
 | 803 |  | 
 | 804 | static void handleAssertExclusiveLockAttr(Sema &S, Decl *D, | 
 | 805 |                                           const AttributeList &Attr) { | 
 | 806 |   SmallVector<Expr*, 1> Args; | 
 | 807 |   if (!checkLockFunAttrCommon(S, D, Attr, Args)) | 
 | 808 |     return; | 
 | 809 |  | 
 | 810 |   unsigned Size = Args.size(); | 
 | 811 |   Expr **StartArg = Size == 0 ? 0 : &Args[0]; | 
 | 812 |   D->addAttr(::new (S.Context) | 
 | 813 |              AssertExclusiveLockAttr(Attr.getRange(), S.Context, | 
 | 814 |                                      StartArg, Size, | 
 | 815 |                                      Attr.getAttributeSpellingListIndex())); | 
 | 816 | } | 
 | 817 |  | 
 | 818 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 819 | static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, | 
 | 820 |                                       const AttributeList &Attr, | 
| Craig Topper | 6b9240e | 2013-07-05 19:34:19 +0000 | [diff] [blame] | 821 |                                       SmallVectorImpl<Expr *> &Args) { | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 822 |   assert(!Attr.isInvalid()); | 
 | 823 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 824 |   if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 825 |     return false; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 826 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 827 |   if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { | 
| DeLesley Hutchins | 0aa52aa | 2012-06-19 23:25:19 +0000 | [diff] [blame] | 828 |     S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) | 
 | 829 |       << Attr.getName() << ThreadExpectedFunctionOrMethod; | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 830 |     return false; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 831 |   } | 
 | 832 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 833 |   if (!isIntOrBool(Attr.getArg(0))) { | 
 | 834 |     S.Diag(Attr.getLoc(), diag::err_attribute_first_argument_not_int_or_bool) | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 835 |       << Attr.getName(); | 
 | 836 |     return false; | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 837 |   } | 
 | 838 |  | 
 | 839 |   // check that all arguments are lockable objects | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 840 |   checkAttrArgsAreLockableObjs(S, D, Attr, Args, 1); | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 841 |  | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 842 |   return true; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 843 | } | 
 | 844 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 845 | static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D, | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 846 |                                             const AttributeList &Attr) { | 
 | 847 |   SmallVector<Expr*, 2> Args; | 
 | 848 |   if (!checkTryLockFunAttrCommon(S, D, Attr, Args)) | 
 | 849 |     return; | 
 | 850 |  | 
 | 851 |   unsigned Size = Args.size(); | 
 | 852 |   Expr **StartArg = Size == 0 ? 0 : &Args[0]; | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 853 |   D->addAttr(::new (S.Context) | 
 | 854 |              SharedTrylockFunctionAttr(Attr.getRange(), S.Context, | 
 | 855 |                                        Attr.getArg(0), StartArg, Size, | 
 | 856 |                                        Attr.getAttributeSpellingListIndex())); | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 857 | } | 
 | 858 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 859 | static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 860 |                                                const AttributeList &Attr) { | 
 | 861 |   SmallVector<Expr*, 2> Args; | 
 | 862 |   if (!checkTryLockFunAttrCommon(S, D, Attr, Args)) | 
 | 863 |     return; | 
 | 864 |  | 
 | 865 |   unsigned Size = Args.size(); | 
 | 866 |   Expr **StartArg = Size == 0 ? 0 : &Args[0]; | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 867 |   D->addAttr(::new (S.Context) | 
 | 868 |              ExclusiveTrylockFunctionAttr(Attr.getRange(), S.Context, | 
 | 869 |                                           Attr.getArg(0), StartArg, Size, | 
 | 870 |                                           Attr.getAttributeSpellingListIndex())); | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 871 | } | 
 | 872 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 873 | static bool checkLocksRequiredCommon(Sema &S, Decl *D, | 
 | 874 |                                      const AttributeList &Attr, | 
| Craig Topper | 6b9240e | 2013-07-05 19:34:19 +0000 | [diff] [blame] | 875 |                                      SmallVectorImpl<Expr *> &Args) { | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 876 |   assert(!Attr.isInvalid()); | 
 | 877 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 878 |   if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 879 |     return false; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 880 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 881 |   if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { | 
| DeLesley Hutchins | 0aa52aa | 2012-06-19 23:25:19 +0000 | [diff] [blame] | 882 |     S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) | 
 | 883 |       << Attr.getName() << ThreadExpectedFunctionOrMethod; | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 884 |     return false; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 885 |   } | 
 | 886 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 887 |   // check that all arguments are lockable objects | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 888 |   checkAttrArgsAreLockableObjs(S, D, Attr, Args); | 
| Dmitri Gribenko | 1f78a50 | 2013-05-03 15:05:50 +0000 | [diff] [blame] | 889 |   if (Args.empty()) | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 890 |     return false; | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 891 |  | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 892 |   return true; | 
 | 893 | } | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 894 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 895 | static void handleExclusiveLocksRequiredAttr(Sema &S, Decl *D, | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 896 |                                              const AttributeList &Attr) { | 
 | 897 |   SmallVector<Expr*, 1> Args; | 
 | 898 |   if (!checkLocksRequiredCommon(S, D, Attr, Args)) | 
 | 899 |     return; | 
 | 900 |  | 
 | 901 |   Expr **StartArg = &Args[0]; | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 902 |   D->addAttr(::new (S.Context) | 
 | 903 |              ExclusiveLocksRequiredAttr(Attr.getRange(), S.Context, | 
 | 904 |                                         StartArg, Args.size(), | 
 | 905 |                                         Attr.getAttributeSpellingListIndex())); | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 906 | } | 
 | 907 |  | 
| Michael Han | f1aae3b | 2012-08-03 17:40:43 +0000 | [diff] [blame] | 908 | static void handleSharedLocksRequiredAttr(Sema &S, Decl *D, | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 909 |                                           const AttributeList &Attr) { | 
 | 910 |   SmallVector<Expr*, 1> Args; | 
 | 911 |   if (!checkLocksRequiredCommon(S, D, Attr, Args)) | 
 | 912 |     return; | 
 | 913 |  | 
 | 914 |   Expr **StartArg = &Args[0]; | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 915 |   D->addAttr(::new (S.Context) | 
 | 916 |              SharedLocksRequiredAttr(Attr.getRange(), S.Context, | 
 | 917 |                                      StartArg, Args.size(), | 
 | 918 |                                      Attr.getAttributeSpellingListIndex())); | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 919 | } | 
 | 920 |  | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 921 | static void handleUnlockFunAttr(Sema &S, Decl *D, | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 922 |                                 const AttributeList &Attr) { | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 923 |   assert(!Attr.isInvalid()); | 
 | 924 |  | 
 | 925 |   // zero or more arguments ok | 
 | 926 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 927 |   if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { | 
| DeLesley Hutchins | 0aa52aa | 2012-06-19 23:25:19 +0000 | [diff] [blame] | 928 |     S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) | 
 | 929 |       << Attr.getName() << ThreadExpectedFunctionOrMethod; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 930 |     return; | 
 | 931 |   } | 
 | 932 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 933 |   // check that all arguments are lockable objects | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 934 |   SmallVector<Expr*, 1> Args; | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 935 |   checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true); | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 936 |   unsigned Size = Args.size(); | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 937 |   Expr **StartArg = Size == 0 ? 0 : &Args[0]; | 
 | 938 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 939 |   D->addAttr(::new (S.Context) | 
 | 940 |              UnlockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size, | 
 | 941 |                                 Attr.getAttributeSpellingListIndex())); | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 942 | } | 
 | 943 |  | 
 | 944 | static void handleLockReturnedAttr(Sema &S, Decl *D, | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 945 |                                    const AttributeList &Attr) { | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 946 |   assert(!Attr.isInvalid()); | 
 | 947 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 948 |   if (!checkAttributeNumArgs(S, Attr, 1)) | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 949 |     return; | 
 | 950 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 951 |   if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { | 
| DeLesley Hutchins | 0aa52aa | 2012-06-19 23:25:19 +0000 | [diff] [blame] | 952 |     S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) | 
 | 953 |       << Attr.getName() << ThreadExpectedFunctionOrMethod; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 954 |     return; | 
 | 955 |   } | 
 | 956 |  | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 957 |   // check that the argument is lockable object | 
| DeLesley Hutchins | f26efd7 | 2012-05-02 17:38:37 +0000 | [diff] [blame] | 958 |   SmallVector<Expr*, 1> Args; | 
 | 959 |   checkAttrArgsAreLockableObjs(S, D, Attr, Args); | 
 | 960 |   unsigned Size = Args.size(); | 
 | 961 |   if (Size == 0) | 
 | 962 |     return; | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 963 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 964 |   D->addAttr(::new (S.Context) | 
 | 965 |              LockReturnedAttr(Attr.getRange(), S.Context, Args[0], | 
 | 966 |                               Attr.getAttributeSpellingListIndex())); | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 967 | } | 
 | 968 |  | 
 | 969 | static void handleLocksExcludedAttr(Sema &S, Decl *D, | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 970 |                                     const AttributeList &Attr) { | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 971 |   assert(!Attr.isInvalid()); | 
 | 972 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 973 |   if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 974 |     return; | 
 | 975 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 976 |   if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { | 
| DeLesley Hutchins | 0aa52aa | 2012-06-19 23:25:19 +0000 | [diff] [blame] | 977 |     S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) | 
 | 978 |       << Attr.getName() << ThreadExpectedFunctionOrMethod; | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 979 |     return; | 
 | 980 |   } | 
 | 981 |  | 
| Caitlin Sadowski | b51e031 | 2011-08-09 17:59:31 +0000 | [diff] [blame] | 982 |   // check that all arguments are lockable objects | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 983 |   SmallVector<Expr*, 1> Args; | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 984 |   checkAttrArgsAreLockableObjs(S, D, Attr, Args); | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 985 |   unsigned Size = Args.size(); | 
| DeLesley Hutchins | ae519c4 | 2012-04-19 16:10:44 +0000 | [diff] [blame] | 986 |   if (Size == 0) | 
 | 987 |     return; | 
 | 988 |   Expr **StartArg = &Args[0]; | 
| Caitlin Sadowski | 3ac1fbc | 2011-08-23 18:46:34 +0000 | [diff] [blame] | 989 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 990 |   D->addAttr(::new (S.Context) | 
 | 991 |              LocksExcludedAttr(Attr.getRange(), S.Context, StartArg, Size, | 
 | 992 |                                Attr.getAttributeSpellingListIndex())); | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 993 | } | 
 | 994 |  | 
 | 995 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 996 | static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D, | 
 | 997 |                                     const AttributeList &Attr) { | 
| Richard Smith | a4fa900 | 2013-01-13 02:11:23 +0000 | [diff] [blame] | 998 |   TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); | 
 | 999 |   if (TD == 0) { | 
 | 1000 |     // __attribute__((ext_vector_type(N))) can only be applied to typedefs | 
 | 1001 |     // and type-ids. | 
| Chris Lattner | 803d080 | 2008-06-29 00:43:07 +0000 | [diff] [blame] | 1002 |     S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); | 
| Chris Lattner | 545dd34 | 2008-06-28 23:36:30 +0000 | [diff] [blame] | 1003 |     return; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1004 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1005 |  | 
| Richard Smith | a4fa900 | 2013-01-13 02:11:23 +0000 | [diff] [blame] | 1006 |   // Remember this typedef decl, we will need it later for diagnostics. | 
 | 1007 |   S.ExtVectorDecls.push_back(TD); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1008 | } | 
 | 1009 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1010 | static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1011 |   // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 1012 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1013 |     return; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1014 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1015 |   if (TagDecl *TD = dyn_cast<TagDecl>(D)) | 
| Argyrios Kyrtzidis | 768d6ca | 2011-09-13 16:05:58 +0000 | [diff] [blame] | 1016 |     TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context)); | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1017 |   else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1018 |     // If the alignment is less than or equal to 8 bits, the packed attribute | 
 | 1019 |     // has no effect. | 
| Eli Friedman | b68ec6b | 2012-11-07 00:35:20 +0000 | [diff] [blame] | 1020 |     if (!FD->getType()->isDependentType() && | 
 | 1021 |         !FD->getType()->isIncompleteType() && | 
| Chris Lattner | 803d080 | 2008-06-29 00:43:07 +0000 | [diff] [blame] | 1022 |         S.Context.getTypeAlign(FD->getType()) <= 8) | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1023 |       S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) | 
| Chris Lattner | 08631c5 | 2008-11-23 21:45:46 +0000 | [diff] [blame] | 1024 |         << Attr.getName() << FD->getType(); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1025 |     else | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1026 |       FD->addAttr(::new (S.Context) | 
 | 1027 |                   PackedAttr(Attr.getRange(), S.Context, | 
 | 1028 |                              Attr.getAttributeSpellingListIndex())); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1029 |   } else | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 1030 |     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1031 | } | 
 | 1032 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1033 | static void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Eli Friedman | 5f608ae | 2012-10-12 23:29:20 +0000 | [diff] [blame] | 1034 |   if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1035 |     RD->addAttr(::new (S.Context) | 
 | 1036 |                 MsStructAttr(Attr.getRange(), S.Context, | 
 | 1037 |                              Attr.getAttributeSpellingListIndex())); | 
| Fariborz Jahanian | c1a0a73 | 2011-04-26 17:54:40 +0000 | [diff] [blame] | 1038 |   else | 
 | 1039 |     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); | 
 | 1040 | } | 
 | 1041 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1042 | static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Ted Kremenek | 96329d4 | 2008-07-15 22:26:48 +0000 | [diff] [blame] | 1043 |   // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 1044 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Ted Kremenek | 96329d4 | 2008-07-15 22:26:48 +0000 | [diff] [blame] | 1045 |     return; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1046 |  | 
| Ted Kremenek | 63e5d7c | 2010-02-18 03:08:58 +0000 | [diff] [blame] | 1047 |   // The IBAction attributes only apply to instance methods. | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1048 |   if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) | 
| Ted Kremenek | 63e5d7c | 2010-02-18 03:08:58 +0000 | [diff] [blame] | 1049 |     if (MD->isInstanceMethod()) { | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1050 |       D->addAttr(::new (S.Context) | 
 | 1051 |                  IBActionAttr(Attr.getRange(), S.Context, | 
 | 1052 |                               Attr.getAttributeSpellingListIndex())); | 
| Ted Kremenek | 63e5d7c | 2010-02-18 03:08:58 +0000 | [diff] [blame] | 1053 |       return; | 
 | 1054 |     } | 
 | 1055 |  | 
| Ted Kremenek | 4ee2bb1 | 2011-02-04 06:54:16 +0000 | [diff] [blame] | 1056 |   S.Diag(Attr.getLoc(), diag::warn_attribute_ibaction) << Attr.getName(); | 
| Ted Kremenek | 63e5d7c | 2010-02-18 03:08:58 +0000 | [diff] [blame] | 1057 | } | 
 | 1058 |  | 
| Ted Kremenek | 2f041d0 | 2011-09-29 07:02:25 +0000 | [diff] [blame] | 1059 | static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) { | 
 | 1060 |   // The IBOutlet/IBOutletCollection attributes only apply to instance | 
 | 1061 |   // variables or properties of Objective-C classes.  The outlet must also | 
 | 1062 |   // have an object reference type. | 
 | 1063 |   if (const ObjCIvarDecl *VD = dyn_cast<ObjCIvarDecl>(D)) { | 
 | 1064 |     if (!VD->getType()->getAs<ObjCObjectPointerType>()) { | 
| Ted Kremenek | 0bfaf06 | 2011-11-01 18:08:35 +0000 | [diff] [blame] | 1065 |       S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type) | 
| Ted Kremenek | 2f041d0 | 2011-09-29 07:02:25 +0000 | [diff] [blame] | 1066 |         << Attr.getName() << VD->getType() << 0; | 
 | 1067 |       return false; | 
 | 1068 |     } | 
 | 1069 |   } | 
 | 1070 |   else if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) { | 
 | 1071 |     if (!PD->getType()->getAs<ObjCObjectPointerType>()) { | 
| Douglas Gregor | f6b8b58 | 2012-03-14 16:55:17 +0000 | [diff] [blame] | 1072 |       S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type) | 
| Ted Kremenek | 2f041d0 | 2011-09-29 07:02:25 +0000 | [diff] [blame] | 1073 |         << Attr.getName() << PD->getType() << 1; | 
 | 1074 |       return false; | 
 | 1075 |     } | 
 | 1076 |   } | 
 | 1077 |   else { | 
 | 1078 |     S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName(); | 
 | 1079 |     return false; | 
 | 1080 |   } | 
| Douglas Gregor | f6b8b58 | 2012-03-14 16:55:17 +0000 | [diff] [blame] | 1081 |  | 
| Ted Kremenek | 2f041d0 | 2011-09-29 07:02:25 +0000 | [diff] [blame] | 1082 |   return true; | 
 | 1083 | } | 
 | 1084 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1085 | static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Ted Kremenek | 63e5d7c | 2010-02-18 03:08:58 +0000 | [diff] [blame] | 1086 |   // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 1087 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Ted Kremenek | 63e5d7c | 2010-02-18 03:08:58 +0000 | [diff] [blame] | 1088 |     return; | 
| Ted Kremenek | 2f041d0 | 2011-09-29 07:02:25 +0000 | [diff] [blame] | 1089 |    | 
 | 1090 |   if (!checkIBOutletCommon(S, D, Attr)) | 
| Ted Kremenek | 63e5d7c | 2010-02-18 03:08:58 +0000 | [diff] [blame] | 1091 |     return; | 
| Ted Kremenek | 63e5d7c | 2010-02-18 03:08:58 +0000 | [diff] [blame] | 1092 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1093 |   D->addAttr(::new (S.Context) | 
 | 1094 |              IBOutletAttr(Attr.getRange(), S.Context, | 
 | 1095 |                           Attr.getAttributeSpellingListIndex())); | 
| Ted Kremenek | 96329d4 | 2008-07-15 22:26:48 +0000 | [diff] [blame] | 1096 | } | 
 | 1097 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1098 | static void handleIBOutletCollection(Sema &S, Decl *D, | 
 | 1099 |                                      const AttributeList &Attr) { | 
| Ted Kremenek | 857e918 | 2010-05-19 17:38:06 +0000 | [diff] [blame] | 1100 |  | 
 | 1101 |   // The iboutletcollection attribute can have zero or one arguments. | 
| Fariborz Jahanian | a8fb24f | 2010-08-17 20:23:12 +0000 | [diff] [blame] | 1102 |   if (Attr.getParameterName() && Attr.getNumArgs() > 0) { | 
| Ted Kremenek | 857e918 | 2010-05-19 17:38:06 +0000 | [diff] [blame] | 1103 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; | 
 | 1104 |     return; | 
 | 1105 |   } | 
 | 1106 |  | 
| Ted Kremenek | 2f041d0 | 2011-09-29 07:02:25 +0000 | [diff] [blame] | 1107 |   if (!checkIBOutletCommon(S, D, Attr)) | 
| Ted Kremenek | 857e918 | 2010-05-19 17:38:06 +0000 | [diff] [blame] | 1108 |     return; | 
| Ted Kremenek | 2f041d0 | 2011-09-29 07:02:25 +0000 | [diff] [blame] | 1109 |  | 
| Fariborz Jahanian | a8fb24f | 2010-08-17 20:23:12 +0000 | [diff] [blame] | 1110 |   IdentifierInfo *II = Attr.getParameterName(); | 
 | 1111 |   if (!II) | 
| Fariborz Jahanian | f4072ae | 2011-10-18 19:54:31 +0000 | [diff] [blame] | 1112 |     II = &S.Context.Idents.get("NSObject"); | 
| Fariborz Jahanian | 3a3400b | 2010-08-17 21:39:27 +0000 | [diff] [blame] | 1113 |    | 
| John McCall | b3d8748 | 2010-08-24 05:47:05 +0000 | [diff] [blame] | 1114 |   ParsedType TypeRep = S.getTypeName(*II, Attr.getLoc(),  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1115 |                         S.getScopeForContext(D->getDeclContext()->getParent())); | 
| Fariborz Jahanian | a8fb24f | 2010-08-17 20:23:12 +0000 | [diff] [blame] | 1116 |   if (!TypeRep) { | 
 | 1117 |     S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; | 
 | 1118 |     return; | 
 | 1119 |   } | 
| John McCall | b3d8748 | 2010-08-24 05:47:05 +0000 | [diff] [blame] | 1120 |   QualType QT = TypeRep.get(); | 
| Fariborz Jahanian | a8fb24f | 2010-08-17 20:23:12 +0000 | [diff] [blame] | 1121 |   // Diagnose use of non-object type in iboutletcollection attribute. | 
 | 1122 |   // FIXME. Gnu attribute extension ignores use of builtin types in | 
 | 1123 |   // attributes. So, __attribute__((iboutletcollection(char))) will be | 
 | 1124 |   // treated as __attribute__((iboutletcollection())). | 
| Fariborz Jahanian | f4072ae | 2011-10-18 19:54:31 +0000 | [diff] [blame] | 1125 |   if (!QT->isObjCIdType() && !QT->isObjCObjectType()) { | 
| Fariborz Jahanian | a8fb24f | 2010-08-17 20:23:12 +0000 | [diff] [blame] | 1126 |     S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; | 
 | 1127 |     return; | 
 | 1128 |   } | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1129 |   D->addAttr(::new (S.Context) | 
 | 1130 |              IBOutletCollectionAttr(Attr.getRange(),S.Context, | 
 | 1131 |                                     QT, Attr.getParameterLoc(), | 
 | 1132 |                                     Attr.getAttributeSpellingListIndex())); | 
| Ted Kremenek | 857e918 | 2010-05-19 17:38:06 +0000 | [diff] [blame] | 1133 | } | 
 | 1134 |  | 
| Chandler Carruth | d309c81 | 2011-07-01 23:49:16 +0000 | [diff] [blame] | 1135 | static void possibleTransparentUnionPointerType(QualType &T) { | 
| Fariborz Jahanian | 68fe96a | 2011-06-27 21:12:03 +0000 | [diff] [blame] | 1136 |   if (const RecordType *UT = T->getAsUnionType()) | 
 | 1137 |     if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) { | 
 | 1138 |       RecordDecl *UD = UT->getDecl(); | 
 | 1139 |       for (RecordDecl::field_iterator it = UD->field_begin(), | 
 | 1140 |            itend = UD->field_end(); it != itend; ++it) { | 
 | 1141 |         QualType QT = it->getType(); | 
 | 1142 |         if (QT->isAnyPointerType() || QT->isBlockPointerType()) { | 
 | 1143 |           T = QT; | 
 | 1144 |           return; | 
 | 1145 |         } | 
 | 1146 |       } | 
 | 1147 |     } | 
 | 1148 | } | 
 | 1149 |  | 
| Nuno Lopes | 587de5b | 2012-05-24 00:22:00 +0000 | [diff] [blame] | 1150 | static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Nuno Lopes | 174930d | 2012-06-18 16:39:04 +0000 | [diff] [blame] | 1151 |   if (!isFunctionOrMethod(D)) { | 
 | 1152 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
 | 1153 |     << "alloc_size" << ExpectedFunctionOrMethod; | 
 | 1154 |     return; | 
 | 1155 |   } | 
 | 1156 |  | 
| Nuno Lopes | 587de5b | 2012-05-24 00:22:00 +0000 | [diff] [blame] | 1157 |   if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) | 
 | 1158 |     return; | 
 | 1159 |  | 
 | 1160 |   // In C++ the implicit 'this' function parameter also counts, and they are | 
 | 1161 |   // counted from one. | 
 | 1162 |   bool HasImplicitThisParam = isInstanceMethod(D); | 
| Argyrios Kyrtzidis | 28965bf | 2013-02-22 06:58:28 +0000 | [diff] [blame] | 1163 |   unsigned NumArgs; | 
 | 1164 |   if (hasFunctionProto(D)) | 
 | 1165 |     NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; | 
 | 1166 |   else | 
 | 1167 |     NumArgs = 0; | 
| Nuno Lopes | 587de5b | 2012-05-24 00:22:00 +0000 | [diff] [blame] | 1168 |  | 
 | 1169 |   SmallVector<unsigned, 8> SizeArgs; | 
 | 1170 |  | 
 | 1171 |   for (AttributeList::arg_iterator I = Attr.arg_begin(), | 
 | 1172 |        E = Attr.arg_end(); I!=E; ++I) { | 
 | 1173 |     // The argument must be an integer constant expression. | 
 | 1174 |     Expr *Ex = *I; | 
 | 1175 |     llvm::APSInt ArgNum; | 
 | 1176 |     if (Ex->isTypeDependent() || Ex->isValueDependent() || | 
 | 1177 |         !Ex->isIntegerConstantExpr(ArgNum, S.Context)) { | 
 | 1178 |       S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) | 
 | 1179 |       << "alloc_size" << Ex->getSourceRange(); | 
 | 1180 |       return; | 
 | 1181 |     } | 
 | 1182 |  | 
 | 1183 |     uint64_t x = ArgNum.getZExtValue(); | 
 | 1184 |  | 
 | 1185 |     if (x < 1 || x > NumArgs) { | 
 | 1186 |       S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) | 
 | 1187 |       << "alloc_size" << I.getArgNum() << Ex->getSourceRange(); | 
 | 1188 |       return; | 
 | 1189 |     } | 
 | 1190 |  | 
 | 1191 |     --x; | 
 | 1192 |     if (HasImplicitThisParam) { | 
 | 1193 |       if (x == 0) { | 
 | 1194 |         S.Diag(Attr.getLoc(), | 
 | 1195 |                diag::err_attribute_invalid_implicit_this_argument) | 
 | 1196 |         << "alloc_size" << Ex->getSourceRange(); | 
 | 1197 |         return; | 
 | 1198 |       } | 
 | 1199 |       --x; | 
 | 1200 |     } | 
 | 1201 |  | 
 | 1202 |     // check if the function argument is of an integer type | 
 | 1203 |     QualType T = getFunctionOrMethodArgType(D, x).getNonReferenceType(); | 
 | 1204 |     if (!T->isIntegerType()) { | 
 | 1205 |       S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) | 
 | 1206 |       << "alloc_size" << Ex->getSourceRange(); | 
 | 1207 |       return; | 
 | 1208 |     } | 
 | 1209 |  | 
| Nuno Lopes | 587de5b | 2012-05-24 00:22:00 +0000 | [diff] [blame] | 1210 |     SizeArgs.push_back(x); | 
 | 1211 |   } | 
 | 1212 |  | 
 | 1213 |   // check if the function returns a pointer | 
 | 1214 |   if (!getFunctionType(D)->getResultType()->isAnyPointerType()) { | 
 | 1215 |     S.Diag(Attr.getLoc(), diag::warn_ns_attribute_wrong_return_type) | 
 | 1216 |     << "alloc_size" << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange(); | 
 | 1217 |   } | 
 | 1218 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1219 |   D->addAttr(::new (S.Context) | 
 | 1220 |              AllocSizeAttr(Attr.getRange(), S.Context, | 
 | 1221 |                            SizeArgs.data(), SizeArgs.size(), | 
 | 1222 |                            Attr.getAttributeSpellingListIndex())); | 
| Nuno Lopes | 587de5b | 2012-05-24 00:22:00 +0000 | [diff] [blame] | 1223 | } | 
 | 1224 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1225 | static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1226 |   // GCC ignores the nonnull attribute on K&R style function prototypes, so we | 
 | 1227 |   // ignore it as well | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1228 |   if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1229 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 1230 |       << Attr.getName() << ExpectedFunction; | 
| Ted Kremenek | eb2b2a3 | 2008-07-21 21:53:04 +0000 | [diff] [blame] | 1231 |     return; | 
 | 1232 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1233 |  | 
| Chandler Carruth | 07d7e7a | 2010-11-16 08:35:43 +0000 | [diff] [blame] | 1234 |   // In C++ the implicit 'this' function parameter also counts, and they are | 
 | 1235 |   // counted from one. | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1236 |   bool HasImplicitThisParam = isInstanceMethod(D); | 
| Nick Lewycky | 5d9484d | 2013-01-24 01:12:16 +0000 | [diff] [blame] | 1237 |   unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; | 
| Ted Kremenek | eb2b2a3 | 2008-07-21 21:53:04 +0000 | [diff] [blame] | 1238 |  | 
 | 1239 |   // The nonnull attribute only applies to pointers. | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 1240 |   SmallVector<unsigned, 10> NonNullArgs; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1241 |  | 
| Nick Lewycky | 5d9484d | 2013-01-24 01:12:16 +0000 | [diff] [blame] | 1242 |   for (AttributeList::arg_iterator I = Attr.arg_begin(), | 
 | 1243 |                                    E = Attr.arg_end(); I != E; ++I) { | 
| Ted Kremenek | eb2b2a3 | 2008-07-21 21:53:04 +0000 | [diff] [blame] | 1244 |     // The argument must be an integer constant expression. | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 1245 |     Expr *Ex = *I; | 
| Ted Kremenek | eb2b2a3 | 2008-07-21 21:53:04 +0000 | [diff] [blame] | 1246 |     llvm::APSInt ArgNum(32); | 
| Douglas Gregor | ac06a0e | 2010-05-18 23:01:22 +0000 | [diff] [blame] | 1247 |     if (Ex->isTypeDependent() || Ex->isValueDependent() || | 
 | 1248 |         !Ex->isIntegerConstantExpr(ArgNum, S.Context)) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1249 |       S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) | 
 | 1250 |         << "nonnull" << Ex->getSourceRange(); | 
| Ted Kremenek | eb2b2a3 | 2008-07-21 21:53:04 +0000 | [diff] [blame] | 1251 |       return; | 
 | 1252 |     } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1253 |  | 
| Ted Kremenek | eb2b2a3 | 2008-07-21 21:53:04 +0000 | [diff] [blame] | 1254 |     unsigned x = (unsigned) ArgNum.getZExtValue(); | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1255 |  | 
| Ted Kremenek | eb2b2a3 | 2008-07-21 21:53:04 +0000 | [diff] [blame] | 1256 |     if (x < 1 || x > NumArgs) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1257 |       S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) | 
| Chris Lattner | 30bc965 | 2008-11-19 07:22:31 +0000 | [diff] [blame] | 1258 |        << "nonnull" << I.getArgNum() << Ex->getSourceRange(); | 
| Ted Kremenek | eb2b2a3 | 2008-07-21 21:53:04 +0000 | [diff] [blame] | 1259 |       return; | 
 | 1260 |     } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1261 |  | 
| Ted Kremenek | 465172f | 2008-07-21 22:09:15 +0000 | [diff] [blame] | 1262 |     --x; | 
| Chandler Carruth | 07d7e7a | 2010-11-16 08:35:43 +0000 | [diff] [blame] | 1263 |     if (HasImplicitThisParam) { | 
 | 1264 |       if (x == 0) { | 
 | 1265 |         S.Diag(Attr.getLoc(), | 
 | 1266 |                diag::err_attribute_invalid_implicit_this_argument) | 
 | 1267 |           << "nonnull" << Ex->getSourceRange(); | 
 | 1268 |         return; | 
 | 1269 |       } | 
 | 1270 |       --x; | 
 | 1271 |     } | 
| Ted Kremenek | eb2b2a3 | 2008-07-21 21:53:04 +0000 | [diff] [blame] | 1272 |  | 
 | 1273 |     // Is the function argument a pointer type? | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1274 |     QualType T = getFunctionOrMethodArgType(D, x).getNonReferenceType(); | 
| Chandler Carruth | d309c81 | 2011-07-01 23:49:16 +0000 | [diff] [blame] | 1275 |     possibleTransparentUnionPointerType(T); | 
| Fariborz Jahanian | 68fe96a | 2011-06-27 21:12:03 +0000 | [diff] [blame] | 1276 |      | 
| Ted Kremenek | dbfe99e | 2009-07-15 23:23:54 +0000 | [diff] [blame] | 1277 |     if (!T->isAnyPointerType() && !T->isBlockPointerType()) { | 
| Ted Kremenek | eb2b2a3 | 2008-07-21 21:53:04 +0000 | [diff] [blame] | 1278 |       // FIXME: Should also highlight argument in decl. | 
| Douglas Gregor | c9ef405 | 2010-08-12 18:48:43 +0000 | [diff] [blame] | 1279 |       S.Diag(Attr.getLoc(), diag::warn_nonnull_pointers_only) | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1280 |         << "nonnull" << Ex->getSourceRange(); | 
| Ted Kremenek | 7fb43c1 | 2008-09-01 19:57:52 +0000 | [diff] [blame] | 1281 |       continue; | 
| Ted Kremenek | eb2b2a3 | 2008-07-21 21:53:04 +0000 | [diff] [blame] | 1282 |     } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1283 |  | 
| Ted Kremenek | eb2b2a3 | 2008-07-21 21:53:04 +0000 | [diff] [blame] | 1284 |     NonNullArgs.push_back(x); | 
 | 1285 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1286 |  | 
 | 1287 |   // If no arguments were specified to __attribute__((nonnull)) then all pointer | 
 | 1288 |   // arguments have a nonnull attribute. | 
| Ted Kremenek | 7fb43c1 | 2008-09-01 19:57:52 +0000 | [diff] [blame] | 1289 |   if (NonNullArgs.empty()) { | 
| Nick Lewycky | 5d9484d | 2013-01-24 01:12:16 +0000 | [diff] [blame] | 1290 |     for (unsigned i = 0, e = getFunctionOrMethodNumArgs(D); i != e; ++i) { | 
 | 1291 |       QualType T = getFunctionOrMethodArgType(D, i).getNonReferenceType(); | 
| Chandler Carruth | d309c81 | 2011-07-01 23:49:16 +0000 | [diff] [blame] | 1292 |       possibleTransparentUnionPointerType(T); | 
| Ted Kremenek | dbfe99e | 2009-07-15 23:23:54 +0000 | [diff] [blame] | 1293 |       if (T->isAnyPointerType() || T->isBlockPointerType()) | 
| Nick Lewycky | 5d9484d | 2013-01-24 01:12:16 +0000 | [diff] [blame] | 1294 |         NonNullArgs.push_back(i); | 
| Ted Kremenek | 46bbaca | 2008-11-18 06:52:58 +0000 | [diff] [blame] | 1295 |     } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1296 |  | 
| Ted Kremenek | ee1c08c | 2010-10-21 18:49:36 +0000 | [diff] [blame] | 1297 |     // No pointer arguments? | 
| Fariborz Jahanian | 60acea4 | 2010-09-27 19:05:51 +0000 | [diff] [blame] | 1298 |     if (NonNullArgs.empty()) { | 
 | 1299 |       // Warn the trivial case only if attribute is not coming from a | 
 | 1300 |       // macro instantiation. | 
 | 1301 |       if (Attr.getLoc().isFileID()) | 
 | 1302 |         S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers); | 
| Ted Kremenek | 7fb43c1 | 2008-09-01 19:57:52 +0000 | [diff] [blame] | 1303 |       return; | 
| Fariborz Jahanian | 60acea4 | 2010-09-27 19:05:51 +0000 | [diff] [blame] | 1304 |     } | 
| Ted Kremenek | eb2b2a3 | 2008-07-21 21:53:04 +0000 | [diff] [blame] | 1305 |   } | 
| Ted Kremenek | 7fb43c1 | 2008-09-01 19:57:52 +0000 | [diff] [blame] | 1306 |  | 
| Nick Lewycky | 5d9484d | 2013-01-24 01:12:16 +0000 | [diff] [blame] | 1307 |   unsigned *start = &NonNullArgs[0]; | 
| Ted Kremenek | 7fb43c1 | 2008-09-01 19:57:52 +0000 | [diff] [blame] | 1308 |   unsigned size = NonNullArgs.size(); | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1309 |   llvm::array_pod_sort(start, start + size); | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1310 |   D->addAttr(::new (S.Context) | 
 | 1311 |              NonNullAttr(Attr.getRange(), S.Context, start, size, | 
 | 1312 |                          Attr.getAttributeSpellingListIndex())); | 
| Ted Kremenek | eb2b2a3 | 2008-07-21 21:53:04 +0000 | [diff] [blame] | 1313 | } | 
 | 1314 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1315 | static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1316 |   // This attribute must be applied to a function declaration. | 
 | 1317 |   // The first argument to the attribute must be a string, | 
 | 1318 |   // the name of the resource, for example "malloc". | 
 | 1319 |   // The following arguments must be argument indexes, the arguments must be | 
 | 1320 |   // of integer type for Returns, otherwise of pointer type. | 
 | 1321 |   // The difference between Holds and Takes is that a pointer may still be used | 
| Jordy Rose | 2a47992 | 2010-08-12 08:54:03 +0000 | [diff] [blame] | 1322 |   // after being held.  free() should be __attribute((ownership_takes)), whereas | 
 | 1323 |   // a list append function may well be __attribute((ownership_holds)). | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1324 |  | 
 | 1325 |   if (!AL.getParameterName()) { | 
 | 1326 |     S.Diag(AL.getLoc(), diag::err_attribute_argument_n_not_string) | 
 | 1327 |         << AL.getName()->getName() << 1; | 
 | 1328 |     return; | 
 | 1329 |   } | 
 | 1330 |   // Figure out our Kind, and check arguments while we're at it. | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 1331 |   OwnershipAttr::OwnershipKind K; | 
| Jordy Rose | 2a47992 | 2010-08-12 08:54:03 +0000 | [diff] [blame] | 1332 |   switch (AL.getKind()) { | 
 | 1333 |   case AttributeList::AT_ownership_takes: | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 1334 |     K = OwnershipAttr::Takes; | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1335 |     if (AL.getNumArgs() < 1) { | 
 | 1336 |       S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; | 
 | 1337 |       return; | 
 | 1338 |     } | 
| Jordy Rose | 2a47992 | 2010-08-12 08:54:03 +0000 | [diff] [blame] | 1339 |     break; | 
 | 1340 |   case AttributeList::AT_ownership_holds: | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 1341 |     K = OwnershipAttr::Holds; | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1342 |     if (AL.getNumArgs() < 1) { | 
 | 1343 |       S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; | 
 | 1344 |       return; | 
 | 1345 |     } | 
| Jordy Rose | 2a47992 | 2010-08-12 08:54:03 +0000 | [diff] [blame] | 1346 |     break; | 
 | 1347 |   case AttributeList::AT_ownership_returns: | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 1348 |     K = OwnershipAttr::Returns; | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1349 |     if (AL.getNumArgs() > 1) { | 
 | 1350 |       S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) | 
 | 1351 |           << AL.getNumArgs() + 1; | 
 | 1352 |       return; | 
 | 1353 |     } | 
| Jordy Rose | 2a47992 | 2010-08-12 08:54:03 +0000 | [diff] [blame] | 1354 |     break; | 
 | 1355 |   default: | 
 | 1356 |     // This should never happen given how we are called. | 
 | 1357 |     llvm_unreachable("Unknown ownership attribute"); | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1358 |   } | 
 | 1359 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1360 |   if (!isFunction(D) || !hasFunctionProto(D)) { | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 1361 |     S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) | 
 | 1362 |       << AL.getName() << ExpectedFunction; | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1363 |     return; | 
 | 1364 |   } | 
 | 1365 |  | 
| Chandler Carruth | 07d7e7a | 2010-11-16 08:35:43 +0000 | [diff] [blame] | 1366 |   // In C++ the implicit 'this' function parameter also counts, and they are | 
 | 1367 |   // counted from one. | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1368 |   bool HasImplicitThisParam = isInstanceMethod(D); | 
 | 1369 |   unsigned NumArgs  = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1370 |  | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 1371 |   StringRef Module = AL.getParameterName()->getName(); | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1372 |  | 
 | 1373 |   // Normalize the argument, __foo__ becomes foo. | 
 | 1374 |   if (Module.startswith("__") && Module.endswith("__")) | 
 | 1375 |     Module = Module.substr(2, Module.size() - 4); | 
 | 1376 |  | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 1377 |   SmallVector<unsigned, 10> OwnershipArgs; | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1378 |  | 
| Jordy Rose | 2a47992 | 2010-08-12 08:54:03 +0000 | [diff] [blame] | 1379 |   for (AttributeList::arg_iterator I = AL.arg_begin(), E = AL.arg_end(); I != E; | 
 | 1380 |        ++I) { | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1381 |  | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 1382 |     Expr *IdxExpr = *I; | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1383 |     llvm::APSInt ArgNum(32); | 
 | 1384 |     if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() | 
 | 1385 |         || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) { | 
 | 1386 |       S.Diag(AL.getLoc(), diag::err_attribute_argument_not_int) | 
 | 1387 |           << AL.getName()->getName() << IdxExpr->getSourceRange(); | 
 | 1388 |       continue; | 
 | 1389 |     } | 
 | 1390 |  | 
 | 1391 |     unsigned x = (unsigned) ArgNum.getZExtValue(); | 
 | 1392 |  | 
 | 1393 |     if (x > NumArgs || x < 1) { | 
 | 1394 |       S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) | 
 | 1395 |           << AL.getName()->getName() << x << IdxExpr->getSourceRange(); | 
 | 1396 |       continue; | 
 | 1397 |     } | 
 | 1398 |     --x; | 
| Chandler Carruth | 07d7e7a | 2010-11-16 08:35:43 +0000 | [diff] [blame] | 1399 |     if (HasImplicitThisParam) { | 
 | 1400 |       if (x == 0) { | 
 | 1401 |         S.Diag(AL.getLoc(), diag::err_attribute_invalid_implicit_this_argument) | 
 | 1402 |           << "ownership" << IdxExpr->getSourceRange(); | 
 | 1403 |         return; | 
 | 1404 |       } | 
 | 1405 |       --x; | 
 | 1406 |     } | 
 | 1407 |  | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1408 |     switch (K) { | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 1409 |     case OwnershipAttr::Takes: | 
 | 1410 |     case OwnershipAttr::Holds: { | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1411 |       // Is the function argument a pointer type? | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1412 |       QualType T = getFunctionOrMethodArgType(D, x); | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1413 |       if (!T->isAnyPointerType() && !T->isBlockPointerType()) { | 
 | 1414 |         // FIXME: Should also highlight argument in decl. | 
 | 1415 |         S.Diag(AL.getLoc(), diag::err_ownership_type) | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 1416 |             << ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds") | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1417 |             << "pointer" | 
 | 1418 |             << IdxExpr->getSourceRange(); | 
 | 1419 |         continue; | 
 | 1420 |       } | 
 | 1421 |       break; | 
 | 1422 |     } | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 1423 |     case OwnershipAttr::Returns: { | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1424 |       if (AL.getNumArgs() > 1) { | 
 | 1425 |           // Is the function argument an integer type? | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 1426 |           Expr *IdxExpr = AL.getArg(0); | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1427 |           llvm::APSInt ArgNum(32); | 
 | 1428 |           if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() | 
 | 1429 |               || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) { | 
 | 1430 |             S.Diag(AL.getLoc(), diag::err_ownership_type) | 
 | 1431 |                 << "ownership_returns" << "integer" | 
 | 1432 |                 << IdxExpr->getSourceRange(); | 
 | 1433 |             return; | 
 | 1434 |           } | 
 | 1435 |       } | 
 | 1436 |       break; | 
 | 1437 |     } | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1438 |     } // switch | 
 | 1439 |  | 
 | 1440 |     // Check we don't have a conflict with another ownership attribute. | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 1441 |     for (specific_attr_iterator<OwnershipAttr> | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1442 |           i = D->specific_attr_begin<OwnershipAttr>(), | 
 | 1443 |           e = D->specific_attr_end<OwnershipAttr>(); | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 1444 |         i != e; ++i) { | 
 | 1445 |       if ((*i)->getOwnKind() != K) { | 
 | 1446 |         for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end(); | 
 | 1447 |              I!=E; ++I) { | 
 | 1448 |           if (x == *I) { | 
 | 1449 |             S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) | 
 | 1450 |                 << AL.getName()->getName() << "ownership_*"; | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1451 |           } | 
 | 1452 |         } | 
 | 1453 |       } | 
 | 1454 |     } | 
 | 1455 |     OwnershipArgs.push_back(x); | 
 | 1456 |   } | 
 | 1457 |  | 
 | 1458 |   unsigned* start = OwnershipArgs.data(); | 
 | 1459 |   unsigned size = OwnershipArgs.size(); | 
 | 1460 |   llvm::array_pod_sort(start, start + size); | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 1461 |  | 
 | 1462 |   if (K != OwnershipAttr::Returns && OwnershipArgs.empty()) { | 
 | 1463 |     S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; | 
 | 1464 |     return; | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1465 |   } | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 1466 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1467 |   D->addAttr(::new (S.Context) | 
 | 1468 |              OwnershipAttr(AL.getLoc(), S.Context, K, Module, start, size, | 
 | 1469 |                            AL.getAttributeSpellingListIndex())); | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 1470 | } | 
 | 1471 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1472 | static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Rafael Espindola | 11e8ce7 | 2010-02-23 22:00:30 +0000 | [diff] [blame] | 1473 |   // Check the attribute arguments. | 
 | 1474 |   if (Attr.getNumArgs() > 1) { | 
 | 1475 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; | 
 | 1476 |     return; | 
 | 1477 |   } | 
 | 1478 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1479 |   if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) { | 
| John McCall | 332bb2a | 2011-02-08 22:35:49 +0000 | [diff] [blame] | 1480 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 1481 |       << Attr.getName() << ExpectedVariableOrFunction; | 
| John McCall | 332bb2a | 2011-02-08 22:35:49 +0000 | [diff] [blame] | 1482 |     return; | 
 | 1483 |   } | 
 | 1484 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1485 |   NamedDecl *nd = cast<NamedDecl>(D); | 
| John McCall | 332bb2a | 2011-02-08 22:35:49 +0000 | [diff] [blame] | 1486 |  | 
| Rafael Espindola | 11e8ce7 | 2010-02-23 22:00:30 +0000 | [diff] [blame] | 1487 |   // gcc rejects | 
 | 1488 |   // class c { | 
 | 1489 |   //   static int a __attribute__((weakref ("v2"))); | 
 | 1490 |   //   static int b() __attribute__((weakref ("f3"))); | 
 | 1491 |   // }; | 
 | 1492 |   // and ignores the attributes of | 
 | 1493 |   // void f(void) { | 
 | 1494 |   //   static int a __attribute__((weakref ("v2"))); | 
 | 1495 |   // } | 
 | 1496 |   // we reject them | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1497 |   const DeclContext *Ctx = D->getDeclContext()->getRedeclContext(); | 
| Sebastian Redl | 7a126a4 | 2010-08-31 00:36:30 +0000 | [diff] [blame] | 1498 |   if (!Ctx->isFileContext()) { | 
 | 1499 |     S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) << | 
| John McCall | 332bb2a | 2011-02-08 22:35:49 +0000 | [diff] [blame] | 1500 |         nd->getNameAsString(); | 
| Sebastian Redl | 7a126a4 | 2010-08-31 00:36:30 +0000 | [diff] [blame] | 1501 |     return; | 
| Rafael Espindola | 11e8ce7 | 2010-02-23 22:00:30 +0000 | [diff] [blame] | 1502 |   } | 
 | 1503 |  | 
 | 1504 |   // The GCC manual says | 
 | 1505 |   // | 
 | 1506 |   // At present, a declaration to which `weakref' is attached can only | 
 | 1507 |   // be `static'. | 
 | 1508 |   // | 
 | 1509 |   // It also says | 
 | 1510 |   // | 
 | 1511 |   // Without a TARGET, | 
 | 1512 |   // given as an argument to `weakref' or to `alias', `weakref' is | 
 | 1513 |   // equivalent to `weak'. | 
 | 1514 |   // | 
 | 1515 |   // gcc 4.4.1 will accept | 
 | 1516 |   // int a7 __attribute__((weakref)); | 
 | 1517 |   // as | 
 | 1518 |   // int a7 __attribute__((weak)); | 
 | 1519 |   // This looks like a bug in gcc. We reject that for now. We should revisit | 
 | 1520 |   // it if this behaviour is actually used. | 
 | 1521 |  | 
| Rafael Espindola | 11e8ce7 | 2010-02-23 22:00:30 +0000 | [diff] [blame] | 1522 |   // GCC rejects | 
 | 1523 |   // static ((alias ("y"), weakref)). | 
 | 1524 |   // Should we? How to check that weakref is before or after alias? | 
 | 1525 |  | 
 | 1526 |   if (Attr.getNumArgs() == 1) { | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 1527 |     Expr *Arg = Attr.getArg(0); | 
| Rafael Espindola | 11e8ce7 | 2010-02-23 22:00:30 +0000 | [diff] [blame] | 1528 |     Arg = Arg->IgnoreParenCasts(); | 
 | 1529 |     StringLiteral *Str = dyn_cast<StringLiteral>(Arg); | 
 | 1530 |  | 
| Douglas Gregor | 5cee119 | 2011-07-27 05:40:30 +0000 | [diff] [blame] | 1531 |     if (!Str || !Str->isAscii()) { | 
| Rafael Espindola | 11e8ce7 | 2010-02-23 22:00:30 +0000 | [diff] [blame] | 1532 |       S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) | 
 | 1533 |           << "weakref" << 1; | 
 | 1534 |       return; | 
 | 1535 |     } | 
 | 1536 |     // GCC will accept anything as the argument of weakref. Should we | 
 | 1537 |     // check for an existing decl? | 
| Argyrios Kyrtzidis | 768d6ca | 2011-09-13 16:05:58 +0000 | [diff] [blame] | 1538 |     D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, | 
| Eric Christopher | f48f367 | 2010-12-01 22:13:54 +0000 | [diff] [blame] | 1539 |                                            Str->getString())); | 
| Rafael Espindola | 11e8ce7 | 2010-02-23 22:00:30 +0000 | [diff] [blame] | 1540 |   } | 
 | 1541 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1542 |   D->addAttr(::new (S.Context) | 
 | 1543 |              WeakRefAttr(Attr.getRange(), S.Context, | 
 | 1544 |                          Attr.getAttributeSpellingListIndex())); | 
| Rafael Espindola | 11e8ce7 | 2010-02-23 22:00:30 +0000 | [diff] [blame] | 1545 | } | 
 | 1546 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1547 | static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1548 |   // check the attribute arguments. | 
| Chris Lattner | 545dd34 | 2008-06-28 23:36:30 +0000 | [diff] [blame] | 1549 |   if (Attr.getNumArgs() != 1) { | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 1550 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1551 |     return; | 
 | 1552 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1553 |  | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 1554 |   Expr *Arg = Attr.getArg(0); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1555 |   Arg = Arg->IgnoreParenCasts(); | 
 | 1556 |   StringLiteral *Str = dyn_cast<StringLiteral>(Arg); | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1557 |  | 
| Douglas Gregor | 5cee119 | 2011-07-27 05:40:30 +0000 | [diff] [blame] | 1558 |   if (!Str || !Str->isAscii()) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1559 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 1560 |       << "alias" << 1; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1561 |     return; | 
 | 1562 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1563 |  | 
| Douglas Gregor | bcfd1f5 | 2011-09-02 00:18:52 +0000 | [diff] [blame] | 1564 |   if (S.Context.getTargetInfo().getTriple().isOSDarwin()) { | 
| Rafael Espindola | f5fe292 | 2010-12-07 15:23:23 +0000 | [diff] [blame] | 1565 |     S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin); | 
 | 1566 |     return; | 
 | 1567 |   } | 
 | 1568 |  | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1569 |   // FIXME: check if target symbol exists in current file | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1570 |  | 
| Argyrios Kyrtzidis | 768d6ca | 2011-09-13 16:05:58 +0000 | [diff] [blame] | 1571 |   D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1572 |                                          Str->getString(), | 
 | 1573 |                                          Attr.getAttributeSpellingListIndex())); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1574 | } | 
 | 1575 |  | 
| Quentin Colombet | aee56fa | 2012-11-01 23:55:47 +0000 | [diff] [blame] | 1576 | static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
 | 1577 |   // Check the attribute arguments. | 
 | 1578 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
 | 1579 |     return; | 
 | 1580 |  | 
 | 1581 |   if (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D)) { | 
 | 1582 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) | 
 | 1583 |       << Attr.getName() << ExpectedFunctionOrMethod; | 
 | 1584 |     return; | 
 | 1585 |   } | 
 | 1586 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1587 |   D->addAttr(::new (S.Context) | 
 | 1588 |              MinSizeAttr(Attr.getRange(), S.Context, | 
 | 1589 |                          Attr.getAttributeSpellingListIndex())); | 
| Quentin Colombet | aee56fa | 2012-11-01 23:55:47 +0000 | [diff] [blame] | 1590 | } | 
 | 1591 |  | 
| Benjamin Kramer | ee409a9 | 2012-05-12 21:10:52 +0000 | [diff] [blame] | 1592 | static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
 | 1593 |   // Check the attribute arguments. | 
 | 1594 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
 | 1595 |     return; | 
 | 1596 |  | 
 | 1597 |   if (!isa<FunctionDecl>(D)) { | 
 | 1598 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
 | 1599 |       << Attr.getName() << ExpectedFunction; | 
 | 1600 |     return; | 
 | 1601 |   } | 
 | 1602 |  | 
 | 1603 |   if (D->hasAttr<HotAttr>()) { | 
 | 1604 |     S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) | 
 | 1605 |       << Attr.getName() << "hot"; | 
 | 1606 |     return; | 
 | 1607 |   } | 
 | 1608 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1609 |   D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context, | 
 | 1610 |                                         Attr.getAttributeSpellingListIndex())); | 
| Benjamin Kramer | ee409a9 | 2012-05-12 21:10:52 +0000 | [diff] [blame] | 1611 | } | 
 | 1612 |  | 
 | 1613 | static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
 | 1614 |   // Check the attribute arguments. | 
 | 1615 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
 | 1616 |     return; | 
 | 1617 |  | 
 | 1618 |   if (!isa<FunctionDecl>(D)) { | 
 | 1619 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
 | 1620 |       << Attr.getName() << ExpectedFunction; | 
 | 1621 |     return; | 
 | 1622 |   } | 
 | 1623 |  | 
 | 1624 |   if (D->hasAttr<ColdAttr>()) { | 
 | 1625 |     S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) | 
 | 1626 |       << Attr.getName() << "cold"; | 
 | 1627 |     return; | 
 | 1628 |   } | 
 | 1629 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1630 |   D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context, | 
 | 1631 |                                        Attr.getAttributeSpellingListIndex())); | 
| Benjamin Kramer | ee409a9 | 2012-05-12 21:10:52 +0000 | [diff] [blame] | 1632 | } | 
 | 1633 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1634 | static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Daniel Dunbar | dd0cb22 | 2010-09-29 18:20:25 +0000 | [diff] [blame] | 1635 |   // Check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 1636 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Daniel Dunbar | af668b0 | 2008-10-28 00:17:57 +0000 | [diff] [blame] | 1637 |     return; | 
| Anders Carlsson | 5bab788 | 2009-02-19 19:16:48 +0000 | [diff] [blame] | 1638 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1639 |   if (!isa<FunctionDecl>(D)) { | 
| Anders Carlsson | 5bab788 | 2009-02-19 19:16:48 +0000 | [diff] [blame] | 1640 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 1641 |       << Attr.getName() << ExpectedFunction; | 
| Daniel Dunbar | dd0cb22 | 2010-09-29 18:20:25 +0000 | [diff] [blame] | 1642 |     return; | 
 | 1643 |   } | 
 | 1644 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1645 |   D->addAttr(::new (S.Context) | 
 | 1646 |              NakedAttr(Attr.getRange(), S.Context, | 
 | 1647 |                        Attr.getAttributeSpellingListIndex())); | 
| Daniel Dunbar | dd0cb22 | 2010-09-29 18:20:25 +0000 | [diff] [blame] | 1648 | } | 
 | 1649 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1650 | static void handleAlwaysInlineAttr(Sema &S, Decl *D, | 
 | 1651 |                                    const AttributeList &Attr) { | 
| Daniel Dunbar | dd0cb22 | 2010-09-29 18:20:25 +0000 | [diff] [blame] | 1652 |   // Check the attribute arguments. | 
| Ted Kremenek | 831efae | 2011-04-15 05:49:29 +0000 | [diff] [blame] | 1653 |   if (Attr.hasParameterOrArguments()) { | 
| Daniel Dunbar | dd0cb22 | 2010-09-29 18:20:25 +0000 | [diff] [blame] | 1654 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; | 
 | 1655 |     return; | 
 | 1656 |   } | 
 | 1657 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1658 |   if (!isa<FunctionDecl>(D)) { | 
| Daniel Dunbar | dd0cb22 | 2010-09-29 18:20:25 +0000 | [diff] [blame] | 1659 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 1660 |       << Attr.getName() << ExpectedFunction; | 
| Anders Carlsson | 5bab788 | 2009-02-19 19:16:48 +0000 | [diff] [blame] | 1661 |     return; | 
 | 1662 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1663 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1664 |   D->addAttr(::new (S.Context) | 
 | 1665 |              AlwaysInlineAttr(Attr.getRange(), S.Context, | 
 | 1666 |                               Attr.getAttributeSpellingListIndex())); | 
| Daniel Dunbar | af668b0 | 2008-10-28 00:17:57 +0000 | [diff] [blame] | 1667 | } | 
 | 1668 |  | 
| Hans Wennborg | 5e2d5de | 2012-06-23 11:51:46 +0000 | [diff] [blame] | 1669 | static void handleTLSModelAttr(Sema &S, Decl *D, | 
 | 1670 |                                const AttributeList &Attr) { | 
 | 1671 |   // Check the attribute arguments. | 
 | 1672 |   if (Attr.getNumArgs() != 1) { | 
 | 1673 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; | 
 | 1674 |     return; | 
 | 1675 |   } | 
 | 1676 |  | 
 | 1677 |   Expr *Arg = Attr.getArg(0); | 
 | 1678 |   Arg = Arg->IgnoreParenCasts(); | 
 | 1679 |   StringLiteral *Str = dyn_cast<StringLiteral>(Arg); | 
 | 1680 |  | 
 | 1681 |   // Check that it is a string. | 
 | 1682 |   if (!Str) { | 
 | 1683 |     S.Diag(Attr.getLoc(), diag::err_attribute_not_string) << "tls_model"; | 
 | 1684 |     return; | 
 | 1685 |   } | 
 | 1686 |  | 
| Richard Smith | 38afbc7 | 2013-04-13 02:43:54 +0000 | [diff] [blame] | 1687 |   if (!isa<VarDecl>(D) || !cast<VarDecl>(D)->getTLSKind()) { | 
| Hans Wennborg | 5e2d5de | 2012-06-23 11:51:46 +0000 | [diff] [blame] | 1688 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) | 
 | 1689 |       << Attr.getName() << ExpectedTLSVar; | 
 | 1690 |     return; | 
 | 1691 |   } | 
 | 1692 |  | 
 | 1693 |   // Check that the value. | 
 | 1694 |   StringRef Model = Str->getString(); | 
 | 1695 |   if (Model != "global-dynamic" && Model != "local-dynamic" | 
 | 1696 |       && Model != "initial-exec" && Model != "local-exec") { | 
 | 1697 |     S.Diag(Attr.getLoc(), diag::err_attr_tlsmodel_arg); | 
 | 1698 |     return; | 
 | 1699 |   } | 
 | 1700 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1701 |   D->addAttr(::new (S.Context) | 
 | 1702 |              TLSModelAttr(Attr.getRange(), S.Context, Model, | 
 | 1703 |                           Attr.getAttributeSpellingListIndex())); | 
| Hans Wennborg | 5e2d5de | 2012-06-23 11:51:46 +0000 | [diff] [blame] | 1704 | } | 
 | 1705 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1706 | static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Daniel Dunbar | dd0cb22 | 2010-09-29 18:20:25 +0000 | [diff] [blame] | 1707 |   // Check the attribute arguments. | 
| Ted Kremenek | 831efae | 2011-04-15 05:49:29 +0000 | [diff] [blame] | 1708 |   if (Attr.hasParameterOrArguments()) { | 
| Ryan Flynn | 76168e2 | 2009-08-09 20:07:29 +0000 | [diff] [blame] | 1709 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; | 
 | 1710 |     return; | 
 | 1711 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1712 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1713 |   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1714 |     QualType RetTy = FD->getResultType(); | 
| Ted Kremenek | 2cff7d1 | 2009-08-15 00:51:46 +0000 | [diff] [blame] | 1715 |     if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) { | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1716 |       D->addAttr(::new (S.Context) | 
 | 1717 |                  MallocAttr(Attr.getRange(), S.Context, | 
 | 1718 |                             Attr.getAttributeSpellingListIndex())); | 
| Ted Kremenek | 2cff7d1 | 2009-08-15 00:51:46 +0000 | [diff] [blame] | 1719 |       return; | 
 | 1720 |     } | 
| Ryan Flynn | 76168e2 | 2009-08-09 20:07:29 +0000 | [diff] [blame] | 1721 |   } | 
 | 1722 |  | 
| Ted Kremenek | 2cff7d1 | 2009-08-15 00:51:46 +0000 | [diff] [blame] | 1723 |   S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only); | 
| Ryan Flynn | 76168e2 | 2009-08-09 20:07:29 +0000 | [diff] [blame] | 1724 | } | 
 | 1725 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1726 | static void handleMayAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Dan Gohman | 34c2630 | 2010-11-17 00:03:07 +0000 | [diff] [blame] | 1727 |   // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 1728 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Dan Gohman | 34c2630 | 2010-11-17 00:03:07 +0000 | [diff] [blame] | 1729 |     return; | 
| Dan Gohman | 34c2630 | 2010-11-17 00:03:07 +0000 | [diff] [blame] | 1730 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1731 |   D->addAttr(::new (S.Context) | 
 | 1732 |              MayAliasAttr(Attr.getRange(), S.Context, | 
 | 1733 |                           Attr.getAttributeSpellingListIndex())); | 
| Dan Gohman | 34c2630 | 2010-11-17 00:03:07 +0000 | [diff] [blame] | 1734 | } | 
 | 1735 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1736 | static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chandler Carruth | 56aeb40 | 2011-07-11 23:33:05 +0000 | [diff] [blame] | 1737 |   assert(!Attr.isInvalid()); | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1738 |   if (isa<VarDecl>(D)) | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1739 |     D->addAttr(::new (S.Context) | 
 | 1740 |                NoCommonAttr(Attr.getRange(), S.Context, | 
 | 1741 |                             Attr.getAttributeSpellingListIndex())); | 
| Eric Christopher | 722109c | 2010-12-03 06:58:14 +0000 | [diff] [blame] | 1742 |   else | 
 | 1743 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 1744 |       << Attr.getName() << ExpectedVariable; | 
| Eric Christopher | a6cf1e7 | 2010-12-02 02:45:55 +0000 | [diff] [blame] | 1745 | } | 
 | 1746 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1747 | static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chandler Carruth | 56aeb40 | 2011-07-11 23:33:05 +0000 | [diff] [blame] | 1748 |   assert(!Attr.isInvalid()); | 
| Eli Friedman | 3e1aca2 | 2013-06-20 22:55:04 +0000 | [diff] [blame] | 1749 |  | 
 | 1750 |   if (S.LangOpts.CPlusPlus) { | 
 | 1751 |     S.Diag(Attr.getLoc(), diag::err_common_not_supported_cplusplus); | 
 | 1752 |     return; | 
 | 1753 |   } | 
 | 1754 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1755 |   if (isa<VarDecl>(D)) | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1756 |     D->addAttr(::new (S.Context) | 
 | 1757 |                CommonAttr(Attr.getRange(), S.Context, | 
 | 1758 |                           Attr.getAttributeSpellingListIndex())); | 
| Eric Christopher | 722109c | 2010-12-03 06:58:14 +0000 | [diff] [blame] | 1759 |   else | 
 | 1760 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 1761 |       << Attr.getName() << ExpectedVariable; | 
| Eric Christopher | a6cf1e7 | 2010-12-02 02:45:55 +0000 | [diff] [blame] | 1762 | } | 
 | 1763 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1764 | static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1765 |   if (hasDeclarator(D)) return; | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 1766 |  | 
 | 1767 |   if (S.CheckNoReturnAttr(attr)) return; | 
 | 1768 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1769 |   if (!isa<ObjCMethodDecl>(D)) { | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 1770 |     S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 1771 |       << attr.getName() << ExpectedFunctionOrMethod; | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 1772 |     return; | 
 | 1773 |   } | 
 | 1774 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1775 |   D->addAttr(::new (S.Context) | 
 | 1776 |              NoReturnAttr(attr.getRange(), S.Context, | 
 | 1777 |                           attr.getAttributeSpellingListIndex())); | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 1778 | } | 
 | 1779 |  | 
 | 1780 | bool Sema::CheckNoReturnAttr(const AttributeList &attr) { | 
| Ted Kremenek | 831efae | 2011-04-15 05:49:29 +0000 | [diff] [blame] | 1781 |   if (attr.hasParameterOrArguments()) { | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 1782 |     Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; | 
 | 1783 |     attr.setInvalid(); | 
 | 1784 |     return true; | 
 | 1785 |   } | 
 | 1786 |  | 
 | 1787 |   return false; | 
| Ted Kremenek | b725232 | 2009-04-10 00:01:14 +0000 | [diff] [blame] | 1788 | } | 
 | 1789 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1790 | static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, | 
 | 1791 |                                        const AttributeList &Attr) { | 
| Ted Kremenek | b56c1cc | 2010-08-19 00:51:58 +0000 | [diff] [blame] | 1792 |    | 
 | 1793 |   // The checking path for 'noreturn' and 'analyzer_noreturn' are different | 
 | 1794 |   // because 'analyzer_noreturn' does not impact the type. | 
 | 1795 |    | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 1796 |   if(!checkAttributeNumArgs(S, Attr, 0)) | 
 | 1797 |       return; | 
| Ted Kremenek | b56c1cc | 2010-08-19 00:51:58 +0000 | [diff] [blame] | 1798 |    | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1799 |   if (!isFunctionOrMethod(D) && !isa<BlockDecl>(D)) { | 
 | 1800 |     ValueDecl *VD = dyn_cast<ValueDecl>(D); | 
| Ted Kremenek | b56c1cc | 2010-08-19 00:51:58 +0000 | [diff] [blame] | 1801 |     if (VD == 0 || (!VD->getType()->isBlockPointerType() | 
 | 1802 |                     && !VD->getType()->isFunctionPointerType())) { | 
 | 1803 |       S.Diag(Attr.getLoc(), | 
| Richard Smith | 4e24f0f | 2013-01-02 12:01:23 +0000 | [diff] [blame] | 1804 |              Attr.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type | 
| Ted Kremenek | b56c1cc | 2010-08-19 00:51:58 +0000 | [diff] [blame] | 1805 |              : diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 1806 |         << Attr.getName() << ExpectedFunctionMethodOrBlock; | 
| Ted Kremenek | b56c1cc | 2010-08-19 00:51:58 +0000 | [diff] [blame] | 1807 |       return; | 
 | 1808 |     } | 
 | 1809 |   } | 
 | 1810 |    | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1811 |   D->addAttr(::new (S.Context) | 
 | 1812 |              AnalyzerNoReturnAttr(Attr.getRange(), S.Context, | 
 | 1813 |                                   Attr.getAttributeSpellingListIndex())); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 1814 | } | 
 | 1815 |  | 
| Richard Smith | cd8ab51 | 2013-01-17 01:30:42 +0000 | [diff] [blame] | 1816 | static void handleCXX11NoReturnAttr(Sema &S, Decl *D, | 
 | 1817 |                                     const AttributeList &Attr) { | 
 | 1818 |   // C++11 [dcl.attr.noreturn]p1: | 
 | 1819 |   //   The attribute may be applied to the declarator-id in a function | 
 | 1820 |   //   declaration. | 
 | 1821 |   FunctionDecl *FD = dyn_cast<FunctionDecl>(D); | 
 | 1822 |   if (!FD) { | 
 | 1823 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) | 
 | 1824 |       << Attr.getName() << ExpectedFunctionOrMethod; | 
 | 1825 |     return; | 
 | 1826 |   } | 
 | 1827 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1828 |   D->addAttr(::new (S.Context) | 
 | 1829 |              CXX11NoReturnAttr(Attr.getRange(), S.Context, | 
 | 1830 |                                Attr.getAttributeSpellingListIndex())); | 
| Richard Smith | cd8ab51 | 2013-01-17 01:30:42 +0000 | [diff] [blame] | 1831 | } | 
 | 1832 |  | 
| John Thompson | 35cc962 | 2010-08-09 21:53:52 +0000 | [diff] [blame] | 1833 | // PS3 PPU-specific. | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1834 | static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| John Thompson | 35cc962 | 2010-08-09 21:53:52 +0000 | [diff] [blame] | 1835 | /* | 
 | 1836 |   Returning a Vector Class in Registers | 
 | 1837 |    | 
| Eric Christopher | f48f367 | 2010-12-01 22:13:54 +0000 | [diff] [blame] | 1838 |   According to the PPU ABI specifications, a class with a single member of  | 
 | 1839 |   vector type is returned in memory when used as the return value of a function. | 
 | 1840 |   This results in inefficient code when implementing vector classes. To return | 
 | 1841 |   the value in a single vector register, add the vecreturn attribute to the | 
 | 1842 |   class definition. This attribute is also applicable to struct types. | 
| John Thompson | 35cc962 | 2010-08-09 21:53:52 +0000 | [diff] [blame] | 1843 |    | 
 | 1844 |   Example: | 
 | 1845 |    | 
 | 1846 |   struct Vector | 
 | 1847 |   { | 
 | 1848 |     __vector float xyzw; | 
 | 1849 |   } __attribute__((vecreturn)); | 
 | 1850 |    | 
 | 1851 |   Vector Add(Vector lhs, Vector rhs) | 
 | 1852 |   { | 
 | 1853 |     Vector result; | 
 | 1854 |     result.xyzw = vec_add(lhs.xyzw, rhs.xyzw); | 
 | 1855 |     return result; // This will be returned in a register | 
 | 1856 |   } | 
 | 1857 | */ | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1858 |   if (!isa<RecordDecl>(D)) { | 
| John Thompson | 35cc962 | 2010-08-09 21:53:52 +0000 | [diff] [blame] | 1859 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 1860 |       << Attr.getName() << ExpectedClass; | 
| John Thompson | 35cc962 | 2010-08-09 21:53:52 +0000 | [diff] [blame] | 1861 |     return; | 
 | 1862 |   } | 
 | 1863 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1864 |   if (D->getAttr<VecReturnAttr>()) { | 
| John Thompson | 35cc962 | 2010-08-09 21:53:52 +0000 | [diff] [blame] | 1865 |     S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn"; | 
 | 1866 |     return; | 
 | 1867 |   } | 
 | 1868 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1869 |   RecordDecl *record = cast<RecordDecl>(D); | 
| John Thompson | 01add59 | 2010-09-18 01:12:07 +0000 | [diff] [blame] | 1870 |   int count = 0; | 
 | 1871 |  | 
 | 1872 |   if (!isa<CXXRecordDecl>(record)) { | 
 | 1873 |     S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member); | 
 | 1874 |     return; | 
 | 1875 |   } | 
 | 1876 |  | 
 | 1877 |   if (!cast<CXXRecordDecl>(record)->isPOD()) { | 
 | 1878 |     S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_pod_record); | 
 | 1879 |     return; | 
 | 1880 |   } | 
 | 1881 |  | 
| Eric Christopher | f48f367 | 2010-12-01 22:13:54 +0000 | [diff] [blame] | 1882 |   for (RecordDecl::field_iterator iter = record->field_begin(); | 
 | 1883 |        iter != record->field_end(); iter++) { | 
| John Thompson | 01add59 | 2010-09-18 01:12:07 +0000 | [diff] [blame] | 1884 |     if ((count == 1) || !iter->getType()->isVectorType()) { | 
 | 1885 |       S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member); | 
 | 1886 |       return; | 
 | 1887 |     } | 
 | 1888 |     count++; | 
 | 1889 |   } | 
 | 1890 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1891 |   D->addAttr(::new (S.Context) | 
 | 1892 |              VecReturnAttr(Attr.getRange(), S.Context, | 
 | 1893 |                            Attr.getAttributeSpellingListIndex())); | 
| John Thompson | 35cc962 | 2010-08-09 21:53:52 +0000 | [diff] [blame] | 1894 | } | 
 | 1895 |  | 
| Richard Smith | 3a2b7a1 | 2013-01-28 22:42:45 +0000 | [diff] [blame] | 1896 | static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, | 
 | 1897 |                                  const AttributeList &Attr) { | 
 | 1898 |   if (isa<ParmVarDecl>(D)) { | 
 | 1899 |     // [[carries_dependency]] can only be applied to a parameter if it is a | 
 | 1900 |     // parameter of a function declaration or lambda. | 
 | 1901 |     if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) { | 
 | 1902 |       S.Diag(Attr.getLoc(), | 
 | 1903 |              diag::err_carries_dependency_param_not_function_decl); | 
 | 1904 |       return; | 
 | 1905 |     } | 
 | 1906 |   } else if (!isa<FunctionDecl>(D)) { | 
| Sean Hunt | bbd37c6 | 2009-11-21 08:43:09 +0000 | [diff] [blame] | 1907 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 1908 |       << Attr.getName() << ExpectedFunctionMethodOrParameter; | 
| Sean Hunt | bbd37c6 | 2009-11-21 08:43:09 +0000 | [diff] [blame] | 1909 |     return; | 
 | 1910 |   } | 
| Richard Smith | 3a2b7a1 | 2013-01-28 22:42:45 +0000 | [diff] [blame] | 1911 |  | 
 | 1912 |   D->addAttr(::new (S.Context) CarriesDependencyAttr( | 
 | 1913 |                                    Attr.getRange(), S.Context, | 
 | 1914 |                                    Attr.getAttributeSpellingListIndex())); | 
| Sean Hunt | bbd37c6 | 2009-11-21 08:43:09 +0000 | [diff] [blame] | 1915 | } | 
 | 1916 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1917 | static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Ted Kremenek | 7379889 | 2008-07-25 04:39:19 +0000 | [diff] [blame] | 1918 |   // check the attribute arguments. | 
| Ted Kremenek | 831efae | 2011-04-15 05:49:29 +0000 | [diff] [blame] | 1919 |   if (Attr.hasParameterOrArguments()) { | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 1920 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; | 
| Ted Kremenek | 7379889 | 2008-07-25 04:39:19 +0000 | [diff] [blame] | 1921 |     return; | 
 | 1922 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1923 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1924 |   if (!isa<VarDecl>(D) && !isa<ObjCIvarDecl>(D) && !isFunctionOrMethod(D) && | 
| Daniel Jasper | 568eae4 | 2012-06-13 18:31:09 +0000 | [diff] [blame] | 1925 |       !isa<TypeDecl>(D) && !isa<LabelDecl>(D) && !isa<FieldDecl>(D)) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1926 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 1927 |       << Attr.getName() << ExpectedVariableFunctionOrLabel; | 
| Ted Kremenek | 7379889 | 2008-07-25 04:39:19 +0000 | [diff] [blame] | 1928 |     return; | 
 | 1929 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1930 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1931 |   D->addAttr(::new (S.Context) | 
 | 1932 |              UnusedAttr(Attr.getRange(), S.Context, | 
 | 1933 |                         Attr.getAttributeSpellingListIndex())); | 
| Ted Kremenek | 7379889 | 2008-07-25 04:39:19 +0000 | [diff] [blame] | 1934 | } | 
 | 1935 |  | 
| Rafael Espindola | f87cced | 2011-10-03 14:59:42 +0000 | [diff] [blame] | 1936 | static void handleReturnsTwiceAttr(Sema &S, Decl *D, | 
 | 1937 |                                    const AttributeList &Attr) { | 
 | 1938 |   // check the attribute arguments. | 
 | 1939 |   if (Attr.hasParameterOrArguments()) { | 
 | 1940 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; | 
 | 1941 |     return; | 
 | 1942 |   } | 
 | 1943 |  | 
 | 1944 |   if (!isa<FunctionDecl>(D)) { | 
 | 1945 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
 | 1946 |       << Attr.getName() << ExpectedFunction; | 
 | 1947 |     return; | 
 | 1948 |   } | 
 | 1949 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1950 |   D->addAttr(::new (S.Context) | 
 | 1951 |              ReturnsTwiceAttr(Attr.getRange(), S.Context, | 
 | 1952 |                               Attr.getAttributeSpellingListIndex())); | 
| Rafael Espindola | f87cced | 2011-10-03 14:59:42 +0000 | [diff] [blame] | 1953 | } | 
 | 1954 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1955 | static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Daniel Dunbar | b805dad | 2009-02-13 19:23:53 +0000 | [diff] [blame] | 1956 |   // check the attribute arguments. | 
| Ted Kremenek | 831efae | 2011-04-15 05:49:29 +0000 | [diff] [blame] | 1957 |   if (Attr.hasParameterOrArguments()) { | 
| Daniel Dunbar | b805dad | 2009-02-13 19:23:53 +0000 | [diff] [blame] | 1958 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; | 
 | 1959 |     return; | 
 | 1960 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1961 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1962 |   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { | 
| Daniel Dunbar | 186204b | 2009-02-13 22:48:56 +0000 | [diff] [blame] | 1963 |     if (VD->hasLocalStorage() || VD->hasExternalStorage()) { | 
| Daniel Dunbar | b805dad | 2009-02-13 19:23:53 +0000 | [diff] [blame] | 1964 |       S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used"; | 
 | 1965 |       return; | 
 | 1966 |     } | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1967 |   } else if (!isFunctionOrMethod(D)) { | 
| Daniel Dunbar | b805dad | 2009-02-13 19:23:53 +0000 | [diff] [blame] | 1968 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 1969 |       << Attr.getName() << ExpectedVariableOrFunction; | 
| Daniel Dunbar | b805dad | 2009-02-13 19:23:53 +0000 | [diff] [blame] | 1970 |     return; | 
 | 1971 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1972 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 1973 |   D->addAttr(::new (S.Context) | 
 | 1974 |              UsedAttr(Attr.getRange(), S.Context, | 
 | 1975 |                       Attr.getAttributeSpellingListIndex())); | 
| Daniel Dunbar | b805dad | 2009-02-13 19:23:53 +0000 | [diff] [blame] | 1976 | } | 
 | 1977 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 1978 | static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Daniel Dunbar | 3068ae0 | 2008-07-31 22:40:48 +0000 | [diff] [blame] | 1979 |   // check the attribute arguments. | 
| John McCall | bdc49d3 | 2011-03-02 12:15:05 +0000 | [diff] [blame] | 1980 |   if (Attr.getNumArgs() > 1) { | 
 | 1981 |     S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; | 
| Daniel Dunbar | 3068ae0 | 2008-07-31 22:40:48 +0000 | [diff] [blame] | 1982 |     return; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1983 |   } | 
| Daniel Dunbar | 3068ae0 | 2008-07-31 22:40:48 +0000 | [diff] [blame] | 1984 |  | 
 | 1985 |   int priority = 65535; // FIXME: Do not hardcode such constants. | 
 | 1986 |   if (Attr.getNumArgs() > 0) { | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 1987 |     Expr *E = Attr.getArg(0); | 
| Daniel Dunbar | 3068ae0 | 2008-07-31 22:40:48 +0000 | [diff] [blame] | 1988 |     llvm::APSInt Idx(32); | 
| Douglas Gregor | ac06a0e | 2010-05-18 23:01:22 +0000 | [diff] [blame] | 1989 |     if (E->isTypeDependent() || E->isValueDependent() || | 
 | 1990 |         !E->isIntegerConstantExpr(Idx, S.Context)) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1991 |       S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 1992 |         << "constructor" << 1 << E->getSourceRange(); | 
| Daniel Dunbar | 3068ae0 | 2008-07-31 22:40:48 +0000 | [diff] [blame] | 1993 |       return; | 
 | 1994 |     } | 
 | 1995 |     priority = Idx.getZExtValue(); | 
 | 1996 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 1997 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 1998 |   if (!isa<FunctionDecl>(D)) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 1999 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 2000 |       << Attr.getName() << ExpectedFunction; | 
| Daniel Dunbar | 3068ae0 | 2008-07-31 22:40:48 +0000 | [diff] [blame] | 2001 |     return; | 
 | 2002 |   } | 
 | 2003 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2004 |   D->addAttr(::new (S.Context) | 
 | 2005 |              ConstructorAttr(Attr.getRange(), S.Context, priority, | 
 | 2006 |                              Attr.getAttributeSpellingListIndex())); | 
| Daniel Dunbar | 3068ae0 | 2008-07-31 22:40:48 +0000 | [diff] [blame] | 2007 | } | 
 | 2008 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2009 | static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Daniel Dunbar | 3068ae0 | 2008-07-31 22:40:48 +0000 | [diff] [blame] | 2010 |   // check the attribute arguments. | 
| John McCall | bdc49d3 | 2011-03-02 12:15:05 +0000 | [diff] [blame] | 2011 |   if (Attr.getNumArgs() > 1) { | 
 | 2012 |     S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; | 
| Daniel Dunbar | 3068ae0 | 2008-07-31 22:40:48 +0000 | [diff] [blame] | 2013 |     return; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2014 |   } | 
| Daniel Dunbar | 3068ae0 | 2008-07-31 22:40:48 +0000 | [diff] [blame] | 2015 |  | 
 | 2016 |   int priority = 65535; // FIXME: Do not hardcode such constants. | 
 | 2017 |   if (Attr.getNumArgs() > 0) { | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 2018 |     Expr *E = Attr.getArg(0); | 
| Daniel Dunbar | 3068ae0 | 2008-07-31 22:40:48 +0000 | [diff] [blame] | 2019 |     llvm::APSInt Idx(32); | 
| Douglas Gregor | ac06a0e | 2010-05-18 23:01:22 +0000 | [diff] [blame] | 2020 |     if (E->isTypeDependent() || E->isValueDependent() || | 
 | 2021 |         !E->isIntegerConstantExpr(Idx, S.Context)) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 2022 |       S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 2023 |         << "destructor" << 1 << E->getSourceRange(); | 
| Daniel Dunbar | 3068ae0 | 2008-07-31 22:40:48 +0000 | [diff] [blame] | 2024 |       return; | 
 | 2025 |     } | 
 | 2026 |     priority = Idx.getZExtValue(); | 
 | 2027 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2028 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2029 |   if (!isa<FunctionDecl>(D)) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 2030 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 2031 |       << Attr.getName() << ExpectedFunction; | 
| Daniel Dunbar | 3068ae0 | 2008-07-31 22:40:48 +0000 | [diff] [blame] | 2032 |     return; | 
 | 2033 |   } | 
 | 2034 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2035 |   D->addAttr(::new (S.Context) | 
 | 2036 |              DestructorAttr(Attr.getRange(), S.Context, priority, | 
 | 2037 |                             Attr.getAttributeSpellingListIndex())); | 
| Daniel Dunbar | 3068ae0 | 2008-07-31 22:40:48 +0000 | [diff] [blame] | 2038 | } | 
 | 2039 |  | 
| Benjamin Kramer | bc3260d | 2012-05-16 12:19:08 +0000 | [diff] [blame] | 2040 | template <typename AttrTy> | 
| Aaron Ballman | 2dbdef2 | 2013-07-18 13:13:52 +0000 | [diff] [blame^] | 2041 | static void handleAttrWithMessage(Sema &S, Decl *D, | 
 | 2042 |                                   const AttributeList &Attr) { | 
| Chris Lattner | 951bbb2 | 2011-02-24 05:42:24 +0000 | [diff] [blame] | 2043 |   unsigned NumArgs = Attr.getNumArgs(); | 
 | 2044 |   if (NumArgs > 1) { | 
| John McCall | bdc49d3 | 2011-03-02 12:15:05 +0000 | [diff] [blame] | 2045 |     S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 2046 |     return; | 
 | 2047 |   } | 
| Benjamin Kramer | bc3260d | 2012-05-16 12:19:08 +0000 | [diff] [blame] | 2048 |  | 
 | 2049 |   // Handle the case where the attribute has a text message. | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 2050 |   StringRef Str; | 
| Chris Lattner | 951bbb2 | 2011-02-24 05:42:24 +0000 | [diff] [blame] | 2051 |   if (NumArgs == 1) { | 
 | 2052 |     StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0)); | 
| Fariborz Jahanian | c4b35cf | 2010-10-06 21:18:44 +0000 | [diff] [blame] | 2053 |     if (!SE) { | 
| Chris Lattner | 951bbb2 | 2011-02-24 05:42:24 +0000 | [diff] [blame] | 2054 |       S.Diag(Attr.getArg(0)->getLocStart(), diag::err_attribute_not_string) | 
| Aaron Ballman | 2dbdef2 | 2013-07-18 13:13:52 +0000 | [diff] [blame^] | 2055 |         << Attr.getName(); | 
| Fariborz Jahanian | c4b35cf | 2010-10-06 21:18:44 +0000 | [diff] [blame] | 2056 |       return; | 
 | 2057 |     } | 
| Chris Lattner | 951bbb2 | 2011-02-24 05:42:24 +0000 | [diff] [blame] | 2058 |     Str = SE->getString(); | 
| Fariborz Jahanian | c4b35cf | 2010-10-06 21:18:44 +0000 | [diff] [blame] | 2059 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2060 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2061 |   D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str, | 
 | 2062 |                                       Attr.getAttributeSpellingListIndex())); | 
| Fariborz Jahanian | bc1c877 | 2008-12-17 01:07:27 +0000 | [diff] [blame] | 2063 | } | 
 | 2064 |  | 
| Fariborz Jahanian | 742352a | 2011-07-06 19:24:05 +0000 | [diff] [blame] | 2065 | static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D,  | 
 | 2066 |                                             const AttributeList &Attr) { | 
 | 2067 |   unsigned NumArgs = Attr.getNumArgs(); | 
 | 2068 |   if (NumArgs > 0) { | 
 | 2069 |     S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0; | 
 | 2070 |     return; | 
 | 2071 |   } | 
 | 2072 |    | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2073 |   D->addAttr(::new (S.Context) | 
 | 2074 |              ArcWeakrefUnavailableAttr(Attr.getRange(), S.Context, | 
 | 2075 |                                        Attr.getAttributeSpellingListIndex())); | 
| Fariborz Jahanian | 742352a | 2011-07-06 19:24:05 +0000 | [diff] [blame] | 2076 | } | 
 | 2077 |  | 
| Patrick Beard | b2f6820 | 2012-04-06 18:12:22 +0000 | [diff] [blame] | 2078 | static void handleObjCRootClassAttr(Sema &S, Decl *D,  | 
 | 2079 |                                     const AttributeList &Attr) { | 
 | 2080 |   if (!isa<ObjCInterfaceDecl>(D)) { | 
 | 2081 |     S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface); | 
 | 2082 |     return; | 
 | 2083 |   } | 
 | 2084 |    | 
 | 2085 |   unsigned NumArgs = Attr.getNumArgs(); | 
 | 2086 |   if (NumArgs > 0) { | 
 | 2087 |     S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0; | 
 | 2088 |     return; | 
 | 2089 |   } | 
 | 2090 |    | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2091 |   D->addAttr(::new (S.Context) | 
 | 2092 |              ObjCRootClassAttr(Attr.getRange(), S.Context, | 
 | 2093 |                                Attr.getAttributeSpellingListIndex())); | 
| Patrick Beard | b2f6820 | 2012-04-06 18:12:22 +0000 | [diff] [blame] | 2094 | } | 
 | 2095 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2096 | static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D, | 
 | 2097 |                                                const AttributeList &Attr) { | 
| Fariborz Jahanian | 341b8be | 2012-01-03 22:52:32 +0000 | [diff] [blame] | 2098 |   if (!isa<ObjCInterfaceDecl>(D)) { | 
 | 2099 |     S.Diag(Attr.getLoc(), diag::err_suppress_autosynthesis); | 
 | 2100 |     return; | 
 | 2101 |   } | 
 | 2102 |    | 
| Fariborz Jahanian | e23dcf3 | 2012-01-03 18:45:41 +0000 | [diff] [blame] | 2103 |   unsigned NumArgs = Attr.getNumArgs(); | 
 | 2104 |   if (NumArgs > 0) { | 
 | 2105 |     S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0; | 
 | 2106 |     return; | 
 | 2107 |   } | 
 | 2108 |    | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2109 |   D->addAttr(::new (S.Context) | 
 | 2110 |              ObjCRequiresPropertyDefsAttr(Attr.getRange(), S.Context, | 
 | 2111 |                                           Attr.getAttributeSpellingListIndex())); | 
| Fariborz Jahanian | e23dcf3 | 2012-01-03 18:45:41 +0000 | [diff] [blame] | 2112 | } | 
 | 2113 |  | 
| Jordy Rose | fad5de9 | 2012-05-08 03:27:22 +0000 | [diff] [blame] | 2114 | static bool checkAvailabilityAttr(Sema &S, SourceRange Range, | 
 | 2115 |                                   IdentifierInfo *Platform, | 
 | 2116 |                                   VersionTuple Introduced, | 
 | 2117 |                                   VersionTuple Deprecated, | 
 | 2118 |                                   VersionTuple Obsoleted) { | 
| Rafael Espindola | 3b29436 | 2012-05-06 19:56:25 +0000 | [diff] [blame] | 2119 |   StringRef PlatformName | 
 | 2120 |     = AvailabilityAttr::getPrettyPlatformName(Platform->getName()); | 
 | 2121 |   if (PlatformName.empty()) | 
 | 2122 |     PlatformName = Platform->getName(); | 
 | 2123 |  | 
 | 2124 |   // Ensure that Introduced <= Deprecated <= Obsoleted (although not all | 
 | 2125 |   // of these steps are needed). | 
 | 2126 |   if (!Introduced.empty() && !Deprecated.empty() && | 
 | 2127 |       !(Introduced <= Deprecated)) { | 
 | 2128 |     S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) | 
 | 2129 |       << 1 << PlatformName << Deprecated.getAsString() | 
 | 2130 |       << 0 << Introduced.getAsString(); | 
 | 2131 |     return true; | 
 | 2132 |   } | 
 | 2133 |  | 
 | 2134 |   if (!Introduced.empty() && !Obsoleted.empty() && | 
 | 2135 |       !(Introduced <= Obsoleted)) { | 
 | 2136 |     S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) | 
 | 2137 |       << 2 << PlatformName << Obsoleted.getAsString() | 
 | 2138 |       << 0 << Introduced.getAsString(); | 
 | 2139 |     return true; | 
 | 2140 |   } | 
 | 2141 |  | 
 | 2142 |   if (!Deprecated.empty() && !Obsoleted.empty() && | 
 | 2143 |       !(Deprecated <= Obsoleted)) { | 
 | 2144 |     S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) | 
 | 2145 |       << 2 << PlatformName << Obsoleted.getAsString() | 
 | 2146 |       << 1 << Deprecated.getAsString(); | 
 | 2147 |     return true; | 
 | 2148 |   } | 
 | 2149 |  | 
 | 2150 |   return false; | 
 | 2151 | } | 
 | 2152 |  | 
| Douglas Gregor | f4d918f | 2013-01-15 22:43:08 +0000 | [diff] [blame] | 2153 | /// \brief Check whether the two versions match. | 
 | 2154 | /// | 
 | 2155 | /// If either version tuple is empty, then they are assumed to match. If | 
 | 2156 | /// \p BeforeIsOkay is true, then \p X can be less than or equal to \p Y. | 
 | 2157 | static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y, | 
 | 2158 |                           bool BeforeIsOkay) { | 
 | 2159 |   if (X.empty() || Y.empty()) | 
 | 2160 |     return true; | 
 | 2161 |  | 
 | 2162 |   if (X == Y) | 
 | 2163 |     return true; | 
 | 2164 |  | 
 | 2165 |   if (BeforeIsOkay && X < Y) | 
 | 2166 |     return true; | 
 | 2167 |  | 
 | 2168 |   return false; | 
 | 2169 | } | 
 | 2170 |  | 
| Rafael Espindola | 51be6e3 | 2013-01-08 22:04:34 +0000 | [diff] [blame] | 2171 | AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 2172 |                                               IdentifierInfo *Platform, | 
 | 2173 |                                               VersionTuple Introduced, | 
 | 2174 |                                               VersionTuple Deprecated, | 
 | 2175 |                                               VersionTuple Obsoleted, | 
 | 2176 |                                               bool IsUnavailable, | 
| Douglas Gregor | f4d918f | 2013-01-15 22:43:08 +0000 | [diff] [blame] | 2177 |                                               StringRef Message, | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2178 |                                               bool Override, | 
 | 2179 |                                               unsigned AttrSpellingListIndex) { | 
| Rafael Espindola | 98ae834 | 2012-05-10 02:50:16 +0000 | [diff] [blame] | 2180 |   VersionTuple MergedIntroduced = Introduced; | 
 | 2181 |   VersionTuple MergedDeprecated = Deprecated; | 
 | 2182 |   VersionTuple MergedObsoleted = Obsoleted; | 
| Rafael Espindola | 3b29436 | 2012-05-06 19:56:25 +0000 | [diff] [blame] | 2183 |   bool FoundAny = false; | 
 | 2184 |  | 
| Rafael Espindola | 98ae834 | 2012-05-10 02:50:16 +0000 | [diff] [blame] | 2185 |   if (D->hasAttrs()) { | 
 | 2186 |     AttrVec &Attrs = D->getAttrs(); | 
 | 2187 |     for (unsigned i = 0, e = Attrs.size(); i != e;) { | 
 | 2188 |       const AvailabilityAttr *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]); | 
 | 2189 |       if (!OldAA) { | 
 | 2190 |         ++i; | 
 | 2191 |         continue; | 
 | 2192 |       } | 
| Rafael Espindola | 3b29436 | 2012-05-06 19:56:25 +0000 | [diff] [blame] | 2193 |  | 
| Rafael Espindola | 98ae834 | 2012-05-10 02:50:16 +0000 | [diff] [blame] | 2194 |       IdentifierInfo *OldPlatform = OldAA->getPlatform(); | 
 | 2195 |       if (OldPlatform != Platform) { | 
 | 2196 |         ++i; | 
 | 2197 |         continue; | 
 | 2198 |       } | 
 | 2199 |  | 
 | 2200 |       FoundAny = true; | 
 | 2201 |       VersionTuple OldIntroduced = OldAA->getIntroduced(); | 
 | 2202 |       VersionTuple OldDeprecated = OldAA->getDeprecated(); | 
 | 2203 |       VersionTuple OldObsoleted = OldAA->getObsoleted(); | 
 | 2204 |       bool OldIsUnavailable = OldAA->getUnavailable(); | 
| Rafael Espindola | 98ae834 | 2012-05-10 02:50:16 +0000 | [diff] [blame] | 2205 |  | 
| Douglas Gregor | f4d918f | 2013-01-15 22:43:08 +0000 | [diff] [blame] | 2206 |       if (!versionsMatch(OldIntroduced, Introduced, Override) || | 
 | 2207 |           !versionsMatch(Deprecated, OldDeprecated, Override) || | 
 | 2208 |           !versionsMatch(Obsoleted, OldObsoleted, Override) || | 
 | 2209 |           !(OldIsUnavailable == IsUnavailable || | 
| Douglas Gregor | 72daa3f | 2013-01-16 00:54:48 +0000 | [diff] [blame] | 2210 |             (Override && !OldIsUnavailable && IsUnavailable))) { | 
| Douglas Gregor | f4d918f | 2013-01-15 22:43:08 +0000 | [diff] [blame] | 2211 |         if (Override) { | 
 | 2212 |           int Which = -1; | 
 | 2213 |           VersionTuple FirstVersion; | 
 | 2214 |           VersionTuple SecondVersion; | 
 | 2215 |           if (!versionsMatch(OldIntroduced, Introduced, Override)) { | 
 | 2216 |             Which = 0; | 
 | 2217 |             FirstVersion = OldIntroduced; | 
 | 2218 |             SecondVersion = Introduced; | 
 | 2219 |           } else if (!versionsMatch(Deprecated, OldDeprecated, Override)) { | 
 | 2220 |             Which = 1; | 
 | 2221 |             FirstVersion = Deprecated; | 
 | 2222 |             SecondVersion = OldDeprecated; | 
 | 2223 |           } else if (!versionsMatch(Obsoleted, OldObsoleted, Override)) { | 
 | 2224 |             Which = 2; | 
 | 2225 |             FirstVersion = Obsoleted; | 
 | 2226 |             SecondVersion = OldObsoleted; | 
 | 2227 |           } | 
 | 2228 |  | 
 | 2229 |           if (Which == -1) { | 
 | 2230 |             Diag(OldAA->getLocation(), | 
 | 2231 |                  diag::warn_mismatched_availability_override_unavail) | 
 | 2232 |               << AvailabilityAttr::getPrettyPlatformName(Platform->getName()); | 
 | 2233 |           } else { | 
 | 2234 |             Diag(OldAA->getLocation(), | 
 | 2235 |                  diag::warn_mismatched_availability_override) | 
 | 2236 |               << Which | 
 | 2237 |               << AvailabilityAttr::getPrettyPlatformName(Platform->getName()) | 
 | 2238 |               << FirstVersion.getAsString() << SecondVersion.getAsString(); | 
 | 2239 |           } | 
 | 2240 |           Diag(Range.getBegin(), diag::note_overridden_method); | 
 | 2241 |         } else { | 
 | 2242 |           Diag(OldAA->getLocation(), diag::warn_mismatched_availability); | 
 | 2243 |           Diag(Range.getBegin(), diag::note_previous_attribute); | 
 | 2244 |         } | 
 | 2245 |  | 
| Rafael Espindola | 98ae834 | 2012-05-10 02:50:16 +0000 | [diff] [blame] | 2246 |         Attrs.erase(Attrs.begin() + i); | 
 | 2247 |         --e; | 
 | 2248 |         continue; | 
 | 2249 |       } | 
 | 2250 |  | 
 | 2251 |       VersionTuple MergedIntroduced2 = MergedIntroduced; | 
 | 2252 |       VersionTuple MergedDeprecated2 = MergedDeprecated; | 
 | 2253 |       VersionTuple MergedObsoleted2 = MergedObsoleted; | 
 | 2254 |  | 
 | 2255 |       if (MergedIntroduced2.empty()) | 
 | 2256 |         MergedIntroduced2 = OldIntroduced; | 
 | 2257 |       if (MergedDeprecated2.empty()) | 
 | 2258 |         MergedDeprecated2 = OldDeprecated; | 
 | 2259 |       if (MergedObsoleted2.empty()) | 
 | 2260 |         MergedObsoleted2 = OldObsoleted; | 
 | 2261 |  | 
 | 2262 |       if (checkAvailabilityAttr(*this, OldAA->getRange(), Platform, | 
 | 2263 |                                 MergedIntroduced2, MergedDeprecated2, | 
 | 2264 |                                 MergedObsoleted2)) { | 
 | 2265 |         Attrs.erase(Attrs.begin() + i); | 
 | 2266 |         --e; | 
 | 2267 |         continue; | 
 | 2268 |       } | 
 | 2269 |  | 
 | 2270 |       MergedIntroduced = MergedIntroduced2; | 
 | 2271 |       MergedDeprecated = MergedDeprecated2; | 
 | 2272 |       MergedObsoleted = MergedObsoleted2; | 
 | 2273 |       ++i; | 
| Rafael Espindola | 3b29436 | 2012-05-06 19:56:25 +0000 | [diff] [blame] | 2274 |     } | 
| Rafael Espindola | 3b29436 | 2012-05-06 19:56:25 +0000 | [diff] [blame] | 2275 |   } | 
 | 2276 |  | 
 | 2277 |   if (FoundAny && | 
 | 2278 |       MergedIntroduced == Introduced && | 
 | 2279 |       MergedDeprecated == Deprecated && | 
 | 2280 |       MergedObsoleted == Obsoleted) | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 2281 |     return NULL; | 
| Rafael Espindola | 3b29436 | 2012-05-06 19:56:25 +0000 | [diff] [blame] | 2282 |  | 
| Ted Kremenek | cb34439 | 2013-04-06 00:34:27 +0000 | [diff] [blame] | 2283 |   // Only create a new attribute if !Override, but we want to do | 
 | 2284 |   // the checking. | 
| Rafael Espindola | 98ae834 | 2012-05-10 02:50:16 +0000 | [diff] [blame] | 2285 |   if (!checkAvailabilityAttr(*this, Range, Platform, MergedIntroduced, | 
| Ted Kremenek | cb34439 | 2013-04-06 00:34:27 +0000 | [diff] [blame] | 2286 |                              MergedDeprecated, MergedObsoleted) && | 
 | 2287 |       !Override) { | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 2288 |     return ::new (Context) AvailabilityAttr(Range, Context, Platform, | 
 | 2289 |                                             Introduced, Deprecated, | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2290 |                                             Obsoleted, IsUnavailable, Message, | 
 | 2291 |                                             AttrSpellingListIndex); | 
| Rafael Espindola | 3b29436 | 2012-05-06 19:56:25 +0000 | [diff] [blame] | 2292 |   } | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 2293 |   return NULL; | 
| Rafael Espindola | 3b29436 | 2012-05-06 19:56:25 +0000 | [diff] [blame] | 2294 | } | 
 | 2295 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2296 | static void handleAvailabilityAttr(Sema &S, Decl *D, | 
 | 2297 |                                    const AttributeList &Attr) { | 
| Douglas Gregor | 0a0d2b1 | 2011-03-23 00:50:03 +0000 | [diff] [blame] | 2298 |   IdentifierInfo *Platform = Attr.getParameterName(); | 
 | 2299 |   SourceLocation PlatformLoc = Attr.getParameterLoc(); | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2300 |   unsigned Index = Attr.getAttributeSpellingListIndex(); | 
 | 2301 |    | 
| Rafael Espindola | 3b29436 | 2012-05-06 19:56:25 +0000 | [diff] [blame] | 2302 |   if (AvailabilityAttr::getPrettyPlatformName(Platform->getName()).empty()) | 
| Douglas Gregor | 0a0d2b1 | 2011-03-23 00:50:03 +0000 | [diff] [blame] | 2303 |     S.Diag(PlatformLoc, diag::warn_availability_unknown_platform) | 
 | 2304 |       << Platform; | 
 | 2305 |  | 
| Rafael Espindola | 8c4222a | 2013-01-08 21:30:32 +0000 | [diff] [blame] | 2306 |   NamedDecl *ND = dyn_cast<NamedDecl>(D); | 
 | 2307 |   if (!ND) { | 
 | 2308 |     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); | 
 | 2309 |     return; | 
 | 2310 |   } | 
 | 2311 |  | 
| Douglas Gregor | 0a0d2b1 | 2011-03-23 00:50:03 +0000 | [diff] [blame] | 2312 |   AvailabilityChange Introduced = Attr.getAvailabilityIntroduced(); | 
 | 2313 |   AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated(); | 
 | 2314 |   AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted(); | 
| Douglas Gregor | b53e417 | 2011-03-26 03:35:55 +0000 | [diff] [blame] | 2315 |   bool IsUnavailable = Attr.getUnavailableLoc().isValid(); | 
| Fariborz Jahanian | 006e42f | 2011-12-10 00:28:41 +0000 | [diff] [blame] | 2316 |   StringRef Str; | 
 | 2317 |   const StringLiteral *SE =  | 
 | 2318 |     dyn_cast_or_null<const StringLiteral>(Attr.getMessageExpr()); | 
 | 2319 |   if (SE) | 
 | 2320 |     Str = SE->getString(); | 
| Rafael Espindola | 3b29436 | 2012-05-06 19:56:25 +0000 | [diff] [blame] | 2321 |  | 
| Rafael Espindola | 51be6e3 | 2013-01-08 22:04:34 +0000 | [diff] [blame] | 2322 |   AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 2323 |                                                       Platform, | 
 | 2324 |                                                       Introduced.Version, | 
 | 2325 |                                                       Deprecated.Version, | 
 | 2326 |                                                       Obsoleted.Version, | 
| Douglas Gregor | f4d918f | 2013-01-15 22:43:08 +0000 | [diff] [blame] | 2327 |                                                       IsUnavailable, Str, | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2328 |                                                       /*Override=*/false, | 
 | 2329 |                                                       Index); | 
| Rafael Espindola | 838dc59 | 2013-01-12 06:42:30 +0000 | [diff] [blame] | 2330 |   if (NewAttr) | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 2331 |     D->addAttr(NewAttr); | 
| Rafael Espindola | 98ae834 | 2012-05-10 02:50:16 +0000 | [diff] [blame] | 2332 | } | 
 | 2333 |  | 
| John McCall | d4c3d66 | 2013-02-20 01:54:26 +0000 | [diff] [blame] | 2334 | template <class T> | 
 | 2335 | static T *mergeVisibilityAttr(Sema &S, Decl *D, SourceRange range, | 
 | 2336 |                               typename T::VisibilityType value, | 
 | 2337 |                               unsigned attrSpellingListIndex) { | 
 | 2338 |   T *existingAttr = D->getAttr<T>(); | 
 | 2339 |   if (existingAttr) { | 
 | 2340 |     typename T::VisibilityType existingValue = existingAttr->getVisibility(); | 
 | 2341 |     if (existingValue == value) | 
 | 2342 |       return NULL; | 
 | 2343 |     S.Diag(existingAttr->getLocation(), diag::err_mismatched_visibility); | 
 | 2344 |     S.Diag(range.getBegin(), diag::note_previous_attribute); | 
 | 2345 |     D->dropAttr<T>(); | 
 | 2346 |   } | 
 | 2347 |   return ::new (S.Context) T(range, S.Context, value, attrSpellingListIndex); | 
 | 2348 | } | 
 | 2349 |  | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 2350 | VisibilityAttr *Sema::mergeVisibilityAttr(Decl *D, SourceRange Range, | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2351 |                                           VisibilityAttr::VisibilityType Vis, | 
 | 2352 |                                           unsigned AttrSpellingListIndex) { | 
| John McCall | d4c3d66 | 2013-02-20 01:54:26 +0000 | [diff] [blame] | 2353 |   return ::mergeVisibilityAttr<VisibilityAttr>(*this, D, Range, Vis, | 
 | 2354 |                                                AttrSpellingListIndex); | 
| Douglas Gregor | 0a0d2b1 | 2011-03-23 00:50:03 +0000 | [diff] [blame] | 2355 | } | 
 | 2356 |  | 
| John McCall | d4c3d66 | 2013-02-20 01:54:26 +0000 | [diff] [blame] | 2357 | TypeVisibilityAttr *Sema::mergeTypeVisibilityAttr(Decl *D, SourceRange Range, | 
 | 2358 |                                       TypeVisibilityAttr::VisibilityType Vis, | 
 | 2359 |                                       unsigned AttrSpellingListIndex) { | 
 | 2360 |   return ::mergeVisibilityAttr<TypeVisibilityAttr>(*this, D, Range, Vis, | 
 | 2361 |                                                    AttrSpellingListIndex); | 
 | 2362 | } | 
 | 2363 |  | 
 | 2364 | static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr, | 
 | 2365 |                                  bool isTypeVisibility) { | 
 | 2366 |   // Visibility attributes don't mean anything on a typedef. | 
 | 2367 |   if (isa<TypedefNameDecl>(D)) { | 
 | 2368 |     S.Diag(Attr.getRange().getBegin(), diag::warn_attribute_ignored) | 
 | 2369 |       << Attr.getName(); | 
 | 2370 |     return; | 
 | 2371 |   } | 
 | 2372 |  | 
 | 2373 |   // 'type_visibility' can only go on a type or namespace. | 
 | 2374 |   if (isTypeVisibility && | 
 | 2375 |       !(isa<TagDecl>(D) || | 
 | 2376 |         isa<ObjCInterfaceDecl>(D) || | 
 | 2377 |         isa<NamespaceDecl>(D))) { | 
 | 2378 |     S.Diag(Attr.getRange().getBegin(), diag::err_attribute_wrong_decl_type) | 
 | 2379 |       << Attr.getName() << ExpectedTypeOrNamespace; | 
 | 2380 |     return; | 
 | 2381 |   } | 
 | 2382 |  | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 2383 |   // check the attribute arguments. | 
| John McCall | d4c3d66 | 2013-02-20 01:54:26 +0000 | [diff] [blame] | 2384 |   if (!checkAttributeNumArgs(S, Attr, 1)) | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 2385 |     return; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2386 |  | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 2387 |   Expr *Arg = Attr.getArg(0); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 2388 |   Arg = Arg->IgnoreParenCasts(); | 
 | 2389 |   StringLiteral *Str = dyn_cast<StringLiteral>(Arg); | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2390 |  | 
| Douglas Gregor | 5cee119 | 2011-07-27 05:40:30 +0000 | [diff] [blame] | 2391 |   if (!Str || !Str->isAscii()) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 2392 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) | 
| John McCall | d4c3d66 | 2013-02-20 01:54:26 +0000 | [diff] [blame] | 2393 |       << (isTypeVisibility ? "type_visibility" : "visibility") << 1; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 2394 |     return; | 
 | 2395 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2396 |  | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 2397 |   StringRef TypeStr = Str->getString(); | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 2398 |   VisibilityAttr::VisibilityType type; | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2399 |    | 
| Benjamin Kramer | c96f494 | 2010-01-23 18:16:35 +0000 | [diff] [blame] | 2400 |   if (TypeStr == "default") | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 2401 |     type = VisibilityAttr::Default; | 
| Benjamin Kramer | c96f494 | 2010-01-23 18:16:35 +0000 | [diff] [blame] | 2402 |   else if (TypeStr == "hidden") | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 2403 |     type = VisibilityAttr::Hidden; | 
| Benjamin Kramer | c96f494 | 2010-01-23 18:16:35 +0000 | [diff] [blame] | 2404 |   else if (TypeStr == "internal") | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 2405 |     type = VisibilityAttr::Hidden; // FIXME | 
| John McCall | 4188760 | 2012-01-29 01:20:30 +0000 | [diff] [blame] | 2406 |   else if (TypeStr == "protected") { | 
 | 2407 |     // Complain about attempts to use protected visibility on targets | 
 | 2408 |     // (like Darwin) that don't support it. | 
 | 2409 |     if (!S.Context.getTargetInfo().hasProtectedVisibility()) { | 
 | 2410 |       S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility); | 
 | 2411 |       type = VisibilityAttr::Default; | 
 | 2412 |     } else { | 
 | 2413 |       type = VisibilityAttr::Protected; | 
 | 2414 |     } | 
 | 2415 |   } else { | 
| Chris Lattner | 08631c5 | 2008-11-23 21:45:46 +0000 | [diff] [blame] | 2416 |     S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 2417 |     return; | 
 | 2418 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2419 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2420 |   unsigned Index = Attr.getAttributeSpellingListIndex(); | 
| John McCall | d4c3d66 | 2013-02-20 01:54:26 +0000 | [diff] [blame] | 2421 |   clang::Attr *newAttr; | 
 | 2422 |   if (isTypeVisibility) { | 
 | 2423 |     newAttr = S.mergeTypeVisibilityAttr(D, Attr.getRange(), | 
 | 2424 |                                     (TypeVisibilityAttr::VisibilityType) type, | 
 | 2425 |                                         Index); | 
 | 2426 |   } else { | 
 | 2427 |     newAttr = S.mergeVisibilityAttr(D, Attr.getRange(), type, Index); | 
 | 2428 |   } | 
 | 2429 |   if (newAttr) | 
 | 2430 |     D->addAttr(newAttr); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 2431 | } | 
 | 2432 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2433 | static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl, | 
 | 2434 |                                        const AttributeList &Attr) { | 
| John McCall | d5313b0 | 2011-03-02 11:33:24 +0000 | [diff] [blame] | 2435 |   ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(decl); | 
 | 2436 |   if (!method) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2437 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 2438 |       << ExpectedMethod; | 
| John McCall | d5313b0 | 2011-03-02 11:33:24 +0000 | [diff] [blame] | 2439 |     return; | 
 | 2440 |   } | 
 | 2441 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2442 |   if (Attr.getNumArgs() != 0 || !Attr.getParameterName()) { | 
 | 2443 |     if (!Attr.getParameterName() && Attr.getNumArgs() == 1) { | 
 | 2444 |       S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) | 
| John McCall | d5313b0 | 2011-03-02 11:33:24 +0000 | [diff] [blame] | 2445 |         << "objc_method_family" << 1; | 
 | 2446 |     } else { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2447 |       S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; | 
| John McCall | d5313b0 | 2011-03-02 11:33:24 +0000 | [diff] [blame] | 2448 |     } | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2449 |     Attr.setInvalid(); | 
| John McCall | d5313b0 | 2011-03-02 11:33:24 +0000 | [diff] [blame] | 2450 |     return; | 
 | 2451 |   } | 
 | 2452 |  | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 2453 |   StringRef param = Attr.getParameterName()->getName(); | 
| John McCall | d5313b0 | 2011-03-02 11:33:24 +0000 | [diff] [blame] | 2454 |   ObjCMethodFamilyAttr::FamilyKind family; | 
 | 2455 |   if (param == "none") | 
 | 2456 |     family = ObjCMethodFamilyAttr::OMF_None; | 
 | 2457 |   else if (param == "alloc") | 
 | 2458 |     family = ObjCMethodFamilyAttr::OMF_alloc; | 
 | 2459 |   else if (param == "copy") | 
 | 2460 |     family = ObjCMethodFamilyAttr::OMF_copy; | 
 | 2461 |   else if (param == "init") | 
 | 2462 |     family = ObjCMethodFamilyAttr::OMF_init; | 
 | 2463 |   else if (param == "mutableCopy") | 
 | 2464 |     family = ObjCMethodFamilyAttr::OMF_mutableCopy; | 
 | 2465 |   else if (param == "new") | 
 | 2466 |     family = ObjCMethodFamilyAttr::OMF_new; | 
 | 2467 |   else { | 
 | 2468 |     // Just warn and ignore it.  This is future-proof against new | 
 | 2469 |     // families being used in system headers. | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2470 |     S.Diag(Attr.getParameterLoc(), diag::warn_unknown_method_family); | 
| John McCall | d5313b0 | 2011-03-02 11:33:24 +0000 | [diff] [blame] | 2471 |     return; | 
 | 2472 |   } | 
 | 2473 |  | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 2474 |   if (family == ObjCMethodFamilyAttr::OMF_init &&  | 
 | 2475 |       !method->getResultType()->isObjCObjectPointerType()) { | 
 | 2476 |     S.Diag(method->getLocation(), diag::err_init_method_bad_return_type) | 
 | 2477 |       << method->getResultType(); | 
 | 2478 |     // Ignore the attribute. | 
 | 2479 |     return; | 
 | 2480 |   } | 
 | 2481 |  | 
| Argyrios Kyrtzidis | 768d6ca | 2011-09-13 16:05:58 +0000 | [diff] [blame] | 2482 |   method->addAttr(new (S.Context) ObjCMethodFamilyAttr(Attr.getRange(), | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 2483 |                                                        S.Context, family)); | 
| John McCall | d5313b0 | 2011-03-02 11:33:24 +0000 | [diff] [blame] | 2484 | } | 
 | 2485 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2486 | static void handleObjCExceptionAttr(Sema &S, Decl *D, | 
 | 2487 |                                     const AttributeList &Attr) { | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 2488 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Chris Lattner | 0db29ec | 2009-02-14 08:09:34 +0000 | [diff] [blame] | 2489 |     return; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2490 |  | 
| Chris Lattner | 0db29ec | 2009-02-14 08:09:34 +0000 | [diff] [blame] | 2491 |   ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D); | 
 | 2492 |   if (OCI == 0) { | 
 | 2493 |     S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface); | 
 | 2494 |     return; | 
 | 2495 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2496 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2497 |   D->addAttr(::new (S.Context) | 
 | 2498 |              ObjCExceptionAttr(Attr.getRange(), S.Context, | 
 | 2499 |                                Attr.getAttributeSpellingListIndex())); | 
| Chris Lattner | 0db29ec | 2009-02-14 08:09:34 +0000 | [diff] [blame] | 2500 | } | 
 | 2501 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2502 | static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Fariborz Jahanian | fa23c1d | 2009-01-13 23:34:40 +0000 | [diff] [blame] | 2503 |   if (Attr.getNumArgs() != 0) { | 
| John McCall | 2b7baf0 | 2010-05-28 18:25:28 +0000 | [diff] [blame] | 2504 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; | 
| Fariborz Jahanian | fa23c1d | 2009-01-13 23:34:40 +0000 | [diff] [blame] | 2505 |     return; | 
 | 2506 |   } | 
| Richard Smith | 162e1c1 | 2011-04-15 14:24:37 +0000 | [diff] [blame] | 2507 |   if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { | 
| Fariborz Jahanian | fa23c1d | 2009-01-13 23:34:40 +0000 | [diff] [blame] | 2508 |     QualType T = TD->getUnderlyingType(); | 
| Ted Kremenek | 9af9122 | 2012-08-29 22:54:47 +0000 | [diff] [blame] | 2509 |     if (!T->isCARCBridgableType()) { | 
| Fariborz Jahanian | fa23c1d | 2009-01-13 23:34:40 +0000 | [diff] [blame] | 2510 |       S.Diag(TD->getLocation(), diag::err_nsobject_attribute); | 
 | 2511 |       return; | 
 | 2512 |     } | 
 | 2513 |   } | 
| Fariborz Jahanian | 3427682 | 2012-05-31 23:18:32 +0000 | [diff] [blame] | 2514 |   else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) { | 
 | 2515 |     QualType T = PD->getType(); | 
| Ted Kremenek | 9af9122 | 2012-08-29 22:54:47 +0000 | [diff] [blame] | 2516 |     if (!T->isCARCBridgableType()) { | 
| Fariborz Jahanian | 3427682 | 2012-05-31 23:18:32 +0000 | [diff] [blame] | 2517 |       S.Diag(PD->getLocation(), diag::err_nsobject_attribute); | 
 | 2518 |       return; | 
 | 2519 |     } | 
 | 2520 |   } | 
 | 2521 |   else { | 
| Ted Kremenek | f6e88d7 | 2012-03-01 01:40:32 +0000 | [diff] [blame] | 2522 |     // It is okay to include this attribute on properties, e.g.: | 
 | 2523 |     // | 
 | 2524 |     //  @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject)); | 
 | 2525 |     // | 
 | 2526 |     // In this case it follows tradition and suppresses an error in the above | 
 | 2527 |     // case.     | 
| Fariborz Jahanian | 9b2eb7b | 2011-11-29 01:48:40 +0000 | [diff] [blame] | 2528 |     S.Diag(D->getLocation(), diag::warn_nsobject_attribute); | 
| Ted Kremenek | f6e88d7 | 2012-03-01 01:40:32 +0000 | [diff] [blame] | 2529 |   } | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2530 |   D->addAttr(::new (S.Context) | 
 | 2531 |              ObjCNSObjectAttr(Attr.getRange(), S.Context, | 
 | 2532 |                               Attr.getAttributeSpellingListIndex())); | 
| Fariborz Jahanian | fa23c1d | 2009-01-13 23:34:40 +0000 | [diff] [blame] | 2533 | } | 
 | 2534 |  | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2535 | static void | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2536 | handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Douglas Gregor | f9201e0 | 2009-02-11 23:02:49 +0000 | [diff] [blame] | 2537 |   if (Attr.getNumArgs() != 0) { | 
| John McCall | 2b7baf0 | 2010-05-28 18:25:28 +0000 | [diff] [blame] | 2538 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; | 
| Douglas Gregor | f9201e0 | 2009-02-11 23:02:49 +0000 | [diff] [blame] | 2539 |     return; | 
 | 2540 |   } | 
 | 2541 |  | 
 | 2542 |   if (!isa<FunctionDecl>(D)) { | 
 | 2543 |     S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function); | 
 | 2544 |     return; | 
 | 2545 |   } | 
 | 2546 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2547 |   D->addAttr(::new (S.Context) | 
 | 2548 |              OverloadableAttr(Attr.getRange(), S.Context, | 
 | 2549 |                               Attr.getAttributeSpellingListIndex())); | 
| Douglas Gregor | f9201e0 | 2009-02-11 23:02:49 +0000 | [diff] [blame] | 2550 | } | 
 | 2551 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2552 | static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2553 |   if (!Attr.getParameterName()) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 2554 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 2555 |       << "blocks" << 1; | 
| Steve Naroff | 9eae576 | 2008-09-18 16:44:58 +0000 | [diff] [blame] | 2556 |     return; | 
 | 2557 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2558 |  | 
| Steve Naroff | 9eae576 | 2008-09-18 16:44:58 +0000 | [diff] [blame] | 2559 |   if (Attr.getNumArgs() != 0) { | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 2560 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; | 
| Steve Naroff | 9eae576 | 2008-09-18 16:44:58 +0000 | [diff] [blame] | 2561 |     return; | 
 | 2562 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2563 |  | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 2564 |   BlocksAttr::BlockType type; | 
| Chris Lattner | 92e62b0 | 2008-11-20 04:42:34 +0000 | [diff] [blame] | 2565 |   if (Attr.getParameterName()->isStr("byref")) | 
| Steve Naroff | 9eae576 | 2008-09-18 16:44:58 +0000 | [diff] [blame] | 2566 |     type = BlocksAttr::ByRef; | 
 | 2567 |   else { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 2568 |     S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 2569 |       << "blocks" << Attr.getParameterName(); | 
| Steve Naroff | 9eae576 | 2008-09-18 16:44:58 +0000 | [diff] [blame] | 2570 |     return; | 
 | 2571 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2572 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2573 |   D->addAttr(::new (S.Context) | 
 | 2574 |              BlocksAttr(Attr.getRange(), S.Context, type, | 
 | 2575 |                         Attr.getAttributeSpellingListIndex())); | 
| Steve Naroff | 9eae576 | 2008-09-18 16:44:58 +0000 | [diff] [blame] | 2576 | } | 
 | 2577 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2578 | static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2579 |   // check the attribute arguments. | 
 | 2580 |   if (Attr.getNumArgs() > 2) { | 
| John McCall | bdc49d3 | 2011-03-02 12:15:05 +0000 | [diff] [blame] | 2581 |     S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2; | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2582 |     return; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2583 |   } | 
 | 2584 |  | 
| John McCall | 3323fad | 2011-09-09 07:56:05 +0000 | [diff] [blame] | 2585 |   unsigned sentinel = 0; | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2586 |   if (Attr.getNumArgs() > 0) { | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 2587 |     Expr *E = Attr.getArg(0); | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2588 |     llvm::APSInt Idx(32); | 
| Douglas Gregor | ac06a0e | 2010-05-18 23:01:22 +0000 | [diff] [blame] | 2589 |     if (E->isTypeDependent() || E->isValueDependent() || | 
 | 2590 |         !E->isIntegerConstantExpr(Idx, S.Context)) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 2591 |       S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 2592 |        << "sentinel" << 1 << E->getSourceRange(); | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2593 |       return; | 
 | 2594 |     } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2595 |  | 
| John McCall | 3323fad | 2011-09-09 07:56:05 +0000 | [diff] [blame] | 2596 |     if (Idx.isSigned() && Idx.isNegative()) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 2597 |       S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero) | 
 | 2598 |         << E->getSourceRange(); | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2599 |       return; | 
 | 2600 |     } | 
| John McCall | 3323fad | 2011-09-09 07:56:05 +0000 | [diff] [blame] | 2601 |  | 
 | 2602 |     sentinel = Idx.getZExtValue(); | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2603 |   } | 
 | 2604 |  | 
| John McCall | 3323fad | 2011-09-09 07:56:05 +0000 | [diff] [blame] | 2605 |   unsigned nullPos = 0; | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2606 |   if (Attr.getNumArgs() > 1) { | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 2607 |     Expr *E = Attr.getArg(1); | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2608 |     llvm::APSInt Idx(32); | 
| Douglas Gregor | ac06a0e | 2010-05-18 23:01:22 +0000 | [diff] [blame] | 2609 |     if (E->isTypeDependent() || E->isValueDependent() || | 
 | 2610 |         !E->isIntegerConstantExpr(Idx, S.Context)) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 2611 |       S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 2612 |         << "sentinel" << 2 << E->getSourceRange(); | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2613 |       return; | 
 | 2614 |     } | 
 | 2615 |     nullPos = Idx.getZExtValue(); | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2616 |  | 
| John McCall | 3323fad | 2011-09-09 07:56:05 +0000 | [diff] [blame] | 2617 |     if ((Idx.isSigned() && Idx.isNegative()) || nullPos > 1) { | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2618 |       // FIXME: This error message could be improved, it would be nice | 
 | 2619 |       // to say what the bounds actually are. | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 2620 |       S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one) | 
 | 2621 |         << E->getSourceRange(); | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2622 |       return; | 
 | 2623 |     } | 
 | 2624 |   } | 
 | 2625 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2626 |   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { | 
| John McCall | 3323fad | 2011-09-09 07:56:05 +0000 | [diff] [blame] | 2627 |     const FunctionType *FT = FD->getType()->castAs<FunctionType>(); | 
| Chris Lattner | 897cd90 | 2009-03-17 23:03:47 +0000 | [diff] [blame] | 2628 |     if (isa<FunctionNoProtoType>(FT)) { | 
 | 2629 |       S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_named_arguments); | 
 | 2630 |       return; | 
 | 2631 |     } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2632 |  | 
| Chris Lattner | 897cd90 | 2009-03-17 23:03:47 +0000 | [diff] [blame] | 2633 |     if (!cast<FunctionProtoType>(FT)->isVariadic()) { | 
| Fariborz Jahanian | 3bba33d | 2009-05-15 21:18:04 +0000 | [diff] [blame] | 2634 |       S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2635 |       return; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2636 |     } | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2637 |   } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2638 |     if (!MD->isVariadic()) { | 
| Fariborz Jahanian | 3bba33d | 2009-05-15 21:18:04 +0000 | [diff] [blame] | 2639 |       S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2640 |       return; | 
| Fariborz Jahanian | 2f7c392 | 2009-05-14 20:53:39 +0000 | [diff] [blame] | 2641 |     } | 
| Eli Friedman | a0b2ba1 | 2012-01-06 01:23:10 +0000 | [diff] [blame] | 2642 |   } else if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) { | 
 | 2643 |     if (!BD->isVariadic()) { | 
 | 2644 |       S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; | 
 | 2645 |       return; | 
 | 2646 |     } | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2647 |   } else if (const VarDecl *V = dyn_cast<VarDecl>(D)) { | 
| Fariborz Jahanian | 2f7c392 | 2009-05-14 20:53:39 +0000 | [diff] [blame] | 2648 |     QualType Ty = V->getType(); | 
| Fariborz Jahanian | daf0415 | 2009-05-15 20:33:25 +0000 | [diff] [blame] | 2649 |     if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2650 |       const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(D) | 
| Eric Christopher | f48f367 | 2010-12-01 22:13:54 +0000 | [diff] [blame] | 2651 |        : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>(); | 
| Fariborz Jahanian | 2f7c392 | 2009-05-14 20:53:39 +0000 | [diff] [blame] | 2652 |       if (!cast<FunctionProtoType>(FT)->isVariadic()) { | 
| Fariborz Jahanian | 3bba33d | 2009-05-15 21:18:04 +0000 | [diff] [blame] | 2653 |         int m = Ty->isFunctionPointerType() ? 0 : 1; | 
 | 2654 |         S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m; | 
| Fariborz Jahanian | 2f7c392 | 2009-05-14 20:53:39 +0000 | [diff] [blame] | 2655 |         return; | 
 | 2656 |       } | 
| Mike Stump | ac5fc7c | 2009-08-04 21:02:39 +0000 | [diff] [blame] | 2657 |     } else { | 
| Fariborz Jahanian | 2f7c392 | 2009-05-14 20:53:39 +0000 | [diff] [blame] | 2658 |       S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 2659 |         << Attr.getName() << ExpectedFunctionMethodOrBlock; | 
| Fariborz Jahanian | 2f7c392 | 2009-05-14 20:53:39 +0000 | [diff] [blame] | 2660 |       return; | 
 | 2661 |     } | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2662 |   } else { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 2663 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 2664 |       << Attr.getName() << ExpectedFunctionMethodOrBlock; | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2665 |     return; | 
 | 2666 |   } | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2667 |   D->addAttr(::new (S.Context) | 
 | 2668 |              SentinelAttr(Attr.getRange(), S.Context, sentinel, nullPos, | 
 | 2669 |                           Attr.getAttributeSpellingListIndex())); | 
| Anders Carlsson | 7709182 | 2008-10-05 18:05:59 +0000 | [diff] [blame] | 2670 | } | 
 | 2671 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2672 | static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chris Lattner | 026dc96 | 2009-02-14 07:37:35 +0000 | [diff] [blame] | 2673 |   // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 2674 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Chris Lattner | 026dc96 | 2009-02-14 07:37:35 +0000 | [diff] [blame] | 2675 |     return; | 
| Chris Lattner | 026dc96 | 2009-02-14 07:37:35 +0000 | [diff] [blame] | 2676 |  | 
| Kaelyn Uhrain | 51ceb7b | 2012-11-12 23:48:05 +0000 | [diff] [blame] | 2677 |   if (!isFunction(D) && !isa<ObjCMethodDecl>(D) && !isa<CXXRecordDecl>(D)) { | 
| Chris Lattner | 026dc96 | 2009-02-14 07:37:35 +0000 | [diff] [blame] | 2678 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| Kaelyn Uhrain | d449c79 | 2012-11-13 00:18:47 +0000 | [diff] [blame] | 2679 |       << Attr.getName() << ExpectedFunctionMethodOrClass; | 
| Chris Lattner | 026dc96 | 2009-02-14 07:37:35 +0000 | [diff] [blame] | 2680 |     return; | 
 | 2681 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2682 |  | 
| Fariborz Jahanian | f031774 | 2010-03-30 18:22:15 +0000 | [diff] [blame] | 2683 |   if (isFunction(D) && getFunctionType(D)->getResultType()->isVoidType()) { | 
 | 2684 |     S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method) | 
 | 2685 |       << Attr.getName() << 0; | 
| Nuno Lopes | f857798 | 2009-12-22 23:59:52 +0000 | [diff] [blame] | 2686 |     return; | 
 | 2687 |   } | 
| Fariborz Jahanian | f031774 | 2010-03-30 18:22:15 +0000 | [diff] [blame] | 2688 |   if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) | 
 | 2689 |     if (MD->getResultType()->isVoidType()) { | 
 | 2690 |       S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method) | 
 | 2691 |       << Attr.getName() << 1; | 
 | 2692 |       return; | 
 | 2693 |     } | 
 | 2694 |    | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2695 |   D->addAttr(::new (S.Context)  | 
 | 2696 |              WarnUnusedResultAttr(Attr.getRange(), S.Context, | 
 | 2697 |                                   Attr.getAttributeSpellingListIndex())); | 
| Chris Lattner | 026dc96 | 2009-02-14 07:37:35 +0000 | [diff] [blame] | 2698 | } | 
 | 2699 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2700 | static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 2701 |   // check the attribute arguments. | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2702 |   if (Attr.hasParameterOrArguments()) { | 
 | 2703 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 2704 |     return; | 
 | 2705 |   } | 
| Daniel Dunbar | 6e775db | 2009-03-06 06:39:57 +0000 | [diff] [blame] | 2706 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2707 |   if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) { | 
| Fariborz Jahanian | 13c7fcc | 2011-10-21 22:27:12 +0000 | [diff] [blame] | 2708 |     if (isa<CXXRecordDecl>(D)) { | 
 | 2709 |       D->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context)); | 
 | 2710 |       return; | 
 | 2711 |     } | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2712 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
 | 2713 |       << Attr.getName() << ExpectedVariableOrFunction; | 
| Fariborz Jahanian | f23ecd9 | 2009-07-16 01:12:24 +0000 | [diff] [blame] | 2714 |     return; | 
 | 2715 |   } | 
 | 2716 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2717 |   NamedDecl *nd = cast<NamedDecl>(D); | 
| John McCall | 332bb2a | 2011-02-08 22:35:49 +0000 | [diff] [blame] | 2718 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2719 |   nd->addAttr(::new (S.Context) | 
 | 2720 |               WeakAttr(Attr.getRange(), S.Context, | 
 | 2721 |                        Attr.getAttributeSpellingListIndex())); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 2722 | } | 
 | 2723 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2724 | static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Daniel Dunbar | 6e775db | 2009-03-06 06:39:57 +0000 | [diff] [blame] | 2725 |   // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 2726 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Daniel Dunbar | 6e775db | 2009-03-06 06:39:57 +0000 | [diff] [blame] | 2727 |     return; | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 2728 |  | 
| Daniel Dunbar | 6e775db | 2009-03-06 06:39:57 +0000 | [diff] [blame] | 2729 |  | 
 | 2730 |   // weak_import only applies to variable & function declarations. | 
 | 2731 |   bool isDef = false; | 
| Douglas Gregor | 0a0d2b1 | 2011-03-23 00:50:03 +0000 | [diff] [blame] | 2732 |   if (!D->canBeWeakImported(isDef)) { | 
 | 2733 |     if (isDef) | 
| Reid Kleckner | beba3e8 | 2013-05-20 21:53:29 +0000 | [diff] [blame] | 2734 |       S.Diag(Attr.getLoc(), diag::warn_attribute_invalid_on_definition) | 
 | 2735 |         << "weak_import"; | 
| Douglas Gregor | def8631 | 2011-03-23 13:27:51 +0000 | [diff] [blame] | 2736 |     else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) || | 
| Douglas Gregor | bcfd1f5 | 2011-09-02 00:18:52 +0000 | [diff] [blame] | 2737 |              (S.Context.getTargetInfo().getTriple().isOSDarwin() && | 
| Fariborz Jahanian | 90eed21 | 2011-10-26 23:59:12 +0000 | [diff] [blame] | 2738 |               (isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) { | 
| Douglas Gregor | def8631 | 2011-03-23 13:27:51 +0000 | [diff] [blame] | 2739 |       // Nothing to warn about here. | 
 | 2740 |     } else | 
| Fariborz Jahanian | c034974 | 2010-04-13 20:22:35 +0000 | [diff] [blame] | 2741 |       S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 2742 |         << Attr.getName() << ExpectedVariableOrFunction; | 
| Daniel Dunbar | 6e775db | 2009-03-06 06:39:57 +0000 | [diff] [blame] | 2743 |  | 
| Daniel Dunbar | 6e775db | 2009-03-06 06:39:57 +0000 | [diff] [blame] | 2744 |     return; | 
 | 2745 |   } | 
 | 2746 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2747 |   D->addAttr(::new (S.Context) | 
 | 2748 |              WeakImportAttr(Attr.getRange(), S.Context, | 
 | 2749 |                             Attr.getAttributeSpellingListIndex())); | 
| Daniel Dunbar | 6e775db | 2009-03-06 06:39:57 +0000 | [diff] [blame] | 2750 | } | 
 | 2751 |  | 
| Tanya Lattner | 0df579e | 2012-07-09 22:06:01 +0000 | [diff] [blame] | 2752 | // Handles reqd_work_group_size and work_group_size_hint. | 
 | 2753 | static void handleWorkGroupSize(Sema &S, Decl *D, | 
| Nick Lewycky | 4ae89bc | 2012-07-24 01:31:55 +0000 | [diff] [blame] | 2754 |                                 const AttributeList &Attr) { | 
| Tanya Lattner | 0df579e | 2012-07-09 22:06:01 +0000 | [diff] [blame] | 2755 |   assert(Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize  | 
 | 2756 |       || Attr.getKind() == AttributeList::AT_WorkGroupSizeHint); | 
 | 2757 |  | 
| Nate Begeman | 6f3d838 | 2009-06-26 06:32:41 +0000 | [diff] [blame] | 2758 |   // Attribute has 3 arguments. | 
| Tanya Lattner | 0df579e | 2012-07-09 22:06:01 +0000 | [diff] [blame] | 2759 |   if (!checkAttributeNumArgs(S, Attr, 3)) return; | 
| Nate Begeman | 6f3d838 | 2009-06-26 06:32:41 +0000 | [diff] [blame] | 2760 |  | 
 | 2761 |   unsigned WGSize[3]; | 
 | 2762 |   for (unsigned i = 0; i < 3; ++i) { | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 2763 |     Expr *E = Attr.getArg(i); | 
| Nate Begeman | 6f3d838 | 2009-06-26 06:32:41 +0000 | [diff] [blame] | 2764 |     llvm::APSInt ArgNum(32); | 
| Douglas Gregor | ac06a0e | 2010-05-18 23:01:22 +0000 | [diff] [blame] | 2765 |     if (E->isTypeDependent() || E->isValueDependent() || | 
 | 2766 |         !E->isIntegerConstantExpr(ArgNum, S.Context)) { | 
| Nate Begeman | 6f3d838 | 2009-06-26 06:32:41 +0000 | [diff] [blame] | 2767 |       S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) | 
| Tanya Lattner | 0df579e | 2012-07-09 22:06:01 +0000 | [diff] [blame] | 2768 |         << Attr.getName()->getName() << E->getSourceRange(); | 
| Nate Begeman | 6f3d838 | 2009-06-26 06:32:41 +0000 | [diff] [blame] | 2769 |       return; | 
 | 2770 |     } | 
 | 2771 |     WGSize[i] = (unsigned) ArgNum.getZExtValue(); | 
 | 2772 |   } | 
| Tanya Lattner | 0df579e | 2012-07-09 22:06:01 +0000 | [diff] [blame] | 2773 |  | 
 | 2774 |   if (Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize | 
 | 2775 |     && D->hasAttr<ReqdWorkGroupSizeAttr>()) { | 
 | 2776 |       ReqdWorkGroupSizeAttr *A = D->getAttr<ReqdWorkGroupSizeAttr>(); | 
 | 2777 |       if (!(A->getXDim() == WGSize[0] && | 
 | 2778 |             A->getYDim() == WGSize[1] && | 
 | 2779 |             A->getZDim() == WGSize[2])) { | 
 | 2780 |         S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << | 
 | 2781 |           Attr.getName(); | 
 | 2782 |       } | 
 | 2783 |   } | 
 | 2784 |  | 
 | 2785 |   if (Attr.getKind() == AttributeList::AT_WorkGroupSizeHint | 
 | 2786 |     && D->hasAttr<WorkGroupSizeHintAttr>()) { | 
 | 2787 |       WorkGroupSizeHintAttr *A = D->getAttr<WorkGroupSizeHintAttr>(); | 
 | 2788 |       if (!(A->getXDim() == WGSize[0] && | 
 | 2789 |             A->getYDim() == WGSize[1] && | 
 | 2790 |             A->getZDim() == WGSize[2])) { | 
 | 2791 |         S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << | 
 | 2792 |           Attr.getName(); | 
 | 2793 |       } | 
 | 2794 |   } | 
 | 2795 |  | 
 | 2796 |   if (Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize) | 
 | 2797 |     D->addAttr(::new (S.Context) | 
 | 2798 |                  ReqdWorkGroupSizeAttr(Attr.getRange(), S.Context, | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2799 |                                        WGSize[0], WGSize[1], WGSize[2], | 
 | 2800 |                                        Attr.getAttributeSpellingListIndex())); | 
| Tanya Lattner | 0df579e | 2012-07-09 22:06:01 +0000 | [diff] [blame] | 2801 |   else | 
 | 2802 |     D->addAttr(::new (S.Context) | 
 | 2803 |                  WorkGroupSizeHintAttr(Attr.getRange(), S.Context, | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2804 |                                        WGSize[0], WGSize[1], WGSize[2], | 
 | 2805 |                                        Attr.getAttributeSpellingListIndex())); | 
| Nate Begeman | 6f3d838 | 2009-06-26 06:32:41 +0000 | [diff] [blame] | 2806 | } | 
 | 2807 |  | 
| Joey Gouly | 37453b9 | 2013-03-08 09:42:32 +0000 | [diff] [blame] | 2808 | static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) { | 
 | 2809 |   assert(Attr.getKind() == AttributeList::AT_VecTypeHint); | 
 | 2810 |  | 
 | 2811 |   // Attribute has 1 argument. | 
 | 2812 |   if (!checkAttributeNumArgs(S, Attr, 1)) | 
 | 2813 |     return; | 
 | 2814 |  | 
 | 2815 |   QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg()); | 
 | 2816 |  | 
 | 2817 |   if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() && | 
 | 2818 |       (ParmType->isBooleanType() || | 
 | 2819 |        !ParmType->isIntegralType(S.getASTContext()))) { | 
 | 2820 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_vec_type_hint) | 
 | 2821 |         << ParmType; | 
 | 2822 |     return; | 
 | 2823 |   } | 
 | 2824 |  | 
 | 2825 |   if (Attr.getKind() == AttributeList::AT_VecTypeHint && | 
 | 2826 |       D->hasAttr<VecTypeHintAttr>()) { | 
 | 2827 |     VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>(); | 
 | 2828 |     if (A->getTypeHint() != ParmType) { | 
 | 2829 |       S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName(); | 
 | 2830 |       return; | 
 | 2831 |     } | 
 | 2832 |   } | 
 | 2833 |  | 
 | 2834 |   D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context, | 
 | 2835 |                                                ParmType, Attr.getLoc())); | 
 | 2836 | } | 
 | 2837 |  | 
| Joey Gouly | 96cead5 | 2013-03-14 09:54:43 +0000 | [diff] [blame] | 2838 | static void handleEndianAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
 | 2839 |   if (!dyn_cast<VarDecl>(D)) | 
 | 2840 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << "endian" | 
 | 2841 |                                                                 << 9; | 
 | 2842 |   StringRef EndianType = Attr.getParameterName()->getName(); | 
 | 2843 |   if (EndianType != "host" && EndianType != "device") | 
 | 2844 |     S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_endian) << EndianType; | 
 | 2845 | } | 
 | 2846 |  | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 2847 | SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range, | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2848 |                                     StringRef Name, | 
 | 2849 |                                     unsigned AttrSpellingListIndex) { | 
| Rafael Espindola | 420efd8 | 2012-05-13 02:42:42 +0000 | [diff] [blame] | 2850 |   if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) { | 
 | 2851 |     if (ExistingAttr->getName() == Name) | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 2852 |       return NULL; | 
| Rafael Espindola | 420efd8 | 2012-05-13 02:42:42 +0000 | [diff] [blame] | 2853 |     Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section); | 
 | 2854 |     Diag(Range.getBegin(), diag::note_previous_attribute); | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 2855 |     return NULL; | 
| Rafael Espindola | 420efd8 | 2012-05-13 02:42:42 +0000 | [diff] [blame] | 2856 |   } | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2857 |   return ::new (Context) SectionAttr(Range, Context, Name, | 
 | 2858 |                                      AttrSpellingListIndex); | 
| Rafael Espindola | 420efd8 | 2012-05-13 02:42:42 +0000 | [diff] [blame] | 2859 | } | 
 | 2860 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2861 | static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Daniel Dunbar | 17f194f | 2009-02-12 17:28:23 +0000 | [diff] [blame] | 2862 |   // Attribute has no arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 2863 |   if (!checkAttributeNumArgs(S, Attr, 1)) | 
| Daniel Dunbar | 17f194f | 2009-02-12 17:28:23 +0000 | [diff] [blame] | 2864 |     return; | 
| Daniel Dunbar | 17f194f | 2009-02-12 17:28:23 +0000 | [diff] [blame] | 2865 |  | 
 | 2866 |   // Make sure that there is a string literal as the sections's single | 
 | 2867 |   // argument. | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 2868 |   Expr *ArgExpr = Attr.getArg(0); | 
| Chris Lattner | 797c3c4 | 2009-08-10 19:03:04 +0000 | [diff] [blame] | 2869 |   StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr); | 
| Daniel Dunbar | 17f194f | 2009-02-12 17:28:23 +0000 | [diff] [blame] | 2870 |   if (!SE) { | 
| Chris Lattner | 797c3c4 | 2009-08-10 19:03:04 +0000 | [diff] [blame] | 2871 |     S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) << "section"; | 
| Daniel Dunbar | 17f194f | 2009-02-12 17:28:23 +0000 | [diff] [blame] | 2872 |     return; | 
 | 2873 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2874 |  | 
| Chris Lattner | 797c3c4 | 2009-08-10 19:03:04 +0000 | [diff] [blame] | 2875 |   // If the target wants to validate the section specifier, make it happen. | 
| Douglas Gregor | bcfd1f5 | 2011-09-02 00:18:52 +0000 | [diff] [blame] | 2876 |   std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(SE->getString()); | 
| Chris Lattner | a1e1dc7 | 2010-01-12 20:58:53 +0000 | [diff] [blame] | 2877 |   if (!Error.empty()) { | 
 | 2878 |     S.Diag(SE->getLocStart(), diag::err_attribute_section_invalid_for_target) | 
 | 2879 |     << Error; | 
| Chris Lattner | 797c3c4 | 2009-08-10 19:03:04 +0000 | [diff] [blame] | 2880 |     return; | 
 | 2881 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 2882 |  | 
| Chris Lattner | a1e1dc7 | 2010-01-12 20:58:53 +0000 | [diff] [blame] | 2883 |   // This attribute cannot be applied to local variables. | 
 | 2884 |   if (isa<VarDecl>(D) && cast<VarDecl>(D)->hasLocalStorage()) { | 
 | 2885 |     S.Diag(SE->getLocStart(), diag::err_attribute_section_local_variable); | 
 | 2886 |     return; | 
 | 2887 |   } | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2888 |    | 
 | 2889 |   unsigned Index = Attr.getAttributeSpellingListIndex(); | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 2890 |   SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2891 |                                             SE->getString(), Index); | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 2892 |   if (NewAttr) | 
 | 2893 |     D->addAttr(NewAttr); | 
| Daniel Dunbar | 17f194f | 2009-02-12 17:28:23 +0000 | [diff] [blame] | 2894 | } | 
 | 2895 |  | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 2896 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2897 | static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 2898 |   // check the attribute arguments. | 
| Ted Kremenek | 831efae | 2011-04-15 05:49:29 +0000 | [diff] [blame] | 2899 |   if (Attr.hasParameterOrArguments()) { | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 2900 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 2901 |     return; | 
 | 2902 |   } | 
| Douglas Gregor | b30cd4a | 2011-06-15 05:45:11 +0000 | [diff] [blame] | 2903 |    | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2904 |   if (NoThrowAttr *Existing = D->getAttr<NoThrowAttr>()) { | 
| Douglas Gregor | b30cd4a | 2011-06-15 05:45:11 +0000 | [diff] [blame] | 2905 |     if (Existing->getLocation().isInvalid()) | 
| Argyrios Kyrtzidis | ffcc310 | 2011-09-13 16:05:53 +0000 | [diff] [blame] | 2906 |       Existing->setRange(Attr.getRange()); | 
| Douglas Gregor | b30cd4a | 2011-06-15 05:45:11 +0000 | [diff] [blame] | 2907 |   } else { | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2908 |     D->addAttr(::new (S.Context) | 
 | 2909 |                NoThrowAttr(Attr.getRange(), S.Context, | 
 | 2910 |                            Attr.getAttributeSpellingListIndex())); | 
| Douglas Gregor | b30cd4a | 2011-06-15 05:45:11 +0000 | [diff] [blame] | 2911 |   } | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 2912 | } | 
 | 2913 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2914 | static void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Anders Carlsson | 232eb7d | 2008-10-05 23:32:53 +0000 | [diff] [blame] | 2915 |   // check the attribute arguments. | 
| Ted Kremenek | 831efae | 2011-04-15 05:49:29 +0000 | [diff] [blame] | 2916 |   if (Attr.hasParameterOrArguments()) { | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 2917 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; | 
| Anders Carlsson | 232eb7d | 2008-10-05 23:32:53 +0000 | [diff] [blame] | 2918 |     return; | 
 | 2919 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2920 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2921 |   if (ConstAttr *Existing = D->getAttr<ConstAttr>()) { | 
| Douglas Gregor | b30cd4a | 2011-06-15 05:45:11 +0000 | [diff] [blame] | 2922 |    if (Existing->getLocation().isInvalid()) | 
| Argyrios Kyrtzidis | ffcc310 | 2011-09-13 16:05:53 +0000 | [diff] [blame] | 2923 |      Existing->setRange(Attr.getRange()); | 
| Douglas Gregor | b30cd4a | 2011-06-15 05:45:11 +0000 | [diff] [blame] | 2924 |   } else { | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2925 |     D->addAttr(::new (S.Context) | 
 | 2926 |                ConstAttr(Attr.getRange(), S.Context, | 
 | 2927 |                          Attr.getAttributeSpellingListIndex() )); | 
| Douglas Gregor | b30cd4a | 2011-06-15 05:45:11 +0000 | [diff] [blame] | 2928 |   } | 
| Anders Carlsson | 232eb7d | 2008-10-05 23:32:53 +0000 | [diff] [blame] | 2929 | } | 
 | 2930 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2931 | static void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Anders Carlsson | 232eb7d | 2008-10-05 23:32:53 +0000 | [diff] [blame] | 2932 |   // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 2933 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Anders Carlsson | 232eb7d | 2008-10-05 23:32:53 +0000 | [diff] [blame] | 2934 |     return; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2935 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2936 |   D->addAttr(::new (S.Context) | 
 | 2937 |              PureAttr(Attr.getRange(), S.Context, | 
 | 2938 |                       Attr.getAttributeSpellingListIndex())); | 
| Anders Carlsson | 232eb7d | 2008-10-05 23:32:53 +0000 | [diff] [blame] | 2939 | } | 
 | 2940 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 2941 | static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2942 |   if (!Attr.getParameterName()) { | 
| Anders Carlsson | f6e35d0 | 2009-01-31 01:16:18 +0000 | [diff] [blame] | 2943 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; | 
 | 2944 |     return; | 
 | 2945 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2946 |  | 
| Anders Carlsson | f6e35d0 | 2009-01-31 01:16:18 +0000 | [diff] [blame] | 2947 |   if (Attr.getNumArgs() != 0) { | 
 | 2948 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; | 
 | 2949 |     return; | 
 | 2950 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2951 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 2952 |   VarDecl *VD = dyn_cast<VarDecl>(D); | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2953 |  | 
| Anders Carlsson | f6e35d0 | 2009-01-31 01:16:18 +0000 | [diff] [blame] | 2954 |   if (!VD || !VD->hasLocalStorage()) { | 
 | 2955 |     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup"; | 
 | 2956 |     return; | 
 | 2957 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2958 |  | 
| Anders Carlsson | f6e35d0 | 2009-01-31 01:16:18 +0000 | [diff] [blame] | 2959 |   // Look up the function | 
| Douglas Gregor | c83c687 | 2010-04-15 22:33:43 +0000 | [diff] [blame] | 2960 |   // FIXME: Lookup probably isn't looking in the right place | 
| John McCall | f36e02d | 2009-10-09 21:13:30 +0000 | [diff] [blame] | 2961 |   NamedDecl *CleanupDecl | 
| Argyrios Kyrtzidis | f0b0ccc | 2010-12-06 17:51:50 +0000 | [diff] [blame] | 2962 |     = S.LookupSingleName(S.TUScope, Attr.getParameterName(), | 
 | 2963 |                          Attr.getParameterLoc(), Sema::LookupOrdinaryName); | 
| Anders Carlsson | f6e35d0 | 2009-01-31 01:16:18 +0000 | [diff] [blame] | 2964 |   if (!CleanupDecl) { | 
| Argyrios Kyrtzidis | f0b0ccc | 2010-12-06 17:51:50 +0000 | [diff] [blame] | 2965 |     S.Diag(Attr.getParameterLoc(), diag::err_attribute_cleanup_arg_not_found) << | 
| Anders Carlsson | f6e35d0 | 2009-01-31 01:16:18 +0000 | [diff] [blame] | 2966 |       Attr.getParameterName(); | 
 | 2967 |     return; | 
 | 2968 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2969 |  | 
| Anders Carlsson | f6e35d0 | 2009-01-31 01:16:18 +0000 | [diff] [blame] | 2970 |   FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl); | 
 | 2971 |   if (!FD) { | 
| Argyrios Kyrtzidis | f0b0ccc | 2010-12-06 17:51:50 +0000 | [diff] [blame] | 2972 |     S.Diag(Attr.getParameterLoc(), | 
 | 2973 |            diag::err_attribute_cleanup_arg_not_function) | 
 | 2974 |       << Attr.getParameterName(); | 
| Anders Carlsson | f6e35d0 | 2009-01-31 01:16:18 +0000 | [diff] [blame] | 2975 |     return; | 
 | 2976 |   } | 
 | 2977 |  | 
| Anders Carlsson | f6e35d0 | 2009-01-31 01:16:18 +0000 | [diff] [blame] | 2978 |   if (FD->getNumParams() != 1) { | 
| Argyrios Kyrtzidis | f0b0ccc | 2010-12-06 17:51:50 +0000 | [diff] [blame] | 2979 |     S.Diag(Attr.getParameterLoc(), | 
 | 2980 |            diag::err_attribute_cleanup_func_must_take_one_arg) | 
 | 2981 |       << Attr.getParameterName(); | 
| Anders Carlsson | f6e35d0 | 2009-01-31 01:16:18 +0000 | [diff] [blame] | 2982 |     return; | 
 | 2983 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2984 |  | 
| Anders Carlsson | 89941c1 | 2009-02-07 23:16:50 +0000 | [diff] [blame] | 2985 |   // We're currently more strict than GCC about what function types we accept. | 
 | 2986 |   // If this ever proves to be a problem it should be easy to fix. | 
 | 2987 |   QualType Ty = S.Context.getPointerType(VD->getType()); | 
 | 2988 |   QualType ParamTy = FD->getParamDecl(0)->getType(); | 
| Douglas Gregor | b608b98 | 2011-01-28 02:26:04 +0000 | [diff] [blame] | 2989 |   if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(), | 
 | 2990 |                                    ParamTy, Ty) != Sema::Compatible) { | 
| Argyrios Kyrtzidis | f0b0ccc | 2010-12-06 17:51:50 +0000 | [diff] [blame] | 2991 |     S.Diag(Attr.getParameterLoc(), | 
| Anders Carlsson | 89941c1 | 2009-02-07 23:16:50 +0000 | [diff] [blame] | 2992 |            diag::err_attribute_cleanup_func_arg_incompatible_type) << | 
 | 2993 |       Attr.getParameterName() << ParamTy << Ty; | 
 | 2994 |     return; | 
 | 2995 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 2996 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 2997 |   D->addAttr(::new (S.Context) | 
 | 2998 |              CleanupAttr(Attr.getRange(), S.Context, FD, | 
 | 2999 |                          Attr.getAttributeSpellingListIndex())); | 
| Eli Friedman | 5f2987c | 2012-02-02 03:46:19 +0000 | [diff] [blame] | 3000 |   S.MarkFunctionReferenced(Attr.getParameterLoc(), FD); | 
| Nick Lewycky | 3c86a5c | 2013-02-12 08:08:54 +0000 | [diff] [blame] | 3001 |   S.DiagnoseUseOfDecl(FD, Attr.getParameterLoc()); | 
| Anders Carlsson | f6e35d0 | 2009-01-31 01:16:18 +0000 | [diff] [blame] | 3002 | } | 
 | 3003 |  | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3004 | /// Handle __attribute__((format_arg((idx)))) attribute based on | 
| Bill Wendling | ad017fa | 2012-12-20 19:22:21 +0000 | [diff] [blame] | 3005 | /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3006 | static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3007 |   if (!checkAttributeNumArgs(S, Attr, 1)) | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3008 |     return; | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3009 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3010 |   if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3011 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 3012 |       << Attr.getName() << ExpectedFunction; | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3013 |     return; | 
 | 3014 |   } | 
| Chandler Carruth | 07d7e7a | 2010-11-16 08:35:43 +0000 | [diff] [blame] | 3015 |  | 
 | 3016 |   // In C++ the implicit 'this' function parameter also counts, and they are | 
 | 3017 |   // counted from one. | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3018 |   bool HasImplicitThisParam = isInstanceMethod(D); | 
 | 3019 |   unsigned NumArgs  = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3020 |   unsigned FirstIdx = 1; | 
| Chandler Carruth | 07d7e7a | 2010-11-16 08:35:43 +0000 | [diff] [blame] | 3021 |  | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3022 |   // checks for the 2nd argument | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 3023 |   Expr *IdxExpr = Attr.getArg(0); | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3024 |   llvm::APSInt Idx(32); | 
| Douglas Gregor | ac06a0e | 2010-05-18 23:01:22 +0000 | [diff] [blame] | 3025 |   if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || | 
 | 3026 |       !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3027 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) | 
 | 3028 |     << "format" << 2 << IdxExpr->getSourceRange(); | 
 | 3029 |     return; | 
 | 3030 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3031 |  | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3032 |   if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { | 
 | 3033 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) | 
 | 3034 |     << "format" << 2 << IdxExpr->getSourceRange(); | 
 | 3035 |     return; | 
 | 3036 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3037 |  | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3038 |   unsigned ArgIdx = Idx.getZExtValue() - 1; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3039 |  | 
| Chandler Carruth | 07d7e7a | 2010-11-16 08:35:43 +0000 | [diff] [blame] | 3040 |   if (HasImplicitThisParam) { | 
 | 3041 |     if (ArgIdx == 0) { | 
 | 3042 |       S.Diag(Attr.getLoc(), diag::err_attribute_invalid_implicit_this_argument) | 
 | 3043 |         << "format_arg" << IdxExpr->getSourceRange(); | 
 | 3044 |       return; | 
 | 3045 |     } | 
 | 3046 |     ArgIdx--; | 
 | 3047 |   } | 
 | 3048 |  | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3049 |   // make sure the format string is really a string | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3050 |   QualType Ty = getFunctionOrMethodArgType(D, ArgIdx); | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3051 |  | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3052 |   bool not_nsstring_type = !isNSStringType(Ty, S.Context); | 
 | 3053 |   if (not_nsstring_type && | 
 | 3054 |       !isCFStringType(Ty, S.Context) && | 
 | 3055 |       (!Ty->isPointerType() || | 
| Ted Kremenek | 6217b80 | 2009-07-29 21:53:49 +0000 | [diff] [blame] | 3056 |        !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) { | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3057 |     // FIXME: Should highlight the actual expression that has the wrong type. | 
 | 3058 |     S.Diag(Attr.getLoc(), diag::err_format_attribute_not) | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3059 |     << (not_nsstring_type ? "a string type" : "an NSString") | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3060 |        << IdxExpr->getSourceRange(); | 
 | 3061 |     return; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3062 |   } | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3063 |   Ty = getFunctionOrMethodResultType(D); | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3064 |   if (!isNSStringType(Ty, S.Context) && | 
 | 3065 |       !isCFStringType(Ty, S.Context) && | 
 | 3066 |       (!Ty->isPointerType() || | 
| Ted Kremenek | 6217b80 | 2009-07-29 21:53:49 +0000 | [diff] [blame] | 3067 |        !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) { | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3068 |     // FIXME: Should highlight the actual expression that has the wrong type. | 
 | 3069 |     S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not) | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3070 |     << (not_nsstring_type ? "string type" : "NSString") | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3071 |        << IdxExpr->getSourceRange(); | 
 | 3072 |     return; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3073 |   } | 
 | 3074 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3075 |   D->addAttr(::new (S.Context) | 
 | 3076 |              FormatArgAttr(Attr.getRange(), S.Context, Idx.getZExtValue(), | 
 | 3077 |                            Attr.getAttributeSpellingListIndex())); | 
| Fariborz Jahanian | 5b16092 | 2009-05-20 17:41:43 +0000 | [diff] [blame] | 3078 | } | 
 | 3079 |  | 
| Daniel Dunbar | 2b0d9a2 | 2009-10-18 02:09:17 +0000 | [diff] [blame] | 3080 | enum FormatAttrKind { | 
 | 3081 |   CFStringFormat, | 
 | 3082 |   NSStringFormat, | 
 | 3083 |   StrftimeFormat, | 
 | 3084 |   SupportedFormat, | 
| Chris Lattner | 3c98902 | 2010-03-22 21:08:50 +0000 | [diff] [blame] | 3085 |   IgnoredFormat, | 
| Daniel Dunbar | 2b0d9a2 | 2009-10-18 02:09:17 +0000 | [diff] [blame] | 3086 |   InvalidFormat | 
 | 3087 | }; | 
 | 3088 |  | 
 | 3089 | /// getFormatAttrKind - Map from format attribute names to supported format | 
 | 3090 | /// types. | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 3091 | static FormatAttrKind getFormatAttrKind(StringRef Format) { | 
| Benjamin Kramer | c51bb99 | 2012-05-16 12:44:25 +0000 | [diff] [blame] | 3092 |   return llvm::StringSwitch<FormatAttrKind>(Format) | 
 | 3093 |     // Check for formats that get handled specially. | 
 | 3094 |     .Case("NSString", NSStringFormat) | 
 | 3095 |     .Case("CFString", CFStringFormat) | 
 | 3096 |     .Case("strftime", StrftimeFormat) | 
| Daniel Dunbar | 2b0d9a2 | 2009-10-18 02:09:17 +0000 | [diff] [blame] | 3097 |  | 
| Benjamin Kramer | c51bb99 | 2012-05-16 12:44:25 +0000 | [diff] [blame] | 3098 |     // Otherwise, check for supported formats. | 
 | 3099 |     .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat) | 
 | 3100 |     .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat) | 
 | 3101 |     .Case("kprintf", SupportedFormat) // OpenBSD. | 
| Daniel Dunbar | 2b0d9a2 | 2009-10-18 02:09:17 +0000 | [diff] [blame] | 3102 |  | 
| Benjamin Kramer | c51bb99 | 2012-05-16 12:44:25 +0000 | [diff] [blame] | 3103 |     .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat) | 
 | 3104 |     .Default(InvalidFormat); | 
| Daniel Dunbar | 2b0d9a2 | 2009-10-18 02:09:17 +0000 | [diff] [blame] | 3105 | } | 
 | 3106 |  | 
| Fariborz Jahanian | 521f12d | 2010-06-18 21:44:06 +0000 | [diff] [blame] | 3107 | /// Handle __attribute__((init_priority(priority))) attributes based on | 
| Bill Wendling | ad017fa | 2012-12-20 19:22:21 +0000 | [diff] [blame] | 3108 | /// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3109 | static void handleInitPriorityAttr(Sema &S, Decl *D, | 
 | 3110 |                                    const AttributeList &Attr) { | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 3111 |   if (!S.getLangOpts().CPlusPlus) { | 
| Fariborz Jahanian | 521f12d | 2010-06-18 21:44:06 +0000 | [diff] [blame] | 3112 |     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); | 
 | 3113 |     return; | 
 | 3114 |   } | 
 | 3115 |    | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3116 |   if (!isa<VarDecl>(D) || S.getCurFunctionOrMethodDecl()) { | 
| Fariborz Jahanian | b9d5c22 | 2010-06-18 23:14:53 +0000 | [diff] [blame] | 3117 |     S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr); | 
 | 3118 |     Attr.setInvalid(); | 
 | 3119 |     return; | 
 | 3120 |   } | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3121 |   QualType T = dyn_cast<VarDecl>(D)->getType(); | 
| Fariborz Jahanian | b9d5c22 | 2010-06-18 23:14:53 +0000 | [diff] [blame] | 3122 |   if (S.Context.getAsArrayType(T)) | 
 | 3123 |     T = S.Context.getBaseElementType(T); | 
 | 3124 |   if (!T->getAs<RecordType>()) { | 
 | 3125 |     S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr); | 
 | 3126 |     Attr.setInvalid(); | 
 | 3127 |     return; | 
 | 3128 |   } | 
 | 3129 |    | 
| Fariborz Jahanian | 521f12d | 2010-06-18 21:44:06 +0000 | [diff] [blame] | 3130 |   if (Attr.getNumArgs() != 1) { | 
 | 3131 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; | 
 | 3132 |     Attr.setInvalid(); | 
 | 3133 |     return; | 
 | 3134 |   } | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 3135 |   Expr *priorityExpr = Attr.getArg(0); | 
| Fariborz Jahanian | b9d5c22 | 2010-06-18 23:14:53 +0000 | [diff] [blame] | 3136 |    | 
| Fariborz Jahanian | 521f12d | 2010-06-18 21:44:06 +0000 | [diff] [blame] | 3137 |   llvm::APSInt priority(32); | 
 | 3138 |   if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() || | 
 | 3139 |       !priorityExpr->isIntegerConstantExpr(priority, S.Context)) { | 
 | 3140 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) | 
 | 3141 |     << "init_priority" << priorityExpr->getSourceRange(); | 
 | 3142 |     Attr.setInvalid(); | 
 | 3143 |     return; | 
 | 3144 |   } | 
| Fariborz Jahanian | 9f967c5 | 2010-06-21 18:45:05 +0000 | [diff] [blame] | 3145 |   unsigned prioritynum = priority.getZExtValue(); | 
| Fariborz Jahanian | 521f12d | 2010-06-18 21:44:06 +0000 | [diff] [blame] | 3146 |   if (prioritynum < 101 || prioritynum > 65535) { | 
 | 3147 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range) | 
 | 3148 |     <<  priorityExpr->getSourceRange(); | 
 | 3149 |     Attr.setInvalid(); | 
 | 3150 |     return; | 
 | 3151 |   } | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3152 |   D->addAttr(::new (S.Context) | 
 | 3153 |              InitPriorityAttr(Attr.getRange(), S.Context, prioritynum, | 
 | 3154 |                               Attr.getAttributeSpellingListIndex())); | 
| Fariborz Jahanian | 521f12d | 2010-06-18 21:44:06 +0000 | [diff] [blame] | 3155 | } | 
 | 3156 |  | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 3157 | FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format, | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3158 |                                   int FormatIdx, int FirstArg, | 
 | 3159 |                                   unsigned AttrSpellingListIndex) { | 
| Rafael Espindola | bf9da1f | 2012-05-11 00:36:07 +0000 | [diff] [blame] | 3160 |   // Check whether we already have an equivalent format attribute. | 
 | 3161 |   for (specific_attr_iterator<FormatAttr> | 
 | 3162 |          i = D->specific_attr_begin<FormatAttr>(), | 
 | 3163 |          e = D->specific_attr_end<FormatAttr>(); | 
 | 3164 |        i != e ; ++i) { | 
 | 3165 |     FormatAttr *f = *i; | 
 | 3166 |     if (f->getType() == Format && | 
 | 3167 |         f->getFormatIdx() == FormatIdx && | 
 | 3168 |         f->getFirstArg() == FirstArg) { | 
 | 3169 |       // If we don't have a valid location for this attribute, adopt the | 
 | 3170 |       // location. | 
 | 3171 |       if (f->getLocation().isInvalid()) | 
 | 3172 |         f->setRange(Range); | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 3173 |       return NULL; | 
| Rafael Espindola | bf9da1f | 2012-05-11 00:36:07 +0000 | [diff] [blame] | 3174 |     } | 
 | 3175 |   } | 
 | 3176 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3177 |   return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx, FirstArg, | 
 | 3178 |                                     AttrSpellingListIndex); | 
| Rafael Espindola | bf9da1f | 2012-05-11 00:36:07 +0000 | [diff] [blame] | 3179 | } | 
 | 3180 |  | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3181 | /// Handle __attribute__((format(type,idx,firstarg))) attributes based on | 
| Bill Wendling | ad017fa | 2012-12-20 19:22:21 +0000 | [diff] [blame] | 3182 | /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3183 | static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3184 |  | 
| Chris Lattner | 545dd34 | 2008-06-28 23:36:30 +0000 | [diff] [blame] | 3185 |   if (!Attr.getParameterName()) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 3186 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 3187 |       << "format" << 1; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3188 |     return; | 
 | 3189 |   } | 
 | 3190 |  | 
| Chris Lattner | 545dd34 | 2008-06-28 23:36:30 +0000 | [diff] [blame] | 3191 |   if (Attr.getNumArgs() != 2) { | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 3192 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3193 |     return; | 
 | 3194 |   } | 
 | 3195 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3196 |   if (!isFunctionOrMethodOrBlock(D) || !hasFunctionProto(D)) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 3197 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 3198 |       << Attr.getName() << ExpectedFunction; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3199 |     return; | 
 | 3200 |   } | 
 | 3201 |  | 
| Chandler Carruth | 07d7e7a | 2010-11-16 08:35:43 +0000 | [diff] [blame] | 3202 |   // In C++ the implicit 'this' function parameter also counts, and they are | 
 | 3203 |   // counted from one. | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3204 |   bool HasImplicitThisParam = isInstanceMethod(D); | 
 | 3205 |   unsigned NumArgs  = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3206 |   unsigned FirstIdx = 1; | 
 | 3207 |  | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 3208 |   StringRef Format = Attr.getParameterName()->getName(); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3209 |  | 
 | 3210 |   // Normalize the argument, __foo__ becomes foo. | 
| Daniel Dunbar | 2b0d9a2 | 2009-10-18 02:09:17 +0000 | [diff] [blame] | 3211 |   if (Format.startswith("__") && Format.endswith("__")) | 
 | 3212 |     Format = Format.substr(2, Format.size() - 4); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3213 |  | 
| Daniel Dunbar | 2b0d9a2 | 2009-10-18 02:09:17 +0000 | [diff] [blame] | 3214 |   // Check for supported formats. | 
 | 3215 |   FormatAttrKind Kind = getFormatAttrKind(Format); | 
| Chris Lattner | 3c98902 | 2010-03-22 21:08:50 +0000 | [diff] [blame] | 3216 |    | 
 | 3217 |   if (Kind == IgnoredFormat) | 
 | 3218 |     return; | 
 | 3219 |    | 
| Daniel Dunbar | 2b0d9a2 | 2009-10-18 02:09:17 +0000 | [diff] [blame] | 3220 |   if (Kind == InvalidFormat) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 3221 |     S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) | 
| Daniel Dunbar | 01eb9b9 | 2009-10-18 21:17:35 +0000 | [diff] [blame] | 3222 |       << "format" << Attr.getParameterName()->getName(); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3223 |     return; | 
 | 3224 |   } | 
 | 3225 |  | 
 | 3226 |   // checks for the 2nd argument | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 3227 |   Expr *IdxExpr = Attr.getArg(0); | 
| Chris Lattner | 803d080 | 2008-06-29 00:43:07 +0000 | [diff] [blame] | 3228 |   llvm::APSInt Idx(32); | 
| Douglas Gregor | ac06a0e | 2010-05-18 23:01:22 +0000 | [diff] [blame] | 3229 |   if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || | 
 | 3230 |       !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 3231 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 3232 |       << "format" << 2 << IdxExpr->getSourceRange(); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3233 |     return; | 
 | 3234 |   } | 
 | 3235 |  | 
 | 3236 |   if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 3237 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 3238 |       << "format" << 2 << IdxExpr->getSourceRange(); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3239 |     return; | 
 | 3240 |   } | 
 | 3241 |  | 
 | 3242 |   // FIXME: Do we need to bounds check? | 
 | 3243 |   unsigned ArgIdx = Idx.getZExtValue() - 1; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3244 |  | 
| Sebastian Redl | 4a2614e | 2009-11-17 18:02:24 +0000 | [diff] [blame] | 3245 |   if (HasImplicitThisParam) { | 
 | 3246 |     if (ArgIdx == 0) { | 
| Chandler Carruth | 07d7e7a | 2010-11-16 08:35:43 +0000 | [diff] [blame] | 3247 |       S.Diag(Attr.getLoc(), | 
 | 3248 |              diag::err_format_attribute_implicit_this_format_string) | 
 | 3249 |         << IdxExpr->getSourceRange(); | 
| Sebastian Redl | 4a2614e | 2009-11-17 18:02:24 +0000 | [diff] [blame] | 3250 |       return; | 
 | 3251 |     } | 
 | 3252 |     ArgIdx--; | 
 | 3253 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 3254 |  | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3255 |   // make sure the format string is really a string | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3256 |   QualType Ty = getFunctionOrMethodArgType(D, ArgIdx); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3257 |  | 
| Daniel Dunbar | 2b0d9a2 | 2009-10-18 02:09:17 +0000 | [diff] [blame] | 3258 |   if (Kind == CFStringFormat) { | 
| Daniel Dunbar | 085e8f7 | 2008-09-26 03:32:58 +0000 | [diff] [blame] | 3259 |     if (!isCFStringType(Ty, S.Context)) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 3260 |       S.Diag(Attr.getLoc(), diag::err_format_attribute_not) | 
 | 3261 |         << "a CFString" << IdxExpr->getSourceRange(); | 
| Daniel Dunbar | 085e8f7 | 2008-09-26 03:32:58 +0000 | [diff] [blame] | 3262 |       return; | 
 | 3263 |     } | 
| Daniel Dunbar | 2b0d9a2 | 2009-10-18 02:09:17 +0000 | [diff] [blame] | 3264 |   } else if (Kind == NSStringFormat) { | 
| Mike Stump | 390b4cc | 2009-05-16 07:39:55 +0000 | [diff] [blame] | 3265 |     // FIXME: do we need to check if the type is NSString*?  What are the | 
 | 3266 |     // semantics? | 
| Chris Lattner | 803d080 | 2008-06-29 00:43:07 +0000 | [diff] [blame] | 3267 |     if (!isNSStringType(Ty, S.Context)) { | 
| Mike Stump | 390b4cc | 2009-05-16 07:39:55 +0000 | [diff] [blame] | 3268 |       // FIXME: Should highlight the actual expression that has the wrong type. | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 3269 |       S.Diag(Attr.getLoc(), diag::err_format_attribute_not) | 
 | 3270 |         << "an NSString" << IdxExpr->getSourceRange(); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3271 |       return; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3272 |     } | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3273 |   } else if (!Ty->isPointerType() || | 
| Ted Kremenek | 6217b80 | 2009-07-29 21:53:49 +0000 | [diff] [blame] | 3274 |              !Ty->getAs<PointerType>()->getPointeeType()->isCharType()) { | 
| Mike Stump | 390b4cc | 2009-05-16 07:39:55 +0000 | [diff] [blame] | 3275 |     // FIXME: Should highlight the actual expression that has the wrong type. | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 3276 |     S.Diag(Attr.getLoc(), diag::err_format_attribute_not) | 
 | 3277 |       << "a string type" << IdxExpr->getSourceRange(); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3278 |     return; | 
 | 3279 |   } | 
 | 3280 |  | 
 | 3281 |   // check the 3rd argument | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 3282 |   Expr *FirstArgExpr = Attr.getArg(1); | 
| Chris Lattner | 803d080 | 2008-06-29 00:43:07 +0000 | [diff] [blame] | 3283 |   llvm::APSInt FirstArg(32); | 
| Douglas Gregor | ac06a0e | 2010-05-18 23:01:22 +0000 | [diff] [blame] | 3284 |   if (FirstArgExpr->isTypeDependent() || FirstArgExpr->isValueDependent() || | 
 | 3285 |       !FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 3286 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 3287 |       << "format" << 3 << FirstArgExpr->getSourceRange(); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3288 |     return; | 
 | 3289 |   } | 
 | 3290 |  | 
 | 3291 |   // check if the function is variadic if the 3rd argument non-zero | 
 | 3292 |   if (FirstArg != 0) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3293 |     if (isFunctionOrMethodVariadic(D)) { | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3294 |       ++NumArgs; // +1 for ... | 
 | 3295 |     } else { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3296 |       S.Diag(D->getLocation(), diag::err_format_attribute_requires_variadic); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3297 |       return; | 
 | 3298 |     } | 
 | 3299 |   } | 
 | 3300 |  | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 3301 |   // strftime requires FirstArg to be 0 because it doesn't read from any | 
 | 3302 |   // variable the input is just the current time + the format string. | 
| Daniel Dunbar | 2b0d9a2 | 2009-10-18 02:09:17 +0000 | [diff] [blame] | 3303 |   if (Kind == StrftimeFormat) { | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3304 |     if (FirstArg != 0) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 3305 |       S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter) | 
 | 3306 |         << FirstArgExpr->getSourceRange(); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3307 |       return; | 
 | 3308 |     } | 
 | 3309 |   // if 0 it disables parameter checking (to use with e.g. va_list) | 
 | 3310 |   } else if (FirstArg != 0 && FirstArg != NumArgs) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 3311 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 3312 |       << "format" << 3 << FirstArgExpr->getSourceRange(); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3313 |     return; | 
 | 3314 |   } | 
 | 3315 |  | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 3316 |   FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), Format, | 
 | 3317 |                                           Idx.getZExtValue(), | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3318 |                                           FirstArg.getZExtValue(), | 
 | 3319 |                                           Attr.getAttributeSpellingListIndex()); | 
| Rafael Espindola | 599f1b7 | 2012-05-13 03:25:18 +0000 | [diff] [blame] | 3320 |   if (NewAttr) | 
 | 3321 |     D->addAttr(NewAttr); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3322 | } | 
 | 3323 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3324 | static void handleTransparentUnionAttr(Sema &S, Decl *D, | 
 | 3325 |                                        const AttributeList &Attr) { | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3326 |   // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3327 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3328 |     return; | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3329 |  | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3330 |  | 
| Douglas Gregor | 0c74e8a | 2009-04-29 22:16:16 +0000 | [diff] [blame] | 3331 |   // Try to find the underlying union declaration. | 
 | 3332 |   RecordDecl *RD = 0; | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3333 |   TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); | 
| Douglas Gregor | 0c74e8a | 2009-04-29 22:16:16 +0000 | [diff] [blame] | 3334 |   if (TD && TD->getUnderlyingType()->isUnionType()) | 
 | 3335 |     RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); | 
 | 3336 |   else | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3337 |     RD = dyn_cast<RecordDecl>(D); | 
| Douglas Gregor | 0c74e8a | 2009-04-29 22:16:16 +0000 | [diff] [blame] | 3338 |  | 
 | 3339 |   if (!RD || !RD->isUnion()) { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 3340 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 3341 |       << Attr.getName() << ExpectedUnion; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3342 |     return; | 
 | 3343 |   } | 
 | 3344 |  | 
| John McCall | 5e1cdac | 2011-10-07 06:10:15 +0000 | [diff] [blame] | 3345 |   if (!RD->isCompleteDefinition()) { | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3346 |     S.Diag(Attr.getLoc(), | 
| Douglas Gregor | 0c74e8a | 2009-04-29 22:16:16 +0000 | [diff] [blame] | 3347 |         diag::warn_transparent_union_attribute_not_definition); | 
 | 3348 |     return; | 
 | 3349 |   } | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3350 |  | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 3351 |   RecordDecl::field_iterator Field = RD->field_begin(), | 
 | 3352 |                           FieldEnd = RD->field_end(); | 
| Douglas Gregor | 0c74e8a | 2009-04-29 22:16:16 +0000 | [diff] [blame] | 3353 |   if (Field == FieldEnd) { | 
 | 3354 |     S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields); | 
 | 3355 |     return; | 
 | 3356 |   } | 
| Eli Friedman | bc88745 | 2008-09-02 05:19:23 +0000 | [diff] [blame] | 3357 |  | 
| David Blaikie | 581deb3 | 2012-06-06 20:45:41 +0000 | [diff] [blame] | 3358 |   FieldDecl *FirstField = *Field; | 
| Douglas Gregor | 0c74e8a | 2009-04-29 22:16:16 +0000 | [diff] [blame] | 3359 |   QualType FirstType = FirstField->getType(); | 
| Douglas Gregor | 90cd672 | 2010-06-30 17:24:13 +0000 | [diff] [blame] | 3360 |   if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) { | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3361 |     S.Diag(FirstField->getLocation(), | 
| Douglas Gregor | 90cd672 | 2010-06-30 17:24:13 +0000 | [diff] [blame] | 3362 |            diag::warn_transparent_union_attribute_floating) | 
 | 3363 |       << FirstType->isVectorType() << FirstType; | 
| Douglas Gregor | 0c74e8a | 2009-04-29 22:16:16 +0000 | [diff] [blame] | 3364 |     return; | 
 | 3365 |   } | 
 | 3366 |  | 
 | 3367 |   uint64_t FirstSize = S.Context.getTypeSize(FirstType); | 
 | 3368 |   uint64_t FirstAlign = S.Context.getTypeAlign(FirstType); | 
 | 3369 |   for (; Field != FieldEnd; ++Field) { | 
 | 3370 |     QualType FieldType = Field->getType(); | 
 | 3371 |     if (S.Context.getTypeSize(FieldType) != FirstSize || | 
 | 3372 |         S.Context.getTypeAlign(FieldType) != FirstAlign) { | 
 | 3373 |       // Warn if we drop the attribute. | 
 | 3374 |       bool isSize = S.Context.getTypeSize(FieldType) != FirstSize; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3375 |       unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType) | 
| Douglas Gregor | 0c74e8a | 2009-04-29 22:16:16 +0000 | [diff] [blame] | 3376 |                                  : S.Context.getTypeAlign(FieldType); | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3377 |       S.Diag(Field->getLocation(), | 
| Douglas Gregor | 0c74e8a | 2009-04-29 22:16:16 +0000 | [diff] [blame] | 3378 |           diag::warn_transparent_union_attribute_field_size_align) | 
 | 3379 |         << isSize << Field->getDeclName() << FieldBits; | 
 | 3380 |       unsigned FirstBits = isSize? FirstSize : FirstAlign; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3381 |       S.Diag(FirstField->getLocation(), | 
| Douglas Gregor | 0c74e8a | 2009-04-29 22:16:16 +0000 | [diff] [blame] | 3382 |              diag::note_transparent_union_first_field_size_align) | 
 | 3383 |         << isSize << FirstBits; | 
| Eli Friedman | bc88745 | 2008-09-02 05:19:23 +0000 | [diff] [blame] | 3384 |       return; | 
 | 3385 |     } | 
 | 3386 |   } | 
 | 3387 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3388 |   RD->addAttr(::new (S.Context) | 
 | 3389 |               TransparentUnionAttr(Attr.getRange(), S.Context, | 
 | 3390 |                                    Attr.getAttributeSpellingListIndex())); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3391 | } | 
 | 3392 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3393 | static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3394 |   // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3395 |   if (!checkAttributeNumArgs(S, Attr, 1)) | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3396 |     return; | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3397 |  | 
| Peter Collingbourne | 7a73002 | 2010-11-23 20:45:58 +0000 | [diff] [blame] | 3398 |   Expr *ArgExpr = Attr.getArg(0); | 
| Chris Lattner | 797c3c4 | 2009-08-10 19:03:04 +0000 | [diff] [blame] | 3399 |   StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr); | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3400 |  | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3401 |   // Make sure that there is a string literal as the annotation's single | 
 | 3402 |   // argument. | 
 | 3403 |   if (!SE) { | 
| Chris Lattner | 797c3c4 | 2009-08-10 19:03:04 +0000 | [diff] [blame] | 3404 |     S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate"; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3405 |     return; | 
 | 3406 |   } | 
| Julien Lerouge | 77f68bb | 2011-09-09 22:41:49 +0000 | [diff] [blame] | 3407 |  | 
 | 3408 |   // Don't duplicate annotations that are already set. | 
 | 3409 |   for (specific_attr_iterator<AnnotateAttr> | 
 | 3410 |        i = D->specific_attr_begin<AnnotateAttr>(), | 
 | 3411 |        e = D->specific_attr_end<AnnotateAttr>(); i != e; ++i) { | 
 | 3412 |       if ((*i)->getAnnotation() == SE->getString()) | 
 | 3413 |           return; | 
 | 3414 |   } | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3415 |    | 
 | 3416 |   D->addAttr(::new (S.Context) | 
 | 3417 |              AnnotateAttr(Attr.getRange(), S.Context, SE->getString(), | 
 | 3418 |                           Attr.getAttributeSpellingListIndex())); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3419 | } | 
 | 3420 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3421 | static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3422 |   // check the attribute arguments. | 
| Chris Lattner | 545dd34 | 2008-06-28 23:36:30 +0000 | [diff] [blame] | 3423 |   if (Attr.getNumArgs() > 1) { | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 3424 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3425 |     return; | 
 | 3426 |   } | 
| Aaron Ballman | fc685ac | 2012-06-19 22:09:27 +0000 | [diff] [blame] | 3427 |  | 
| Richard Smith | be507b6 | 2013-02-01 08:12:08 +0000 | [diff] [blame] | 3428 |   if (Attr.getNumArgs() == 0) { | 
 | 3429 |     D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context, | 
 | 3430 |                true, 0, Attr.getAttributeSpellingListIndex())); | 
 | 3431 |     return; | 
 | 3432 |   } | 
 | 3433 |  | 
| Richard Smith | f6565a9 | 2013-02-22 08:32:16 +0000 | [diff] [blame] | 3434 |   Expr *E = Attr.getArg(0); | 
 | 3435 |   if (Attr.isPackExpansion() && !E->containsUnexpandedParameterPack()) { | 
 | 3436 |     S.Diag(Attr.getEllipsisLoc(), | 
 | 3437 |            diag::err_pack_expansion_without_parameter_packs); | 
 | 3438 |     return; | 
 | 3439 |   } | 
 | 3440 |  | 
 | 3441 |   if (!Attr.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E)) | 
 | 3442 |     return; | 
 | 3443 |  | 
 | 3444 |   S.AddAlignedAttr(Attr.getRange(), D, E, Attr.getAttributeSpellingListIndex(), | 
 | 3445 |                    Attr.isPackExpansion()); | 
| Richard Smith | be507b6 | 2013-02-01 08:12:08 +0000 | [diff] [blame] | 3446 | } | 
 | 3447 |  | 
 | 3448 | void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, | 
| Richard Smith | f6565a9 | 2013-02-22 08:32:16 +0000 | [diff] [blame] | 3449 |                           unsigned SpellingListIndex, bool IsPackExpansion) { | 
| Richard Smith | be507b6 | 2013-02-01 08:12:08 +0000 | [diff] [blame] | 3450 |   AlignedAttr TmpAttr(AttrRange, Context, true, E, SpellingListIndex); | 
 | 3451 |   SourceLocation AttrLoc = AttrRange.getBegin(); | 
 | 3452 |  | 
| Richard Smith | 4cd81c5 | 2013-01-29 09:02:09 +0000 | [diff] [blame] | 3453 |   // C++11 alignas(...) and C11 _Alignas(...) have additional requirements. | 
| Richard Smith | be507b6 | 2013-02-01 08:12:08 +0000 | [diff] [blame] | 3454 |   if (TmpAttr.isAlignas()) { | 
| Richard Smith | 4cd81c5 | 2013-01-29 09:02:09 +0000 | [diff] [blame] | 3455 |     // C++11 [dcl.align]p1: | 
 | 3456 |     //   An alignment-specifier may be applied to a variable or to a class | 
 | 3457 |     //   data member, but it shall not be applied to a bit-field, a function | 
 | 3458 |     //   parameter, the formal parameter of a catch clause, or a variable | 
 | 3459 |     //   declared with the register storage class specifier. An | 
 | 3460 |     //   alignment-specifier may also be applied to the declaration of a class | 
 | 3461 |     //   or enumeration type. | 
 | 3462 |     // C11 6.7.5/2: | 
 | 3463 |     //   An alignment attribute shall not be specified in a declaration of | 
 | 3464 |     //   a typedef, or a bit-field, or a function, or a parameter, or an | 
 | 3465 |     //   object declared with the register storage-class specifier. | 
 | 3466 |     int DiagKind = -1; | 
 | 3467 |     if (isa<ParmVarDecl>(D)) { | 
 | 3468 |       DiagKind = 0; | 
 | 3469 |     } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { | 
 | 3470 |       if (VD->getStorageClass() == SC_Register) | 
 | 3471 |         DiagKind = 1; | 
 | 3472 |       if (VD->isExceptionVariable()) | 
 | 3473 |         DiagKind = 2; | 
 | 3474 |     } else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { | 
 | 3475 |       if (FD->isBitField()) | 
 | 3476 |         DiagKind = 3; | 
 | 3477 |     } else if (!isa<TagDecl>(D)) { | 
| Richard Smith | be507b6 | 2013-02-01 08:12:08 +0000 | [diff] [blame] | 3478 |       Diag(AttrLoc, diag::err_attribute_wrong_decl_type) | 
 | 3479 |         << (TmpAttr.isC11() ? "'_Alignas'" : "'alignas'") | 
| Richard Smith | 5f838aa | 2013-02-01 08:25:07 +0000 | [diff] [blame] | 3480 |         << (TmpAttr.isC11() ? ExpectedVariableOrField | 
 | 3481 |                             : ExpectedVariableFieldOrTag); | 
| Richard Smith | 4cd81c5 | 2013-01-29 09:02:09 +0000 | [diff] [blame] | 3482 |       return; | 
 | 3483 |     } | 
 | 3484 |     if (DiagKind != -1) { | 
| Richard Smith | be507b6 | 2013-02-01 08:12:08 +0000 | [diff] [blame] | 3485 |       Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type) | 
| Richard Smith | 671b321 | 2013-02-22 04:55:39 +0000 | [diff] [blame] | 3486 |         << TmpAttr.isC11() << DiagKind; | 
| Richard Smith | 4cd81c5 | 2013-01-29 09:02:09 +0000 | [diff] [blame] | 3487 |       return; | 
 | 3488 |     } | 
 | 3489 |   } | 
 | 3490 |  | 
| Chandler Carruth | 4ced79f | 2010-06-25 03:22:07 +0000 | [diff] [blame] | 3491 |   if (E->isTypeDependent() || E->isValueDependent()) { | 
 | 3492 |     // Save dependent expressions in the AST to be instantiated. | 
| Richard Smith | f6565a9 | 2013-02-22 08:32:16 +0000 | [diff] [blame] | 3493 |     AlignedAttr *AA = ::new (Context) AlignedAttr(TmpAttr); | 
 | 3494 |     AA->setPackExpansion(IsPackExpansion); | 
 | 3495 |     D->addAttr(AA); | 
| Chandler Carruth | 4ced79f | 2010-06-25 03:22:07 +0000 | [diff] [blame] | 3496 |     return; | 
 | 3497 |   } | 
| Michael Han | a31f65b | 2013-02-01 01:19:17 +0000 | [diff] [blame] | 3498 |  | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 3499 |   // FIXME: Cache the number on the Attr object? | 
| Chris Lattner | 49e2d34 | 2008-06-28 23:50:44 +0000 | [diff] [blame] | 3500 |   llvm::APSInt Alignment(32); | 
| Douglas Gregor | ab41fe9 | 2012-05-04 22:38:52 +0000 | [diff] [blame] | 3501 |   ExprResult ICE | 
 | 3502 |     = VerifyIntegerConstantExpression(E, &Alignment, | 
 | 3503 |         diag::err_aligned_attribute_argument_not_int, | 
 | 3504 |         /*AllowFold*/ false); | 
| Richard Smith | 282e7e6 | 2012-02-04 09:53:13 +0000 | [diff] [blame] | 3505 |   if (ICE.isInvalid()) | 
| Chris Lattner | 49e2d34 | 2008-06-28 23:50:44 +0000 | [diff] [blame] | 3506 |     return; | 
| Richard Smith | be507b6 | 2013-02-01 08:12:08 +0000 | [diff] [blame] | 3507 |  | 
 | 3508 |   // C++11 [dcl.align]p2: | 
 | 3509 |   //   -- if the constant expression evaluates to zero, the alignment | 
 | 3510 |   //      specifier shall have no effect | 
 | 3511 |   // C11 6.7.5p6: | 
 | 3512 |   //   An alignment specification of zero has no effect. | 
 | 3513 |   if (!(TmpAttr.isAlignas() && !Alignment) && | 
 | 3514 |       !llvm::isPowerOf2_64(Alignment.getZExtValue())) { | 
| Chandler Carruth | 4ced79f | 2010-06-25 03:22:07 +0000 | [diff] [blame] | 3515 |     Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two) | 
 | 3516 |       << E->getSourceRange(); | 
| Daniel Dunbar | 396b2a2 | 2009-02-16 23:37:57 +0000 | [diff] [blame] | 3517 |     return; | 
 | 3518 |   } | 
| Michael Han | a31f65b | 2013-02-01 01:19:17 +0000 | [diff] [blame] | 3519 |  | 
| Richard Smith | be507b6 | 2013-02-01 08:12:08 +0000 | [diff] [blame] | 3520 |   if (TmpAttr.isDeclspec()) { | 
| Aaron Ballman | fc685ac | 2012-06-19 22:09:27 +0000 | [diff] [blame] | 3521 |     // We've already verified it's a power of 2, now let's make sure it's | 
 | 3522 |     // 8192 or less. | 
 | 3523 |     if (Alignment.getZExtValue() > 8192) { | 
| Michael Han | a31f65b | 2013-02-01 01:19:17 +0000 | [diff] [blame] | 3524 |       Diag(AttrLoc, diag::err_attribute_aligned_greater_than_8192) | 
| Aaron Ballman | fc685ac | 2012-06-19 22:09:27 +0000 | [diff] [blame] | 3525 |         << E->getSourceRange(); | 
 | 3526 |       return; | 
 | 3527 |     } | 
 | 3528 |   } | 
| Daniel Dunbar | 396b2a2 | 2009-02-16 23:37:57 +0000 | [diff] [blame] | 3529 |  | 
| Richard Smith | f6565a9 | 2013-02-22 08:32:16 +0000 | [diff] [blame] | 3530 |   AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, true, | 
 | 3531 |                                                 ICE.take(), SpellingListIndex); | 
 | 3532 |   AA->setPackExpansion(IsPackExpansion); | 
 | 3533 |   D->addAttr(AA); | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 3534 | } | 
 | 3535 |  | 
| Michael Han | a31f65b | 2013-02-01 01:19:17 +0000 | [diff] [blame] | 3536 | void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS, | 
| Richard Smith | f6565a9 | 2013-02-22 08:32:16 +0000 | [diff] [blame] | 3537 |                           unsigned SpellingListIndex, bool IsPackExpansion) { | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 3538 |   // FIXME: Cache the number on the Attr object if non-dependent? | 
 | 3539 |   // FIXME: Perform checking of type validity | 
| Richard Smith | f6565a9 | 2013-02-22 08:32:16 +0000 | [diff] [blame] | 3540 |   AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, false, TS, | 
 | 3541 |                                                 SpellingListIndex); | 
 | 3542 |   AA->setPackExpansion(IsPackExpansion); | 
 | 3543 |   D->addAttr(AA); | 
| Chris Lattner | 6b6b537 | 2008-06-26 18:38:35 +0000 | [diff] [blame] | 3544 | } | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3545 |  | 
| Richard Smith | be507b6 | 2013-02-01 08:12:08 +0000 | [diff] [blame] | 3546 | void Sema::CheckAlignasUnderalignment(Decl *D) { | 
 | 3547 |   assert(D->hasAttrs() && "no attributes on decl"); | 
 | 3548 |  | 
 | 3549 |   QualType Ty; | 
 | 3550 |   if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) | 
 | 3551 |     Ty = VD->getType(); | 
 | 3552 |   else | 
 | 3553 |     Ty = Context.getTagDeclType(cast<TagDecl>(D)); | 
| Richard Smith | 4da0903 | 2013-02-22 09:21:42 +0000 | [diff] [blame] | 3554 |   if (Ty->isDependentType() || Ty->isIncompleteType()) | 
| Richard Smith | be507b6 | 2013-02-01 08:12:08 +0000 | [diff] [blame] | 3555 |     return; | 
 | 3556 |  | 
 | 3557 |   // C++11 [dcl.align]p5, C11 6.7.5/4: | 
 | 3558 |   //   The combined effect of all alignment attributes in a declaration shall | 
 | 3559 |   //   not specify an alignment that is less strict than the alignment that | 
 | 3560 |   //   would otherwise be required for the entity being declared. | 
 | 3561 |   AlignedAttr *AlignasAttr = 0; | 
 | 3562 |   unsigned Align = 0; | 
 | 3563 |   for (specific_attr_iterator<AlignedAttr> | 
 | 3564 |          I = D->specific_attr_begin<AlignedAttr>(), | 
 | 3565 |          E = D->specific_attr_end<AlignedAttr>(); I != E; ++I) { | 
 | 3566 |     if (I->isAlignmentDependent()) | 
 | 3567 |       return; | 
 | 3568 |     if (I->isAlignas()) | 
 | 3569 |       AlignasAttr = *I; | 
 | 3570 |     Align = std::max(Align, I->getAlignment(Context)); | 
 | 3571 |   } | 
 | 3572 |  | 
 | 3573 |   if (AlignasAttr && Align) { | 
 | 3574 |     CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align); | 
 | 3575 |     CharUnits NaturalAlign = Context.getTypeAlignInChars(Ty); | 
 | 3576 |     if (NaturalAlign > RequestedAlign) | 
 | 3577 |       Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned) | 
 | 3578 |         << Ty << (unsigned)NaturalAlign.getQuantity(); | 
 | 3579 |   } | 
 | 3580 | } | 
 | 3581 |  | 
| Chandler Carruth | d309c81 | 2011-07-01 23:49:16 +0000 | [diff] [blame] | 3582 | /// handleModeAttr - This attribute modifies the width of a decl with primitive | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3583 | /// type. | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3584 | /// | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3585 | /// Despite what would be logical, the mode attribute is a decl attribute, not a | 
 | 3586 | /// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be | 
 | 3587 | /// HImode, not an intermediate pointer. | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3588 | static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3589 |   // This attribute isn't documented, but glibc uses it.  It changes | 
 | 3590 |   // the width of an int or unsigned int to the specified size. | 
 | 3591 |  | 
 | 3592 |   // Check that there aren't any arguments | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3593 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3594 |     return; | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3595 |  | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3596 |  | 
 | 3597 |   IdentifierInfo *Name = Attr.getParameterName(); | 
 | 3598 |   if (!Name) { | 
| Chris Lattner | 0b2f4da | 2008-06-29 00:28:59 +0000 | [diff] [blame] | 3599 |     S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name); | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3600 |     return; | 
 | 3601 |   } | 
| Daniel Dunbar | 210ae98 | 2009-10-18 02:09:24 +0000 | [diff] [blame] | 3602 |  | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 3603 |   StringRef Str = Attr.getParameterName()->getName(); | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3604 |  | 
 | 3605 |   // Normalize the attribute name, __foo__ becomes foo. | 
| Daniel Dunbar | 210ae98 | 2009-10-18 02:09:24 +0000 | [diff] [blame] | 3606 |   if (Str.startswith("__") && Str.endswith("__")) | 
 | 3607 |     Str = Str.substr(2, Str.size() - 4); | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3608 |  | 
 | 3609 |   unsigned DestWidth = 0; | 
 | 3610 |   bool IntegerMode = true; | 
| Eli Friedman | 7339749 | 2009-03-03 06:41:03 +0000 | [diff] [blame] | 3611 |   bool ComplexMode = false; | 
| Daniel Dunbar | 210ae98 | 2009-10-18 02:09:24 +0000 | [diff] [blame] | 3612 |   switch (Str.size()) { | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3613 |   case 2: | 
| Eli Friedman | 7339749 | 2009-03-03 06:41:03 +0000 | [diff] [blame] | 3614 |     switch (Str[0]) { | 
 | 3615 |     case 'Q': DestWidth = 8; break; | 
 | 3616 |     case 'H': DestWidth = 16; break; | 
 | 3617 |     case 'S': DestWidth = 32; break; | 
 | 3618 |     case 'D': DestWidth = 64; break; | 
 | 3619 |     case 'X': DestWidth = 96; break; | 
 | 3620 |     case 'T': DestWidth = 128; break; | 
 | 3621 |     } | 
 | 3622 |     if (Str[1] == 'F') { | 
 | 3623 |       IntegerMode = false; | 
 | 3624 |     } else if (Str[1] == 'C') { | 
 | 3625 |       IntegerMode = false; | 
 | 3626 |       ComplexMode = true; | 
 | 3627 |     } else if (Str[1] != 'I') { | 
 | 3628 |       DestWidth = 0; | 
 | 3629 |     } | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3630 |     break; | 
 | 3631 |   case 4: | 
 | 3632 |     // FIXME: glibc uses 'word' to define register_t; this is narrower than a | 
 | 3633 |     // pointer on PIC16 and other embedded platforms. | 
| Daniel Dunbar | 210ae98 | 2009-10-18 02:09:24 +0000 | [diff] [blame] | 3634 |     if (Str == "word") | 
| Douglas Gregor | bcfd1f5 | 2011-09-02 00:18:52 +0000 | [diff] [blame] | 3635 |       DestWidth = S.Context.getTargetInfo().getPointerWidth(0); | 
| Daniel Dunbar | 210ae98 | 2009-10-18 02:09:24 +0000 | [diff] [blame] | 3636 |     else if (Str == "byte") | 
| Douglas Gregor | bcfd1f5 | 2011-09-02 00:18:52 +0000 | [diff] [blame] | 3637 |       DestWidth = S.Context.getTargetInfo().getCharWidth(); | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3638 |     break; | 
 | 3639 |   case 7: | 
| Daniel Dunbar | 210ae98 | 2009-10-18 02:09:24 +0000 | [diff] [blame] | 3640 |     if (Str == "pointer") | 
| Douglas Gregor | bcfd1f5 | 2011-09-02 00:18:52 +0000 | [diff] [blame] | 3641 |       DestWidth = S.Context.getTargetInfo().getPointerWidth(0); | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3642 |     break; | 
| Rafael Espindola | 8e721b7 | 2013-01-07 19:58:54 +0000 | [diff] [blame] | 3643 |   case 11: | 
 | 3644 |     if (Str == "unwind_word") | 
| Rafael Espindola | 0b1de54 | 2013-01-07 20:01:57 +0000 | [diff] [blame] | 3645 |       DestWidth = S.Context.getTargetInfo().getUnwindWordWidth(); | 
| Rafael Espindola | 8e721b7 | 2013-01-07 19:58:54 +0000 | [diff] [blame] | 3646 |     break; | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3647 |   } | 
 | 3648 |  | 
 | 3649 |   QualType OldTy; | 
| Richard Smith | 162e1c1 | 2011-04-15 14:24:37 +0000 | [diff] [blame] | 3650 |   if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3651 |     OldTy = TD->getUnderlyingType(); | 
 | 3652 |   else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) | 
 | 3653 |     OldTy = VD->getType(); | 
 | 3654 |   else { | 
| Chris Lattner | fa25bbb | 2008-11-19 05:08:23 +0000 | [diff] [blame] | 3655 |     S.Diag(D->getLocation(), diag::err_attr_wrong_decl) | 
| Argyrios Kyrtzidis | 768d6ca | 2011-09-13 16:05:58 +0000 | [diff] [blame] | 3656 |       << "mode" << Attr.getRange(); | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3657 |     return; | 
 | 3658 |   } | 
| Eli Friedman | 7339749 | 2009-03-03 06:41:03 +0000 | [diff] [blame] | 3659 |  | 
| John McCall | 183700f | 2009-09-21 23:43:11 +0000 | [diff] [blame] | 3660 |   if (!OldTy->getAs<BuiltinType>() && !OldTy->isComplexType()) | 
| Eli Friedman | 7339749 | 2009-03-03 06:41:03 +0000 | [diff] [blame] | 3661 |     S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); | 
 | 3662 |   else if (IntegerMode) { | 
| Douglas Gregor | 2ade35e | 2010-06-16 00:17:44 +0000 | [diff] [blame] | 3663 |     if (!OldTy->isIntegralOrEnumerationType()) | 
| Eli Friedman | 7339749 | 2009-03-03 06:41:03 +0000 | [diff] [blame] | 3664 |       S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); | 
 | 3665 |   } else if (ComplexMode) { | 
 | 3666 |     if (!OldTy->isComplexType()) | 
 | 3667 |       S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); | 
 | 3668 |   } else { | 
 | 3669 |     if (!OldTy->isFloatingType()) | 
 | 3670 |       S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); | 
 | 3671 |   } | 
 | 3672 |  | 
| Mike Stump | 390b4cc | 2009-05-16 07:39:55 +0000 | [diff] [blame] | 3673 |   // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t | 
 | 3674 |   // and friends, at least with glibc. | 
 | 3675 |   // FIXME: Make sure 32/64-bit integers don't get defined to types of the wrong | 
 | 3676 |   // width on unusual platforms. | 
| Eli Friedman | f98aba3 | 2009-02-13 02:31:07 +0000 | [diff] [blame] | 3677 |   // FIXME: Make sure floating-point mappings are accurate | 
 | 3678 |   // FIXME: Support XF and TF types | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3679 |   QualType NewTy; | 
 | 3680 |   switch (DestWidth) { | 
 | 3681 |   case 0: | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 3682 |     S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name; | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3683 |     return; | 
 | 3684 |   default: | 
| Chris Lattner | 3c73c41 | 2008-11-19 08:23:25 +0000 | [diff] [blame] | 3685 |     S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3686 |     return; | 
 | 3687 |   case 8: | 
| Eli Friedman | 7339749 | 2009-03-03 06:41:03 +0000 | [diff] [blame] | 3688 |     if (!IntegerMode) { | 
 | 3689 |       S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; | 
 | 3690 |       return; | 
 | 3691 |     } | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3692 |     if (OldTy->isSignedIntegerType()) | 
| Chris Lattner | 0b2f4da | 2008-06-29 00:28:59 +0000 | [diff] [blame] | 3693 |       NewTy = S.Context.SignedCharTy; | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3694 |     else | 
| Chris Lattner | 0b2f4da | 2008-06-29 00:28:59 +0000 | [diff] [blame] | 3695 |       NewTy = S.Context.UnsignedCharTy; | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3696 |     break; | 
 | 3697 |   case 16: | 
| Eli Friedman | 7339749 | 2009-03-03 06:41:03 +0000 | [diff] [blame] | 3698 |     if (!IntegerMode) { | 
 | 3699 |       S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; | 
 | 3700 |       return; | 
 | 3701 |     } | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3702 |     if (OldTy->isSignedIntegerType()) | 
| Chris Lattner | 0b2f4da | 2008-06-29 00:28:59 +0000 | [diff] [blame] | 3703 |       NewTy = S.Context.ShortTy; | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3704 |     else | 
| Chris Lattner | 0b2f4da | 2008-06-29 00:28:59 +0000 | [diff] [blame] | 3705 |       NewTy = S.Context.UnsignedShortTy; | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3706 |     break; | 
 | 3707 |   case 32: | 
 | 3708 |     if (!IntegerMode) | 
| Chris Lattner | 0b2f4da | 2008-06-29 00:28:59 +0000 | [diff] [blame] | 3709 |       NewTy = S.Context.FloatTy; | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3710 |     else if (OldTy->isSignedIntegerType()) | 
| Chris Lattner | 0b2f4da | 2008-06-29 00:28:59 +0000 | [diff] [blame] | 3711 |       NewTy = S.Context.IntTy; | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3712 |     else | 
| Chris Lattner | 0b2f4da | 2008-06-29 00:28:59 +0000 | [diff] [blame] | 3713 |       NewTy = S.Context.UnsignedIntTy; | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3714 |     break; | 
 | 3715 |   case 64: | 
 | 3716 |     if (!IntegerMode) | 
| Chris Lattner | 0b2f4da | 2008-06-29 00:28:59 +0000 | [diff] [blame] | 3717 |       NewTy = S.Context.DoubleTy; | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3718 |     else if (OldTy->isSignedIntegerType()) | 
| Douglas Gregor | bcfd1f5 | 2011-09-02 00:18:52 +0000 | [diff] [blame] | 3719 |       if (S.Context.getTargetInfo().getLongWidth() == 64) | 
| Chandler Carruth | aec7caa | 2010-01-26 06:39:24 +0000 | [diff] [blame] | 3720 |         NewTy = S.Context.LongTy; | 
 | 3721 |       else | 
 | 3722 |         NewTy = S.Context.LongLongTy; | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3723 |     else | 
| Douglas Gregor | bcfd1f5 | 2011-09-02 00:18:52 +0000 | [diff] [blame] | 3724 |       if (S.Context.getTargetInfo().getLongWidth() == 64) | 
| Chandler Carruth | aec7caa | 2010-01-26 06:39:24 +0000 | [diff] [blame] | 3725 |         NewTy = S.Context.UnsignedLongTy; | 
 | 3726 |       else | 
 | 3727 |         NewTy = S.Context.UnsignedLongLongTy; | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3728 |     break; | 
| Eli Friedman | 7339749 | 2009-03-03 06:41:03 +0000 | [diff] [blame] | 3729 |   case 96: | 
 | 3730 |     NewTy = S.Context.LongDoubleTy; | 
 | 3731 |     break; | 
| Eli Friedman | f98aba3 | 2009-02-13 02:31:07 +0000 | [diff] [blame] | 3732 |   case 128: | 
| Roman Divacky | 1964554 | 2013-07-03 21:08:41 +0000 | [diff] [blame] | 3733 |     if (!IntegerMode && &S.Context.getTargetInfo().getLongDoubleFormat() != | 
 | 3734 |         &llvm::APFloat::PPCDoubleDouble) { | 
| Eli Friedman | f98aba3 | 2009-02-13 02:31:07 +0000 | [diff] [blame] | 3735 |       S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; | 
 | 3736 |       return; | 
 | 3737 |     } | 
| Roman Divacky | f0d14cb | 2013-07-03 20:48:06 +0000 | [diff] [blame] | 3738 |     if (IntegerMode) { | 
 | 3739 |       if (OldTy->isSignedIntegerType()) | 
 | 3740 |         NewTy = S.Context.Int128Ty; | 
 | 3741 |       else | 
 | 3742 |         NewTy = S.Context.UnsignedInt128Ty; | 
 | 3743 |     } else | 
 | 3744 |       NewTy = S.Context.LongDoubleTy; | 
| Eli Friedman | 7339749 | 2009-03-03 06:41:03 +0000 | [diff] [blame] | 3745 |     break; | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3746 |   } | 
 | 3747 |  | 
| Eli Friedman | 7339749 | 2009-03-03 06:41:03 +0000 | [diff] [blame] | 3748 |   if (ComplexMode) { | 
 | 3749 |     NewTy = S.Context.getComplexType(NewTy); | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3750 |   } | 
 | 3751 |  | 
 | 3752 |   // Install the new type. | 
| Enea Zaffanella | c2fa6b6 | 2013-06-20 12:46:19 +0000 | [diff] [blame] | 3753 |   if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) | 
 | 3754 |     TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy); | 
 | 3755 |   else | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3756 |     cast<ValueDecl>(D)->setType(NewTy); | 
| Enea Zaffanella | c2fa6b6 | 2013-06-20 12:46:19 +0000 | [diff] [blame] | 3757 |  | 
 | 3758 |   D->addAttr(::new (S.Context) | 
 | 3759 |              ModeAttr(Attr.getRange(), S.Context, Name, | 
 | 3760 |                       Attr.getAttributeSpellingListIndex())); | 
| Chris Lattner | fbf1347 | 2008-06-27 22:18:37 +0000 | [diff] [blame] | 3761 | } | 
| Chris Lattner | 0744e5f | 2008-06-29 00:23:49 +0000 | [diff] [blame] | 3762 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3763 | static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Anders Carlsson | d87df37 | 2009-02-13 06:46:13 +0000 | [diff] [blame] | 3764 |   // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3765 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Anders Carlsson | d87df37 | 2009-02-13 06:46:13 +0000 | [diff] [blame] | 3766 |     return; | 
| Anders Carlsson | e896d98 | 2009-02-13 08:11:52 +0000 | [diff] [blame] | 3767 |  | 
| Nick Lewycky | 78d1a10 | 2012-07-24 01:40:49 +0000 | [diff] [blame] | 3768 |   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { | 
 | 3769 |     if (!VD->hasGlobalStorage()) | 
 | 3770 |       S.Diag(Attr.getLoc(), | 
 | 3771 |              diag::warn_attribute_requires_functions_or_static_globals) | 
 | 3772 |         << Attr.getName(); | 
 | 3773 |   } else if (!isFunctionOrMethod(D)) { | 
 | 3774 |     S.Diag(Attr.getLoc(), | 
 | 3775 |            diag::warn_attribute_requires_functions_or_static_globals) | 
 | 3776 |       << Attr.getName(); | 
| Anders Carlsson | d87df37 | 2009-02-13 06:46:13 +0000 | [diff] [blame] | 3777 |     return; | 
 | 3778 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3779 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3780 |   D->addAttr(::new (S.Context) | 
 | 3781 |              NoDebugAttr(Attr.getRange(), S.Context, | 
 | 3782 |                          Attr.getAttributeSpellingListIndex())); | 
| Anders Carlsson | d87df37 | 2009-02-13 06:46:13 +0000 | [diff] [blame] | 3783 | } | 
 | 3784 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3785 | static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Anders Carlsson | 5bab788 | 2009-02-19 19:16:48 +0000 | [diff] [blame] | 3786 |   // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3787 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Anders Carlsson | 5bab788 | 2009-02-19 19:16:48 +0000 | [diff] [blame] | 3788 |     return; | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3789 |  | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3790 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3791 |   if (!isa<FunctionDecl>(D)) { | 
| Anders Carlsson | 5bab788 | 2009-02-19 19:16:48 +0000 | [diff] [blame] | 3792 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 3793 |       << Attr.getName() << ExpectedFunction; | 
| Anders Carlsson | 5bab788 | 2009-02-19 19:16:48 +0000 | [diff] [blame] | 3794 |     return; | 
 | 3795 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3796 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3797 |   D->addAttr(::new (S.Context) | 
 | 3798 |              NoInlineAttr(Attr.getRange(), S.Context, | 
 | 3799 |              Attr.getAttributeSpellingListIndex())); | 
| Anders Carlsson | 5bab788 | 2009-02-19 19:16:48 +0000 | [diff] [blame] | 3800 | } | 
 | 3801 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3802 | static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D, | 
 | 3803 |                                            const AttributeList &Attr) { | 
| Chris Lattner | 7255a2d | 2010-06-22 00:03:40 +0000 | [diff] [blame] | 3804 |   // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3805 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Chris Lattner | 7255a2d | 2010-06-22 00:03:40 +0000 | [diff] [blame] | 3806 |     return; | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3807 |  | 
| Chris Lattner | 7255a2d | 2010-06-22 00:03:40 +0000 | [diff] [blame] | 3808 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3809 |   if (!isa<FunctionDecl>(D)) { | 
| Chris Lattner | 7255a2d | 2010-06-22 00:03:40 +0000 | [diff] [blame] | 3810 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 3811 |       << Attr.getName() << ExpectedFunction; | 
| Chris Lattner | 7255a2d | 2010-06-22 00:03:40 +0000 | [diff] [blame] | 3812 |     return; | 
 | 3813 |   } | 
 | 3814 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3815 |   D->addAttr(::new (S.Context) | 
 | 3816 |              NoInstrumentFunctionAttr(Attr.getRange(), S.Context, | 
 | 3817 |                                       Attr.getAttributeSpellingListIndex())); | 
| Chris Lattner | 7255a2d | 2010-06-22 00:03:40 +0000 | [diff] [blame] | 3818 | } | 
 | 3819 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3820 | static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3821 |   if (S.LangOpts.CUDA) { | 
 | 3822 |     // check the attribute arguments. | 
| Ted Kremenek | 831efae | 2011-04-15 05:49:29 +0000 | [diff] [blame] | 3823 |     if (Attr.hasParameterOrArguments()) { | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3824 |       S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; | 
 | 3825 |       return; | 
 | 3826 |     } | 
 | 3827 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3828 |     if (!isa<VarDecl>(D)) { | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3829 |       S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 3830 |         << Attr.getName() << ExpectedVariable; | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3831 |       return; | 
 | 3832 |     } | 
 | 3833 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3834 |     D->addAttr(::new (S.Context) | 
 | 3835 |                CUDAConstantAttr(Attr.getRange(), S.Context, | 
 | 3836 |                                 Attr.getAttributeSpellingListIndex())); | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3837 |   } else { | 
 | 3838 |     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "constant"; | 
 | 3839 |   } | 
 | 3840 | } | 
 | 3841 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3842 | static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3843 |   if (S.LangOpts.CUDA) { | 
 | 3844 |     // check the attribute arguments. | 
 | 3845 |     if (Attr.getNumArgs() != 0) { | 
 | 3846 |       S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; | 
 | 3847 |       return; | 
 | 3848 |     } | 
 | 3849 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3850 |     if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D)) { | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3851 |       S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 3852 |         << Attr.getName() << ExpectedVariableOrFunction; | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3853 |       return; | 
 | 3854 |     } | 
 | 3855 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3856 |     D->addAttr(::new (S.Context) | 
 | 3857 |                CUDADeviceAttr(Attr.getRange(), S.Context, | 
 | 3858 |                               Attr.getAttributeSpellingListIndex())); | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3859 |   } else { | 
 | 3860 |     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "device"; | 
 | 3861 |   } | 
 | 3862 | } | 
 | 3863 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3864 | static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3865 |   if (S.LangOpts.CUDA) { | 
 | 3866 |     // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3867 |     if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3868 |       return; | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3869 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3870 |     if (!isa<FunctionDecl>(D)) { | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3871 |       S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 3872 |         << Attr.getName() << ExpectedFunction; | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3873 |       return; | 
 | 3874 |     } | 
 | 3875 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3876 |     FunctionDecl *FD = cast<FunctionDecl>(D); | 
| Peter Collingbourne | 2c2c8dd | 2010-12-12 23:02:57 +0000 | [diff] [blame] | 3877 |     if (!FD->getResultType()->isVoidType()) { | 
| Abramo Bagnara | 723df24 | 2010-12-14 22:11:44 +0000 | [diff] [blame] | 3878 |       TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens(); | 
| David Blaikie | 39e6ab4 | 2013-02-18 22:06:02 +0000 | [diff] [blame] | 3879 |       if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { | 
| Peter Collingbourne | 2c2c8dd | 2010-12-12 23:02:57 +0000 | [diff] [blame] | 3880 |         S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) | 
 | 3881 |           << FD->getType() | 
| David Blaikie | 39e6ab4 | 2013-02-18 22:06:02 +0000 | [diff] [blame] | 3882 |           << FixItHint::CreateReplacement(FTL.getResultLoc().getSourceRange(), | 
| Peter Collingbourne | 2c2c8dd | 2010-12-12 23:02:57 +0000 | [diff] [blame] | 3883 |                                           "void"); | 
 | 3884 |       } else { | 
 | 3885 |         S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) | 
 | 3886 |           << FD->getType(); | 
 | 3887 |       } | 
 | 3888 |       return; | 
 | 3889 |     } | 
 | 3890 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3891 |     D->addAttr(::new (S.Context) | 
 | 3892 |                CUDAGlobalAttr(Attr.getRange(), S.Context, | 
 | 3893 |                               Attr.getAttributeSpellingListIndex())); | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3894 |   } else { | 
 | 3895 |     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "global"; | 
 | 3896 |   } | 
 | 3897 | } | 
 | 3898 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3899 | static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3900 |   if (S.LangOpts.CUDA) { | 
 | 3901 |     // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3902 |     if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3903 |       return; | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3904 |  | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3905 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3906 |     if (!isa<FunctionDecl>(D)) { | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3907 |       S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 3908 |         << Attr.getName() << ExpectedFunction; | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3909 |       return; | 
 | 3910 |     } | 
 | 3911 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3912 |     D->addAttr(::new (S.Context) | 
 | 3913 |                CUDAHostAttr(Attr.getRange(), S.Context, | 
 | 3914 |                             Attr.getAttributeSpellingListIndex())); | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3915 |   } else { | 
 | 3916 |     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "host"; | 
 | 3917 |   } | 
 | 3918 | } | 
 | 3919 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3920 | static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3921 |   if (S.LangOpts.CUDA) { | 
 | 3922 |     // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3923 |     if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3924 |       return; | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3925 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3926 |     if (!isa<VarDecl>(D)) { | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3927 |       S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 3928 |         << Attr.getName() << ExpectedVariable; | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3929 |       return; | 
 | 3930 |     } | 
 | 3931 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3932 |     D->addAttr(::new (S.Context) | 
 | 3933 |                CUDASharedAttr(Attr.getRange(), S.Context, | 
 | 3934 |                               Attr.getAttributeSpellingListIndex())); | 
| Peter Collingbourne | ced7671 | 2010-12-01 03:15:31 +0000 | [diff] [blame] | 3935 |   } else { | 
 | 3936 |     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "shared"; | 
 | 3937 |   } | 
 | 3938 | } | 
 | 3939 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3940 | static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chris Lattner | 26e2554 | 2009-04-14 16:30:50 +0000 | [diff] [blame] | 3941 |   // check the attribute arguments. | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 3942 |   if (!checkAttributeNumArgs(S, Attr, 0)) | 
| Chris Lattner | 26e2554 | 2009-04-14 16:30:50 +0000 | [diff] [blame] | 3943 |     return; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3944 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3945 |   FunctionDecl *Fn = dyn_cast<FunctionDecl>(D); | 
| Chris Lattner | c519743 | 2009-04-14 17:02:11 +0000 | [diff] [blame] | 3946 |   if (Fn == 0) { | 
| Chris Lattner | 26e2554 | 2009-04-14 16:30:50 +0000 | [diff] [blame] | 3947 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 3948 |       << Attr.getName() << ExpectedFunction; | 
| Chris Lattner | 26e2554 | 2009-04-14 16:30:50 +0000 | [diff] [blame] | 3949 |     return; | 
 | 3950 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3951 |  | 
| Douglas Gregor | 0130f3c | 2009-10-27 21:01:01 +0000 | [diff] [blame] | 3952 |   if (!Fn->isInlineSpecified()) { | 
| Chris Lattner | cf2a721 | 2009-04-20 19:12:28 +0000 | [diff] [blame] | 3953 |     S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline); | 
| Chris Lattner | c519743 | 2009-04-14 17:02:11 +0000 | [diff] [blame] | 3954 |     return; | 
 | 3955 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 3956 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3957 |   D->addAttr(::new (S.Context) | 
 | 3958 |              GNUInlineAttr(Attr.getRange(), S.Context, | 
 | 3959 |                            Attr.getAttributeSpellingListIndex())); | 
| Chris Lattner | 26e2554 | 2009-04-14 16:30:50 +0000 | [diff] [blame] | 3960 | } | 
 | 3961 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 3962 | static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3963 |   if (hasDeclarator(D)) return; | 
| Abramo Bagnara | e215f72 | 2010-04-30 13:10:51 +0000 | [diff] [blame] | 3964 |  | 
| Aaron Ballman | fff3248 | 2012-12-09 17:45:41 +0000 | [diff] [blame] | 3965 |   const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3966 |   // Diagnostic is emitted elsewhere: here we store the (valid) Attr | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 3967 |   // in the Decl node for syntactic reasoning, e.g., pretty-printing. | 
 | 3968 |   CallingConv CC; | 
| Aaron Ballman | fff3248 | 2012-12-09 17:45:41 +0000 | [diff] [blame] | 3969 |   if (S.CheckCallingConvAttr(Attr, CC, FD)) | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 3970 |     return; | 
 | 3971 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3972 |   if (!isa<ObjCMethodDecl>(D)) { | 
 | 3973 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
 | 3974 |       << Attr.getName() << ExpectedFunctionOrMethod; | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 3975 |     return; | 
 | 3976 |   } | 
 | 3977 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 3978 |   switch (Attr.getKind()) { | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 3979 |   case AttributeList::AT_FastCall: | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3980 |     D->addAttr(::new (S.Context) | 
 | 3981 |                FastCallAttr(Attr.getRange(), S.Context, | 
 | 3982 |                             Attr.getAttributeSpellingListIndex())); | 
| Abramo Bagnara | e215f72 | 2010-04-30 13:10:51 +0000 | [diff] [blame] | 3983 |     return; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 3984 |   case AttributeList::AT_StdCall: | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3985 |     D->addAttr(::new (S.Context) | 
 | 3986 |                StdCallAttr(Attr.getRange(), S.Context, | 
 | 3987 |                            Attr.getAttributeSpellingListIndex())); | 
| Abramo Bagnara | e215f72 | 2010-04-30 13:10:51 +0000 | [diff] [blame] | 3988 |     return; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 3989 |   case AttributeList::AT_ThisCall: | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3990 |     D->addAttr(::new (S.Context) | 
 | 3991 |                ThisCallAttr(Attr.getRange(), S.Context, | 
 | 3992 |                             Attr.getAttributeSpellingListIndex())); | 
| Douglas Gregor | 04633eb | 2010-08-30 23:30:49 +0000 | [diff] [blame] | 3993 |     return; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 3994 |   case AttributeList::AT_CDecl: | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 3995 |     D->addAttr(::new (S.Context) | 
 | 3996 |                CDeclAttr(Attr.getRange(), S.Context, | 
 | 3997 |                          Attr.getAttributeSpellingListIndex())); | 
| Abramo Bagnara | e215f72 | 2010-04-30 13:10:51 +0000 | [diff] [blame] | 3998 |     return; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 3999 |   case AttributeList::AT_Pascal: | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4000 |     D->addAttr(::new (S.Context) | 
 | 4001 |                PascalAttr(Attr.getRange(), S.Context, | 
 | 4002 |                           Attr.getAttributeSpellingListIndex())); | 
| Dawn Perchik | 52fc314 | 2010-09-03 01:29:35 +0000 | [diff] [blame] | 4003 |     return; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4004 |   case AttributeList::AT_Pcs: { | 
| Anton Korobeynikov | 414d896 | 2011-04-14 20:06:49 +0000 | [diff] [blame] | 4005 |     PcsAttr::PCSType PCS; | 
| Benjamin Kramer | 9071def | 2012-08-14 13:24:39 +0000 | [diff] [blame] | 4006 |     switch (CC) { | 
 | 4007 |     case CC_AAPCS: | 
| Anton Korobeynikov | 414d896 | 2011-04-14 20:06:49 +0000 | [diff] [blame] | 4008 |       PCS = PcsAttr::AAPCS; | 
| Benjamin Kramer | 9071def | 2012-08-14 13:24:39 +0000 | [diff] [blame] | 4009 |       break; | 
 | 4010 |     case CC_AAPCS_VFP: | 
| Anton Korobeynikov | 414d896 | 2011-04-14 20:06:49 +0000 | [diff] [blame] | 4011 |       PCS = PcsAttr::AAPCS_VFP; | 
| Benjamin Kramer | 9071def | 2012-08-14 13:24:39 +0000 | [diff] [blame] | 4012 |       break; | 
 | 4013 |     default: | 
 | 4014 |       llvm_unreachable("unexpected calling convention in pcs attribute"); | 
| Anton Korobeynikov | 414d896 | 2011-04-14 20:06:49 +0000 | [diff] [blame] | 4015 |     } | 
 | 4016 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4017 |     D->addAttr(::new (S.Context) | 
 | 4018 |                PcsAttr(Attr.getRange(), S.Context, PCS, | 
 | 4019 |                        Attr.getAttributeSpellingListIndex())); | 
| Derek Schuff | 263366f | 2012-10-16 22:30:41 +0000 | [diff] [blame] | 4020 |     return; | 
| Anton Korobeynikov | 414d896 | 2011-04-14 20:06:49 +0000 | [diff] [blame] | 4021 |   } | 
| Derek Schuff | 263366f | 2012-10-16 22:30:41 +0000 | [diff] [blame] | 4022 |   case AttributeList::AT_PnaclCall: | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4023 |     D->addAttr(::new (S.Context) | 
 | 4024 |                PnaclCallAttr(Attr.getRange(), S.Context, | 
 | 4025 |                              Attr.getAttributeSpellingListIndex())); | 
| Derek Schuff | 263366f | 2012-10-16 22:30:41 +0000 | [diff] [blame] | 4026 |     return; | 
| Guy Benyei | 3898008 | 2012-12-25 08:53:55 +0000 | [diff] [blame] | 4027 |   case AttributeList::AT_IntelOclBicc: | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4028 |     D->addAttr(::new (S.Context) | 
 | 4029 |                IntelOclBiccAttr(Attr.getRange(), S.Context, | 
 | 4030 |                                 Attr.getAttributeSpellingListIndex())); | 
| Guy Benyei | 3898008 | 2012-12-25 08:53:55 +0000 | [diff] [blame] | 4031 |     return; | 
| Derek Schuff | 263366f | 2012-10-16 22:30:41 +0000 | [diff] [blame] | 4032 |  | 
| Abramo Bagnara | e215f72 | 2010-04-30 13:10:51 +0000 | [diff] [blame] | 4033 |   default: | 
 | 4034 |     llvm_unreachable("unexpected attribute kind"); | 
| Abramo Bagnara | e215f72 | 2010-04-30 13:10:51 +0000 | [diff] [blame] | 4035 |   } | 
 | 4036 | } | 
 | 4037 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4038 | static void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){ | 
| Chandler Carruth | 56aeb40 | 2011-07-11 23:33:05 +0000 | [diff] [blame] | 4039 |   assert(!Attr.isInvalid()); | 
| Argyrios Kyrtzidis | 768d6ca | 2011-09-13 16:05:58 +0000 | [diff] [blame] | 4040 |   D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getRange(), S.Context)); | 
| Peter Collingbourne | f315fa8 | 2011-02-14 01:42:53 +0000 | [diff] [blame] | 4041 | } | 
 | 4042 |  | 
| Guy Benyei | 1db7040 | 2013-03-24 13:58:12 +0000 | [diff] [blame] | 4043 | static void handleOpenCLImageAccessAttr(Sema &S, Decl *D, const AttributeList &Attr){ | 
 | 4044 |   assert(!Attr.isInvalid()); | 
 | 4045 |  | 
 | 4046 |   Expr *E = Attr.getArg(0); | 
 | 4047 |   llvm::APSInt ArgNum(32); | 
 | 4048 |   if (E->isTypeDependent() || E->isValueDependent() || | 
 | 4049 |       !E->isIntegerConstantExpr(ArgNum, S.Context)) { | 
 | 4050 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) | 
 | 4051 |       << Attr.getName()->getName() << E->getSourceRange(); | 
 | 4052 |     return; | 
 | 4053 |   } | 
 | 4054 |  | 
 | 4055 |   D->addAttr(::new (S.Context) OpenCLImageAccessAttr( | 
 | 4056 |     Attr.getRange(), S.Context, ArgNum.getZExtValue())); | 
 | 4057 | } | 
 | 4058 |  | 
| Aaron Ballman | fff3248 | 2012-12-09 17:45:41 +0000 | [diff] [blame] | 4059 | bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,  | 
 | 4060 |                                 const FunctionDecl *FD) { | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4061 |   if (attr.isInvalid()) | 
 | 4062 |     return true; | 
 | 4063 |  | 
| Benjamin Kramer | fac8e43 | 2012-08-14 13:13:47 +0000 | [diff] [blame] | 4064 |   unsigned ReqArgs = attr.getKind() == AttributeList::AT_Pcs ? 1 : 0; | 
 | 4065 |   if (attr.getNumArgs() != ReqArgs || attr.getParameterName()) { | 
 | 4066 |     Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << ReqArgs; | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4067 |     attr.setInvalid(); | 
 | 4068 |     return true; | 
 | 4069 |   } | 
 | 4070 |  | 
| Anton Korobeynikov | 414d896 | 2011-04-14 20:06:49 +0000 | [diff] [blame] | 4071 |   // TODO: diagnose uses of these conventions on the wrong target. Or, better | 
 | 4072 |   // move to TargetAttributesSema one day. | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4073 |   switch (attr.getKind()) { | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4074 |   case AttributeList::AT_CDecl: CC = CC_C; break; | 
 | 4075 |   case AttributeList::AT_FastCall: CC = CC_X86FastCall; break; | 
 | 4076 |   case AttributeList::AT_StdCall: CC = CC_X86StdCall; break; | 
 | 4077 |   case AttributeList::AT_ThisCall: CC = CC_X86ThisCall; break; | 
 | 4078 |   case AttributeList::AT_Pascal: CC = CC_X86Pascal; break; | 
 | 4079 |   case AttributeList::AT_Pcs: { | 
| Anton Korobeynikov | 414d896 | 2011-04-14 20:06:49 +0000 | [diff] [blame] | 4080 |     Expr *Arg = attr.getArg(0); | 
 | 4081 |     StringLiteral *Str = dyn_cast<StringLiteral>(Arg); | 
| Douglas Gregor | 5cee119 | 2011-07-27 05:40:30 +0000 | [diff] [blame] | 4082 |     if (!Str || !Str->isAscii()) { | 
| Anton Korobeynikov | 414d896 | 2011-04-14 20:06:49 +0000 | [diff] [blame] | 4083 |       Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) | 
 | 4084 |         << "pcs" << 1; | 
 | 4085 |       attr.setInvalid(); | 
 | 4086 |       return true; | 
 | 4087 |     } | 
 | 4088 |  | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 4089 |     StringRef StrRef = Str->getString(); | 
| Anton Korobeynikov | 414d896 | 2011-04-14 20:06:49 +0000 | [diff] [blame] | 4090 |     if (StrRef == "aapcs") { | 
 | 4091 |       CC = CC_AAPCS; | 
 | 4092 |       break; | 
 | 4093 |     } else if (StrRef == "aapcs-vfp") { | 
 | 4094 |       CC = CC_AAPCS_VFP; | 
 | 4095 |       break; | 
 | 4096 |     } | 
| Benjamin Kramer | fac8e43 | 2012-08-14 13:13:47 +0000 | [diff] [blame] | 4097 |  | 
 | 4098 |     attr.setInvalid(); | 
 | 4099 |     Diag(attr.getLoc(), diag::err_invalid_pcs); | 
 | 4100 |     return true; | 
| Anton Korobeynikov | 414d896 | 2011-04-14 20:06:49 +0000 | [diff] [blame] | 4101 |   } | 
| Derek Schuff | 263366f | 2012-10-16 22:30:41 +0000 | [diff] [blame] | 4102 |   case AttributeList::AT_PnaclCall: CC = CC_PnaclCall; break; | 
| Guy Benyei | 3898008 | 2012-12-25 08:53:55 +0000 | [diff] [blame] | 4103 |   case AttributeList::AT_IntelOclBicc: CC = CC_IntelOclBicc; break; | 
| David Blaikie | 7530c03 | 2012-01-17 06:56:22 +0000 | [diff] [blame] | 4104 |   default: llvm_unreachable("unexpected attribute kind"); | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4105 |   } | 
 | 4106 |  | 
| Aaron Ballman | 82bfa19 | 2012-10-02 14:26:08 +0000 | [diff] [blame] | 4107 |   const TargetInfo &TI = Context.getTargetInfo(); | 
 | 4108 |   TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC); | 
 | 4109 |   if (A == TargetInfo::CCCR_Warning) { | 
 | 4110 |     Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName(); | 
| Aaron Ballman | fff3248 | 2012-12-09 17:45:41 +0000 | [diff] [blame] | 4111 |  | 
 | 4112 |     TargetInfo::CallingConvMethodType MT = TargetInfo::CCMT_Unknown; | 
 | 4113 |     if (FD) | 
 | 4114 |       MT = FD->isCXXInstanceMember() ? TargetInfo::CCMT_Member :  | 
 | 4115 |                                     TargetInfo::CCMT_NonMember; | 
 | 4116 |     CC = TI.getDefaultCallingConv(MT); | 
| Aaron Ballman | 82bfa19 | 2012-10-02 14:26:08 +0000 | [diff] [blame] | 4117 |   } | 
 | 4118 |  | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4119 |   return false; | 
 | 4120 | } | 
 | 4121 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4122 | static void handleRegparmAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4123 |   if (hasDeclarator(D)) return; | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4124 |  | 
 | 4125 |   unsigned numParams; | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4126 |   if (S.CheckRegparmAttr(Attr, numParams)) | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4127 |     return; | 
 | 4128 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4129 |   if (!isa<ObjCMethodDecl>(D)) { | 
 | 4130 |     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
 | 4131 |       << Attr.getName() << ExpectedFunctionOrMethod; | 
| Fariborz Jahanian | ee76033 | 2009-03-27 18:38:55 +0000 | [diff] [blame] | 4132 |     return; | 
 | 4133 |   } | 
| Eli Friedman | 55d3aaf | 2009-03-27 21:06:47 +0000 | [diff] [blame] | 4134 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4135 |   D->addAttr(::new (S.Context) | 
 | 4136 |              RegparmAttr(Attr.getRange(), S.Context, numParams, | 
 | 4137 |                          Attr.getAttributeSpellingListIndex())); | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4138 | } | 
 | 4139 |  | 
 | 4140 | /// Checks a regparm attribute, returning true if it is ill-formed and | 
 | 4141 | /// otherwise setting numParams to the appropriate value. | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4142 | bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) { | 
 | 4143 |   if (Attr.isInvalid()) | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4144 |     return true; | 
 | 4145 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4146 |   if (Attr.getNumArgs() != 1) { | 
 | 4147 |     Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; | 
 | 4148 |     Attr.setInvalid(); | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4149 |     return true; | 
| Fariborz Jahanian | ee76033 | 2009-03-27 18:38:55 +0000 | [diff] [blame] | 4150 |   } | 
| Eli Friedman | 55d3aaf | 2009-03-27 21:06:47 +0000 | [diff] [blame] | 4151 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4152 |   Expr *NumParamsExpr = Attr.getArg(0); | 
| Eli Friedman | 55d3aaf | 2009-03-27 21:06:47 +0000 | [diff] [blame] | 4153 |   llvm::APSInt NumParams(32); | 
| Douglas Gregor | ac06a0e | 2010-05-18 23:01:22 +0000 | [diff] [blame] | 4154 |   if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() || | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4155 |       !NumParamsExpr->isIntegerConstantExpr(NumParams, Context)) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4156 |     Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) | 
| Eli Friedman | 55d3aaf | 2009-03-27 21:06:47 +0000 | [diff] [blame] | 4157 |       << "regparm" << NumParamsExpr->getSourceRange(); | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4158 |     Attr.setInvalid(); | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4159 |     return true; | 
| Eli Friedman | 55d3aaf | 2009-03-27 21:06:47 +0000 | [diff] [blame] | 4160 |   } | 
 | 4161 |  | 
| Douglas Gregor | bcfd1f5 | 2011-09-02 00:18:52 +0000 | [diff] [blame] | 4162 |   if (Context.getTargetInfo().getRegParmMax() == 0) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4163 |     Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform) | 
| Eli Friedman | 55d3aaf | 2009-03-27 21:06:47 +0000 | [diff] [blame] | 4164 |       << NumParamsExpr->getSourceRange(); | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4165 |     Attr.setInvalid(); | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4166 |     return true; | 
| Eli Friedman | 55d3aaf | 2009-03-27 21:06:47 +0000 | [diff] [blame] | 4167 |   } | 
 | 4168 |  | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4169 |   numParams = NumParams.getZExtValue(); | 
| Douglas Gregor | bcfd1f5 | 2011-09-02 00:18:52 +0000 | [diff] [blame] | 4170 |   if (numParams > Context.getTargetInfo().getRegParmMax()) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4171 |     Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number) | 
| Douglas Gregor | bcfd1f5 | 2011-09-02 00:18:52 +0000 | [diff] [blame] | 4172 |       << Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange(); | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4173 |     Attr.setInvalid(); | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4174 |     return true; | 
| Eli Friedman | 55d3aaf | 2009-03-27 21:06:47 +0000 | [diff] [blame] | 4175 |   } | 
 | 4176 |  | 
| John McCall | 711c52b | 2011-01-05 12:14:39 +0000 | [diff] [blame] | 4177 |   return false; | 
| Fariborz Jahanian | ee76033 | 2009-03-27 18:38:55 +0000 | [diff] [blame] | 4178 | } | 
 | 4179 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4180 | static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){ | 
| Peter Collingbourne | 7b38198 | 2010-12-12 23:03:07 +0000 | [diff] [blame] | 4181 |   if (S.LangOpts.CUDA) { | 
 | 4182 |     // check the attribute arguments. | 
 | 4183 |     if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) { | 
| John McCall | bdc49d3 | 2011-03-02 12:15:05 +0000 | [diff] [blame] | 4184 |       // FIXME: 0 is not okay. | 
 | 4185 |       S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2; | 
| Peter Collingbourne | 7b38198 | 2010-12-12 23:03:07 +0000 | [diff] [blame] | 4186 |       return; | 
 | 4187 |     } | 
 | 4188 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4189 |     if (!isFunctionOrMethod(D)) { | 
| Peter Collingbourne | 7b38198 | 2010-12-12 23:03:07 +0000 | [diff] [blame] | 4190 |       S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 4191 |         << Attr.getName() << ExpectedFunctionOrMethod; | 
| Peter Collingbourne | 7b38198 | 2010-12-12 23:03:07 +0000 | [diff] [blame] | 4192 |       return; | 
 | 4193 |     } | 
 | 4194 |  | 
 | 4195 |     Expr *MaxThreadsExpr = Attr.getArg(0); | 
 | 4196 |     llvm::APSInt MaxThreads(32); | 
 | 4197 |     if (MaxThreadsExpr->isTypeDependent() || | 
 | 4198 |         MaxThreadsExpr->isValueDependent() || | 
 | 4199 |         !MaxThreadsExpr->isIntegerConstantExpr(MaxThreads, S.Context)) { | 
 | 4200 |       S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) | 
 | 4201 |         << "launch_bounds" << 1 << MaxThreadsExpr->getSourceRange(); | 
 | 4202 |       return; | 
 | 4203 |     } | 
 | 4204 |  | 
 | 4205 |     llvm::APSInt MinBlocks(32); | 
 | 4206 |     if (Attr.getNumArgs() > 1) { | 
 | 4207 |       Expr *MinBlocksExpr = Attr.getArg(1); | 
 | 4208 |       if (MinBlocksExpr->isTypeDependent() || | 
 | 4209 |           MinBlocksExpr->isValueDependent() || | 
 | 4210 |           !MinBlocksExpr->isIntegerConstantExpr(MinBlocks, S.Context)) { | 
 | 4211 |         S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) | 
 | 4212 |           << "launch_bounds" << 2 << MinBlocksExpr->getSourceRange(); | 
 | 4213 |         return; | 
 | 4214 |       } | 
 | 4215 |     } | 
 | 4216 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4217 |     D->addAttr(::new (S.Context) | 
 | 4218 |                CUDALaunchBoundsAttr(Attr.getRange(), S.Context, | 
 | 4219 |                                     MaxThreads.getZExtValue(), | 
 | 4220 |                                     MinBlocks.getZExtValue(), | 
 | 4221 |                                     Attr.getAttributeSpellingListIndex())); | 
| Peter Collingbourne | 7b38198 | 2010-12-12 23:03:07 +0000 | [diff] [blame] | 4222 |   } else { | 
 | 4223 |     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "launch_bounds"; | 
 | 4224 |   } | 
 | 4225 | } | 
 | 4226 |  | 
| Dmitri Gribenko | 0d5a069 | 2012-08-17 00:08:38 +0000 | [diff] [blame] | 4227 | static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, | 
 | 4228 |                                           const AttributeList &Attr) { | 
 | 4229 |   StringRef AttrName = Attr.getName()->getName(); | 
 | 4230 |   if (!Attr.getParameterName()) { | 
 | 4231 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_identifier) | 
 | 4232 |       << Attr.getName() << /* arg num = */ 1; | 
 | 4233 |     return; | 
 | 4234 |   } | 
 | 4235 |  | 
 | 4236 |   if (Attr.getNumArgs() != 2) { | 
 | 4237 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) | 
 | 4238 |       << /* required args = */ 3; | 
 | 4239 |     return; | 
 | 4240 |   } | 
 | 4241 |  | 
 | 4242 |   IdentifierInfo *ArgumentKind = Attr.getParameterName(); | 
 | 4243 |  | 
 | 4244 |   if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { | 
 | 4245 |     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) | 
 | 4246 |       << Attr.getName() << ExpectedFunctionOrMethod; | 
 | 4247 |     return; | 
 | 4248 |   } | 
 | 4249 |  | 
 | 4250 |   uint64_t ArgumentIdx; | 
 | 4251 |   if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName, | 
 | 4252 |                                           Attr.getLoc(), 2, | 
 | 4253 |                                           Attr.getArg(0), ArgumentIdx)) | 
 | 4254 |     return; | 
 | 4255 |  | 
 | 4256 |   uint64_t TypeTagIdx; | 
 | 4257 |   if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName, | 
 | 4258 |                                           Attr.getLoc(), 3, | 
 | 4259 |                                           Attr.getArg(1), TypeTagIdx)) | 
 | 4260 |     return; | 
 | 4261 |  | 
 | 4262 |   bool IsPointer = (AttrName == "pointer_with_type_tag"); | 
 | 4263 |   if (IsPointer) { | 
 | 4264 |     // Ensure that buffer has a pointer type. | 
 | 4265 |     QualType BufferTy = getFunctionOrMethodArgType(D, ArgumentIdx); | 
 | 4266 |     if (!BufferTy->isPointerType()) { | 
 | 4267 |       S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only) | 
| Aaron Ballman | aa9df09 | 2013-05-22 23:25:32 +0000 | [diff] [blame] | 4268 |         << Attr.getName(); | 
| Dmitri Gribenko | 0d5a069 | 2012-08-17 00:08:38 +0000 | [diff] [blame] | 4269 |     } | 
 | 4270 |   } | 
 | 4271 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4272 |   D->addAttr(::new (S.Context) | 
 | 4273 |              ArgumentWithTypeTagAttr(Attr.getRange(), S.Context, ArgumentKind, | 
 | 4274 |                                      ArgumentIdx, TypeTagIdx, IsPointer, | 
 | 4275 |                                      Attr.getAttributeSpellingListIndex())); | 
| Dmitri Gribenko | 0d5a069 | 2012-08-17 00:08:38 +0000 | [diff] [blame] | 4276 | } | 
 | 4277 |  | 
 | 4278 | static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, | 
 | 4279 |                                          const AttributeList &Attr) { | 
 | 4280 |   IdentifierInfo *PointerKind = Attr.getParameterName(); | 
 | 4281 |   if (!PointerKind) { | 
 | 4282 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_identifier) | 
 | 4283 |       << "type_tag_for_datatype" << 1; | 
 | 4284 |     return; | 
 | 4285 |   } | 
 | 4286 |  | 
 | 4287 |   QualType MatchingCType = S.GetTypeFromParser(Attr.getMatchingCType(), NULL); | 
 | 4288 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4289 |   D->addAttr(::new (S.Context) | 
 | 4290 |              TypeTagForDatatypeAttr(Attr.getRange(), S.Context, PointerKind, | 
 | 4291 |                                     MatchingCType, | 
 | 4292 |                                     Attr.getLayoutCompatible(), | 
 | 4293 |                                     Attr.getMustBeNull(), | 
 | 4294 |                                     Attr.getAttributeSpellingListIndex())); | 
| Dmitri Gribenko | 0d5a069 | 2012-08-17 00:08:38 +0000 | [diff] [blame] | 4295 | } | 
 | 4296 |  | 
| Chris Lattner | 0744e5f | 2008-06-29 00:23:49 +0000 | [diff] [blame] | 4297 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | b71368d | 2009-05-09 02:44:38 +0000 | [diff] [blame] | 4298 | // Checker-specific attribute handlers. | 
 | 4299 | //===----------------------------------------------------------------------===// | 
 | 4300 |  | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4301 | static bool isValidSubjectOfNSAttribute(Sema &S, QualType type) { | 
| Douglas Gregor | 6c73a29 | 2011-10-09 22:26:49 +0000 | [diff] [blame] | 4302 |   return type->isDependentType() ||  | 
 | 4303 |          type->isObjCObjectPointerType() ||  | 
 | 4304 |          S.Context.isObjCNSObjectType(type); | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4305 | } | 
 | 4306 | static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) { | 
| Douglas Gregor | 6c73a29 | 2011-10-09 22:26:49 +0000 | [diff] [blame] | 4307 |   return type->isDependentType() ||  | 
 | 4308 |          type->isPointerType() ||  | 
 | 4309 |          isValidSubjectOfNSAttribute(S, type); | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4310 | } | 
 | 4311 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4312 | static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4313 |   ParmVarDecl *param = dyn_cast<ParmVarDecl>(D); | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4314 |   if (!param) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4315 |     S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) | 
| Argyrios Kyrtzidis | 768d6ca | 2011-09-13 16:05:58 +0000 | [diff] [blame] | 4316 |       << Attr.getRange() << Attr.getName() << ExpectedParameter; | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4317 |     return; | 
 | 4318 |   } | 
 | 4319 |  | 
 | 4320 |   bool typeOK, cf; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4321 |   if (Attr.getKind() == AttributeList::AT_NSConsumed) { | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4322 |     typeOK = isValidSubjectOfNSAttribute(S, param->getType()); | 
 | 4323 |     cf = false; | 
 | 4324 |   } else { | 
 | 4325 |     typeOK = isValidSubjectOfCFAttribute(S, param->getType()); | 
 | 4326 |     cf = true; | 
 | 4327 |   } | 
 | 4328 |  | 
 | 4329 |   if (!typeOK) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4330 |     S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type) | 
| Argyrios Kyrtzidis | 768d6ca | 2011-09-13 16:05:58 +0000 | [diff] [blame] | 4331 |       << Attr.getRange() << Attr.getName() << cf; | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4332 |     return; | 
 | 4333 |   } | 
 | 4334 |  | 
 | 4335 |   if (cf) | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4336 |     param->addAttr(::new (S.Context) | 
 | 4337 |                    CFConsumedAttr(Attr.getRange(), S.Context, | 
 | 4338 |                                   Attr.getAttributeSpellingListIndex())); | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4339 |   else | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4340 |     param->addAttr(::new (S.Context) | 
 | 4341 |                    NSConsumedAttr(Attr.getRange(), S.Context, | 
 | 4342 |                                   Attr.getAttributeSpellingListIndex())); | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4343 | } | 
 | 4344 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4345 | static void handleNSConsumesSelfAttr(Sema &S, Decl *D, | 
 | 4346 |                                      const AttributeList &Attr) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4347 |   if (!isa<ObjCMethodDecl>(D)) { | 
 | 4348 |     S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) | 
| Argyrios Kyrtzidis | 768d6ca | 2011-09-13 16:05:58 +0000 | [diff] [blame] | 4349 |       << Attr.getRange() << Attr.getName() << ExpectedMethod; | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4350 |     return; | 
 | 4351 |   } | 
 | 4352 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4353 |   D->addAttr(::new (S.Context) | 
 | 4354 |              NSConsumesSelfAttr(Attr.getRange(), S.Context, | 
 | 4355 |                                 Attr.getAttributeSpellingListIndex())); | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4356 | } | 
 | 4357 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4358 | static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, | 
 | 4359 |                                         const AttributeList &Attr) { | 
| Ted Kremenek | b71368d | 2009-05-09 02:44:38 +0000 | [diff] [blame] | 4360 |  | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4361 |   QualType returnType; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 4362 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4363 |   if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4364 |     returnType = MD->getResultType(); | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 4365 |   else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) && | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4366 |            (Attr.getKind() == AttributeList::AT_NSReturnsRetained)) | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4367 |     return; // ignore: was handled as a type attribute | 
| Fariborz Jahanian | a23bd4c | 2012-08-28 22:26:21 +0000 | [diff] [blame] | 4368 |   else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) | 
 | 4369 |     returnType = PD->getType(); | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4370 |   else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4371 |     returnType = FD->getResultType(); | 
| Ted Kremenek | 5dc53c9 | 2009-05-13 21:07:32 +0000 | [diff] [blame] | 4372 |   else { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4373 |     S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) | 
| Argyrios Kyrtzidis | 768d6ca | 2011-09-13 16:05:58 +0000 | [diff] [blame] | 4374 |         << Attr.getRange() << Attr.getName() | 
| John McCall | 883cc2c | 2011-03-02 12:29:23 +0000 | [diff] [blame] | 4375 |         << ExpectedFunctionOrMethod; | 
| Ted Kremenek | b71368d | 2009-05-09 02:44:38 +0000 | [diff] [blame] | 4376 |     return; | 
 | 4377 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 4378 |  | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4379 |   bool typeOK; | 
 | 4380 |   bool cf; | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4381 |   switch (Attr.getKind()) { | 
| David Blaikie | 7530c03 | 2012-01-17 06:56:22 +0000 | [diff] [blame] | 4382 |   default: llvm_unreachable("invalid ownership attribute"); | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4383 |   case AttributeList::AT_NSReturnsAutoreleased: | 
 | 4384 |   case AttributeList::AT_NSReturnsRetained: | 
 | 4385 |   case AttributeList::AT_NSReturnsNotRetained: | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4386 |     typeOK = isValidSubjectOfNSAttribute(S, returnType); | 
 | 4387 |     cf = false; | 
 | 4388 |     break; | 
 | 4389 |  | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4390 |   case AttributeList::AT_CFReturnsRetained: | 
 | 4391 |   case AttributeList::AT_CFReturnsNotRetained: | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4392 |     typeOK = isValidSubjectOfCFAttribute(S, returnType); | 
 | 4393 |     cf = true; | 
 | 4394 |     break; | 
 | 4395 |   } | 
 | 4396 |  | 
 | 4397 |   if (!typeOK) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4398 |     S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type) | 
| Argyrios Kyrtzidis | 768d6ca | 2011-09-13 16:05:58 +0000 | [diff] [blame] | 4399 |       << Attr.getRange() << Attr.getName() << isa<ObjCMethodDecl>(D) << cf; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 4400 |     return; | 
| Ted Kremenek | 5dc53c9 | 2009-05-13 21:07:32 +0000 | [diff] [blame] | 4401 |   } | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 4402 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4403 |   switch (Attr.getKind()) { | 
| Ted Kremenek | b71368d | 2009-05-09 02:44:38 +0000 | [diff] [blame] | 4404 |     default: | 
| David Blaikie | b219cfc | 2011-09-23 05:06:16 +0000 | [diff] [blame] | 4405 |       llvm_unreachable("invalid ownership attribute"); | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4406 |     case AttributeList::AT_NSReturnsAutoreleased: | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4407 |       D->addAttr(::new (S.Context) | 
 | 4408 |                  NSReturnsAutoreleasedAttr(Attr.getRange(), S.Context, | 
 | 4409 |                                            Attr.getAttributeSpellingListIndex())); | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4410 |       return; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4411 |     case AttributeList::AT_CFReturnsNotRetained: | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4412 |       D->addAttr(::new (S.Context) | 
 | 4413 |                  CFReturnsNotRetainedAttr(Attr.getRange(), S.Context, | 
 | 4414 |                                           Attr.getAttributeSpellingListIndex())); | 
| Ted Kremenek | 31c780d | 2010-02-18 00:05:45 +0000 | [diff] [blame] | 4415 |       return; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4416 |     case AttributeList::AT_NSReturnsNotRetained: | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4417 |       D->addAttr(::new (S.Context) | 
 | 4418 |                  NSReturnsNotRetainedAttr(Attr.getRange(), S.Context, | 
 | 4419 |                                           Attr.getAttributeSpellingListIndex())); | 
| Ted Kremenek | 31c780d | 2010-02-18 00:05:45 +0000 | [diff] [blame] | 4420 |       return; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4421 |     case AttributeList::AT_CFReturnsRetained: | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4422 |       D->addAttr(::new (S.Context) | 
 | 4423 |                  CFReturnsRetainedAttr(Attr.getRange(), S.Context, | 
 | 4424 |                                        Attr.getAttributeSpellingListIndex())); | 
| Ted Kremenek | b71368d | 2009-05-09 02:44:38 +0000 | [diff] [blame] | 4425 |       return; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4426 |     case AttributeList::AT_NSReturnsRetained: | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4427 |       D->addAttr(::new (S.Context) | 
 | 4428 |                  NSReturnsRetainedAttr(Attr.getRange(), S.Context, | 
 | 4429 |                                        Attr.getAttributeSpellingListIndex())); | 
| Ted Kremenek | b71368d | 2009-05-09 02:44:38 +0000 | [diff] [blame] | 4430 |       return; | 
 | 4431 |   }; | 
 | 4432 | } | 
 | 4433 |  | 
| John McCall | dc7c5ad | 2011-07-22 08:53:00 +0000 | [diff] [blame] | 4434 | static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, | 
 | 4435 |                                               const AttributeList &attr) { | 
 | 4436 |   SourceLocation loc = attr.getLoc(); | 
 | 4437 |  | 
 | 4438 |   ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D); | 
 | 4439 |  | 
| Fariborz Jahanian | 94d55d7 | 2012-04-21 17:51:44 +0000 | [diff] [blame] | 4440 |   if (!method) { | 
| Fariborz Jahanian | 0e78afb | 2012-04-20 22:00:46 +0000 | [diff] [blame] | 4441 |     S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) | 
| Douglas Gregor | f6b8b58 | 2012-03-14 16:55:17 +0000 | [diff] [blame] | 4442 |       << SourceRange(loc, loc) << attr.getName() << ExpectedMethod; | 
| John McCall | dc7c5ad | 2011-07-22 08:53:00 +0000 | [diff] [blame] | 4443 |     return; | 
 | 4444 |   } | 
 | 4445 |  | 
 | 4446 |   // Check that the method returns a normal pointer. | 
 | 4447 |   QualType resultType = method->getResultType(); | 
| Fariborz Jahanian | f2e5945 | 2011-09-30 20:50:23 +0000 | [diff] [blame] | 4448 |      | 
 | 4449 |   if (!resultType->isReferenceType() && | 
 | 4450 |       (!resultType->isPointerType() || resultType->isObjCRetainableType())) { | 
| John McCall | dc7c5ad | 2011-07-22 08:53:00 +0000 | [diff] [blame] | 4451 |     S.Diag(method->getLocStart(), diag::warn_ns_attribute_wrong_return_type) | 
 | 4452 |       << SourceRange(loc) | 
 | 4453 |       << attr.getName() << /*method*/ 1 << /*non-retainable pointer*/ 2; | 
 | 4454 |  | 
 | 4455 |     // Drop the attribute. | 
 | 4456 |     return; | 
 | 4457 |   } | 
 | 4458 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4459 |   method->addAttr(::new (S.Context) | 
 | 4460 |                   ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context, | 
 | 4461 |                                               attr.getAttributeSpellingListIndex())); | 
| John McCall | dc7c5ad | 2011-07-22 08:53:00 +0000 | [diff] [blame] | 4462 | } | 
 | 4463 |  | 
| Fariborz Jahanian | 8410113 | 2012-09-07 23:46:23 +0000 | [diff] [blame] | 4464 | static void handleObjCRequiresSuperAttr(Sema &S, Decl *D, | 
 | 4465 |                                         const AttributeList &attr) { | 
 | 4466 |   SourceLocation loc = attr.getLoc(); | 
 | 4467 |   ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D); | 
 | 4468 |    | 
 | 4469 |   if (!method) { | 
 | 4470 |    S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) | 
 | 4471 |    << SourceRange(loc, loc) << attr.getName() << ExpectedMethod; | 
 | 4472 |     return; | 
 | 4473 |   } | 
 | 4474 |   DeclContext *DC = method->getDeclContext(); | 
 | 4475 |   if (const ObjCProtocolDecl *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) { | 
 | 4476 |     S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol) | 
 | 4477 |     << attr.getName() << 0; | 
 | 4478 |     S.Diag(PDecl->getLocation(), diag::note_protocol_decl); | 
 | 4479 |     return; | 
 | 4480 |   } | 
 | 4481 |   if (method->getMethodFamily() == OMF_dealloc) { | 
 | 4482 |     S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol) | 
 | 4483 |     << attr.getName() << 1; | 
 | 4484 |     return; | 
 | 4485 |   } | 
 | 4486 |    | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4487 |   method->addAttr(::new (S.Context) | 
 | 4488 |                   ObjCRequiresSuperAttr(attr.getRange(), S.Context, | 
 | 4489 |                                         attr.getAttributeSpellingListIndex())); | 
| Fariborz Jahanian | 8410113 | 2012-09-07 23:46:23 +0000 | [diff] [blame] | 4490 | } | 
 | 4491 |  | 
| John McCall | 8dfac0b | 2011-09-30 05:12:12 +0000 | [diff] [blame] | 4492 | /// Handle cf_audited_transfer and cf_unknown_transfer. | 
 | 4493 | static void handleCFTransferAttr(Sema &S, Decl *D, const AttributeList &A) { | 
 | 4494 |   if (!isa<FunctionDecl>(D)) { | 
 | 4495 |     S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) | 
| Douglas Gregor | f6b8b58 | 2012-03-14 16:55:17 +0000 | [diff] [blame] | 4496 |       << A.getRange() << A.getName() << ExpectedFunction; | 
| John McCall | 8dfac0b | 2011-09-30 05:12:12 +0000 | [diff] [blame] | 4497 |     return; | 
 | 4498 |   } | 
 | 4499 |  | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4500 |   bool IsAudited = (A.getKind() == AttributeList::AT_CFAuditedTransfer); | 
| John McCall | 8dfac0b | 2011-09-30 05:12:12 +0000 | [diff] [blame] | 4501 |  | 
 | 4502 |   // Check whether there's a conflicting attribute already present. | 
 | 4503 |   Attr *Existing; | 
 | 4504 |   if (IsAudited) { | 
 | 4505 |     Existing = D->getAttr<CFUnknownTransferAttr>(); | 
 | 4506 |   } else { | 
 | 4507 |     Existing = D->getAttr<CFAuditedTransferAttr>(); | 
 | 4508 |   } | 
 | 4509 |   if (Existing) { | 
 | 4510 |     S.Diag(D->getLocStart(), diag::err_attributes_are_not_compatible) | 
 | 4511 |       << A.getName() | 
 | 4512 |       << (IsAudited ? "cf_unknown_transfer" : "cf_audited_transfer") | 
 | 4513 |       << A.getRange() << Existing->getRange(); | 
 | 4514 |     return; | 
 | 4515 |   } | 
 | 4516 |  | 
 | 4517 |   // All clear;  add the attribute. | 
 | 4518 |   if (IsAudited) { | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4519 |     D->addAttr(::new (S.Context) | 
 | 4520 |                CFAuditedTransferAttr(A.getRange(), S.Context, | 
 | 4521 |                                      A.getAttributeSpellingListIndex())); | 
| John McCall | 8dfac0b | 2011-09-30 05:12:12 +0000 | [diff] [blame] | 4522 |   } else { | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4523 |     D->addAttr(::new (S.Context) | 
 | 4524 |                CFUnknownTransferAttr(A.getRange(), S.Context, | 
 | 4525 |                                      A.getAttributeSpellingListIndex())); | 
| John McCall | 8dfac0b | 2011-09-30 05:12:12 +0000 | [diff] [blame] | 4526 |   } | 
 | 4527 | } | 
 | 4528 |  | 
| John McCall | fe98da0 | 2011-09-29 07:17:38 +0000 | [diff] [blame] | 4529 | static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D, | 
 | 4530 |                                 const AttributeList &Attr) { | 
 | 4531 |   RecordDecl *RD = dyn_cast<RecordDecl>(D); | 
 | 4532 |   if (!RD || RD->isUnion()) { | 
 | 4533 |     S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) | 
| Douglas Gregor | f6b8b58 | 2012-03-14 16:55:17 +0000 | [diff] [blame] | 4534 |       << Attr.getRange() << Attr.getName() << ExpectedStruct; | 
| John McCall | fe98da0 | 2011-09-29 07:17:38 +0000 | [diff] [blame] | 4535 |   } | 
 | 4536 |  | 
 | 4537 |   IdentifierInfo *ParmName = Attr.getParameterName(); | 
 | 4538 |  | 
 | 4539 |   // In Objective-C, verify that the type names an Objective-C type. | 
 | 4540 |   // We don't want to check this outside of ObjC because people sometimes | 
 | 4541 |   // do crazy C declarations of Objective-C types. | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 4542 |   if (ParmName && S.getLangOpts().ObjC1) { | 
| John McCall | fe98da0 | 2011-09-29 07:17:38 +0000 | [diff] [blame] | 4543 |     // Check for an existing type with this name. | 
 | 4544 |     LookupResult R(S, DeclarationName(ParmName), Attr.getParameterLoc(), | 
 | 4545 |                    Sema::LookupOrdinaryName); | 
 | 4546 |     if (S.LookupName(R, Sc)) { | 
 | 4547 |       NamedDecl *Target = R.getFoundDecl(); | 
 | 4548 |       if (Target && !isa<ObjCInterfaceDecl>(Target)) { | 
 | 4549 |         S.Diag(D->getLocStart(), diag::err_ns_bridged_not_interface); | 
 | 4550 |         S.Diag(Target->getLocStart(), diag::note_declared_at); | 
 | 4551 |       } | 
 | 4552 |     } | 
 | 4553 |   } | 
 | 4554 |  | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4555 |   D->addAttr(::new (S.Context) | 
 | 4556 |              NSBridgedAttr(Attr.getRange(), S.Context, ParmName, | 
 | 4557 |                            Attr.getAttributeSpellingListIndex())); | 
| John McCall | fe98da0 | 2011-09-29 07:17:38 +0000 | [diff] [blame] | 4558 | } | 
 | 4559 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4560 | static void handleObjCOwnershipAttr(Sema &S, Decl *D, | 
 | 4561 |                                     const AttributeList &Attr) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4562 |   if (hasDeclarator(D)) return; | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4563 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4564 |   S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) | 
| Douglas Gregor | f6b8b58 | 2012-03-14 16:55:17 +0000 | [diff] [blame] | 4565 |     << Attr.getRange() << Attr.getName() << ExpectedVariable; | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4566 | } | 
 | 4567 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4568 | static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, | 
 | 4569 |                                           const AttributeList &Attr) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4570 |   if (!isa<VarDecl>(D) && !isa<FieldDecl>(D)) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4571 |     S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) | 
| Douglas Gregor | f6b8b58 | 2012-03-14 16:55:17 +0000 | [diff] [blame] | 4572 |       << Attr.getRange() << Attr.getName() << ExpectedVariable; | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4573 |     return; | 
 | 4574 |   } | 
 | 4575 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4576 |   ValueDecl *vd = cast<ValueDecl>(D); | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4577 |   QualType type = vd->getType(); | 
 | 4578 |  | 
 | 4579 |   if (!type->isDependentType() && | 
 | 4580 |       !type->isObjCLifetimeType()) { | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4581 |     S.Diag(Attr.getLoc(), diag::err_objc_precise_lifetime_bad_type) | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4582 |       << type; | 
 | 4583 |     return; | 
 | 4584 |   } | 
 | 4585 |  | 
 | 4586 |   Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime(); | 
 | 4587 |  | 
 | 4588 |   // If we have no lifetime yet, check the lifetime we're presumably | 
 | 4589 |   // going to infer. | 
 | 4590 |   if (lifetime == Qualifiers::OCL_None && !type->isDependentType()) | 
 | 4591 |     lifetime = type->getObjCARCImplicitLifetime(); | 
 | 4592 |  | 
 | 4593 |   switch (lifetime) { | 
 | 4594 |   case Qualifiers::OCL_None: | 
 | 4595 |     assert(type->isDependentType() && | 
 | 4596 |            "didn't infer lifetime for non-dependent type?"); | 
 | 4597 |     break; | 
 | 4598 |  | 
 | 4599 |   case Qualifiers::OCL_Weak:   // meaningful | 
 | 4600 |   case Qualifiers::OCL_Strong: // meaningful | 
 | 4601 |     break; | 
 | 4602 |  | 
 | 4603 |   case Qualifiers::OCL_ExplicitNone: | 
 | 4604 |   case Qualifiers::OCL_Autoreleasing: | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4605 |     S.Diag(Attr.getLoc(), diag::warn_objc_precise_lifetime_meaningless) | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4606 |       << (lifetime == Qualifiers::OCL_Autoreleasing); | 
 | 4607 |     break; | 
 | 4608 |   } | 
 | 4609 |  | 
| Chandler Carruth | 87c4460 | 2011-07-01 23:49:12 +0000 | [diff] [blame] | 4610 |   D->addAttr(::new (S.Context) | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4611 |              ObjCPreciseLifetimeAttr(Attr.getRange(), S.Context, | 
 | 4612 |                                      Attr.getAttributeSpellingListIndex())); | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4613 | } | 
 | 4614 |  | 
| Francois Pichet | 1154214 | 2010-12-19 06:50:37 +0000 | [diff] [blame] | 4615 | //===----------------------------------------------------------------------===// | 
 | 4616 | // Microsoft specific attribute handlers. | 
 | 4617 | //===----------------------------------------------------------------------===// | 
 | 4618 |  | 
| Reid Kleckner | 8fbda8e | 2013-05-17 14:04:52 +0000 | [diff] [blame] | 4619 | // Check if MS extensions or some other language extensions are enabled.  If | 
 | 4620 | // not, issue a diagnostic that the given attribute is unused. | 
 | 4621 | static bool checkMicrosoftExt(Sema &S, const AttributeList &Attr, | 
 | 4622 |                               bool OtherExtension = false) { | 
 | 4623 |   if (S.LangOpts.MicrosoftExt || OtherExtension) | 
 | 4624 |     return true; | 
 | 4625 |   S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); | 
 | 4626 |   return false; | 
 | 4627 | } | 
 | 4628 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4629 | static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Reid Kleckner | 8fbda8e | 2013-05-17 14:04:52 +0000 | [diff] [blame] | 4630 |   if (!checkMicrosoftExt(S, Attr, S.LangOpts.Borland)) | 
 | 4631 |     return; | 
| Chandler Carruth | 1731e20 | 2011-07-11 23:30:35 +0000 | [diff] [blame] | 4632 |  | 
| Reid Kleckner | 8fbda8e | 2013-05-17 14:04:52 +0000 | [diff] [blame] | 4633 |   // check the attribute arguments. | 
 | 4634 |   if (!checkAttributeNumArgs(S, Attr, 1)) | 
 | 4635 |     return; | 
| Francois Pichet | d3d3be9 | 2010-12-20 01:41:49 +0000 | [diff] [blame] | 4636 |  | 
| Reid Kleckner | 8fbda8e | 2013-05-17 14:04:52 +0000 | [diff] [blame] | 4637 |   Expr *Arg = Attr.getArg(0); | 
 | 4638 |   StringLiteral *Str = dyn_cast<StringLiteral>(Arg); | 
 | 4639 |   if (!Str || !Str->isAscii()) { | 
 | 4640 |     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) | 
 | 4641 |       << "uuid" << 1; | 
 | 4642 |     return; | 
 | 4643 |   } | 
| Francois Pichet | d3d3be9 | 2010-12-20 01:41:49 +0000 | [diff] [blame] | 4644 |  | 
| Reid Kleckner | 8fbda8e | 2013-05-17 14:04:52 +0000 | [diff] [blame] | 4645 |   StringRef StrRef = Str->getString(); | 
| Douglas Gregor | f6b8b58 | 2012-03-14 16:55:17 +0000 | [diff] [blame] | 4646 |  | 
| Reid Kleckner | 8fbda8e | 2013-05-17 14:04:52 +0000 | [diff] [blame] | 4647 |   bool IsCurly = StrRef.size() > 1 && StrRef.front() == '{' && | 
 | 4648 |                  StrRef.back() == '}'; | 
| Francois Pichet | d3d3be9 | 2010-12-20 01:41:49 +0000 | [diff] [blame] | 4649 |  | 
| Reid Kleckner | 8fbda8e | 2013-05-17 14:04:52 +0000 | [diff] [blame] | 4650 |   // Validate GUID length. | 
 | 4651 |   if (IsCurly && StrRef.size() != 38) { | 
 | 4652 |     S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); | 
 | 4653 |     return; | 
 | 4654 |   } | 
 | 4655 |   if (!IsCurly && StrRef.size() != 36) { | 
 | 4656 |     S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); | 
 | 4657 |     return; | 
 | 4658 |   } | 
| Anders Carlsson | f89e042 | 2011-01-23 21:07:30 +0000 | [diff] [blame] | 4659 |  | 
| Reid Kleckner | 8fbda8e | 2013-05-17 14:04:52 +0000 | [diff] [blame] | 4660 |   // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or | 
 | 4661 |   // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" | 
 | 4662 |   StringRef::iterator I = StrRef.begin(); | 
 | 4663 |   if (IsCurly) // Skip the optional '{' | 
 | 4664 |      ++I; | 
 | 4665 |  | 
 | 4666 |   for (int i = 0; i < 36; ++i) { | 
 | 4667 |     if (i == 8 || i == 13 || i == 18 || i == 23) { | 
 | 4668 |       if (*I != '-') { | 
| Francois Pichet | d3d3be9 | 2010-12-20 01:41:49 +0000 | [diff] [blame] | 4669 |         S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); | 
 | 4670 |         return; | 
 | 4671 |       } | 
| Reid Kleckner | 8fbda8e | 2013-05-17 14:04:52 +0000 | [diff] [blame] | 4672 |     } else if (!isHexDigit(*I)) { | 
 | 4673 |       S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); | 
 | 4674 |       return; | 
| Francois Pichet | d3d3be9 | 2010-12-20 01:41:49 +0000 | [diff] [blame] | 4675 |     } | 
| Reid Kleckner | 8fbda8e | 2013-05-17 14:04:52 +0000 | [diff] [blame] | 4676 |     I++; | 
 | 4677 |   } | 
| Francois Pichet | 1154214 | 2010-12-19 06:50:37 +0000 | [diff] [blame] | 4678 |  | 
| Reid Kleckner | 8fbda8e | 2013-05-17 14:04:52 +0000 | [diff] [blame] | 4679 |   D->addAttr(::new (S.Context) | 
 | 4680 |              UuidAttr(Attr.getRange(), S.Context, Str->getString(), | 
 | 4681 |                       Attr.getAttributeSpellingListIndex())); | 
| Charles Davis | f0122fe | 2010-02-16 18:27:26 +0000 | [diff] [blame] | 4682 | } | 
 | 4683 |  | 
| John McCall | c052dbb | 2012-05-22 21:28:12 +0000 | [diff] [blame] | 4684 | static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Reid Kleckner | 8fbda8e | 2013-05-17 14:04:52 +0000 | [diff] [blame] | 4685 |   if (!checkMicrosoftExt(S, Attr)) | 
| Nico Weber | 7b89ab7 | 2012-11-07 21:31:36 +0000 | [diff] [blame] | 4686 |     return; | 
| Nico Weber | 7b89ab7 | 2012-11-07 21:31:36 +0000 | [diff] [blame] | 4687 |  | 
 | 4688 |   AttributeList::Kind Kind = Attr.getKind(); | 
 | 4689 |   if (Kind == AttributeList::AT_SingleInheritance) | 
 | 4690 |     D->addAttr( | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4691 |         ::new (S.Context) | 
 | 4692 |                SingleInheritanceAttr(Attr.getRange(), S.Context, | 
 | 4693 |                                      Attr.getAttributeSpellingListIndex())); | 
| Nico Weber | 7b89ab7 | 2012-11-07 21:31:36 +0000 | [diff] [blame] | 4694 |   else if (Kind == AttributeList::AT_MultipleInheritance) | 
 | 4695 |     D->addAttr( | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4696 |         ::new (S.Context) | 
 | 4697 |                MultipleInheritanceAttr(Attr.getRange(), S.Context, | 
 | 4698 |                                        Attr.getAttributeSpellingListIndex())); | 
| Nico Weber | 7b89ab7 | 2012-11-07 21:31:36 +0000 | [diff] [blame] | 4699 |   else if (Kind == AttributeList::AT_VirtualInheritance) | 
 | 4700 |     D->addAttr( | 
| Michael Han | 51d8c52 | 2013-01-24 16:46:58 +0000 | [diff] [blame] | 4701 |         ::new (S.Context) | 
 | 4702 |                VirtualInheritanceAttr(Attr.getRange(), S.Context, | 
 | 4703 |                                       Attr.getAttributeSpellingListIndex())); | 
| John McCall | c052dbb | 2012-05-22 21:28:12 +0000 | [diff] [blame] | 4704 | } | 
 | 4705 |  | 
 | 4706 | static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Reid Kleckner | 8fbda8e | 2013-05-17 14:04:52 +0000 | [diff] [blame] | 4707 |   if (!checkMicrosoftExt(S, Attr)) | 
 | 4708 |     return; | 
 | 4709 |  | 
 | 4710 |   AttributeList::Kind Kind = Attr.getKind(); | 
| Aaron Ballman | aa9df09 | 2013-05-22 23:25:32 +0000 | [diff] [blame] | 4711 |     if (Kind == AttributeList::AT_Win64) | 
| Reid Kleckner | 8fbda8e | 2013-05-17 14:04:52 +0000 | [diff] [blame] | 4712 |     D->addAttr( | 
 | 4713 |         ::new (S.Context) Win64Attr(Attr.getRange(), S.Context, | 
 | 4714 |                                     Attr.getAttributeSpellingListIndex())); | 
| John McCall | c052dbb | 2012-05-22 21:28:12 +0000 | [diff] [blame] | 4715 | } | 
 | 4716 |  | 
| Michael J. Spencer | adc6cbf | 2012-06-18 07:00:48 +0000 | [diff] [blame] | 4717 | static void handleForceInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
| Reid Kleckner | 8fbda8e | 2013-05-17 14:04:52 +0000 | [diff] [blame] | 4718 |   if (!checkMicrosoftExt(S, Attr)) | 
 | 4719 |     return; | 
 | 4720 |   D->addAttr(::new (S.Context) | 
 | 4721 |              ForceInlineAttr(Attr.getRange(), S.Context, | 
 | 4722 |                              Attr.getAttributeSpellingListIndex())); | 
| Michael J. Spencer | adc6cbf | 2012-06-18 07:00:48 +0000 | [diff] [blame] | 4723 | } | 
 | 4724 |  | 
| Reid Kleckner | a722534 | 2013-05-20 14:02:37 +0000 | [diff] [blame] | 4725 | static void handleSelectAnyAttr(Sema &S, Decl *D, const AttributeList &Attr) { | 
 | 4726 |   if (!checkMicrosoftExt(S, Attr)) | 
 | 4727 |     return; | 
 | 4728 |   // Check linkage after possibly merging declaratinos.  See | 
 | 4729 |   // checkAttributesAfterMerging(). | 
 | 4730 |   D->addAttr(::new (S.Context) | 
 | 4731 |              SelectAnyAttr(Attr.getRange(), S.Context, | 
 | 4732 |                            Attr.getAttributeSpellingListIndex())); | 
 | 4733 | } | 
 | 4734 |  | 
| Ted Kremenek | b71368d | 2009-05-09 02:44:38 +0000 | [diff] [blame] | 4735 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 0744e5f | 2008-06-29 00:23:49 +0000 | [diff] [blame] | 4736 | // Top Level Sema Entry Points | 
 | 4737 | //===----------------------------------------------------------------------===// | 
 | 4738 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4739 | static void ProcessNonInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, | 
 | 4740 |                                           const AttributeList &Attr) { | 
| Peter Collingbourne | 6070039 | 2011-01-21 02:08:45 +0000 | [diff] [blame] | 4741 |   switch (Attr.getKind()) { | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4742 |   case AttributeList::AT_CUDADevice:  handleDeviceAttr      (S, D, Attr); break; | 
 | 4743 |   case AttributeList::AT_CUDAHost:    handleHostAttr        (S, D, Attr); break; | 
 | 4744 |   case AttributeList::AT_Overloadable:handleOverloadableAttr(S, D, Attr); break; | 
| Peter Collingbourne | 6070039 | 2011-01-21 02:08:45 +0000 | [diff] [blame] | 4745 |   default: | 
 | 4746 |     break; | 
 | 4747 |   } | 
 | 4748 | } | 
| Abramo Bagnara | e215f72 | 2010-04-30 13:10:51 +0000 | [diff] [blame] | 4749 |  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4750 | static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, | 
 | 4751 |                                        const AttributeList &Attr) { | 
| Chris Lattner | 803d080 | 2008-06-29 00:43:07 +0000 | [diff] [blame] | 4752 |   switch (Attr.getKind()) { | 
| Richard Smith | cd8ab51 | 2013-01-17 01:30:42 +0000 | [diff] [blame] | 4753 |   case AttributeList::AT_IBAction:    handleIBAction(S, D, Attr); break; | 
 | 4754 |   case AttributeList::AT_IBOutlet:    handleIBOutlet(S, D, Attr); break; | 
 | 4755 |   case AttributeList::AT_IBOutletCollection: | 
 | 4756 |     handleIBOutletCollection(S, D, Attr); break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4757 |   case AttributeList::AT_AddressSpace: | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4758 |   case AttributeList::AT_ObjCGC: | 
 | 4759 |   case AttributeList::AT_VectorSize: | 
 | 4760 |   case AttributeList::AT_NeonVectorType: | 
 | 4761 |   case AttributeList::AT_NeonPolyVectorType: | 
| Aaron Ballman | aa9df09 | 2013-05-22 23:25:32 +0000 | [diff] [blame] | 4762 |   case AttributeList::AT_Ptr32: | 
 | 4763 |   case AttributeList::AT_Ptr64: | 
 | 4764 |   case AttributeList::AT_SPtr: | 
 | 4765 |   case AttributeList::AT_UPtr: | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 4766 |     // Ignore these, these are type attributes, handled by | 
 | 4767 |     // ProcessTypeAttributes. | 
| Chris Lattner | 803d080 | 2008-06-29 00:43:07 +0000 | [diff] [blame] | 4768 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4769 |   case AttributeList::AT_CUDADevice: | 
 | 4770 |   case AttributeList::AT_CUDAHost: | 
 | 4771 |   case AttributeList::AT_Overloadable: | 
| Peter Collingbourne | 6070039 | 2011-01-21 02:08:45 +0000 | [diff] [blame] | 4772 |     // Ignore, this is a non-inheritable attribute, handled | 
 | 4773 |     // by ProcessNonInheritableDeclAttr. | 
 | 4774 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4775 |   case AttributeList::AT_Alias:       handleAliasAttr       (S, D, Attr); break; | 
 | 4776 |   case AttributeList::AT_Aligned:     handleAlignedAttr     (S, D, Attr); break; | 
 | 4777 |   case AttributeList::AT_AllocSize:   handleAllocSizeAttr   (S, D, Attr); break; | 
 | 4778 |   case AttributeList::AT_AlwaysInline: | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4779 |     handleAlwaysInlineAttr  (S, D, Attr); break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4780 |   case AttributeList::AT_AnalyzerNoReturn: | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4781 |     handleAnalyzerNoReturnAttr  (S, D, Attr); break; | 
| Hans Wennborg | 5e2d5de | 2012-06-23 11:51:46 +0000 | [diff] [blame] | 4782 |   case AttributeList::AT_TLSModel:    handleTLSModelAttr    (S, D, Attr); break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4783 |   case AttributeList::AT_Annotate:    handleAnnotateAttr    (S, D, Attr); break; | 
 | 4784 |   case AttributeList::AT_Availability:handleAvailabilityAttr(S, D, Attr); break; | 
 | 4785 |   case AttributeList::AT_CarriesDependency: | 
| Richard Smith | 3a2b7a1 | 2013-01-28 22:42:45 +0000 | [diff] [blame] | 4786 |     handleDependencyAttr(S, scope, D, Attr); | 
 | 4787 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4788 |   case AttributeList::AT_Common:      handleCommonAttr      (S, D, Attr); break; | 
 | 4789 |   case AttributeList::AT_CUDAConstant:handleConstantAttr    (S, D, Attr); break; | 
 | 4790 |   case AttributeList::AT_Constructor: handleConstructorAttr (S, D, Attr); break; | 
| Richard Smith | cd8ab51 | 2013-01-17 01:30:42 +0000 | [diff] [blame] | 4791 |   case AttributeList::AT_CXX11NoReturn: | 
 | 4792 |     handleCXX11NoReturnAttr(S, D, Attr); | 
 | 4793 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4794 |   case AttributeList::AT_Deprecated: | 
| Aaron Ballman | 2dbdef2 | 2013-07-18 13:13:52 +0000 | [diff] [blame^] | 4795 |     handleAttrWithMessage<DeprecatedAttr>(S, D, Attr); | 
| Benjamin Kramer | bc3260d | 2012-05-16 12:19:08 +0000 | [diff] [blame] | 4796 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4797 |   case AttributeList::AT_Destructor:  handleDestructorAttr  (S, D, Attr); break; | 
 | 4798 |   case AttributeList::AT_ExtVectorType: | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4799 |     handleExtVectorTypeAttr(S, scope, D, Attr); | 
| Chris Lattner | 803d080 | 2008-06-29 00:43:07 +0000 | [diff] [blame] | 4800 |     break; | 
| Quentin Colombet | aee56fa | 2012-11-01 23:55:47 +0000 | [diff] [blame] | 4801 |   case AttributeList::AT_MinSize: | 
 | 4802 |     handleMinSizeAttr(S, D, Attr); | 
 | 4803 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4804 |   case AttributeList::AT_Format:      handleFormatAttr      (S, D, Attr); break; | 
 | 4805 |   case AttributeList::AT_FormatArg:   handleFormatArgAttr   (S, D, Attr); break; | 
 | 4806 |   case AttributeList::AT_CUDAGlobal:  handleGlobalAttr      (S, D, Attr); break; | 
 | 4807 |   case AttributeList::AT_GNUInline:   handleGNUInlineAttr   (S, D, Attr); break; | 
 | 4808 |   case AttributeList::AT_CUDALaunchBounds: | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4809 |     handleLaunchBoundsAttr(S, D, Attr); | 
| Peter Collingbourne | 7b38198 | 2010-12-12 23:03:07 +0000 | [diff] [blame] | 4810 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4811 |   case AttributeList::AT_Mode:        handleModeAttr        (S, D, Attr); break; | 
 | 4812 |   case AttributeList::AT_Malloc:      handleMallocAttr      (S, D, Attr); break; | 
 | 4813 |   case AttributeList::AT_MayAlias:    handleMayAliasAttr    (S, D, Attr); break; | 
 | 4814 |   case AttributeList::AT_NoCommon:    handleNoCommonAttr    (S, D, Attr); break; | 
 | 4815 |   case AttributeList::AT_NonNull:     handleNonNullAttr     (S, D, Attr); break; | 
| Ted Kremenek | dd0e490 | 2010-07-31 01:52:11 +0000 | [diff] [blame] | 4816 |   case AttributeList::AT_ownership_returns: | 
 | 4817 |   case AttributeList::AT_ownership_takes: | 
 | 4818 |   case AttributeList::AT_ownership_holds: | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4819 |       handleOwnershipAttr     (S, D, Attr); break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4820 |   case AttributeList::AT_Cold:        handleColdAttr        (S, D, Attr); break; | 
 | 4821 |   case AttributeList::AT_Hot:         handleHotAttr         (S, D, Attr); break; | 
 | 4822 |   case AttributeList::AT_Naked:       handleNakedAttr       (S, D, Attr); break; | 
 | 4823 |   case AttributeList::AT_NoReturn:    handleNoReturnAttr    (S, D, Attr); break; | 
 | 4824 |   case AttributeList::AT_NoThrow:     handleNothrowAttr     (S, D, Attr); break; | 
 | 4825 |   case AttributeList::AT_CUDAShared:  handleSharedAttr      (S, D, Attr); break; | 
 | 4826 |   case AttributeList::AT_VecReturn:   handleVecReturnAttr   (S, D, Attr); break; | 
| Ted Kremenek | b71368d | 2009-05-09 02:44:38 +0000 | [diff] [blame] | 4827 |  | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4828 |   case AttributeList::AT_ObjCOwnership: | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4829 |     handleObjCOwnershipAttr(S, D, Attr); break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4830 |   case AttributeList::AT_ObjCPreciseLifetime: | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4831 |     handleObjCPreciseLifetimeAttr(S, D, Attr); break; | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 4832 |  | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4833 |   case AttributeList::AT_ObjCReturnsInnerPointer: | 
| John McCall | dc7c5ad | 2011-07-22 08:53:00 +0000 | [diff] [blame] | 4834 |     handleObjCReturnsInnerPointerAttr(S, D, Attr); break; | 
 | 4835 |  | 
| Fariborz Jahanian | 8410113 | 2012-09-07 23:46:23 +0000 | [diff] [blame] | 4836 |   case AttributeList::AT_ObjCRequiresSuper: | 
 | 4837 |       handleObjCRequiresSuperAttr(S, D, Attr); break; | 
 | 4838 |        | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4839 |   case AttributeList::AT_NSBridged: | 
| John McCall | fe98da0 | 2011-09-29 07:17:38 +0000 | [diff] [blame] | 4840 |     handleNSBridgedAttr(S, scope, D, Attr); break; | 
 | 4841 |  | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4842 |   case AttributeList::AT_CFAuditedTransfer: | 
 | 4843 |   case AttributeList::AT_CFUnknownTransfer: | 
| John McCall | 8dfac0b | 2011-09-30 05:12:12 +0000 | [diff] [blame] | 4844 |     handleCFTransferAttr(S, D, Attr); break; | 
 | 4845 |  | 
| Ted Kremenek | b71368d | 2009-05-09 02:44:38 +0000 | [diff] [blame] | 4846 |   // Checker-specific. | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4847 |   case AttributeList::AT_CFConsumed: | 
 | 4848 |   case AttributeList::AT_NSConsumed:  handleNSConsumedAttr  (S, D, Attr); break; | 
 | 4849 |   case AttributeList::AT_NSConsumesSelf: | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4850 |     handleNSConsumesSelfAttr(S, D, Attr); break; | 
| John McCall | c7ad381 | 2011-01-25 03:31:58 +0000 | [diff] [blame] | 4851 |  | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4852 |   case AttributeList::AT_NSReturnsAutoreleased: | 
 | 4853 |   case AttributeList::AT_NSReturnsNotRetained: | 
 | 4854 |   case AttributeList::AT_CFReturnsNotRetained: | 
 | 4855 |   case AttributeList::AT_NSReturnsRetained: | 
 | 4856 |   case AttributeList::AT_CFReturnsRetained: | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4857 |     handleNSReturnsRetainedAttr(S, D, Attr); break; | 
| Ted Kremenek | b71368d | 2009-05-09 02:44:38 +0000 | [diff] [blame] | 4858 |  | 
| Tanya Lattner | 0df579e | 2012-07-09 22:06:01 +0000 | [diff] [blame] | 4859 |   case AttributeList::AT_WorkGroupSizeHint: | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4860 |   case AttributeList::AT_ReqdWorkGroupSize: | 
| Tanya Lattner | 0df579e | 2012-07-09 22:06:01 +0000 | [diff] [blame] | 4861 |     handleWorkGroupSize(S, D, Attr); break; | 
| Nate Begeman | 6f3d838 | 2009-06-26 06:32:41 +0000 | [diff] [blame] | 4862 |  | 
| Joey Gouly | 37453b9 | 2013-03-08 09:42:32 +0000 | [diff] [blame] | 4863 |   case AttributeList::AT_VecTypeHint: | 
 | 4864 |     handleVecTypeHint(S, D, Attr); break; | 
 | 4865 |  | 
| Joey Gouly | 96cead5 | 2013-03-14 09:54:43 +0000 | [diff] [blame] | 4866 |   case AttributeList::AT_Endian: | 
 | 4867 |     handleEndianAttr(S, D, Attr); | 
 | 4868 |     break; | 
 | 4869 |  | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4870 |   case AttributeList::AT_InitPriority:  | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4871 |       handleInitPriorityAttr(S, D, Attr); break; | 
| Fariborz Jahanian | 521f12d | 2010-06-18 21:44:06 +0000 | [diff] [blame] | 4872 |        | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4873 |   case AttributeList::AT_Packed:      handlePackedAttr      (S, D, Attr); break; | 
 | 4874 |   case AttributeList::AT_Section:     handleSectionAttr     (S, D, Attr); break; | 
 | 4875 |   case AttributeList::AT_Unavailable: | 
| Aaron Ballman | 2dbdef2 | 2013-07-18 13:13:52 +0000 | [diff] [blame^] | 4876 |     handleAttrWithMessage<UnavailableAttr>(S, D, Attr); | 
| Benjamin Kramer | bc3260d | 2012-05-16 12:19:08 +0000 | [diff] [blame] | 4877 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4878 |   case AttributeList::AT_ArcWeakrefUnavailable:  | 
| Fariborz Jahanian | 742352a | 2011-07-06 19:24:05 +0000 | [diff] [blame] | 4879 |     handleArcWeakrefUnavailableAttr (S, D, Attr);  | 
 | 4880 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4881 |   case AttributeList::AT_ObjCRootClass: | 
| Patrick Beard | b2f6820 | 2012-04-06 18:12:22 +0000 | [diff] [blame] | 4882 |     handleObjCRootClassAttr(S, D, Attr); | 
 | 4883 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4884 |   case AttributeList::AT_ObjCRequiresPropertyDefs:  | 
| Ted Kremenek | 71207fc | 2012-01-05 22:47:47 +0000 | [diff] [blame] | 4885 |     handleObjCRequiresPropertyDefsAttr (S, D, Attr);  | 
| Fariborz Jahanian | e23dcf3 | 2012-01-03 18:45:41 +0000 | [diff] [blame] | 4886 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4887 |   case AttributeList::AT_Unused:      handleUnusedAttr      (S, D, Attr); break; | 
 | 4888 |   case AttributeList::AT_ReturnsTwice: | 
| Rafael Espindola | f87cced | 2011-10-03 14:59:42 +0000 | [diff] [blame] | 4889 |     handleReturnsTwiceAttr(S, D, Attr); | 
 | 4890 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4891 |   case AttributeList::AT_Used:        handleUsedAttr        (S, D, Attr); break; | 
| John McCall | d4c3d66 | 2013-02-20 01:54:26 +0000 | [diff] [blame] | 4892 |   case AttributeList::AT_Visibility: | 
 | 4893 |     handleVisibilityAttr(S, D, Attr, false); | 
 | 4894 |     break; | 
 | 4895 |   case AttributeList::AT_TypeVisibility: | 
 | 4896 |     handleVisibilityAttr(S, D, Attr, true); | 
 | 4897 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4898 |   case AttributeList::AT_WarnUnusedResult: handleWarnUnusedResult(S, D, Attr); | 
| Chris Lattner | 026dc96 | 2009-02-14 07:37:35 +0000 | [diff] [blame] | 4899 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4900 |   case AttributeList::AT_Weak:        handleWeakAttr        (S, D, Attr); break; | 
 | 4901 |   case AttributeList::AT_WeakRef:     handleWeakRefAttr     (S, D, Attr); break; | 
 | 4902 |   case AttributeList::AT_WeakImport:  handleWeakImportAttr  (S, D, Attr); break; | 
 | 4903 |   case AttributeList::AT_TransparentUnion: | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4904 |     handleTransparentUnionAttr(S, D, Attr); | 
| Chris Lattner | 803d080 | 2008-06-29 00:43:07 +0000 | [diff] [blame] | 4905 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4906 |   case AttributeList::AT_ObjCException: | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4907 |     handleObjCExceptionAttr(S, D, Attr); | 
| Chris Lattner | 0db29ec | 2009-02-14 08:09:34 +0000 | [diff] [blame] | 4908 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4909 |   case AttributeList::AT_ObjCMethodFamily: | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4910 |     handleObjCMethodFamilyAttr(S, D, Attr); | 
| John McCall | d5313b0 | 2011-03-02 11:33:24 +0000 | [diff] [blame] | 4911 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4912 |   case AttributeList::AT_ObjCNSObject:handleObjCNSObject    (S, D, Attr); break; | 
 | 4913 |   case AttributeList::AT_Blocks:      handleBlocksAttr      (S, D, Attr); break; | 
 | 4914 |   case AttributeList::AT_Sentinel:    handleSentinelAttr    (S, D, Attr); break; | 
 | 4915 |   case AttributeList::AT_Const:       handleConstAttr       (S, D, Attr); break; | 
 | 4916 |   case AttributeList::AT_Pure:        handlePureAttr        (S, D, Attr); break; | 
 | 4917 |   case AttributeList::AT_Cleanup:     handleCleanupAttr     (S, D, Attr); break; | 
 | 4918 |   case AttributeList::AT_NoDebug:     handleNoDebugAttr     (S, D, Attr); break; | 
 | 4919 |   case AttributeList::AT_NoInline:    handleNoInlineAttr    (S, D, Attr); break; | 
 | 4920 |   case AttributeList::AT_Regparm:     handleRegparmAttr     (S, D, Attr); break; | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 4921 |   case AttributeList::IgnoredAttribute: | 
| Anders Carlsson | 05f8e47 | 2009-02-13 08:16:43 +0000 | [diff] [blame] | 4922 |     // Just ignore | 
 | 4923 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4924 |   case AttributeList::AT_NoInstrumentFunction:  // Interacts with -pg. | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4925 |     handleNoInstrumentFunctionAttr(S, D, Attr); | 
| Chris Lattner | 7255a2d | 2010-06-22 00:03:40 +0000 | [diff] [blame] | 4926 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4927 |   case AttributeList::AT_StdCall: | 
 | 4928 |   case AttributeList::AT_CDecl: | 
 | 4929 |   case AttributeList::AT_FastCall: | 
 | 4930 |   case AttributeList::AT_ThisCall: | 
 | 4931 |   case AttributeList::AT_Pascal: | 
 | 4932 |   case AttributeList::AT_Pcs: | 
| Derek Schuff | 263366f | 2012-10-16 22:30:41 +0000 | [diff] [blame] | 4933 |   case AttributeList::AT_PnaclCall: | 
| Guy Benyei | 3898008 | 2012-12-25 08:53:55 +0000 | [diff] [blame] | 4934 |   case AttributeList::AT_IntelOclBicc: | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4935 |     handleCallConvAttr(S, D, Attr); | 
| John McCall | 04a67a6 | 2010-02-05 21:31:56 +0000 | [diff] [blame] | 4936 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4937 |   case AttributeList::AT_OpenCLKernel: | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4938 |     handleOpenCLKernelAttr(S, D, Attr); | 
| Peter Collingbourne | f315fa8 | 2011-02-14 01:42:53 +0000 | [diff] [blame] | 4939 |     break; | 
| Guy Benyei | 1db7040 | 2013-03-24 13:58:12 +0000 | [diff] [blame] | 4940 |   case AttributeList::AT_OpenCLImageAccess: | 
 | 4941 |     handleOpenCLImageAccessAttr(S, D, Attr); | 
 | 4942 |     break; | 
| John McCall | c052dbb | 2012-05-22 21:28:12 +0000 | [diff] [blame] | 4943 |  | 
 | 4944 |   // Microsoft attributes: | 
| John McCall | 76da55d | 2013-04-16 07:28:30 +0000 | [diff] [blame] | 4945 |   case AttributeList::AT_MsProperty: break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4946 |   case AttributeList::AT_MsStruct: | 
| John McCall | c052dbb | 2012-05-22 21:28:12 +0000 | [diff] [blame] | 4947 |     handleMsStructAttr(S, D, Attr); | 
 | 4948 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4949 |   case AttributeList::AT_Uuid: | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 4950 |     handleUuidAttr(S, D, Attr); | 
| Francois Pichet | 1154214 | 2010-12-19 06:50:37 +0000 | [diff] [blame] | 4951 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4952 |   case AttributeList::AT_SingleInheritance: | 
 | 4953 |   case AttributeList::AT_MultipleInheritance: | 
 | 4954 |   case AttributeList::AT_VirtualInheritance: | 
| John McCall | c052dbb | 2012-05-22 21:28:12 +0000 | [diff] [blame] | 4955 |     handleInheritanceAttr(S, D, Attr); | 
 | 4956 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4957 |   case AttributeList::AT_Win64: | 
| John McCall | c052dbb | 2012-05-22 21:28:12 +0000 | [diff] [blame] | 4958 |     handlePortabilityAttr(S, D, Attr); | 
 | 4959 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4960 |   case AttributeList::AT_ForceInline: | 
| Michael J. Spencer | adc6cbf | 2012-06-18 07:00:48 +0000 | [diff] [blame] | 4961 |     handleForceInlineAttr(S, D, Attr); | 
 | 4962 |     break; | 
| Reid Kleckner | a722534 | 2013-05-20 14:02:37 +0000 | [diff] [blame] | 4963 |   case AttributeList::AT_SelectAny: | 
 | 4964 |     handleSelectAnyAttr(S, D, Attr); | 
 | 4965 |     break; | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 4966 |  | 
 | 4967 |   // Thread safety attributes: | 
| DeLesley Hutchins | 5c6134f | 2013-05-17 23:02:59 +0000 | [diff] [blame] | 4968 |   case AttributeList::AT_AssertExclusiveLock: | 
 | 4969 |     handleAssertExclusiveLockAttr(S, D, Attr); | 
 | 4970 |     break; | 
 | 4971 |   case AttributeList::AT_AssertSharedLock: | 
 | 4972 |     handleAssertSharedLockAttr(S, D, Attr); | 
 | 4973 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4974 |   case AttributeList::AT_GuardedVar: | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 4975 |     handleGuardedVarAttr(S, D, Attr); | 
 | 4976 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4977 |   case AttributeList::AT_PtGuardedVar: | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 4978 |     handlePtGuardedVarAttr(S, D, Attr); | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 4979 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4980 |   case AttributeList::AT_ScopedLockable: | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 4981 |     handleScopedLockableAttr(S, D, Attr); | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 4982 |     break; | 
| Kostya Serebryany | 85aee96 | 2013-02-26 06:58:27 +0000 | [diff] [blame] | 4983 |   case AttributeList::AT_NoSanitizeAddress: | 
 | 4984 |     handleNoSanitizeAddressAttr(S, D, Attr); | 
| Kostya Serebryany | 71efba0 | 2012-01-24 19:25:38 +0000 | [diff] [blame] | 4985 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4986 |   case AttributeList::AT_NoThreadSafetyAnalysis: | 
| Kostya Serebryany | 85aee96 | 2013-02-26 06:58:27 +0000 | [diff] [blame] | 4987 |     handleNoThreadSafetyAnalysis(S, D, Attr); | 
 | 4988 |     break; | 
 | 4989 |   case AttributeList::AT_NoSanitizeThread: | 
 | 4990 |     handleNoSanitizeThread(S, D, Attr); | 
 | 4991 |     break; | 
 | 4992 |   case AttributeList::AT_NoSanitizeMemory: | 
 | 4993 |     handleNoSanitizeMemory(S, D, Attr); | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 4994 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4995 |   case AttributeList::AT_Lockable: | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 4996 |     handleLockableAttr(S, D, Attr); | 
 | 4997 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 4998 |   case AttributeList::AT_GuardedBy: | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 4999 |     handleGuardedByAttr(S, D, Attr); | 
 | 5000 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 5001 |   case AttributeList::AT_PtGuardedBy: | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 5002 |     handlePtGuardedByAttr(S, D, Attr); | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 5003 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 5004 |   case AttributeList::AT_ExclusiveLockFunction: | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 5005 |     handleExclusiveLockFunctionAttr(S, D, Attr); | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 5006 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 5007 |   case AttributeList::AT_ExclusiveLocksRequired: | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 5008 |     handleExclusiveLocksRequiredAttr(S, D, Attr); | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 5009 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 5010 |   case AttributeList::AT_ExclusiveTrylockFunction: | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 5011 |     handleExclusiveTrylockFunctionAttr(S, D, Attr); | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 5012 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 5013 |   case AttributeList::AT_LockReturned: | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 5014 |     handleLockReturnedAttr(S, D, Attr); | 
 | 5015 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 5016 |   case AttributeList::AT_LocksExcluded: | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 5017 |     handleLocksExcludedAttr(S, D, Attr); | 
 | 5018 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 5019 |   case AttributeList::AT_SharedLockFunction: | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 5020 |     handleSharedLockFunctionAttr(S, D, Attr); | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 5021 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 5022 |   case AttributeList::AT_SharedLocksRequired: | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 5023 |     handleSharedLocksRequiredAttr(S, D, Attr); | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 5024 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 5025 |   case AttributeList::AT_SharedTrylockFunction: | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 5026 |     handleSharedTrylockFunctionAttr(S, D, Attr); | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 5027 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 5028 |   case AttributeList::AT_UnlockFunction: | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 5029 |     handleUnlockFunAttr(S, D, Attr); | 
 | 5030 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 5031 |   case AttributeList::AT_AcquiredBefore: | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 5032 |     handleAcquiredBeforeAttr(S, D, Attr); | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 5033 |     break; | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 5034 |   case AttributeList::AT_AcquiredAfter: | 
| Michael Han | dc69157 | 2012-07-23 18:48:41 +0000 | [diff] [blame] | 5035 |     handleAcquiredAfterAttr(S, D, Attr); | 
| Caitlin Sadowski | db33e14 | 2011-07-28 20:12:35 +0000 | [diff] [blame] | 5036 |     break; | 
| Caitlin Sadowski | fdde9e7 | 2011-07-28 17:21:07 +0000 | [diff] [blame] | 5037 |  | 
| Dmitri Gribenko | 0d5a069 | 2012-08-17 00:08:38 +0000 | [diff] [blame] | 5038 |   // Type safety attributes. | 
 | 5039 |   case AttributeList::AT_ArgumentWithTypeTag: | 
 | 5040 |     handleArgumentWithTypeTagAttr(S, D, Attr); | 
 | 5041 |     break; | 
 | 5042 |   case AttributeList::AT_TypeTagForDatatype: | 
 | 5043 |     handleTypeTagForDatatypeAttr(S, D, Attr); | 
 | 5044 |     break; | 
 | 5045 |  | 
| Chris Lattner | 803d080 | 2008-06-29 00:43:07 +0000 | [diff] [blame] | 5046 |   default: | 
| Anton Korobeynikov | 82d0a41 | 2010-01-10 12:58:08 +0000 | [diff] [blame] | 5047 |     // Ask target about the attribute. | 
 | 5048 |     const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema(); | 
 | 5049 |     if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S)) | 
| Aaron Ballman | fc685ac | 2012-06-19 22:09:27 +0000 | [diff] [blame] | 5050 |       S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute() ?  | 
 | 5051 |              diag::warn_unhandled_ms_attribute_ignored :  | 
 | 5052 |              diag::warn_unknown_attribute_ignored) << Attr.getName(); | 
| Chris Lattner | 803d080 | 2008-06-29 00:43:07 +0000 | [diff] [blame] | 5053 |     break; | 
 | 5054 |   } | 
 | 5055 | } | 
 | 5056 |  | 
| Peter Collingbourne | 6070039 | 2011-01-21 02:08:45 +0000 | [diff] [blame] | 5057 | /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if | 
 | 5058 | /// the attribute applies to decls.  If the attribute is a type attribute, just | 
| Richard Smith | cd8ab51 | 2013-01-17 01:30:42 +0000 | [diff] [blame] | 5059 | /// silently ignore it if a GNU attribute. | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 5060 | static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, | 
 | 5061 |                                  const AttributeList &Attr, | 
| Richard Smith | cd8ab51 | 2013-01-17 01:30:42 +0000 | [diff] [blame] | 5062 |                                  bool NonInheritable, bool Inheritable, | 
 | 5063 |                                  bool IncludeCXX11Attributes) { | 
| Peter Collingbourne | 6070039 | 2011-01-21 02:08:45 +0000 | [diff] [blame] | 5064 |   if (Attr.isInvalid()) | 
 | 5065 |     return; | 
 | 5066 |  | 
| Richard Smith | cd8ab51 | 2013-01-17 01:30:42 +0000 | [diff] [blame] | 5067 |   // Ignore C++11 attributes on declarator chunks: they appertain to the type | 
 | 5068 |   // instead. | 
 | 5069 |   if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes) | 
 | 5070 |     return; | 
 | 5071 |  | 
| Peter Collingbourne | 6070039 | 2011-01-21 02:08:45 +0000 | [diff] [blame] | 5072 |   if (NonInheritable) | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 5073 |     ProcessNonInheritableDeclAttr(S, scope, D, Attr); | 
| Peter Collingbourne | 6070039 | 2011-01-21 02:08:45 +0000 | [diff] [blame] | 5074 |  | 
 | 5075 |   if (Inheritable) | 
| Chandler Carruth | 1b03c87 | 2011-07-02 00:01:44 +0000 | [diff] [blame] | 5076 |     ProcessInheritableDeclAttr(S, scope, D, Attr); | 
| Peter Collingbourne | 6070039 | 2011-01-21 02:08:45 +0000 | [diff] [blame] | 5077 | } | 
 | 5078 |  | 
| Chris Lattner | 803d080 | 2008-06-29 00:43:07 +0000 | [diff] [blame] | 5079 | /// ProcessDeclAttributeList - Apply all the decl attributes in the specified | 
 | 5080 | /// attribute list to the specified decl, ignoring any type attributes. | 
| Eric Christopher | f48f367 | 2010-12-01 22:13:54 +0000 | [diff] [blame] | 5081 | void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, | 
| Peter Collingbourne | 6070039 | 2011-01-21 02:08:45 +0000 | [diff] [blame] | 5082 |                                     const AttributeList *AttrList, | 
| Richard Smith | cd8ab51 | 2013-01-17 01:30:42 +0000 | [diff] [blame] | 5083 |                                     bool NonInheritable, bool Inheritable, | 
 | 5084 |                                     bool IncludeCXX11Attributes) { | 
 | 5085 |   for (const AttributeList* l = AttrList; l; l = l->getNext()) | 
 | 5086 |     ProcessDeclAttribute(*this, S, D, *l, NonInheritable, Inheritable, | 
 | 5087 |                          IncludeCXX11Attributes); | 
| Rafael Espindola | 11e8ce7 | 2010-02-23 22:00:30 +0000 | [diff] [blame] | 5088 |  | 
 | 5089 |   // GCC accepts | 
 | 5090 |   // static int a9 __attribute__((weakref)); | 
 | 5091 |   // but that looks really pointless. We reject it. | 
| Peter Collingbourne | 6070039 | 2011-01-21 02:08:45 +0000 | [diff] [blame] | 5092 |   if (Inheritable && D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) { | 
| Rafael Espindola | 11e8ce7 | 2010-02-23 22:00:30 +0000 | [diff] [blame] | 5093 |     Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) << | 
| Rafael Espindola | 4d8a33b | 2013-01-16 23:49:06 +0000 | [diff] [blame] | 5094 |     cast<NamedDecl>(D)->getNameAsString(); | 
 | 5095 |     D->dropAttr<WeakRefAttr>(); | 
| Rafael Espindola | 11e8ce7 | 2010-02-23 22:00:30 +0000 | [diff] [blame] | 5096 |     return; | 
| Chris Lattner | 803d080 | 2008-06-29 00:43:07 +0000 | [diff] [blame] | 5097 |   } | 
 | 5098 | } | 
 | 5099 |  | 
| Erik Verbruggen | 5f1c822 | 2011-10-13 09:41:32 +0000 | [diff] [blame] | 5100 | // Annotation attributes are the only attributes allowed after an access | 
 | 5101 | // specifier. | 
 | 5102 | bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, | 
 | 5103 |                                           const AttributeList *AttrList) { | 
 | 5104 |   for (const AttributeList* l = AttrList; l; l = l->getNext()) { | 
| Sean Hunt | 8e083e7 | 2012-06-19 23:57:03 +0000 | [diff] [blame] | 5105 |     if (l->getKind() == AttributeList::AT_Annotate) { | 
| Erik Verbruggen | 5f1c822 | 2011-10-13 09:41:32 +0000 | [diff] [blame] | 5106 |       handleAnnotateAttr(*this, ASDecl, *l); | 
 | 5107 |     } else { | 
 | 5108 |       Diag(l->getLoc(), diag::err_only_annotate_after_access_spec); | 
 | 5109 |       return true; | 
 | 5110 |     } | 
 | 5111 |   } | 
 | 5112 |  | 
 | 5113 |   return false; | 
 | 5114 | } | 
 | 5115 |  | 
| John McCall | e82247a | 2011-10-01 05:17:03 +0000 | [diff] [blame] | 5116 | /// checkUnusedDeclAttributes - Check a list of attributes to see if it | 
 | 5117 | /// contains any decl attributes that we should warn about. | 
 | 5118 | static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) { | 
 | 5119 |   for ( ; A; A = A->getNext()) { | 
 | 5120 |     // Only warn if the attribute is an unignored, non-type attribute. | 
| Richard Smith | d03de6a | 2013-01-29 10:02:16 +0000 | [diff] [blame] | 5121 |     if (A->isUsedAsTypeAttr() || A->isInvalid()) continue; | 
| John McCall | e82247a | 2011-10-01 05:17:03 +0000 | [diff] [blame] | 5122 |     if (A->getKind() == AttributeList::IgnoredAttribute) continue; | 
 | 5123 |  | 
 | 5124 |     if (A->getKind() == AttributeList::UnknownAttribute) { | 
 | 5125 |       S.Diag(A->getLoc(), diag::warn_unknown_attribute_ignored) | 
 | 5126 |         << A->getName() << A->getRange(); | 
 | 5127 |     } else { | 
 | 5128 |       S.Diag(A->getLoc(), diag::warn_attribute_not_on_decl) | 
 | 5129 |         << A->getName() << A->getRange(); | 
 | 5130 |     } | 
 | 5131 |   } | 
 | 5132 | } | 
 | 5133 |  | 
 | 5134 | /// checkUnusedDeclAttributes - Given a declarator which is not being | 
 | 5135 | /// used to build a declaration, complain about any decl attributes | 
 | 5136 | /// which might be lying around on it. | 
 | 5137 | void Sema::checkUnusedDeclAttributes(Declarator &D) { | 
 | 5138 |   ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes().getList()); | 
 | 5139 |   ::checkUnusedDeclAttributes(*this, D.getAttributes()); | 
 | 5140 |   for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) | 
 | 5141 |     ::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs()); | 
 | 5142 | } | 
 | 5143 |  | 
| Ryan Flynn | e25ff83 | 2009-07-30 03:15:39 +0000 | [diff] [blame] | 5144 | /// DeclClonePragmaWeak - clone existing decl (maybe definition), | 
| James Dennett | 1dfbd92 | 2012-06-14 21:40:34 +0000 | [diff] [blame] | 5145 | /// \#pragma weak needs a non-definition decl and source may not have one. | 
| Eli Friedman | 900693b | 2011-09-07 04:05:06 +0000 | [diff] [blame] | 5146 | NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, | 
 | 5147 |                                       SourceLocation Loc) { | 
| Ryan Flynn | 7b1fdbd | 2009-07-31 02:52:19 +0000 | [diff] [blame] | 5148 |   assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND)); | 
| Ryan Flynn | e25ff83 | 2009-07-30 03:15:39 +0000 | [diff] [blame] | 5149 |   NamedDecl *NewD = 0; | 
 | 5150 |   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { | 
| Eli Friedman | 900693b | 2011-09-07 04:05:06 +0000 | [diff] [blame] | 5151 |     FunctionDecl *NewFD; | 
 | 5152 |     // FIXME: Missing call to CheckFunctionDeclaration(). | 
 | 5153 |     // FIXME: Mangling? | 
 | 5154 |     // FIXME: Is the qualifier info correct? | 
 | 5155 |     // FIXME: Is the DeclContext correct? | 
 | 5156 |     NewFD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(), | 
 | 5157 |                                  Loc, Loc, DeclarationName(II), | 
 | 5158 |                                  FD->getType(), FD->getTypeSourceInfo(), | 
| Rafael Espindola | d2615cc | 2013-04-03 19:27:57 +0000 | [diff] [blame] | 5159 |                                  SC_None, false/*isInlineSpecified*/, | 
| Eli Friedman | 900693b | 2011-09-07 04:05:06 +0000 | [diff] [blame] | 5160 |                                  FD->hasPrototype(), | 
 | 5161 |                                  false/*isConstexprSpecified*/); | 
 | 5162 |     NewD = NewFD; | 
 | 5163 |  | 
 | 5164 |     if (FD->getQualifier()) | 
| Douglas Gregor | c22b5ff | 2011-02-25 02:25:35 +0000 | [diff] [blame] | 5165 |       NewFD->setQualifierInfo(FD->getQualifierLoc()); | 
| Eli Friedman | 900693b | 2011-09-07 04:05:06 +0000 | [diff] [blame] | 5166 |  | 
 | 5167 |     // Fake up parameter variables; they are declared as if this were | 
 | 5168 |     // a typedef. | 
 | 5169 |     QualType FDTy = FD->getType(); | 
 | 5170 |     if (const FunctionProtoType *FT = FDTy->getAs<FunctionProtoType>()) { | 
 | 5171 |       SmallVector<ParmVarDecl*, 16> Params; | 
 | 5172 |       for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(), | 
 | 5173 |            AE = FT->arg_type_end(); AI != AE; ++AI) { | 
 | 5174 |         ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, *AI); | 
 | 5175 |         Param->setScopeInfo(0, Params.size()); | 
 | 5176 |         Params.push_back(Param); | 
 | 5177 |       } | 
| David Blaikie | 4278c65 | 2011-09-21 18:16:56 +0000 | [diff] [blame] | 5178 |       NewFD->setParams(Params); | 
| John McCall | b621766 | 2010-03-15 10:12:16 +0000 | [diff] [blame] | 5179 |     } | 
| Ryan Flynn | e25ff83 | 2009-07-30 03:15:39 +0000 | [diff] [blame] | 5180 |   } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) { | 
 | 5181 |     NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(), | 
| Abramo Bagnara | ff676cb | 2011-03-08 08:55:46 +0000 | [diff] [blame] | 5182 |                            VD->getInnerLocStart(), VD->getLocation(), II, | 
| John McCall | a93c934 | 2009-12-07 02:54:59 +0000 | [diff] [blame] | 5183 |                            VD->getType(), VD->getTypeSourceInfo(), | 
| Rafael Espindola | d2615cc | 2013-04-03 19:27:57 +0000 | [diff] [blame] | 5184 |                            VD->getStorageClass()); | 
| John McCall | b621766 | 2010-03-15 10:12:16 +0000 | [diff] [blame] | 5185 |     if (VD->getQualifier()) { | 
 | 5186 |       VarDecl *NewVD = cast<VarDecl>(NewD); | 
| Douglas Gregor | c22b5ff | 2011-02-25 02:25:35 +0000 | [diff] [blame] | 5187 |       NewVD->setQualifierInfo(VD->getQualifierLoc()); | 
| John McCall | b621766 | 2010-03-15 10:12:16 +0000 | [diff] [blame] | 5188 |     } | 
| Ryan Flynn | e25ff83 | 2009-07-30 03:15:39 +0000 | [diff] [blame] | 5189 |   } | 
 | 5190 |   return NewD; | 
 | 5191 | } | 
 | 5192 |  | 
| James Dennett | 1dfbd92 | 2012-06-14 21:40:34 +0000 | [diff] [blame] | 5193 | /// DeclApplyPragmaWeak - A declaration (maybe definition) needs \#pragma weak | 
| Ryan Flynn | e25ff83 | 2009-07-30 03:15:39 +0000 | [diff] [blame] | 5194 | /// applied to it, possibly with an alias. | 
| Ryan Flynn | 7b1fdbd | 2009-07-31 02:52:19 +0000 | [diff] [blame] | 5195 | void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) { | 
| Chris Lattner | c4f1fb1 | 2009-09-08 18:10:11 +0000 | [diff] [blame] | 5196 |   if (W.getUsed()) return; // only do this once | 
 | 5197 |   W.setUsed(true); | 
 | 5198 |   if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...)) | 
 | 5199 |     IdentifierInfo *NDId = ND->getIdentifier(); | 
| Eli Friedman | 900693b | 2011-09-07 04:05:06 +0000 | [diff] [blame] | 5200 |     NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation()); | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 5201 |     NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context, | 
 | 5202 |                                             NDId->getName())); | 
 | 5203 |     NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context)); | 
| Chris Lattner | c4f1fb1 | 2009-09-08 18:10:11 +0000 | [diff] [blame] | 5204 |     WeakTopLevelDecl.push_back(NewD); | 
 | 5205 |     // FIXME: "hideous" code from Sema::LazilyCreateBuiltin | 
 | 5206 |     // to insert Decl at TU scope, sorry. | 
 | 5207 |     DeclContext *SavedContext = CurContext; | 
 | 5208 |     CurContext = Context.getTranslationUnitDecl(); | 
 | 5209 |     PushOnScopeChains(NewD, S); | 
 | 5210 |     CurContext = SavedContext; | 
 | 5211 |   } else { // just add weak to existing | 
| Sean Hunt | cf807c4 | 2010-08-18 23:23:40 +0000 | [diff] [blame] | 5212 |     ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context)); | 
| Ryan Flynn | e25ff83 | 2009-07-30 03:15:39 +0000 | [diff] [blame] | 5213 |   } | 
 | 5214 | } | 
 | 5215 |  | 
| Rafael Espindola | 65611bf | 2013-03-02 21:41:48 +0000 | [diff] [blame] | 5216 | void Sema::ProcessPragmaWeak(Scope *S, Decl *D) { | 
 | 5217 |   // It's valid to "forward-declare" #pragma weak, in which case we | 
 | 5218 |   // have to do this. | 
 | 5219 |   LoadExternalWeakUndeclaredIdentifiers(); | 
 | 5220 |   if (!WeakUndeclaredIdentifiers.empty()) { | 
 | 5221 |     NamedDecl *ND = NULL; | 
 | 5222 |     if (VarDecl *VD = dyn_cast<VarDecl>(D)) | 
 | 5223 |       if (VD->isExternC()) | 
 | 5224 |         ND = VD; | 
 | 5225 |     if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) | 
 | 5226 |       if (FD->isExternC()) | 
 | 5227 |         ND = FD; | 
 | 5228 |     if (ND) { | 
 | 5229 |       if (IdentifierInfo *Id = ND->getIdentifier()) { | 
 | 5230 |         llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I | 
 | 5231 |           = WeakUndeclaredIdentifiers.find(Id); | 
 | 5232 |         if (I != WeakUndeclaredIdentifiers.end()) { | 
 | 5233 |           WeakInfo W = I->second; | 
 | 5234 |           DeclApplyPragmaWeak(S, ND, W); | 
 | 5235 |           WeakUndeclaredIdentifiers[Id] = W; | 
 | 5236 |         } | 
 | 5237 |       } | 
 | 5238 |     } | 
 | 5239 |   } | 
 | 5240 | } | 
 | 5241 |  | 
| Chris Lattner | 0744e5f | 2008-06-29 00:23:49 +0000 | [diff] [blame] | 5242 | /// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in | 
 | 5243 | /// it, apply them to D.  This is a bit tricky because PD can have attributes | 
 | 5244 | /// specified in many different places, and we need to find and apply them all. | 
| Peter Collingbourne | 6070039 | 2011-01-21 02:08:45 +0000 | [diff] [blame] | 5245 | void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD, | 
 | 5246 |                                  bool NonInheritable, bool Inheritable) { | 
| Chris Lattner | 0744e5f | 2008-06-29 00:23:49 +0000 | [diff] [blame] | 5247 |   // Apply decl attributes from the DeclSpec if present. | 
| John McCall | 7f040a9 | 2010-12-24 02:08:15 +0000 | [diff] [blame] | 5248 |   if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList()) | 
| Peter Collingbourne | 6070039 | 2011-01-21 02:08:45 +0000 | [diff] [blame] | 5249 |     ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 5250 |  | 
| Chris Lattner | 0744e5f | 2008-06-29 00:23:49 +0000 | [diff] [blame] | 5251 |   // Walk the declarator structure, applying decl attributes that were in a type | 
 | 5252 |   // position to the decl itself.  This handles cases like: | 
 | 5253 |   //   int *__attr__(x)** D; | 
 | 5254 |   // when X is a decl attribute. | 
 | 5255 |   for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) | 
 | 5256 |     if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) | 
| Richard Smith | cd8ab51 | 2013-01-17 01:30:42 +0000 | [diff] [blame] | 5257 |       ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable, | 
 | 5258 |                                /*IncludeCXX11Attributes=*/false); | 
| Mike Stump | bf91650 | 2009-07-24 19:02:52 +0000 | [diff] [blame] | 5259 |  | 
| Chris Lattner | 0744e5f | 2008-06-29 00:23:49 +0000 | [diff] [blame] | 5260 |   // Finally, apply any attributes on the decl itself. | 
 | 5261 |   if (const AttributeList *Attrs = PD.getAttributes()) | 
| Peter Collingbourne | 6070039 | 2011-01-21 02:08:45 +0000 | [diff] [blame] | 5262 |     ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); | 
| Chris Lattner | 0744e5f | 2008-06-29 00:23:49 +0000 | [diff] [blame] | 5263 | } | 
| John McCall | 54abf7d | 2009-11-04 02:18:39 +0000 | [diff] [blame] | 5264 |  | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 5265 | /// Is the given declaration allowed to use a forbidden type? | 
 | 5266 | static bool isForbiddenTypeAllowed(Sema &S, Decl *decl) { | 
 | 5267 |   // Private ivars are always okay.  Unfortunately, people don't | 
 | 5268 |   // always properly make their ivars private, even in system headers. | 
 | 5269 |   // Plus we need to make fields okay, too. | 
| Fariborz Jahanian | a6b3380 | 2011-09-26 21:23:35 +0000 | [diff] [blame] | 5270 |   // Function declarations in sys headers will be marked unavailable. | 
 | 5271 |   if (!isa<FieldDecl>(decl) && !isa<ObjCPropertyDecl>(decl) && | 
 | 5272 |       !isa<FunctionDecl>(decl)) | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 5273 |     return false; | 
 | 5274 |  | 
 | 5275 |   // Require it to be declared in a system header. | 
 | 5276 |   return S.Context.getSourceManager().isInSystemHeader(decl->getLocation()); | 
 | 5277 | } | 
 | 5278 |  | 
 | 5279 | /// Handle a delayed forbidden-type diagnostic. | 
 | 5280 | static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag, | 
 | 5281 |                                        Decl *decl) { | 
 | 5282 |   if (decl && isForbiddenTypeAllowed(S, decl)) { | 
 | 5283 |     decl->addAttr(new (S.Context) UnavailableAttr(diag.Loc, S.Context, | 
 | 5284 |                         "this system declaration uses an unsupported type")); | 
 | 5285 |     return; | 
 | 5286 |   } | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 5287 |   if (S.getLangOpts().ObjCAutoRefCount) | 
| Fariborz Jahanian | 175fb10 | 2011-10-03 22:11:57 +0000 | [diff] [blame] | 5288 |     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(decl)) { | 
| Benjamin Kramer | 48d798c | 2012-06-02 10:20:41 +0000 | [diff] [blame] | 5289 |       // FIXME: we may want to suppress diagnostics for all | 
| Fariborz Jahanian | 175fb10 | 2011-10-03 22:11:57 +0000 | [diff] [blame] | 5290 |       // kind of forbidden type messages on unavailable functions.  | 
 | 5291 |       if (FD->hasAttr<UnavailableAttr>() && | 
 | 5292 |           diag.getForbiddenTypeDiagnostic() ==  | 
 | 5293 |           diag::err_arc_array_param_no_ownership) { | 
 | 5294 |         diag.Triggered = true; | 
 | 5295 |         return; | 
 | 5296 |       } | 
 | 5297 |     } | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 5298 |  | 
 | 5299 |   S.Diag(diag.Loc, diag.getForbiddenTypeDiagnostic()) | 
 | 5300 |     << diag.getForbiddenTypeOperand() << diag.getForbiddenTypeArgument(); | 
 | 5301 |   diag.Triggered = true; | 
 | 5302 | } | 
 | 5303 |  | 
| John McCall | 9257664 | 2012-05-07 06:16:41 +0000 | [diff] [blame] | 5304 | void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) { | 
 | 5305 |   assert(DelayedDiagnostics.getCurrentPool()); | 
| John McCall | 1348967 | 2012-05-07 06:16:58 +0000 | [diff] [blame] | 5306 |   DelayedDiagnosticPool &poppedPool = *DelayedDiagnostics.getCurrentPool(); | 
| John McCall | 9257664 | 2012-05-07 06:16:41 +0000 | [diff] [blame] | 5307 |   DelayedDiagnostics.popWithoutEmitting(state); | 
| John McCall | eee1d54 | 2011-02-14 07:13:47 +0000 | [diff] [blame] | 5308 |  | 
| John McCall | 9257664 | 2012-05-07 06:16:41 +0000 | [diff] [blame] | 5309 |   // When delaying diagnostics to run in the context of a parsed | 
 | 5310 |   // declaration, we only want to actually emit anything if parsing | 
 | 5311 |   // succeeds. | 
 | 5312 |   if (!decl) return; | 
| John McCall | eee1d54 | 2011-02-14 07:13:47 +0000 | [diff] [blame] | 5313 |  | 
| John McCall | 9257664 | 2012-05-07 06:16:41 +0000 | [diff] [blame] | 5314 |   // We emit all the active diagnostics in this pool or any of its | 
 | 5315 |   // parents.  In general, we'll get one pool for the decl spec | 
 | 5316 |   // and a child pool for each declarator; in a decl group like: | 
 | 5317 |   //   deprecated_typedef foo, *bar, baz(); | 
 | 5318 |   // only the declarator pops will be passed decls.  This is correct; | 
 | 5319 |   // we really do need to consider delayed diagnostics from the decl spec | 
 | 5320 |   // for each of the different declarations. | 
| John McCall | 1348967 | 2012-05-07 06:16:58 +0000 | [diff] [blame] | 5321 |   const DelayedDiagnosticPool *pool = &poppedPool; | 
| John McCall | 9257664 | 2012-05-07 06:16:41 +0000 | [diff] [blame] | 5322 |   do { | 
| John McCall | 1348967 | 2012-05-07 06:16:58 +0000 | [diff] [blame] | 5323 |     for (DelayedDiagnosticPool::pool_iterator | 
| John McCall | 9257664 | 2012-05-07 06:16:41 +0000 | [diff] [blame] | 5324 |            i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) { | 
 | 5325 |       // This const_cast is a bit lame.  Really, Triggered should be mutable. | 
 | 5326 |       DelayedDiagnostic &diag = const_cast<DelayedDiagnostic&>(*i); | 
| John McCall | eee1d54 | 2011-02-14 07:13:47 +0000 | [diff] [blame] | 5327 |       if (diag.Triggered) | 
| John McCall | 2f51448 | 2010-01-27 03:50:35 +0000 | [diff] [blame] | 5328 |         continue; | 
 | 5329 |  | 
| John McCall | eee1d54 | 2011-02-14 07:13:47 +0000 | [diff] [blame] | 5330 |       switch (diag.Kind) { | 
| John McCall | 2f51448 | 2010-01-27 03:50:35 +0000 | [diff] [blame] | 5331 |       case DelayedDiagnostic::Deprecation: | 
| John McCall | e8c904f | 2012-01-26 20:04:03 +0000 | [diff] [blame] | 5332 |         // Don't bother giving deprecation diagnostics if the decl is invalid. | 
 | 5333 |         if (!decl->isInvalidDecl()) | 
| John McCall | 9257664 | 2012-05-07 06:16:41 +0000 | [diff] [blame] | 5334 |           HandleDelayedDeprecationCheck(diag, decl); | 
| John McCall | 2f51448 | 2010-01-27 03:50:35 +0000 | [diff] [blame] | 5335 |         break; | 
 | 5336 |  | 
 | 5337 |       case DelayedDiagnostic::Access: | 
| John McCall | 9257664 | 2012-05-07 06:16:41 +0000 | [diff] [blame] | 5338 |         HandleDelayedAccessCheck(diag, decl); | 
| John McCall | 2f51448 | 2010-01-27 03:50:35 +0000 | [diff] [blame] | 5339 |         break; | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 5340 |  | 
 | 5341 |       case DelayedDiagnostic::ForbiddenType: | 
| John McCall | 9257664 | 2012-05-07 06:16:41 +0000 | [diff] [blame] | 5342 |         handleDelayedForbiddenType(*this, diag, decl); | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 5343 |         break; | 
| John McCall | 2f51448 | 2010-01-27 03:50:35 +0000 | [diff] [blame] | 5344 |       } | 
 | 5345 |     } | 
| John McCall | 9257664 | 2012-05-07 06:16:41 +0000 | [diff] [blame] | 5346 |   } while ((pool = pool->getParent())); | 
| John McCall | 54abf7d | 2009-11-04 02:18:39 +0000 | [diff] [blame] | 5347 | } | 
 | 5348 |  | 
| John McCall | 1348967 | 2012-05-07 06:16:58 +0000 | [diff] [blame] | 5349 | /// Given a set of delayed diagnostics, re-emit them as if they had | 
 | 5350 | /// been delayed in the current context instead of in the given pool. | 
 | 5351 | /// Essentially, this just moves them to the current pool. | 
 | 5352 | void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) { | 
 | 5353 |   DelayedDiagnosticPool *curPool = DelayedDiagnostics.getCurrentPool(); | 
 | 5354 |   assert(curPool && "re-emitting in undelayed context not supported"); | 
 | 5355 |   curPool->steal(pool); | 
 | 5356 | } | 
 | 5357 |  | 
| John McCall | 54abf7d | 2009-11-04 02:18:39 +0000 | [diff] [blame] | 5358 | static bool isDeclDeprecated(Decl *D) { | 
 | 5359 |   do { | 
| Douglas Gregor | 0a0d2b1 | 2011-03-23 00:50:03 +0000 | [diff] [blame] | 5360 |     if (D->isDeprecated()) | 
| John McCall | 54abf7d | 2009-11-04 02:18:39 +0000 | [diff] [blame] | 5361 |       return true; | 
| Argyrios Kyrtzidis | c076e37 | 2011-10-06 23:23:27 +0000 | [diff] [blame] | 5362 |     // A category implicitly has the availability of the interface. | 
 | 5363 |     if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D)) | 
 | 5364 |       return CatD->getClassInterface()->isDeprecated(); | 
| John McCall | 54abf7d | 2009-11-04 02:18:39 +0000 | [diff] [blame] | 5365 |   } while ((D = cast_or_null<Decl>(D->getDeclContext()))); | 
 | 5366 |   return false; | 
 | 5367 | } | 
 | 5368 |  | 
| Eli Friedman | c3b2308 | 2012-08-08 21:52:41 +0000 | [diff] [blame] | 5369 | static void | 
 | 5370 | DoEmitDeprecationWarning(Sema &S, const NamedDecl *D, StringRef Message, | 
 | 5371 |                          SourceLocation Loc, | 
| Fariborz Jahanian | fd09088 | 2012-09-21 20:46:37 +0000 | [diff] [blame] | 5372 |                          const ObjCInterfaceDecl *UnknownObjCClass, | 
 | 5373 |                          const ObjCPropertyDecl *ObjCPropery) { | 
| Eli Friedman | c3b2308 | 2012-08-08 21:52:41 +0000 | [diff] [blame] | 5374 |   DeclarationName Name = D->getDeclName(); | 
 | 5375 |   if (!Message.empty()) { | 
 | 5376 |     S.Diag(Loc, diag::warn_deprecated_message) << Name << Message; | 
 | 5377 |     S.Diag(D->getLocation(), | 
 | 5378 |            isa<ObjCMethodDecl>(D) ? diag::note_method_declared_at | 
 | 5379 |                                   : diag::note_previous_decl) << Name; | 
| Fariborz Jahanian | fd09088 | 2012-09-21 20:46:37 +0000 | [diff] [blame] | 5380 |     if (ObjCPropery) | 
 | 5381 |       S.Diag(ObjCPropery->getLocation(), diag::note_property_attribute) | 
 | 5382 |         << ObjCPropery->getDeclName() << 0; | 
| Eli Friedman | c3b2308 | 2012-08-08 21:52:41 +0000 | [diff] [blame] | 5383 |   } else if (!UnknownObjCClass) { | 
 | 5384 |     S.Diag(Loc, diag::warn_deprecated) << D->getDeclName(); | 
 | 5385 |     S.Diag(D->getLocation(), | 
 | 5386 |            isa<ObjCMethodDecl>(D) ? diag::note_method_declared_at | 
 | 5387 |                                   : diag::note_previous_decl) << Name; | 
| Fariborz Jahanian | fd09088 | 2012-09-21 20:46:37 +0000 | [diff] [blame] | 5388 |     if (ObjCPropery) | 
 | 5389 |       S.Diag(ObjCPropery->getLocation(), diag::note_property_attribute) | 
 | 5390 |         << ObjCPropery->getDeclName() << 0; | 
| Eli Friedman | c3b2308 | 2012-08-08 21:52:41 +0000 | [diff] [blame] | 5391 |   } else { | 
 | 5392 |     S.Diag(Loc, diag::warn_deprecated_fwdclass_message) << Name; | 
 | 5393 |     S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); | 
 | 5394 |   } | 
 | 5395 | } | 
 | 5396 |  | 
| John McCall | 9c3087b | 2010-08-26 02:13:20 +0000 | [diff] [blame] | 5397 | void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, | 
| John McCall | 2f51448 | 2010-01-27 03:50:35 +0000 | [diff] [blame] | 5398 |                                          Decl *Ctx) { | 
 | 5399 |   if (isDeclDeprecated(Ctx)) | 
| John McCall | 54abf7d | 2009-11-04 02:18:39 +0000 | [diff] [blame] | 5400 |     return; | 
 | 5401 |  | 
| John McCall | 2f51448 | 2010-01-27 03:50:35 +0000 | [diff] [blame] | 5402 |   DD.Triggered = true; | 
| Eli Friedman | c3b2308 | 2012-08-08 21:52:41 +0000 | [diff] [blame] | 5403 |   DoEmitDeprecationWarning(*this, DD.getDeprecationDecl(), | 
 | 5404 |                            DD.getDeprecationMessage(), DD.Loc, | 
| Fariborz Jahanian | fd09088 | 2012-09-21 20:46:37 +0000 | [diff] [blame] | 5405 |                            DD.getUnknownObjCClass(), | 
 | 5406 |                            DD.getObjCProperty()); | 
| John McCall | 54abf7d | 2009-11-04 02:18:39 +0000 | [diff] [blame] | 5407 | } | 
 | 5408 |  | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 5409 | void Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message, | 
| Fariborz Jahanian | 8e5fc9b | 2010-12-21 00:44:01 +0000 | [diff] [blame] | 5410 |                                   SourceLocation Loc, | 
| Fariborz Jahanian | fd09088 | 2012-09-21 20:46:37 +0000 | [diff] [blame] | 5411 |                                   const ObjCInterfaceDecl *UnknownObjCClass, | 
 | 5412 |                                   const ObjCPropertyDecl  *ObjCProperty) { | 
| John McCall | 54abf7d | 2009-11-04 02:18:39 +0000 | [diff] [blame] | 5413 |   // Delay if we're currently parsing a declaration. | 
| John McCall | eee1d54 | 2011-02-14 07:13:47 +0000 | [diff] [blame] | 5414 |   if (DelayedDiagnostics.shouldDelayDiagnostics()) { | 
| Fariborz Jahanian | b0a6615 | 2012-03-02 21:50:02 +0000 | [diff] [blame] | 5415 |     DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D,  | 
 | 5416 |                                                               UnknownObjCClass, | 
| Fariborz Jahanian | fd09088 | 2012-09-21 20:46:37 +0000 | [diff] [blame] | 5417 |                                                               ObjCProperty, | 
| Fariborz Jahanian | b0a6615 | 2012-03-02 21:50:02 +0000 | [diff] [blame] | 5418 |                                                               Message)); | 
| John McCall | 54abf7d | 2009-11-04 02:18:39 +0000 | [diff] [blame] | 5419 |     return; | 
 | 5420 |   } | 
 | 5421 |  | 
 | 5422 |   // Otherwise, don't warn if our current context is deprecated. | 
| Argyrios Kyrtzidis | 3a38744 | 2011-10-06 23:23:20 +0000 | [diff] [blame] | 5423 |   if (isDeclDeprecated(cast<Decl>(getCurLexicalContext()))) | 
| John McCall | 54abf7d | 2009-11-04 02:18:39 +0000 | [diff] [blame] | 5424 |     return; | 
| Fariborz Jahanian | fd09088 | 2012-09-21 20:46:37 +0000 | [diff] [blame] | 5425 |   DoEmitDeprecationWarning(*this, D, Message, Loc, UnknownObjCClass, ObjCProperty); | 
| John McCall | 54abf7d | 2009-11-04 02:18:39 +0000 | [diff] [blame] | 5426 | } |