baloghadamsoftware updated this revision to Diff 266296.
baloghadamsoftware added a comment.
Herald added subscribers: llvm-commits, MaskRay, hiraditya, arichardson, 
nemanjai, emaste.
Herald added a reviewer: espindola.
Herald added a reviewer: MaskRay.
Herald added a project: LLVM.

Updated according to the comments.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80522/new/

https://reviews.llvm.org/D80522

Files:
  clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
  clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
  clang/lib/StaticAnalyzer/Core/CallEvent.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
  clang/lib/StaticAnalyzer/Core/MemRegion.cpp
  clang/lib/StaticAnalyzer/Core/Store.cpp
  clang/test/Analysis/explain-svals.c
  clang/test/Analysis/explain-svals.cpp
  clang/test/Analysis/explain-svals.m
  clang/unittests/StaticAnalyzer/CMakeLists.txt
  clang/unittests/StaticAnalyzer/ParamRegionTest.cpp
  compiler-rt/lib/fuzzer/afl/afl_driver.cpp
  lld/ELF/InputFiles.cpp
  lld/test/ELF/invalid/verneed-shared.test
  lld/test/ELF/invalid/verneed-shared.yaml
  lldb/include/lldb/Utility/Args.h
  lldb/test/API/python_api/hello_world/TestHelloWorld.py
  lldb/test/API/python_api/sbdata/TestSBData.py
  llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h
  llvm/include/llvm/CodeGen/ResourcePriorityQueue.h
  llvm/include/llvm/Support/YAMLTraits.h
  llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp
  llvm/lib/CodeGen/SelectionDAG/ResourcePriorityQueue.cpp
  llvm/lib/Support/YAMLTraits.cpp
  llvm/test/CodeGen/PowerPC/pr45709.ll
  llvm/unittests/Support/YAMLIOTest.cpp
  llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Core/BUILD.gn

Index: llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Core/BUILD.gn
===================================================================
--- llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Core/BUILD.gn
+++ llvm/utils/gn/secondary/clang/lib/StaticAnalyzer/Core/BUILD.gn
@@ -55,6 +55,7 @@
     "SimpleConstraintManager.cpp",
     "SimpleSValBuilder.cpp",
     "Store.cpp",
+    "SubEngine.cpp",
     "SymbolManager.cpp",
     "TextDiagnostics.cpp",
     "WorkList.cpp",
Index: llvm/unittests/Support/YAMLIOTest.cpp
===================================================================
--- llvm/unittests/Support/YAMLIOTest.cpp
+++ llvm/unittests/Support/YAMLIOTest.cpp
@@ -333,6 +333,7 @@
   uint16_t        u16;
   uint8_t         u8;
   bool            b;
+  char            c;
   int64_t         s64;
   int32_t         s32;
   int16_t         s16;
@@ -357,6 +358,7 @@
       io.mapRequired("u16",      bt.u16);
       io.mapRequired("u8",       bt.u8);
       io.mapRequired("b",        bt.b);
+      io.mapRequired("c",        bt.c);
       io.mapRequired("s64",      bt.s64);
       io.mapRequired("s32",      bt.s32);
       io.mapRequired("s16",      bt.s16);
@@ -386,6 +388,7 @@
             "u16:      65000\n"
             "u8:       255\n"
             "b:        false\n"
+            "c:        'c'\n"
             "s64:      -5000000000\n"
             "s32:      -2000000000\n"
             "s16:      -32000\n"
@@ -396,7 +399,7 @@
             "h16:      0x8765\n"
             "h32:      0xFEDCBA98\n"
             "h64:      0xFEDCBA9876543210\n"
-           "...\n");
+            "...\n");
   yin >> map;
 
   EXPECT_FALSE(yin.error());
@@ -407,6 +410,7 @@
   EXPECT_EQ(map.u16, 65000);
   EXPECT_EQ(map.u8,  255);
   EXPECT_EQ(map.b,   false);
+  EXPECT_EQ(map.c,   'c');
   EXPECT_EQ(map.s64, -5000000000LL);
   EXPECT_EQ(map.s32, -2000000000L);
   EXPECT_EQ(map.s16, -32000);
@@ -434,6 +438,7 @@
     map.u16 = 50000;
     map.u8  = 254;
     map.b   = true;
+    map.c   = 'd';
     map.s64 = -6000000000LL;
     map.s32 = -2000000000;
     map.s16 = -32000;
@@ -463,6 +468,7 @@
     EXPECT_EQ(map.u16,      50000);
     EXPECT_EQ(map.u8,       254);
     EXPECT_EQ(map.b,        true);
+    EXPECT_EQ(map.c,        'd');
     EXPECT_EQ(map.s64,      -6000000000LL);
     EXPECT_EQ(map.s32,      -2000000000L);
     EXPECT_EQ(map.s16,      -32000);
Index: llvm/test/CodeGen/PowerPC/pr45709.ll
===================================================================
--- llvm/test/CodeGen/PowerPC/pr45709.ll
+++ llvm/test/CodeGen/PowerPC/pr45709.ll
@@ -10,37 +10,30 @@
 define dso_local void @_ZN1a1bEv(<4 x float> %in) local_unnamed_addr #0 align 2 {
 ; CHECK-LABEL: _ZN1a1bEv:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    bc 12, 4*cr5+lt, .LBB0_6
-; CHECK-NEXT:    b .LBB0_1
-; CHECK-NEXT:  .LBB0_1: # %.preheader
-; CHECK-NEXT:    b .LBB0_2
-; CHECK-NEXT:  .LBB0_2:
-; CHECK-NEXT:    b .LBB0_3
-; CHECK-NEXT:  .LBB0_3:
+; CHECK-NEXT:    bclr 12, 4*cr5+lt, 0
+; CHECK-NEXT:  # %bb.1: # %.preheader
 ; CHECK-NEXT:    addis r3, r2, .LCPI0_0@toc@ha
-; CHECK-NEXT:    addi r3, r3, .LCPI0_0@toc@l
-; CHECK-NEXT:    lvx v3, 0, r3
-; CHECK-NEXT:    vperm v2, v2, v2, v3
 ; CHECK-NEXT:    vxor v3, v3, v3
+; CHECK-NEXT:    addi r3, r3, .LCPI0_0@toc@l
+; CHECK-NEXT:    lvx v4, 0, r3
 ; CHECK-NEXT:    addi r3, r1, -48
 ; CHECK-NEXT:    stvx v3, 0, r3
 ; CHECK-NEXT:    addi r3, r1, -32
+; CHECK-NEXT:    vperm v2, v2, v2, v4
 ; CHECK-NEXT:    stvx v2, 0, r3
 ; CHECK-NEXT:    lwz r3, -48(r1)
 ; CHECK-NEXT:    lwz r4, -32(r1)
 ; CHECK-NEXT:    cmpw r4, r3
-; CHECK-NEXT:    bc 12, gt, .LBB0_4
-; CHECK-NEXT:    b .LBB0_5
-; CHECK-NEXT:  .LBB0_4:
+; CHECK-NEXT:    bc 12, gt, .LBB0_2
+; CHECK-NEXT:    b .LBB0_3
+; CHECK-NEXT:  .LBB0_2: # %.preheader
 ; CHECK-NEXT:    addi r3, r4, 0
-; CHECK-NEXT:  .LBB0_5:
-; CHECK-NEXT:    cmpw r3, r3
+; CHECK-NEXT:  .LBB0_3: # %.preheader
 ; CHECK-NEXT:    stw r3, -64(r1)
 ; CHECK-NEXT:    addi r3, r1, -64
 ; CHECK-NEXT:    lvx v2, 0, r3
 ; CHECK-NEXT:    addi r3, r1, -16
 ; CHECK-NEXT:    stvx v2, 0, r3
-; CHECK-NEXT:  .LBB0_6:
 ; CHECK-NEXT:    blr
   br i1 undef, label %7, label %1
 
@@ -62,4 +55,4 @@
 
 declare <4 x float> @llvm.maxnum.v4f32(<4 x float>, <4 x float>) #0
 
-attributes #0 = { nounwind optnone noinline }
+attributes #0 = { nounwind }
Index: llvm/lib/Support/YAMLTraits.cpp
===================================================================
--- llvm/lib/Support/YAMLTraits.cpp
+++ llvm/lib/Support/YAMLTraits.cpp
@@ -864,6 +864,17 @@
   return "invalid boolean";
 }
 
+void ScalarTraits<char>::output(const char &Val, void *, raw_ostream &Out) {
+  Out << Val;
+}
+
+StringRef ScalarTraits<char>::input(StringRef Scalar, void *, char &Val) {
+  if (Scalar.size() != 1)
+    return "invalid character";
+  Val = Scalar[0];
+  return StringRef();
+}
+
 void ScalarTraits<StringRef>::output(const StringRef &Val, void *,
                                      raw_ostream &Out) {
   Out << Val;
Index: llvm/lib/CodeGen/SelectionDAG/ResourcePriorityQueue.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/ResourcePriorityQueue.cpp
+++ llvm/lib/CodeGen/SelectionDAG/ResourcePriorityQueue.cpp
@@ -19,13 +19,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/ResourcePriorityQueue.h"
-#include "llvm/CodeGen/DFAPacketizer.h"
 #include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/SelectionDAGISel.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
-#include "llvm/CodeGen/TargetInstrInfo.h"
 #include "llvm/CodeGen/TargetLowering.h"
-#include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
Index: llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp
===================================================================
--- llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp
+++ llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp
@@ -24,7 +24,6 @@
 
 #include "llvm/Analysis/ObjCARCAliasAnalysis.h"
 #include "llvm/Analysis/ObjCARCAnalysisUtils.h"
-#include "llvm/Analysis/Passes.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Value.h"
Index: llvm/include/llvm/Support/YAMLTraits.h
===================================================================
--- llvm/include/llvm/Support/YAMLTraits.h
+++ llvm/include/llvm/Support/YAMLTraits.h
@@ -1159,6 +1159,12 @@
   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
 };
 
+template <> struct ScalarTraits<char> {
+  static void output(const char &, void *, raw_ostream &);
+  static StringRef input(StringRef, void *, char &);
+  static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
+};
+
 template<>
 struct ScalarTraits<StringRef> {
   static void output(const StringRef &, void *, raw_ostream &);
Index: llvm/include/llvm/CodeGen/ResourcePriorityQueue.h
===================================================================
--- llvm/include/llvm/CodeGen/ResourcePriorityQueue.h
+++ llvm/include/llvm/CodeGen/ResourcePriorityQueue.h
@@ -16,15 +16,15 @@
 #ifndef LLVM_CODEGEN_RESOURCEPRIORITYQUEUE_H
 #define LLVM_CODEGEN_RESOURCEPRIORITYQUEUE_H
 
+#include "llvm/CodeGen/DFAPacketizer.h"
 #include "llvm/CodeGen/ScheduleDAG.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+#include "llvm/MC/MCInstrItineraries.h"
 
 namespace llvm {
-  class DFAPacketizer;
-  class InstrItineraryData;
   class ResourcePriorityQueue;
-  class SelectionDAGISel;
-  class TargetInstrInfo;
-  class TargetRegisterInfo;
 
   /// Sorting functions for the Available queue.
   struct resource_sort {
Index: llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h
===================================================================
--- llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h
+++ llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h
@@ -23,13 +23,17 @@
 #define LLVM_LIB_ANALYSIS_OBJCARCANALYSISUTILS_H
 
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/ObjCARCInstKind.h"
+#include "llvm/Analysis/Passes.h"
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/InstIterator.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/ValueHandle.h"
+#include "llvm/Pass.h"
 
 namespace llvm {
 namespace objcarc {
Index: lldb/test/API/python_api/sbdata/TestSBData.py
===================================================================
--- lldb/test/API/python_api/sbdata/TestSBData.py
+++ lldb/test/API/python_api/sbdata/TestSBData.py
@@ -21,7 +21,6 @@
         self.line = line_number('main.cpp', '// set breakpoint here')
 
     @add_test_categories(['pyapi'])
-    @skipIfReproducer # SBData::SetData is not instrumented.
     def test_byte_order_and_address_byte_size(self):
         """Test the SBData::SetData() to ensure the byte order and address
         byte size are obeyed"""
@@ -42,7 +41,6 @@
         self.assertTrue(addr == 0x8877665544332211);
 
     @add_test_categories(['pyapi'])
-    @skipIfReproducer # SBData::SetData is not instrumented.
     def test_with_run_command(self):
         """Test the SBData APIs."""
         self.build()
Index: lldb/test/API/python_api/hello_world/TestHelloWorld.py
===================================================================
--- lldb/test/API/python_api/hello_world/TestHelloWorld.py
+++ lldb/test/API/python_api/hello_world/TestHelloWorld.py
@@ -75,7 +75,6 @@
     @add_test_categories(['pyapi'])
     @skipIfiOSSimulator
     @expectedFailureNetBSD
-    @skipIfReproducer # File synchronization is not supported during replay.
     def test_with_attach_to_process_with_id_api(self):
         """Create target, spawn a process, and attach to it with process id."""
         exe = '%s_%d'%(self.testMethodName, os.getpid())
Index: lldb/include/lldb/Utility/Args.h
===================================================================
--- lldb/include/lldb/Utility/Args.h
+++ lldb/include/lldb/Utility/Args.h
@@ -391,7 +391,7 @@
       return lldb_private::Args::ArgEntry(value, quote);
     }
     StringRef value;
-    uint8_t quote;
+    char quote;
   };
   static void mapping(IO &io, lldb_private::Args::ArgEntry &v);
 };
Index: lld/test/ELF/invalid/verneed-shared.yaml
===================================================================
--- lld/test/ELF/invalid/verneed-shared.yaml
+++ lld/test/ELF/invalid/verneed-shared.yaml
@@ -6,7 +6,7 @@
 ## sh_offset(SHT_GNU_verneed) is out of bounds.
 # RUN: yaml2obj --docnum=1 %s -o %t1.so
 # RUN: not ld.lld %t.o %t1.so -o /dev/null 2>&1 | FileCheck --check-prefix=SHOFFSET %s
-# SHOFFSET: error: {{.*}}.so: section [index 1] has a sh_offset (0xffffffff) + sh_size (0x0) that is greater than the file size (0x168)
+# SHOFFSET: error: {{.*}}.so: section [index 1] has a sh_offset (0xffffffff) + sh_size (0x0) that is greater than the file size (0x228)
 --- !ELF
 FileHeader:
   Class:   ELFCLASS64
@@ -17,14 +17,12 @@
   - Name:  .gnu.version_r
     Type:  SHT_GNU_verneed
     Flags: [ SHF_ALLOC ]
-    Info:  1
     ShOffset: 0xFFFFFFFF
 
-## A Verneed entry is misaligned (not a multiple of 4). This may happen
-## some interface shared objects. We use memcpy to read the fields, so
-## misalignment isn't a problem and there is no need to diagnose.
+## A Verneed entry is misaligned (not a multiple of 4).
 # RUN: yaml2obj --docnum=2 %s -o %t2.so
-# RUN: ld.lld %t.o %t2.so -o /dev/null
+# RUN: not ld.lld %t.o %t2.so -o /dev/null 2>&1 | FileCheck --check-prefix=VN-MISALIGNED %s
+# VN-MISALIGNED: {{.*}}.so has an invalid Verneed
 --- !ELF
 FileHeader:
   Class:   ELFCLASS64
Index: lld/ELF/InputFiles.cpp
===================================================================
--- lld/ELF/InputFiles.cpp
+++ lld/ELF/InputFiles.cpp
@@ -1224,12 +1224,14 @@
   ArrayRef<uint8_t> data = CHECK(obj.getSectionContents(sec), this);
   const uint8_t *verneedBuf = data.begin();
   for (unsigned i = 0; i != sec->sh_info; ++i) {
-    if (verneedBuf + sizeof(typename ELFT::Verneed) > data.end())
+    if (verneedBuf + sizeof(typename ELFT::Verneed) > data.end() ||
+        uintptr_t(verneedBuf) % sizeof(uint32_t) != 0)
       fatal(toString(this) + " has an invalid Verneed");
     auto *vn = reinterpret_cast<const typename ELFT::Verneed *>(verneedBuf);
     const uint8_t *vernauxBuf = verneedBuf + vn->vn_aux;
     for (unsigned j = 0; j != vn->vn_cnt; ++j) {
-      if (vernauxBuf + sizeof(typename ELFT::Vernaux) > data.end())
+      if (vernauxBuf + sizeof(typename ELFT::Vernaux) > data.end() ||
+          uintptr_t(vernauxBuf) % sizeof(uint32_t) != 0)
         fatal(toString(this) + " has an invalid Vernaux");
       auto *aux = reinterpret_cast<const typename ELFT::Vernaux *>(vernauxBuf);
       if (aux->vna_name >= this->stringTable.size())
Index: compiler-rt/lib/fuzzer/afl/afl_driver.cpp
===================================================================
--- compiler-rt/lib/fuzzer/afl/afl_driver.cpp
+++ compiler-rt/lib/fuzzer/afl/afl_driver.cpp
@@ -111,7 +111,7 @@
 
 // Use this optionally defined function to output sanitizer messages even if
 // user asks to close stderr.
-extern "C" __attribute__((weak)) void __sanitizer_set_report_fd(void *);
+__attribute__((weak)) extern "C" void __sanitizer_set_report_fd(void *);
 
 // Keep track of where stderr content is being written to, so that
 // dup_and_close_stderr can use the correct one.
Index: clang/unittests/StaticAnalyzer/ParamRegionTest.cpp
===================================================================
--- /dev/null
+++ clang/unittests/StaticAnalyzer/ParamRegionTest.cpp
@@ -0,0 +1,109 @@
+//===- unittests/StaticAnalyzer/ParamRegionTest.cpp -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Reusables.h"
+
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ento {
+namespace {
+
+class ParamRegionTestConsumer : public ExprEngineConsumer {
+  void performTest(const Decl *D) {
+    StoreManager &StMgr = Eng.getStoreManager();
+    MemRegionManager &MRMgr = StMgr.getRegionManager();
+    const StackFrameContext *SFC =
+        Eng.getAnalysisDeclContextManager().getStackFrame(D);
+
+    if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+      for (const auto *P : FD->parameters()) {
+        const TypedValueRegion *Reg = MRMgr.getVarRegion(P, SFC);
+        if (SFC->inTopFrame())
+          assert(isa<NonParamVarRegion>(Reg));
+        else
+          assert(isa<ParamVarRegion>(Reg));
+      }
+    } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
+      for (const auto *P : CD->parameters()) {
+        const TypedValueRegion *Reg = MRMgr.getVarRegion(P, SFC);
+        if (SFC->inTopFrame())
+          assert(isa<NonParamVarRegion>(Reg));
+        else
+          assert(isa<ParamVarRegion>(Reg));
+      }
+    } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
+      for (const auto *P : MD->parameters()) {
+        const TypedValueRegion *Reg = MRMgr.getVarRegion(P, SFC);
+        if (SFC->inTopFrame())
+          assert(isa<NonParamVarRegion>(Reg));
+        else
+          assert(isa<ParamVarRegion>(Reg));
+      }
+    }
+  }
+
+public:
+  ParamRegionTestConsumer(CompilerInstance &C) : ExprEngineConsumer(C) {}
+
+  bool HandleTopLevelDecl(DeclGroupRef DG) override {
+    for (const auto *D : DG) {
+      performTest(D);
+    }
+    return true;
+  }
+};
+
+class ParamRegionTestAction : public ASTFrontendAction {
+public:
+  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
+                                                 StringRef File) override {
+    return std::make_unique<ParamRegionTestConsumer>(Compiler);
+  }
+};
+
+TEST(ParamRegion, ParamRegionTest) {
+  EXPECT_TRUE(
+      tooling::runToolOnCode(std::make_unique<ParamRegionTestAction>(),
+                             R"(void foo(int n) {
+                                 auto lambda = [n](int m) {
+                                   return n + m;
+                                 };
+
+                                 int k = lambda(2);
+                               }
+
+                               void bar(int l) {
+                                 foo(l);
+                               }
+
+                               struct S {
+                                 int n;
+                                 S(int nn): n(nn) {}
+                               };
+
+                               void baz(int p) {
+                                 S s(p);
+                               })"));
+  EXPECT_TRUE(
+      tooling::runToolOnCode(std::make_unique<ParamRegionTestAction>(),
+                             R"(@interface O
+                               + alloc;
+                               - initWithInt:(int)q;
+                               @end
+
+                               void qix(int r) {
+                                 O *o = [[O alloc] initWithInt:r];
+                               })",
+                             "input.m"));
+}
+
+} // namespace
+} // namespace ento
+} // namespace clang
Index: clang/unittests/StaticAnalyzer/CMakeLists.txt
===================================================================
--- clang/unittests/StaticAnalyzer/CMakeLists.txt
+++ clang/unittests/StaticAnalyzer/CMakeLists.txt
@@ -8,6 +8,7 @@
   CallDescriptionTest.cpp
   CallEventTest.cpp
   StoreTest.cpp
+  ParamRegionTest.cpp
   RegisterCustomCheckersTest.cpp
   SymbolReaperTest.cpp
   RangeSetTest.cpp
Index: clang/test/Analysis/explain-svals.m
===================================================================
--- clang/test/Analysis/explain-svals.m
+++ clang/test/Analysis/explain-svals.m
@@ -28,3 +28,44 @@
   };
   clang_analyzer_explain(&x); // expected-warning-re{{{{^pointer to block variable 'x'$}}}}
 }
+
+@interface O
++ (instancetype)top_level_class_method:(int)param;
++ (instancetype)non_top_level_class_method:(int)param;
+- top_level_instance_method:(int)param;
+- non_top_level_instance_method:(int)param;
+@end
+
+@implementation O
++ (instancetype)top_level_class_method:(int)param {
+  clang_analyzer_explain(&param); // expected-warning-re{{{{^pointer to parameter 'param'$}}}}
+}
+
++ (instancetype)non_top_level_class_method:(int)param {
+  clang_analyzer_explain(&param); // expected-warning-re{{{{^pointer to parameter 'param'$}}}}
+}
+
+- top_level_instance_method:(int)param {
+  clang_analyzer_explain(&param); // expected-warning-re{{{{^pointer to parameter 'param'$}}}}
+}
+
+- non_top_level_instance_method:(int)param {
+  clang_analyzer_explain(&param); // expected-warning-re{{{{^pointer to parameter 'param'$}}}}
+}
+@end
+
+void test_3(int n, int m) {
+  O *o = [O non_top_level_class_method:n];
+  [o non_top_level_instance_method:m];
+
+  void (^block_top_level)(int) = ^(int param) {
+    clang_analyzer_explain(&param); // expected-warning-re{{{{^pointer to parameter 'param'$}}}}
+    clang_analyzer_explain(&n);     // expected-warning-re{{{{^pointer to parameter 'n'$}}}}
+  };
+  void (^block_non_top_level)(int) = ^(int param) {
+    clang_analyzer_explain(&param); // expected-warning-re{{{{^pointer to parameter 'param'$}}}}
+    clang_analyzer_explain(&n);     // expected-warning-re{{{{^pointer to parameter 'n'$}}}}
+  };
+
+  block_non_top_level(n);
+}
Index: clang/test/Analysis/explain-svals.cpp
===================================================================
--- clang/test/Analysis/explain-svals.cpp
+++ clang/test/Analysis/explain-svals.cpp
@@ -19,6 +19,7 @@
 
 void clang_analyzer_explain(int);
 void clang_analyzer_explain(void *);
+void clang_analyzer_explain(const int *);
 void clang_analyzer_explain(S);
 
 size_t clang_analyzer_getExtent(void *);
@@ -100,3 +101,30 @@
   clang_analyzer_explain(conjure_S()); // expected-warning-re{{{{^lazily frozen compound value of temporary object constructed at statement 'conjure_S\(\)'$}}}}
   clang_analyzer_explain(conjure_S().z); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at statement 'conjure_S\(\)'\) for field 'z' of temporary object constructed at statement 'conjure_S\(\)'$}}}}
 }
+
+class C_top_level {
+public:
+  C_top_level(int param) {
+    clang_analyzer_explain(&param); // expected-warning-re{{{{^pointer to parameter 'param'$}}}}
+  }
+};
+
+class C_non_top_level {
+public:
+  C_non_top_level(int param) {
+    clang_analyzer_explain(&param); // expected-warning-re{{{{^pointer to parameter 'param'$}}}}
+  }
+};
+
+void test_7(int n) {
+  C_non_top_level c(n);
+
+  auto lambda_top_level = [n](int param) {
+    clang_analyzer_explain(&param); // expected-warning-re{{{{^pointer to parameter 'param'$}}}}
+  };
+  auto lambda_non_top_level = [n](int param) {
+    clang_analyzer_explain(&param); // expected-warning-re{{{{^pointer to parameter 'param'$}}}}
+  };
+
+  lambda_non_top_level(n);
+}
Index: clang/test/Analysis/explain-svals.c
===================================================================
--- clang/test/Analysis/explain-svals.c
+++ clang/test/Analysis/explain-svals.c
@@ -27,3 +27,15 @@
   clang_analyzer_explain_voidp(&s); // expected-warning-re{{{{^pointer to parameter 's'$}}}}
   clang_analyzer_explain_int(s.z);  // expected-warning-re{{{{^initial value of field 'z' of parameter 's'$}}}}
 }
+
+void test_3(int param) {
+  clang_analyzer_explain_voidp(&param); // expected-warning-re{{{{^pointer to parameter 'param'$}}}}
+}
+
+void test_non_top_level(int param) {
+  clang_analyzer_explain_voidp(&param); // expected-warning-re{{{{^pointer to parameter 'param'$}}}}
+}
+
+void test_4(int n) {
+  test_non_top_level(n);
+}
Index: clang/lib/StaticAnalyzer/Core/Store.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/Store.cpp
+++ clang/lib/StaticAnalyzer/Core/Store.cpp
@@ -134,7 +134,8 @@
     case MemRegion::FieldRegionKind:
     case MemRegion::ObjCIvarRegionKind:
     case MemRegion::ObjCStringRegionKind:
-    case MemRegion::VarRegionKind:
+    case MemRegion::NonParamVarRegionKind:
+    case MemRegion::ParamVarRegionKind:
     case MemRegion::CXXTempObjectRegionKind:
     case MemRegion::CXXBaseObjectRegionKind:
     case MemRegion::CXXDerivedObjectRegionKind:
Index: clang/lib/StaticAnalyzer/Core/MemRegion.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -160,11 +160,9 @@
 }
 
 ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg)
-    : DeclRegion(ivd, sReg, ObjCIvarRegionKind) {}
+    : DeclRegion(sReg, ObjCIvarRegionKind), IVD(ivd) {}
 
-const ObjCIvarDecl *ObjCIvarRegion::getDecl() const {
-  return cast<ObjCIvarDecl>(D);
-}
+const ObjCIvarDecl *ObjCIvarRegion::getDecl() const { return IVD; }
 
 QualType ObjCIvarRegion::getValueType() const {
   return getDecl()->getType();
@@ -178,6 +176,33 @@
   return QualType(getDecl()->getTypeForDecl(), 0);
 }
 
+QualType ParamVarRegion::getValueType() const {
+  assert(getDecl() &&
+         "`ParamVarRegion` support functions without `Decl` not implemented"
+         " yet.");
+  return getDecl()->getType();
+}
+
+const ParmVarDecl *ParamVarRegion::getDecl() const {
+  const Decl *D = getStackFrame()->getDecl();
+
+  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+    assert(Index < FD->param_size());
+    return FD->parameters()[Index];
+  } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
+    assert(Index < BD->param_size());
+    return BD->parameters()[Index];
+  } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
+    assert(Index < MD->param_size());
+    return MD->parameters()[Index];
+  } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
+    assert(Index < CD->param_size());
+    return CD->parameters()[Index];
+  } else {
+    llvm_unreachable("Unexpected Decl kind!");
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // FoldingSet profiling.
 //===----------------------------------------------------------------------===//
@@ -249,25 +274,44 @@
   CXXThisRegion::ProfileRegion(ID, ThisPointerTy, superRegion);
 }
 
+void FieldRegion::Profile(llvm::FoldingSetNodeID &ID) const {
+  ProfileRegion(ID, getDecl(), superRegion);
+}
+
 void ObjCIvarRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
                                    const ObjCIvarDecl *ivd,
                                    const MemRegion* superRegion) {
-  DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCIvarRegionKind);
+  ID.AddInteger(static_cast<unsigned>(ObjCIvarRegionKind));
+  ID.AddPointer(ivd);
+  ID.AddPointer(superRegion);
+}
+
+void ObjCIvarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
+  ProfileRegion(ID, getDecl(), superRegion);
 }
 
-void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D,
-                               const MemRegion* superRegion, Kind k) {
-  ID.AddInteger(static_cast<unsigned>(k));
-  ID.AddPointer(D);
+void NonParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
+                                      const VarDecl *VD,
+                                      const MemRegion *superRegion) {
+  ID.AddInteger(static_cast<unsigned>(NonParamVarRegionKind));
+  ID.AddPointer(VD);
   ID.AddPointer(superRegion);
 }
 
-void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const {
-  DeclRegion::ProfileRegion(ID, D, superRegion, getKind());
+void NonParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
+  ProfileRegion(ID, getDecl(), superRegion);
 }
 
-void VarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
-  VarRegion::ProfileRegion(ID, getDecl(), superRegion);
+void ParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, const Expr *OE,
+                                   unsigned Idx, const MemRegion *SReg) {
+  ID.AddInteger(static_cast<unsigned>(ParamVarRegionKind));
+  ID.AddPointer(OE);
+  ID.AddInteger(Idx);
+  ID.AddPointer(SReg);
+}
+
+void ParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
+  ProfileRegion(ID, getOriginExpr(), getIndex(), superRegion);
 }
 
 void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym,
@@ -479,12 +523,11 @@
   os << "SymRegion{" << sym << '}';
 }
 
-void VarRegion::dumpToStream(raw_ostream &os) const {
-  const auto *VD = cast<VarDecl>(D);
+void NonParamVarRegion::dumpToStream(raw_ostream &os) const {
   if (const IdentifierInfo *ID = VD->getIdentifier())
     os << ID->getName();
   else
-    os << "VarRegion{D" << VD->getID() << '}';
+    os << "NonParamVarRegion{D" << VD->getID() << '}';
 }
 
 LLVM_DUMP_METHOD void RegionRawOffset::dump() const {
@@ -531,6 +574,18 @@
   os << "StackLocalsSpaceRegion";
 }
 
+void ParamVarRegion::dumpToStream(raw_ostream &os) const {
+  const ParmVarDecl *PVD = getDecl();
+  assert(PVD &&
+         "`ParamVarRegion` support functions without `Decl` not implemented"
+         " yet.");
+  if (const IdentifierInfo *ID = PVD->getIdentifier()) {
+    os << ID->getName();
+  } else {
+    os << "ParamVarRegion{P" << PVD->getID() << '}';
+  }
+}
+
 bool MemRegion::canPrintPretty() const {
   return canPrintPrettyAsExpr();
 }
@@ -550,11 +605,18 @@
   llvm_unreachable("This region cannot be printed pretty.");
 }
 
-bool VarRegion::canPrintPrettyAsExpr() const {
-  return true;
+bool NonParamVarRegion::canPrintPrettyAsExpr() const { return true; }
+
+void NonParamVarRegion::printPrettyAsExpr(raw_ostream &os) const {
+  os << getDecl()->getName();
 }
 
-void VarRegion::printPrettyAsExpr(raw_ostream &os) const {
+bool ParamVarRegion::canPrintPrettyAsExpr() const { return true; }
+
+void ParamVarRegion::printPrettyAsExpr(raw_ostream &os) const {
+  assert(getDecl() &&
+         "`ParamVarRegion` support functions without `Decl` not implemented"
+         " yet.");
   os << getDecl()->getName();
 }
 
@@ -693,7 +755,8 @@
   case MemRegion::CXXTempObjectRegionKind:
   case MemRegion::CXXThisRegionKind:
   case MemRegion::ObjCIvarRegionKind:
-  case MemRegion::VarRegionKind:
+  case MemRegion::NonParamVarRegionKind:
+  case MemRegion::ParamVarRegionKind:
   case MemRegion::ElementRegionKind:
   case MemRegion::ObjCStringRegionKind: {
     QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx);
@@ -847,9 +910,11 @@
       for (BlockDataRegion::referenced_vars_iterator
            I = BR->referenced_vars_begin(),
            E = BR->referenced_vars_end(); I != E; ++I) {
-        const VarRegion *VR = I.getOriginalRegion();
-        if (VR->getDecl() == VD)
-          return cast<VarRegion>(I.getCapturedRegion());
+        const TypedValueRegion *OrigR = I.getOriginalRegion();
+        if (const auto *VR = dyn_cast<VarRegion>(OrigR)) {
+          if (VR->getDecl() == VD)
+            return cast<VarRegion>(I.getCapturedRegion());
+        }
       }
     }
 
@@ -858,8 +923,30 @@
   return (const StackFrameContext *)nullptr;
 }
 
-const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
+const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D,
                                                 const LocationContext *LC) {
+  const auto *PVD = dyn_cast<ParmVarDecl>(D);
+  if (PVD) {
+    unsigned Index = PVD->getFunctionScopeIndex();
+    const StackFrameContext *SFC = LC->getStackFrame();
+    const Stmt *CallSite = SFC->getCallSite();
+    if (CallSite) {
+      const Decl *D = SFC->getDecl();
+      if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+        if (Index < FD->param_size() && FD->parameters()[Index] == PVD)
+          return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index,
+                                              getStackArgumentsRegion(SFC));
+      } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
+        if (Index < BD->param_size() && BD->parameters()[Index] == PVD)
+          return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index,
+                                              getStackArgumentsRegion(SFC));
+      } else {
+        return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index,
+                                            getStackArgumentsRegion(SFC));
+      }
+    }
+  }
+
   D = D->getCanonicalDecl();
   const MemRegion *sReg = nullptr;
 
@@ -942,13 +1029,23 @@
     }
   }
 
-  return getSubRegion<VarRegion>(D, sReg);
+  return getSubRegion<NonParamVarRegion>(D, sReg);
 }
 
-const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D,
-                                                const MemRegion *superR) {
+const NonParamVarRegion *
+MemRegionManager::getNonParamVarRegion(const VarDecl *D,
+                                       const MemRegion *superR) {
   D = D->getCanonicalDecl();
-  return getSubRegion<VarRegion>(D, superR);
+  return getSubRegion<NonParamVarRegion>(D, superR);
+}
+
+const ParamVarRegion *
+MemRegionManager::getParamVarRegion(const Expr *OriginExpr, unsigned Index,
+                                    const LocationContext *LC) {
+  const StackFrameContext *SFC = LC->getStackFrame();
+  assert(SFC);
+  return getSubRegion<ParamVarRegion>(OriginExpr, Index,
+                                      getStackArgumentsRegion(SFC));
 }
 
 const BlockDataRegion *
@@ -1341,7 +1438,8 @@
     case MemRegion::CXXThisRegionKind:
     case MemRegion::StringRegionKind:
     case MemRegion::ObjCStringRegionKind:
-    case MemRegion::VarRegionKind:
+    case MemRegion::NonParamVarRegionKind:
+    case MemRegion::ParamVarRegionKind:
     case MemRegion::CXXTempObjectRegionKind:
       // Usual base regions.
       goto Finish;
@@ -1497,7 +1595,7 @@
   const VarRegion *OriginalVR = nullptr;
 
   if (!VD->hasAttr<BlocksAttr>() && VD->hasLocalStorage()) {
-    VR = MemMgr.getVarRegion(VD, this);
+    VR = MemMgr.getNonParamVarRegion(VD, this);
     OriginalVR = MemMgr.getVarRegion(VD, LC);
   }
   else {
@@ -1506,7 +1604,7 @@
       OriginalVR = VR;
     }
     else {
-      VR = MemMgr.getVarRegion(VD, MemMgr.getUnknownRegion());
+      VR = MemMgr.getNonParamVarRegion(VD, MemMgr.getUnknownRegion());
       OriginalVR = MemMgr.getVarRegion(VD, LC);
     }
   }
Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -342,12 +342,12 @@
         // Operator arguments do not correspond to operator parameters
         // because this-argument is implemented as a normal argument in
         // operator call expressions but not in operator declarations.
-        const VarRegion *VR = Caller->getParameterLocation(
+        const TypedValueRegion *TVR = Caller->getParameterLocation(
             *Caller->getAdjustedParameterIndex(Idx), currBldrCtx->blockCount());
-        if (!VR)
+        if (!TVR)
           return None;
 
-        return loc::MemRegionVal(VR);
+        return loc::MemRegionVal(TVR);
       };
 
       if (const auto *CE = dyn_cast<CallExpr>(E)) {
Index: clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -218,7 +218,7 @@
     auto CE = BD->capture_end();
     for (; I != E; ++I) {
       const VarRegion *capturedR = I.getCapturedRegion();
-      const VarRegion *originalR = I.getOriginalRegion();
+      const TypedValueRegion *originalR = I.getOriginalRegion();
 
       // If the capture had a copy expression, use the result of evaluating
       // that expression, otherwise use the original value.
Index: clang/lib/StaticAnalyzer/Core/CallEvent.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -222,39 +222,17 @@
   return ADC->getManager()->getStackFrame(ADC, LCtx, E, B, BlockCount, Idx);
 }
 
-const VarRegion *CallEvent::getParameterLocation(unsigned Index,
-                                                 unsigned BlockCount) const {
+const ParamVarRegion
+*CallEvent::getParameterLocation(unsigned Index, unsigned BlockCount) const {
   const StackFrameContext *SFC = getCalleeStackFrame(BlockCount);
   // We cannot construct a VarRegion without a stack frame.
   if (!SFC)
     return nullptr;
 
-  // Retrieve parameters of the definition, which are different from
-  // CallEvent's parameters() because getDecl() isn't necessarily
-  // the definition. SFC contains the definition that would be used
-  // during analysis.
-  const Decl *D = SFC->getDecl();
-
-  // TODO: Refactor into a virtual method of CallEvent, like parameters().
-  const ParmVarDecl *PVD = nullptr;
-  if (const auto *FD = dyn_cast<FunctionDecl>(D))
-    PVD = FD->parameters()[Index];
-  else if (const auto *BD = dyn_cast<BlockDecl>(D))
-    PVD = BD->parameters()[Index];
-  else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
-    PVD = MD->parameters()[Index];
-  else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D))
-    PVD = CD->parameters()[Index];
-  assert(PVD && "Unexpected Decl kind!");
-
-  const VarRegion *VR =
-      State->getStateManager().getRegionManager().getVarRegion(PVD, SFC);
-
-  // This sanity check would fail if our parameter declaration doesn't
-  // correspond to the stack frame's function declaration.
-  assert(VR->getStackFrame() == SFC);
-
-  return VR;
+  const ParamVarRegion *PVR =
+    State->getStateManager().getRegionManager().getParamVarRegion(
+        getOriginExpr(), Index, SFC);
+  return PVR;
 }
 
 /// Returns true if a type is a pointer-to-const or reference-to-const
@@ -325,8 +303,9 @@
     if (getKind() != CE_CXXAllocator)
       if (isArgumentConstructedDirectly(Idx))
         if (auto AdjIdx = getAdjustedParameterIndex(Idx))
-          if (const VarRegion *VR = getParameterLocation(*AdjIdx, BlockCount))
-            ValuesToInvalidate.push_back(loc::MemRegionVal(VR));
+          if (const TypedValueRegion *TVR =
+                  getParameterLocation(*AdjIdx, BlockCount))
+            ValuesToInvalidate.push_back(loc::MemRegionVal(TVR));
   }
 
   // Invalidate designated regions using the batch invalidation API.
@@ -527,7 +506,8 @@
     // which makes getArgSVal() fail and return UnknownVal.
     SVal ArgVal = Call.getArgSVal(Idx);
     if (!ArgVal.isUnknown()) {
-      Loc ParamLoc = SVB.makeLoc(MRMgr.getVarRegion(ParamDecl, CalleeCtx));
+      Loc ParamLoc = SVB.makeLoc(
+          MRMgr.getParamVarRegion(Call.getOriginExpr(), Idx, CalleeCtx));
       Bindings.push_back(std::make_pair(ParamLoc, ArgVal));
     }
   }
Index: clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -709,7 +709,8 @@
 
   case MemRegion::SymbolicRegionKind:
   case MemRegion::AllocaRegionKind:
-  case MemRegion::VarRegionKind:
+  case MemRegion::NonParamVarRegionKind:
+  case MemRegion::ParamVarRegionKind:
   case MemRegion::FieldRegionKind:
   case MemRegion::ObjCIvarRegionKind:
     // These are the types we can currently track string lengths for.
@@ -814,7 +815,8 @@
   }
   case MemRegion::SymbolicRegionKind:
   case MemRegion::AllocaRegionKind:
-  case MemRegion::VarRegionKind:
+  case MemRegion::NonParamVarRegionKind:
+  case MemRegion::ParamVarRegionKind:
   case MemRegion::FieldRegionKind:
   case MemRegion::ObjCIvarRegionKind:
     return getCStringLengthForRegion(C, state, Ex, MR, hypothetical);
@@ -1009,10 +1011,14 @@
     os << "a C++ temp object of type "
        << cast<TypedValueRegion>(MR)->getValueType().getAsString();
     return true;
-  case MemRegion::VarRegionKind:
+  case MemRegion::NonParamVarRegionKind:
     os << "a variable of type"
        << cast<TypedValueRegion>(MR)->getValueType().getAsString();
     return true;
+  case MemRegion::ParamVarRegionKind:
+    os << "a parameter of type"
+       << cast<TypedValueRegion>(MR)->getValueType().getAsString();
+    return true;
   case MemRegion::FieldRegionKind:
     os << "a field of type "
        << cast<TypedValueRegion>(MR)->getValueType().getAsString();
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
@@ -73,9 +73,13 @@
       ABSTRACT_REGION(DeclRegion, TypedValueRegion)
         REGION(FieldRegion, DeclRegion)
         REGION(ObjCIvarRegion, DeclRegion)
-        REGION(VarRegion, DeclRegion)
-        REGION_RANGE(DECL_REGIONS, FieldRegionKind,
-                                   VarRegionKind)
+        ABSTRACT_REGION(VarRegion, DeclRegion)
+          REGION(NonParamVarRegion, VarRegion)
+          REGION(ParamVarRegion, VarRegion)
+        REGION_RANGE(VAR_REGIONS, NonParamVarRegionKind,
+                                  ParamVarRegionKind)
+      REGION_RANGE(DECL_REGIONS, FieldRegionKind,
+                                 ParamVarRegionKind)
       REGION(ElementRegion, TypedValueRegion)
       REGION(ObjCStringRegion, TypedValueRegion)
       REGION(StringRegion, TypedValueRegion)
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -308,6 +308,10 @@
   Loc getLValue(const CXXRecordDecl *BaseClass, const SubRegion *Super,
                 bool IsVirtual) const;
 
+  /// Get the lvalue for a parameter.
+  Loc getLValue(const Expr *Call, unsigned Index,
+                const LocationContext *LC) const;
+
   /// Get the lvalue for a variable reference.
   Loc getLValue(const VarDecl *D, const LocationContext *LC) const;
 
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -890,20 +890,12 @@
 
 class DeclRegion : public TypedValueRegion {
 protected:
-  const ValueDecl *D;
-
-  DeclRegion(const ValueDecl *d, const MemRegion *sReg, Kind k)
-      : TypedValueRegion(sReg, k), D(d) {
+  DeclRegion(const MemRegion *sReg, Kind k) : TypedValueRegion(sReg, k) {
     assert(classof(this));
-    assert(d && d->isCanonicalDecl());
   }
 
-  static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D,
-                      const MemRegion* superRegion, Kind k);
-
 public:
-  const ValueDecl *getDecl() const { return D; }
-  void Profile(llvm::FoldingSetNodeID& ID) const override;
+  virtual const ValueDecl *getDecl() const = 0;
 
   static bool classof(const MemRegion* R) {
     unsigned k = R->getKind();
@@ -914,9 +906,9 @@
 class VarRegion : public DeclRegion {
   friend class MemRegionManager;
 
-  // Constructors and private methods.
-  VarRegion(const VarDecl *vd, const MemRegion *sReg)
-      : DeclRegion(vd, sReg, VarRegionKind) {
+protected:
+  // Constructors and protected methods.
+  VarRegion(const MemRegion *sReg, Kind k) : DeclRegion(sReg, k) {
     // VarRegion appears in unknown space when it's a block variable as seen
     // from a block using it, when this block is analyzed at top-level.
     // Other block variables appear within block data regions,
@@ -925,17 +917,45 @@
            isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg));
   }
 
-  static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl *VD,
-                            const MemRegion *superRegion) {
-    DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
+public:
+  const VarDecl *getDecl() const override = 0;
+
+  const StackFrameContext *getStackFrame() const;
+
+  QualType getValueType() const override {
+    // FIXME: We can cache this if needed.
+    return getDecl()->getType();
   }
 
-public:
-  void Profile(llvm::FoldingSetNodeID& ID) const override;
+  static bool classof(const MemRegion *R) {
+    unsigned k = R->getKind();
+    return k >= BEGIN_VAR_REGIONS && k <= END_VAR_REGIONS;
+  }
+};
+
+class NonParamVarRegion : public VarRegion {
+  friend class MemRegionManager;
 
-  const VarDecl *getDecl() const { return cast<VarDecl>(D); }
+  const VarDecl *VD;
 
-  const StackFrameContext *getStackFrame() const;
+  // Constructors and private methods.
+  NonParamVarRegion(const VarDecl *vd, const MemRegion *sReg)
+      : VarRegion(sReg, NonParamVarRegionKind), VD(vd) {
+    // VarRegion appears in unknown space when it's a block variable as seen
+    // from a block using it, when this block is analyzed at top-level.
+    // Other block variables appear within block data regions,
+    // which, unlike everything else on this list, are not memory spaces.
+    assert(isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion>(sReg) ||
+           isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg));
+  }
+
+  static void ProfileRegion(llvm::FoldingSetNodeID &ID, const VarDecl *VD,
+                            const MemRegion *superRegion);
+
+public:
+  void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+  const VarDecl *getDecl() const override { return VD; }
 
   QualType getValueType() const override {
     // FIXME: We can cache this if needed.
@@ -949,7 +969,49 @@
   void printPrettyAsExpr(raw_ostream &os) const override;
 
   static bool classof(const MemRegion* R) {
-    return R->getKind() == VarRegionKind;
+    return R->getKind() == NonParamVarRegionKind;
+  }
+};
+
+/// ParamVarRegion - Represents a region for paremters. Only parameters of the
+/// function in the current stack frame are represented as `ParamVarRegion`s.
+/// Parameters of top-level analyzed functions as well as captured paremeters
+/// by lambdas and blocks are repesented as `VarRegion`s.
+
+// FIXME: `ParamVarRegion` only supports parameters of functions, C++
+// constructors, blocks and Objective-C methods with existing `Decl`. Upon
+// implementing stack frame creations for functions without decl (functions
+// passed by function pointer) methods of `ParamVarRegion` must be updated.
+class ParamVarRegion : public VarRegion {
+  friend class MemRegionManager;
+
+  const Expr *OriginExpr;
+  unsigned Index;
+
+  ParamVarRegion(const Expr *OE, unsigned Idx, const MemRegion *SReg)
+      : VarRegion(SReg, ParamVarRegionKind), OriginExpr(OE), Index(Idx) {
+    assert(!cast<StackSpaceRegion>(SReg)->getStackFrame()->inTopFrame());
+  }
+
+  static void ProfileRegion(llvm::FoldingSetNodeID &ID, const Expr *OE,
+                            unsigned Idx, const MemRegion *SReg);
+
+public:
+  const Expr *getOriginExpr() const { return OriginExpr; }
+  unsigned getIndex() const { return Index; }
+
+  void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+  void dumpToStream(raw_ostream &os) const override;
+
+  QualType getValueType() const override;
+  const ParmVarDecl *getDecl() const override;
+
+  bool canPrintPrettyAsExpr() const override;
+  void printPrettyAsExpr(raw_ostream &os) const override;
+
+  static bool classof(const MemRegion *R) {
+    return R->getKind() == ParamVarRegionKind;
   }
 };
 
@@ -991,16 +1053,22 @@
 class FieldRegion : public DeclRegion {
   friend class MemRegionManager;
 
-  FieldRegion(const FieldDecl *fd, const SubRegion* sReg)
-      : DeclRegion(fd, sReg, FieldRegionKind) {}
+  const FieldDecl *FD;
 
-  static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD,
+  FieldRegion(const FieldDecl *fd, const SubRegion *sReg)
+      : DeclRegion(sReg, FieldRegionKind), FD(fd) {}
+
+  static void ProfileRegion(llvm::FoldingSetNodeID &ID, const FieldDecl *FD,
                             const MemRegion* superRegion) {
-    DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind);
+    ID.AddInteger(static_cast<unsigned>(FieldRegionKind));
+    ID.AddPointer(FD);
+    ID.AddPointer(superRegion);
   }
 
 public:
-  const FieldDecl *getDecl() const { return cast<FieldDecl>(D); }
+  const FieldDecl *getDecl() const override { return FD; }
+
+  void Profile(llvm::FoldingSetNodeID &ID) const override;
 
   QualType getValueType() const override {
     // FIXME: We can cache this if needed.
@@ -1022,6 +1090,8 @@
 class ObjCIvarRegion : public DeclRegion {
   friend class MemRegionManager;
 
+  const ObjCIvarDecl *IVD;
+
   ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg);
 
   static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl *ivd,
@@ -1029,6 +1099,9 @@
 
 public:
   const ObjCIvarDecl *getDecl() const;
+
+  void Profile(llvm::FoldingSetNodeID& ID) const override;
+
   QualType getValueType() const override;
 
   bool canPrintPrettyAsExpr() const override;
@@ -1312,11 +1385,18 @@
 
   /// getVarRegion - Retrieve or create the memory region associated with
   ///  a specified VarDecl and LocationContext.
-  const VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC);
+  const VarRegion *getVarRegion(const VarDecl *VD, const LocationContext *LC);
 
   /// getVarRegion - Retrieve or create the memory region associated with
-  ///  a specified VarDecl and super region.
-  const VarRegion *getVarRegion(const VarDecl *D, const MemRegion *superR);
+  ///  a specified VarDecl and LocationContext.
+  const NonParamVarRegion *getNonParamVarRegion(const VarDecl *VD,
+                                                const MemRegion *superR);
+
+  /// getParamVarRegion - Retrieve or create the memory region
+  /// associated with a specified CallExpr, Index and LocationContext.
+  const ParamVarRegion *getParamVarRegion(const Expr *OriginExpr,
+                                          unsigned Index,
+                                          const LocationContext *LC);
 
   /// getElementRegion - Retrieve the memory region associated with the
   ///  associated element type, index, and super region.
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -97,7 +97,7 @@
 class SwitchNodeBuilder;
 
 class ExprEngine {
-  void anchor();
+  virtual void anchor();
 public:
   /// The modes of inlining, which override the default analysis-wide settings.
   enum InliningModes {
@@ -177,7 +177,7 @@
              SetOfConstDecls *VisitedCalleesIn,
              FunctionSummariesTy *FS, InliningModes HowToInlineIn);
 
-  virtual ~ExprEngine() = default;
+  ~ExprEngine() = default;
 
   /// Returns true if there is still simulation state on the worklist.
   bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -403,8 +403,8 @@
 
   /// Returns memory location for a parameter variable within the callee stack
   /// frame. May fail; returns null on failure.
-  const VarRegion *getParameterLocation(unsigned Index,
-                                        unsigned BlockCount) const;
+  const ParamVarRegion *getParameterLocation(unsigned Index,
+                                             unsigned BlockCount) const;
 
   /// Returns true if on the current path, the argument was constructed by
   /// calling a C++ constructor over it. This is an internal detail of the
Index: clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
+++ clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
@@ -18,6 +18,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
+#include "llvm/ADT/StringExtras.h"
 
 namespace clang {
 
@@ -179,7 +180,7 @@
     return OS.str();
   }
 
-  std::string VisitVarRegion(const VarRegion *R) {
+  std::string VisitNonParamVarRegion(const NonParamVarRegion *R) {
     const VarDecl *VD = R->getDecl();
     std::string Name = VD->getQualifiedNameAsString();
     if (isa<ParmVarDecl>(VD))
@@ -216,6 +217,39 @@
            "' inside " + Visit(R->getSuperRegion());
   }
 
+  std::string VisitParamVarRegion(const ParamVarRegion *R) {
+    std::string Str;
+    llvm::raw_string_ostream OS(Str);
+
+    const ParmVarDecl *PVD = R->getDecl();
+    std::string Name = PVD->getQualifiedNameAsString();
+    if (!Name.empty()) {
+      OS << "parameter '" << Name << "'";
+      return std::string(OS.str());
+    }
+
+    unsigned Index = R->getIndex() + 1;
+    OS << Index << llvm::getOrdinalSuffix(Index) << " of parameter ";
+    const Decl *Parent = R->getStackFrame()->getDecl();
+    if (const auto *FD = dyn_cast<FunctionDecl>(Parent))
+      OS << "function '" << FD->getQualifiedNameAsString() << "()'";
+    else if (const auto *CD = dyn_cast<CXXConstructorDecl>(Parent))
+      OS << "C++ constructor '" << CD->getQualifiedNameAsString() << "()'";
+    else if (const auto *MD = dyn_cast<ObjCMethodDecl>(Parent)) {
+      if (MD->isClassMethod())
+        OS << "Objective-C method '+" << MD->getQualifiedNameAsString() << "'";
+      else
+        OS << "Objective-C method '-" << MD->getQualifiedNameAsString() << "'";
+    } else if (isa<BlockDecl>(Parent)) {
+      if (cast<BlockDecl>(Parent)->isConversionFromLambda())
+        OS << "lambda";
+      else
+        OS << "block";
+    }
+
+    return std::string(OS.str());
+  }
+
   std::string VisitSVal(SVal V) {
     std::string Str;
     llvm::raw_string_ostream OS(Str);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to