Left: | ||
Right: |
LEFT | RIGHT |
---|---|
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 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
264 const RecordType *getRecordType(QualType QT) { | 264 const RecordType *getRecordType(QualType QT) { |
265 const RecordType *RT = QT->getAs<RecordType>(); | 265 const RecordType *RT = QT->getAs<RecordType>(); |
266 // now check if we point to record type | 266 // now check if we point to record type |
267 if(!RT && QT->isPointerType()){ | 267 if(!RT && QT->isPointerType()){ |
268 QualType PT = QT->getAs<PointerType>()->getPointeeType(); | 268 QualType PT = QT->getAs<PointerType>()->getPointeeType(); |
269 RT = PT->getAs<RecordType>(); | 269 RT = PT->getAs<RecordType>(); |
270 } | 270 } |
271 return RT; | 271 return RT; |
272 } | 272 } |
273 | 273 |
274 /// \brief Thread Safety Analysis: Checks that the passed in RecordType | |
275 /// resolves to a lockable object. | |
chandlerc
2011/08/23 18:10:04
Join with the previous line.
supertri
2011/08/23 18:26:04
Done.
| |
276 /// May flag an error. | |
277 bool checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr, | |
278 const RecordType *RT) { | |
279 // Flag error if could not get record type for this argument. | |
chandlerc
2011/08/23 18:10:04
no 2 spaces after '//'
supertri
2011/08/23 18:26:04
Done.
| |
280 if(!RT) { | |
281 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_class) | |
282 << Attr.getName(); | |
283 return false; | |
284 } | |
285 // Flag error if the type is not lockable. | |
286 if(!RT->getDecl()->getAttr<LockableAttr>()) { | |
287 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_lockable) | |
288 << Attr.getName(); | |
289 return false; | |
290 } | |
291 return true; | |
292 } | |
293 | |
274 /// \brief Thread Safety Analysis: Checks that all attribute arguments, starting | 294 /// \brief Thread Safety Analysis: Checks that all attribute arguments, starting |
275 /// from Sidx, resolve to a lockable object. May flag an error. | 295 /// from Sidx, resolve to a lockable object. May flag an error. |
276 static bool checkAttrArgsAreLockableObjs(Sema &S, Decl *D, | 296 static bool checkAttrArgsAreLockableObjs(Sema &S, Decl *D, |
277 const AttributeList &Attr, | 297 const AttributeList &Attr, |
278 SmallVectorImpl<Expr*> &outArgs, | 298 SmallVectorImpl<Expr*> &Args, |
279 int Sidx = 0, | 299 int Sidx = 0, |
chandlerc
2011/08/23 18:10:04
Sidx? Huh?
supertri
2011/08/23 18:26:04
Done.
| |
280 bool ParamIdxOk = false) { | 300 bool ParamIdxOk = false) { |
281 for(unsigned int Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) { | 301 for(unsigned int Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) { |
chandlerc
2011/08/23 18:10:04
s/unsigned int/unsigned/
supertri
2011/08/23 18:26:04
Done.
| |
282 Expr *ArgExp = Attr.getArg(Idx); | 302 Expr *ArgExp = Attr.getArg(Idx); |
303 | |
283 if (ArgExp->isTypeDependent()) | 304 if (ArgExp->isTypeDependent()) |
284 continue; | 305 continue; |
285 | 306 |
286 QualType Arg_QT = ArgExp->getType(); | 307 QualType Arg_QT = ArgExp->getType(); |
chandlerc
2011/08/23 18:10:04
Arg_QT -> ArgTy
supertri
2011/08/23 18:26:04
Done.
| |
287 | 308 |
288 // Get record type. | 309 // Get record type. |
chandlerc
2011/08/23 18:10:04
This doesn't seem to to add information reall...
supertri
2011/08/23 18:26:04
Done.
| |
289 // first see if we can just cast to record type, or point to record type | 310 // First see if we can just cast to record type, or point to record type. |
290 const RecordType *RT = getRecordType(Arg_QT); | 311 const RecordType *RT = getRecordType(Arg_QT); |
291 | 312 |
292 // now check if we idx into a record type function param | 313 // Now check if we idx into a record type function param. |
chandlerc
2011/08/23 18:10:04
s/idx/index/
supertri
2011/08/23 18:26:04
Done.
| |
293 if (!RT && ParamIdxOk) { | 314 if(!RT && ParamIdxOk) { |
294 FunctionDecl *FD = dyn_cast <FunctionDecl>(D); | 315 FunctionDecl *FD = dyn_cast<FunctionDecl>(D); |
295 IntegerLiteral *IL = dyn_cast<IntegerLiteral>(ArgExp); | 316 IntegerLiteral *IL = dyn_cast<IntegerLiteral>(ArgExp); |
296 if(FD && IL) { | 317 if(FD && IL) { |
297 unsigned int NumParams = FD->getNumParams(); | 318 unsigned int NumParams = FD->getNumParams(); |
298 llvm::APInt ArgValue = IL->getValue(); | 319 llvm::APInt ArgValue = IL->getValue(); |
299 uint64_t ParamIdx_from1 = ArgValue.getZExtValue(); | 320 uint64_t ParamIdx_from1 = ArgValue.getZExtValue(); |
chandlerc
2011/08/23 18:10:04
ParamIdxFromOne?
supertri
2011/08/23 18:26:04
Done.
| |
300 uint64_t ParamIdx_from0 = ParamIdx_from1 - 1; | 321 uint64_t ParamIdx_from0 = ParamIdx_from1 - 1; |
chandlerc
2011/08/23 18:10:04
ParamIdxFromZero?
supertri
2011/08/23 18:26:04
Done.
| |
301 if(!ArgValue.isStrictlyPositive() || ParamIdx_from1 > NumParams) { | 322 if(!ArgValue.isStrictlyPositive() || ParamIdx_from1 > NumParams) { |
302 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_range) | 323 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_range) |
303 << Attr.getName() << Idx + 1 << NumParams; | 324 << Attr.getName() << Idx + 1 << NumParams; |
304 return false; | 325 return false; |
305 } | 326 } |
306 Arg_QT = FD->getParamDecl(ParamIdx_from0)->getType(); | 327 Arg_QT = FD->getParamDecl(ParamIdx_from0)->getType(); |
307 RT = getRecordType(Arg_QT); | 328 RT = getRecordType(Arg_QT); |
308 } | 329 } |
309 } | 330 } |
310 | 331 |
311 // Flag error if could not get record type for this argument | 332 if (!checkForLockableRecord(S, D, Attr, RT)) |
312 if (!RT) { | |
313 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_class) | |
314 << Attr.getName(); | |
315 return false; | 333 return false; |
316 } | 334 |
317 | 335 Args.push_back(ArgExp); |
318 // Flag error if the type is not lockable | |
319 if (!RT->getDecl()->getAttr<LockableAttr>()) { | |
320 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_lockable) | |
321 << Attr.getName(); | |
322 return false; | |
323 } | |
324 | |
325 outArgs.push_back(ArgExp); | |
326 } | 336 } |
327 return true; | 337 return true; |
328 } | 338 } |
329 | 339 |
330 //===----------------------------------------------------------------------===// | 340 //===----------------------------------------------------------------------===// |
331 // Attribute Implementations | 341 // Attribute Implementations |
332 //===----------------------------------------------------------------------===// | 342 //===----------------------------------------------------------------------===// |
333 | 343 |
334 // FIXME: All this manual attribute parsing code is gross. At the | 344 // FIXME: All this manual attribute parsing code is gross. At the |
335 // least add some helper functions to check most argument patterns (# | 345 // least add some helper functions to check most argument patterns (# |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
370 // D must be either a member field or global (potentially shared) variable. | 380 // D must be either a member field or global (potentially shared) variable. |
371 if (!mayBeSharedVariable(D)) { | 381 if (!mayBeSharedVariable(D)) { |
372 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 382 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) |
373 << Attr.getName() << ExpectedFieldOrGlobalVar; | 383 << Attr.getName() << ExpectedFieldOrGlobalVar; |
374 return; | 384 return; |
375 } | 385 } |
376 | 386 |
377 if (pointer && !checkIsPointer(S, D, Attr)) | 387 if (pointer && !checkIsPointer(S, D, Attr)) |
378 return; | 388 return; |
379 | 389 |
380 // check that all arguments are lockable objects | 390 if (Arg->isTypeDependent()) |
381 SmallVector<Expr*, 1> ArgVector; | 391 return; |
382 if (!checkAttrArgsAreLockableObjs(S, D, Attr, ArgVector)) | 392 |
393 // check that the argument is lockable object | |
394 if (!checkForLockableRecord(S, D, Attr, getRecordType(Arg->getType()))) | |
383 return; | 395 return; |
384 | 396 |
385 if (pointer) | 397 if (pointer) |
386 D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getLoc(), | 398 D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getLoc(), |
387 S.Context, Arg)); | 399 S.Context, Arg)); |
388 else | 400 else |
389 D->addAttr(::new (S.Context) GuardedByAttr(Attr.getLoc(), S.Context, Arg)); | 401 D->addAttr(::new (S.Context) GuardedByAttr(Attr.getLoc(), S.Context, Arg)); |
390 } | 402 } |
391 | 403 |
392 | 404 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
456 // check that all arguments are lockable objects | 468 // check that all arguments are lockable objects |
457 if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args)) | 469 if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args)) |
458 return; | 470 return; |
459 | 471 |
460 unsigned Size = Args.size(); | 472 unsigned Size = Args.size(); |
461 assert(Size == Attr.getNumArgs()); | 473 assert(Size == Attr.getNumArgs()); |
462 Expr **StartArg = Size == 0 ? 0 : &Args[0]; | 474 Expr **StartArg = Size == 0 ? 0 : &Args[0]; |
463 | 475 |
464 if (before) | 476 if (before) |
465 D->addAttr(::new (S.Context) AcquiredBeforeAttr(Attr.getLoc(), S.Context, | 477 D->addAttr(::new (S.Context) AcquiredBeforeAttr(Attr.getLoc(), S.Context, |
466 StartArg, Size)); | 478 StartArg, Size)); |
467 else | 479 else |
468 D->addAttr(::new (S.Context) AcquiredAfterAttr(Attr.getLoc(), S.Context, | 480 D->addAttr(::new (S.Context) AcquiredAfterAttr(Attr.getLoc(), S.Context, |
469 StartArg, Size)); | 481 StartArg, Size)); |
470 } | 482 } |
471 | 483 |
472 static void handleLockFunAttr(Sema &S, Decl *D, const AttributeList &Attr, | 484 static void handleLockFunAttr(Sema &S, Decl *D, const AttributeList &Attr, |
473 bool exclusive = false) { | 485 bool exclusive = false) { |
474 assert(!Attr.isInvalid()); | 486 assert(!Attr.isInvalid()); |
475 | 487 |
476 // zero or more arguments ok | 488 // zero or more arguments ok |
477 | 489 |
478 // check that the attribute is applied to a function | 490 // check that the attribute is applied to a function |
479 if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { | 491 if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
605 if (!checkAttributeNumArgs(S, Attr, 1)) | 617 if (!checkAttributeNumArgs(S, Attr, 1)) |
606 return; | 618 return; |
607 Expr *Arg = Attr.getArg(0); | 619 Expr *Arg = Attr.getArg(0); |
608 | 620 |
609 if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { | 621 if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { |
610 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) | 622 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) |
611 << Attr.getName() << ExpectedFunctionOrMethod; | 623 << Attr.getName() << ExpectedFunctionOrMethod; |
612 return; | 624 return; |
613 } | 625 } |
614 | 626 |
615 // check that all arguments are lockable objects | 627 if (Arg->isTypeDependent()) |
616 SmallVector<Expr*, 1> Args; | 628 return; |
617 if (!checkAttrArgsAreLockableObjs(S, D, Attr, Args)) | 629 |
630 // check that the argument is lockable object | |
631 if (!checkForLockableRecord(S, D, Attr, getRecordType(Arg->getType()))) | |
618 return; | 632 return; |
619 | 633 |
620 D->addAttr(::new (S.Context) LockReturnedAttr(Attr.getLoc(), S.Context, Arg)); | 634 D->addAttr(::new (S.Context) LockReturnedAttr(Attr.getLoc(), S.Context, Arg)); |
621 } | 635 } |
622 | 636 |
623 static void handleLocksExcludedAttr(Sema &S, Decl *D, | 637 static void handleLocksExcludedAttr(Sema &S, Decl *D, |
624 const AttributeList &Attr) { | 638 const AttributeList &Attr) { |
625 assert(!Attr.isInvalid()); | 639 assert(!Attr.isInvalid()); |
626 | 640 |
627 if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) | 641 if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) |
(...skipping 3220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3848 << Message; | 3862 << Message; |
3849 else { | 3863 else { |
3850 if (!UnknownObjCClass) | 3864 if (!UnknownObjCClass) |
3851 Diag(Loc, diag::warn_deprecated) << D->getDeclName(); | 3865 Diag(Loc, diag::warn_deprecated) << D->getDeclName(); |
3852 else { | 3866 else { |
3853 Diag(Loc, diag::warn_deprecated_fwdclass_message) << D->getDeclName(); | 3867 Diag(Loc, diag::warn_deprecated_fwdclass_message) << D->getDeclName(); |
3854 Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); | 3868 Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); |
3855 } | 3869 } |
3856 } | 3870 } |
3857 } | 3871 } |
LEFT | RIGHT |