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/Analysis/Consumed.cpp b/lib/Analysis/Consumed.cpp
index 09676a8..59ebbb2 100644
--- a/lib/Analysis/Consumed.cpp
+++ b/lib/Analysis/Consumed.cpp
@@ -65,6 +65,13 @@
llvm_unreachable("invalid enum");
}
+static bool isConsumableType(const QualType &QT) {
+ if (const CXXRecordDecl *RD = QT->getAsCXXRecordDecl())
+ return RD->hasAttr<ConsumableAttr>();
+ else
+ return false;
+}
+
static bool isKnownState(ConsumedState State) {
switch (State) {
case CS_Unconsumed:
@@ -475,7 +482,7 @@
ASTContext &CurrContext = AC.getASTContext();
QualType ThisType = Constructor->getThisType(CurrContext)->getPointeeType();
- if (Analyzer.isConsumableType(ThisType)) {
+ if (isConsumableType(ThisType)) {
if (Constructor->hasAttr<ConsumesAttr>() ||
Constructor->isDefaultConstructor()) {
@@ -666,7 +673,7 @@
void ConsumedStmtVisitor::VisitParmVarDecl(const ParmVarDecl *Param) {
- if (Analyzer.isConsumableType(Param->getType()))
+ if (isConsumableType(Param->getType()))
StateMap->setState(Param, consumed::CS_Unknown);
}
@@ -690,7 +697,7 @@
}
void ConsumedStmtVisitor::VisitVarDecl(const VarDecl *Var) {
- if (Analyzer.isConsumableType(Var->getType())) {
+ if (isConsumableType(Var->getType())) {
if (Var->hasInit()) {
PropagationInfo PInfo =
PropagationMap.find(Var->getInit())->second;
@@ -891,44 +898,6 @@
Map.erase(Var);
}
-bool ConsumedAnalyzer::isConsumableType(QualType Type) {
- const CXXRecordDecl *RD =
- dyn_cast_or_null<CXXRecordDecl>(Type->getAsCXXRecordDecl());
-
- if (!RD) return false;
-
- std::pair<CacheMapType::iterator, bool> Entry =
- ConsumableTypeCache.insert(std::make_pair(RD, false));
-
- if (Entry.second)
- Entry.first->second = hasConsumableAttributes(RD);
-
- return Entry.first->second;
-}
-
-// TODO: Walk the base classes to see if any of them are unique types.
-// (Deferred)
-bool ConsumedAnalyzer::hasConsumableAttributes(const CXXRecordDecl *RD) {
- for (CXXRecordDecl::method_iterator MI = RD->method_begin(),
- ME = RD->method_end(); MI != ME; ++MI) {
-
- for (Decl::attr_iterator AI = (*MI)->attr_begin(), AE = (*MI)->attr_end();
- AI != AE; ++AI) {
-
- switch ((*AI)->getKind()) {
- case attr::CallableWhenUnconsumed:
- case attr::TestsUnconsumed:
- return true;
-
- default:
- break;
- }
- }
- }
-
- return false;
-}
-
bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
const ConsumedStmtVisitor &Visitor) {