Browse Source

[analyzer] Memoize complexity of SymExpr

Summary:
This patch introduces a new member to SymExpr, which stores the symbol complexity, avoiding recalculating it every time computeComplexity() is called.

Also, increase the complexity of conjured Symbols by one, so it's clear that it has a greater complexity than its underlying symbols.

Reviewers: NoQ, george.karpenkov

Reviewed By: NoQ, george.karpenkov

Subscribers: xazax.hun, szepet, a.sidorin

Differential Revision: https://reviews.llvm.org/D49232

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337472 91177308-0d34-0410-b5e6-96231b3b80d8
Mikhail R. Gadelha 7 years ago
parent
commit
6efe165706

+ 7 - 1
include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h

@@ -49,6 +49,8 @@ protected:
     return !T.isNull() && !T->isVoidType();
   }
 
+  mutable unsigned Complexity = 0;
+
 public:
   virtual ~SymExpr() = default;
 
@@ -85,7 +87,7 @@ public:
   symbol_iterator symbol_begin() const { return symbol_iterator(this); }
   static symbol_iterator symbol_end() { return symbol_iterator(); }
 
-  unsigned computeComplexity() const;
+  virtual unsigned computeComplexity() const = 0;
 
   /// Find the region from which this symbol originates.
   ///
@@ -127,6 +129,10 @@ public:
 
   SymbolID getSymbolID() const { return Sym; }
 
+  unsigned computeComplexity() const override {
+    return 1;
+  };
+
   // Implement isa<T> support.
   static inline bool classof(const SymExpr *SE) {
     Kind k = SE->getKind();

+ 24 - 0
include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h

@@ -270,6 +270,12 @@ public:
     // Otherwise, 'To' should also be a valid type.
   }
 
+  unsigned computeComplexity() const override {
+    if (Complexity == 0)
+      Complexity = 1 + Operand->computeComplexity();
+    return Complexity;
+  }
+
   QualType getType() const override { return ToTy; }
 
   const SymExpr *getOperand() const { return Operand; }
@@ -337,6 +343,12 @@ public:
   const SymExpr *getLHS() const { return LHS; }
   const llvm::APSInt &getRHS() const { return RHS; }
 
+  unsigned computeComplexity() const override {
+    if (Complexity == 0)
+      Complexity = 1 + LHS->computeComplexity();
+    return Complexity;
+  }
+
   static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
                       BinaryOperator::Opcode op, const llvm::APSInt& rhs,
                       QualType t) {
@@ -374,6 +386,12 @@ public:
   const SymExpr *getRHS() const { return RHS; }
   const llvm::APSInt &getLHS() const { return LHS; }
 
+  unsigned computeComplexity() const override {
+    if (Complexity == 0)
+      Complexity = 1 + RHS->computeComplexity();
+    return Complexity;
+  }
+
   static void Profile(llvm::FoldingSetNodeID& ID, const llvm::APSInt& lhs,
                       BinaryOperator::Opcode op, const SymExpr *rhs,
                       QualType t) {
@@ -412,6 +430,12 @@ public:
 
   void dumpToStream(raw_ostream &os) const override;
 
+  unsigned computeComplexity() const override {
+    if (Complexity == 0)
+      Complexity = RHS->computeComplexity() + LHS->computeComplexity();
+    return Complexity;
+  }
+
   static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
                     BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) {
     ID.AddInteger((unsigned) SymSymExprKind);

+ 1 - 1
lib/StaticAnalyzer/Core/AnalyzerOptions.cpp

@@ -390,7 +390,7 @@ unsigned AnalyzerOptions::getGraphTrimInterval() {
 
 unsigned AnalyzerOptions::getMaxSymbolComplexity() {
   if (!MaxSymbolComplexity.hasValue())
-    MaxSymbolComplexity = getOptionAsInteger("max-symbol-complexity", 25);
+    MaxSymbolComplexity = getOptionAsInteger("max-symbol-complexity", 35);
   return MaxSymbolComplexity.getValue();
 }
 

+ 0 - 7
lib/StaticAnalyzer/Core/SymbolManager.cpp

@@ -159,13 +159,6 @@ void SymExpr::symbol_iterator::expand() {
   llvm_unreachable("unhandled expansion case");
 }
 
-unsigned SymExpr::computeComplexity() const {
-  unsigned R = 0;
-  for (symbol_iterator I = symbol_begin(), E = symbol_end(); I != E; ++I)
-    R++;
-  return R;
-}
-
 const SymbolRegionValue*
 SymbolManager::getRegionValueSymbol(const TypedValueRegion* R) {
   llvm::FoldingSetNodeID profile;