]> granicus.if.org Git - clang/commitdiff
[analyzer] Proper caching in CallDescription objects.
authorGabor Horvath <xazax.hun@gmail.com>
Wed, 15 Feb 2017 15:35:56 +0000 (15:35 +0000)
committerGabor Horvath <xazax.hun@gmail.com>
Wed, 15 Feb 2017 15:35:56 +0000 (15:35 +0000)
During the review of D29567 it turned out the caching in CallDescription is not implemented properly. In case an identifier does not exist in a translation unit, repeated identifier lookups will be done which might have bad impact on the performance. This patch guarantees that the lookup is only executed once. Moreover this patch fixes a corner case when the identifier of CallDescription does not exist in the translation unit and the called function does not have an identifier (e.g.: overloaded operator in C++).

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

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

include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
lib/StaticAnalyzer/Core/CallEvent.cpp

index 89610ef5c17d47428f64bd79d00a67516ef47262..aaecf38f333fb9f3af660bc3d92e4bbb6a21579f 100644 (file)
@@ -55,6 +55,7 @@ class CallEventManager;
 class CallDescription {
   friend CallEvent;
   mutable IdentifierInfo *II;
+  mutable bool IsLookupDone;
   StringRef FuncName;
   unsigned RequiredArgs;
 
@@ -68,7 +69,8 @@ public:
   /// call. Omit this parameter to match every occurance of call with a given
   /// name regardless the number of arguments.
   CallDescription(StringRef FuncName, unsigned RequiredArgs = NoArgRequirement)
-      : II(nullptr), FuncName(FuncName), RequiredArgs(RequiredArgs) {}
+      : II(nullptr), IsLookupDone(false), FuncName(FuncName),
+        RequiredArgs(RequiredArgs) {}
 
   /// \brief Get the name of the function that this object matches.
   StringRef getFunctionName() const { return FuncName; }
index af610395a87cad25647a013c41fbcf4090457d5a..ef824b8a3b11c4cb753faf155261fc526a79a105 100644 (file)
@@ -212,9 +212,12 @@ ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit,
 
 bool CallEvent::isCalled(const CallDescription &CD) const {
   assert(getKind() != CE_ObjCMessage && "Obj-C methods are not supported");
-  if (!CD.II)
+  if (!CD.IsLookupDone) {
+    CD.IsLookupDone = true;
     CD.II = &getState()->getStateManager().getContext().Idents.get(CD.FuncName);
-  if (getCalleeIdentifier() != CD.II)
+  }
+  const IdentifierInfo *II = getCalleeIdentifier();
+  if (!II || II != CD.II)
     return false;
   return (CD.RequiredArgs == CallDescription::NoArgRequirement ||
           CD.RequiredArgs == getNumArgs());