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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189702 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 2bf56c7..b9e4ef0 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -969,19 +969,52 @@
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 @@
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 @@
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 @@
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 @@
break;
// Uniqueness analysis attributes.
+ case AttributeList::AT_Consumable:
+ handleConsumableAttr(S, D, Attr);
+ break;
case AttributeList::AT_Consumes:
handleConsumesAttr(S, D, Attr);
break;