OLD | NEW |
1 //===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===// | 1 //===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file implements decl-related attribute processing. | 10 // This file implements decl-related attribute processing. |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 if (!RT) | 187 if (!RT) |
188 return false; | 188 return false; |
189 | 189 |
190 const RecordDecl *RD = RT->getDecl(); | 190 const RecordDecl *RD = RT->getDecl(); |
191 if (RD->getTagKind() != TTK_Struct) | 191 if (RD->getTagKind() != TTK_Struct) |
192 return false; | 192 return false; |
193 | 193 |
194 return RD->getIdentifier() == &Ctx.Idents.get("__CFString"); | 194 return RD->getIdentifier() == &Ctx.Idents.get("__CFString"); |
195 } | 195 } |
196 | 196 |
| 197 /// |
| 198 /// \brief Check if passed in num matches num args; output an error if not |
| 199 /// Note that this function may produce an error message. |
| 200 /// \return true if the argument matches the num args; false otherwise |
| 201 /// |
197 static bool checkNumArgs(Sema &S, const AttributeList &Attr, unsigned int num) { | 202 static bool checkNumArgs(Sema &S, const AttributeList &Attr, unsigned int num) { |
198 if (Attr.getNumArgs() != num) { | 203 if (Attr.getNumArgs() != num) { |
199 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << num; | 204 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << num; |
200 return false; | 205 return false; |
201 } | 206 } |
202 | 207 |
203 return true; | 208 return true; |
204 } | 209 } |
205 | 210 |
| 211 /// |
| 212 /// \brief Check if passed in Decl is a field or potentially shared global var |
| 213 /// \return true if the Decl is a field or potentially shared global variable |
| 214 /// |
| 215 static bool mayBeSharedVariable(Decl *D) { |
| 216 if (isa<FieldDecl>(D)) |
| 217 return true; |
| 218 if(VarDecl *vd = dyn_cast<VarDecl>(D)) |
| 219 return (vd->hasGlobalStorage() && !(vd->isThreadSpecified())); |
| 220 |
| 221 return false; |
| 222 } |
| 223 |
| 224 /// |
| 225 /// \brief Check if passed in Decl is a pointer type. |
| 226 /// Note that this function may produce an error message. |
| 227 /// \return true if the Decl is a pointer type; false otherwise |
| 228 /// |
| 229 bool checkIsPointer(Sema & S, Decl * D, const AttributeList & Attr) { |
| 230 if(ValueDecl * vd = dyn_cast <ValueDecl>(D)) { |
| 231 QualType QT = vd->getType(); |
| 232 if(QT->isAnyPointerType()){ |
| 233 return true; |
| 234 } |
| 235 S.Diag(Attr.getLoc(), diag::warn_pointer_attribute_wrong_type) |
| 236 << Attr.getName()->getName() << QT; |
| 237 } else { |
| 238 S.Diag(Attr.getLoc(), diag::err_attribute_can_be_applied_only_to_value_decl) |
| 239 << Attr.getName(); |
| 240 } |
| 241 return false; |
| 242 } |
| 243 |
206 //===----------------------------------------------------------------------===// | 244 //===----------------------------------------------------------------------===// |
207 // Attribute Implementations | 245 // Attribute Implementations |
208 //===----------------------------------------------------------------------===// | 246 //===----------------------------------------------------------------------===// |
209 | 247 |
210 // FIXME: All this manual attribute parsing code is gross. At the | 248 // FIXME: All this manual attribute parsing code is gross. At the |
211 // least add some helper functions to check most argument patterns (# | 249 // least add some helper functions to check most argument patterns (# |
212 // and types of args). | 250 // and types of args). |
213 | 251 |
| 252 static void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr, |
| 253 bool pointer = false) { |
| 254 assert(!Attr.isInvalid()); |
| 255 |
| 256 if (!checkNumArgs(S, Attr, 0)) |
| 257 return; |
| 258 |
| 259 // D must be either a member field or global (potentially shared) variable. |
| 260 if (!mayBeSharedVariable(D)) { |
| 261 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) |
| 262 << Attr.getName() << 15; /*fields and global vars*/; |
| 263 return; |
| 264 } |
| 265 |
| 266 if (pointer && !checkIsPointer(S, D, Attr)) |
| 267 return; |
| 268 |
| 269 if (pointer) |
| 270 D->addAttr(::new (S.Context) PtGuardedVarAttr(Attr.getLoc(), S.Context)); |
| 271 else |
| 272 D->addAttr(::new (S.Context) GuardedVarAttr(Attr.getLoc(), S.Context)); |
| 273 } |
| 274 |
| 275 static void handleLockableAttr(Sema &S, Decl *D, const AttributeList &Attr, |
| 276 bool scoped = false) { |
| 277 assert(!Attr.isInvalid()); |
| 278 |
| 279 if (!checkNumArgs(S, Attr, 0)) |
| 280 return; |
| 281 |
| 282 if (!isa<CXXRecordDecl>(D)) { |
| 283 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) |
| 284 << Attr.getName() << ExpectedClass; |
| 285 return; |
| 286 } |
| 287 |
| 288 if (scoped) |
| 289 D->addAttr(::new (S.Context) ScopedLockableAttr(Attr.getLoc(), S.Context)); |
| 290 else |
| 291 D->addAttr(::new (S.Context) LockableAttr(Attr.getLoc(), S.Context)); |
| 292 } |
| 293 |
| 294 static void handleNoThreadSafetyAttr(Sema &S, Decl *D, |
| 295 const AttributeList &Attr) { |
| 296 assert(!Attr.isInvalid()); |
| 297 |
| 298 if (!checkNumArgs(S, Attr, 0)) |
| 299 return; |
| 300 |
| 301 if (!isFunction(D)) { |
| 302 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) |
| 303 << Attr.getName() << ExpectedFunctionOrMethod; |
| 304 return; |
| 305 } |
| 306 |
| 307 D->addAttr(::new (S.Context) NoThreadSafetyAnalysisAttr(Attr.getLoc(), |
| 308 S.Context)); |
| 309 } |
214 static void handleExtVectorTypeAttr(Scope *scope, Decl *D, | 310 static void handleExtVectorTypeAttr(Scope *scope, Decl *D, |
215 const AttributeList &Attr, Sema &S) { | 311 const AttributeList &Attr, Sema &S) { |
216 TypedefNameDecl *tDecl = dyn_cast<TypedefNameDecl>(D); | 312 TypedefNameDecl *tDecl = dyn_cast<TypedefNameDecl>(D); |
217 if (tDecl == 0) { | 313 if (tDecl == 0) { |
218 S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); | 314 S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); |
219 return; | 315 return; |
220 } | 316 } |
221 | 317 |
222 QualType curType = tDecl->getUnderlyingType(); | 318 QualType curType = tDecl->getUnderlyingType(); |
223 | 319 |
(...skipping 2795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3019 case AttributeList::AT_pascal: | 3115 case AttributeList::AT_pascal: |
3020 case AttributeList::AT_pcs: | 3116 case AttributeList::AT_pcs: |
3021 handleCallConvAttr(S, D, Attr); | 3117 handleCallConvAttr(S, D, Attr); |
3022 break; | 3118 break; |
3023 case AttributeList::AT_opencl_kernel_function: | 3119 case AttributeList::AT_opencl_kernel_function: |
3024 handleOpenCLKernelAttr(S, D, Attr); | 3120 handleOpenCLKernelAttr(S, D, Attr); |
3025 break; | 3121 break; |
3026 case AttributeList::AT_uuid: | 3122 case AttributeList::AT_uuid: |
3027 handleUuidAttr(S, D, Attr); | 3123 handleUuidAttr(S, D, Attr); |
3028 break; | 3124 break; |
| 3125 |
| 3126 // Thread safety attributes: |
| 3127 case AttributeList::AT_guarded_var: |
| 3128 handleGuardedVarAttr(S, D, Attr); |
| 3129 break; |
| 3130 case AttributeList::AT_pt_guarded_var: |
| 3131 handleGuardedVarAttr(S, D, Attr, /*pointer = */true); |
| 3132 break; |
| 3133 case AttributeList::AT_scoped_lockable: |
| 3134 handleLockableAttr(S, D, Attr, /*scoped = */true); |
| 3135 break; |
| 3136 case AttributeList::AT_no_thread_safety_analysis: |
| 3137 handleNoThreadSafetyAttr(S, D, Attr); |
| 3138 break; |
| 3139 case AttributeList::AT_lockable: |
| 3140 handleLockableAttr(S, D, Attr); |
| 3141 break; |
| 3142 |
3029 default: | 3143 default: |
3030 // Ask target about the attribute. | 3144 // Ask target about the attribute. |
3031 const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema(); | 3145 const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema(); |
3032 if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S)) | 3146 if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S)) |
3033 S.Diag(Attr.getLoc(), diag::warn_unknown_attribute_ignored) | 3147 S.Diag(Attr.getLoc(), diag::warn_unknown_attribute_ignored) |
3034 << Attr.getName(); | 3148 << Attr.getName(); |
3035 break; | 3149 break; |
3036 } | 3150 } |
3037 } | 3151 } |
3038 | 3152 |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3308 << Message; | 3422 << Message; |
3309 else { | 3423 else { |
3310 if (!UnknownObjCClass) | 3424 if (!UnknownObjCClass) |
3311 Diag(Loc, diag::warn_deprecated) << D->getDeclName(); | 3425 Diag(Loc, diag::warn_deprecated) << D->getDeclName(); |
3312 else { | 3426 else { |
3313 Diag(Loc, diag::warn_deprecated_fwdclass_message) << D->getDeclName(); | 3427 Diag(Loc, diag::warn_deprecated_fwdclass_message) << D->getDeclName(); |
3314 Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); | 3428 Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); |
3315 } | 3429 } |
3316 } | 3430 } |
3317 } | 3431 } |
OLD | NEW |