]> granicus.if.org Git - clang/commitdiff
Consumed analysis: track function parameters.
authorDeLesley Hutchins <delesley@google.com>
Thu, 29 Aug 2013 22:36:05 +0000 (22:36 +0000)
committerDeLesley Hutchins <delesley@google.com>
Thu, 29 Aug 2013 22:36:05 +0000 (22:36 +0000)
Patch by chris.wailes@gmail.com.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189616 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/Consumed.cpp
test/SemaCXX/warn-consumed-analysis-strict.cpp
test/SemaCXX/warn-consumed-analysis.cpp

index e5231e07c284e81d7ba0329a6df5ef2466400eb1..09676a8c23f02c02d04f763b0f80be72e2bf7ef4 100644 (file)
@@ -44,8 +44,6 @@
 //       (Deferred)
 // TODO: Test nested conditionals: A) Checking the same value multiple times,
 //       and 2) Checking different values. (Deferred)
-// TODO: Test IsFalseVisitor with values in the unknown state. (Deferred)
-// TODO: Look into combining IsFalseVisitor and TestedVarsVisitor. (Deferred)
 
 using namespace clang;
 using namespace consumed;
@@ -266,11 +264,13 @@ public:
   void VisitDeclStmt(const DeclStmt *DelcS);
   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Temp);
   void VisitMemberExpr(const MemberExpr *MExpr);
+  void VisitParmVarDecl(const ParmVarDecl *Param);
   void VisitUnaryOperator(const UnaryOperator *UOp);
   void VisitVarDecl(const VarDecl *Var);
 
-  ConsumedStmtVisitor(AnalysisDeclContext &AC, ConsumedAnalyzer &Analyzer)
-      : AC(AC), Analyzer(Analyzer), StateMap(NULL) {}
+  ConsumedStmtVisitor(AnalysisDeclContext &AC, ConsumedAnalyzer &Analyzer,
+                      ConsumedStateMap *StateMap)
+      : AC(AC), Analyzer(Analyzer), StateMap(StateMap) {}
   
   PropagationInfo getInfo(const Stmt *StmtNode) const {
     ConstInfoEntry Entry = PropagationMap.find(StmtNode);
@@ -664,6 +664,12 @@ void ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) {
   forwardInfo(MExpr->getBase(), MExpr);
 }
 
+
+void ConsumedStmtVisitor::VisitParmVarDecl(const ParmVarDecl *Param) {
+  if (Analyzer.isConsumableType(Param->getType()))
+    StateMap->setState(Param, consumed::CS_Unknown);
+}
+
 void ConsumedStmtVisitor::VisitUnaryOperator(const UnaryOperator *UOp) {
   InfoEntry Entry = PropagationMap.find(UOp->getSubExpr()->IgnoreParens());
   if (Entry == PropagationMap.end()) return;
@@ -685,11 +691,16 @@ void ConsumedStmtVisitor::VisitUnaryOperator(const UnaryOperator *UOp) {
 
 void ConsumedStmtVisitor::VisitVarDecl(const VarDecl *Var) {
   if (Analyzer.isConsumableType(Var->getType())) {
-    PropagationInfo PInfo =
-      PropagationMap.find(Var->getInit())->second;
-    
-    StateMap->setState(Var, PInfo.isVar() ?
-      StateMap->getState(PInfo.getVar()) : PInfo.getState());
+    if (Var->hasInit()) {
+      PropagationInfo PInfo =
+        PropagationMap.find(Var->getInit())->second;
+      
+      StateMap->setState(Var, PInfo.isVar() ?
+        StateMap->getState(PInfo.getVar()) : PInfo.getState());
+      
+    } else {
+      StateMap->setState(Var, consumed::CS_Unknown);
+    }
   }
 }
 }} // end clang::consumed::ConsumedStmtVisitor
@@ -1022,7 +1033,13 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {
   PostOrderCFGView *SortedGraph = AC.getAnalysis<PostOrderCFGView>();
   
   CurrStates = new ConsumedStateMap();
-  ConsumedStmtVisitor Visitor(AC, *this);
+  ConsumedStmtVisitor Visitor(AC, *this, CurrStates);
+  
+  // Add all trackable parameters to the state map.
+  for (FunctionDecl::param_const_iterator PI = D->param_begin(),
+       PE = D->param_end(); PI != PE; ++PI) {
+    Visitor.VisitParmVarDecl(*PI);
+  }
   
   // Visit all of the function's basic blocks.
   for (PostOrderCFGView::iterator I = SortedGraph->begin(),
index c3b254d781d6a0f56241f53dcb511ead360361f8..b8a2982fc5b89116740fb170633711b442a95c66 100644 (file)
@@ -192,6 +192,10 @@ void testNoWarnTestFromMacroExpansion() {
   }
 }
 
+void testFunctionParam(ConsumableClass<int> param) {
+  *param; // expected-warning {{invocation of method 'operator*' on object 'param' while it is in an unknown state}}
+}
+
 void testSimpleForLoop() {
   ConsumableClass<int> var;
   
index c6646559465f02350d9bda18e65addcd6c3c63f5..adaab647e1569da401a8096b5fe8386f50b0de06 100644 (file)
@@ -224,6 +224,18 @@ void testStateChangeInBranch() {
   *var;
 }
 
+void testFunctionParam(ConsumableClass<int> param) {
+  
+  if (param.isValid()) {
+    *param;
+  } else {
+    *param; // expected-warning {{invocation of method 'operator*' on object 'param' while it is in the 'consumed' state}}
+  }
+  
+  param = nullptr;
+  *param; // expected-warning {{invocation of method 'operator*' on object 'param' while it is in the 'consumed' state}}
+}
+
 void testCallingConventions() {
   ConsumableClass<int> var(42);