diff options
| author | DeLesley Hutchins <delesley@google.com> | 2013-08-30 22:56:34 +0000 |
|---|---|---|
| committer | DeLesley Hutchins <delesley@google.com> | 2013-08-30 22:56:34 +0000 |
| commit | 5a715c4f00acdb54787244be3b857ad716e5d18f (patch) | |
| tree | a742b3ca0c2ff84f66a2e4a78b57cab2c3b342cb /clang/lib/Sema | |
| parent | 8470b0f96c0f87aa886a810e400f8204b3bb7bed (diff) | |
| download | bcm5719-llvm-5a715c4f00acdb54787244be3b857ad716e5d18f.tar.gz bcm5719-llvm-5a715c4f00acdb54787244be3b857ad716e5d18f.zip | |
Consumed analysis: add 'consumable' class attribute.
Patch by chris.wailes@gmail.com
Adds the 'consumable' attribute that can be attached to classes. This replaces
the previous method of scanning a class's methods to see if any of them have
consumed analysis attributes attached to them. If consumed analysis attributes
are attached to methods of a class that isn't marked 'consumable' a warning
is generated.
llvm-svn: 189702
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 75 |
1 files changed, 60 insertions, 15 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 2bf56c737a2..b9e4ef06330 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -969,19 +969,52 @@ static void handleLocksExcludedAttr(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } -static void handleConsumesAttr(Sema &S, Decl *D, - const AttributeList &Attr) { +static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkAttributeNumArgs(S, Attr, 0)) return; - if (!(isa<CXXMethodDecl>(D) || isa<CXXConstructorDecl>(D))) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << ExpectedMethod; + if (!isa<CXXRecordDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << + Attr.getName() << ExpectedClass; return; } D->addAttr(::new (S.Context) + ConsumableAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); +} + +static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, + const AttributeList &Attr) { + ASTContext &CurrContext = S.getASTContext(); + QualType ThisType = MD->getThisType(CurrContext)->getPointeeType(); + + if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) { + if (!RD->hasAttr<ConsumableAttr>()) { + S.Diag(Attr.getLoc(), diag::warn_attr_on_unconsumable_class) << + RD->getNameAsString(); + + return false; + } + } + + return true; +} + +static void handleConsumesAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!checkAttributeNumArgs(S, Attr, 0)) return; + + if (!isa<CXXMethodDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << + Attr.getName() << ExpectedMethod; + return; + } + + if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) + return; + + D->addAttr(::new (S.Context) ConsumesAttr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); + Attr.getAttributeSpellingListIndex())); } static void handleCallableWhenUnconsumedAttr(Sema &S, Decl *D, @@ -989,14 +1022,17 @@ static void handleCallableWhenUnconsumedAttr(Sema &S, Decl *D, if (!checkAttributeNumArgs(S, Attr, 0)) return; if (!isa<CXXMethodDecl>(D)) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << ExpectedMethod; + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << + Attr.getName() << ExpectedMethod; return; } + if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) + return; + D->addAttr(::new (S.Context) CallableWhenUnconsumedAttr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); + Attr.getAttributeSpellingListIndex())); } static void handleTestsConsumedAttr(Sema &S, Decl *D, @@ -1004,14 +1040,17 @@ static void handleTestsConsumedAttr(Sema &S, Decl *D, if (!checkAttributeNumArgs(S, Attr, 0)) return; if (!isa<CXXMethodDecl>(D)) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << ExpectedMethod; + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << + Attr.getName() << ExpectedMethod; return; } + if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) + return; + D->addAttr(::new (S.Context) TestsConsumedAttr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); + Attr.getAttributeSpellingListIndex())); } static void handleTestsUnconsumedAttr(Sema &S, Decl *D, @@ -1019,14 +1058,17 @@ static void handleTestsUnconsumedAttr(Sema &S, Decl *D, if (!checkAttributeNumArgs(S, Attr, 0)) return; if (!isa<CXXMethodDecl>(D)) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << ExpectedMethod; + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << + Attr.getName() << ExpectedMethod; return; } + if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) + return; + D->addAttr(::new (S.Context) TestsUnconsumedAttr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); + Attr.getAttributeSpellingListIndex())); } static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D, @@ -4995,6 +5037,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, break; // Uniqueness analysis attributes. + case AttributeList::AT_Consumable: + handleConsumableAttr(S, D, Attr); + break; case AttributeList::AT_Consumes: handleConsumesAttr(S, D, Attr); break; |

