summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorDeLesley Hutchins <delesley@google.com>2013-08-30 22:56:34 +0000
committerDeLesley Hutchins <delesley@google.com>2013-08-30 22:56:34 +0000
commit5a715c4f00acdb54787244be3b857ad716e5d18f (patch)
treea742b3ca0c2ff84f66a2e4a78b57cab2c3b342cb /clang/lib/Sema
parent8470b0f96c0f87aa886a810e400f8204b3bb7bed (diff)
downloadbcm5719-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.cpp75
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;
OpenPOWER on IntegriCloud