Merge remote-tracking branch 'origin/swift-4.1-branch' into stable
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 99eee5f..15383a2 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -758,6 +758,15 @@
   Fn->removeFnAttr(llvm::Attribute::SanitizeThread);
 }
 
+/// Return the UBSan prologue signature for \p FD if one is available.
+static llvm::Constant *getPrologueSignature(CodeGenModule &CGM,
+                                            const FunctionDecl *FD) {
+  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
+    if (!MD->isStatic())
+      return nullptr;
+  return CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM);
+}
+
 void CodeGenFunction::StartFunction(GlobalDecl GD,
                                     QualType RetTy,
                                     llvm::Function *Fn,
@@ -865,8 +874,7 @@
   // prologue data.
   if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function)) {
     if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
-      if (llvm::Constant *PrologueSig =
-              CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) {
+      if (llvm::Constant *PrologueSig = getPrologueSignature(CGM, FD)) {
         llvm::Constant *FTRTTIConst =
             CGM.GetAddrOfRTTIDescriptor(FD->getType(), /*ForEH=*/true);
         llvm::Constant *FTRTTIConstEncoded =
diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp
index 8f6f3ed..08b8c2e 100644
--- a/lib/CodeGen/CoverageMappingGen.cpp
+++ b/lib/CodeGen/CoverageMappingGen.cpp
@@ -758,6 +758,22 @@
     handleFileExit(getEnd(S));
   }
 
+  /// Determine whether the final deferred region emitted in \p Body should be
+  /// discarded.
+  static bool discardFinalDeferredRegionInDecl(Stmt *Body) {
+    if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
+      Stmt *LastStmt = CS->body_back();
+      if (auto *IfElse = dyn_cast<IfStmt>(LastStmt)) {
+        if (auto *Else = dyn_cast_or_null<CompoundStmt>(IfElse->getElse()))
+          LastStmt = Else->body_back();
+        else
+          LastStmt = IfElse->getElse();
+      }
+      return dyn_cast_or_null<ReturnStmt>(LastStmt);
+    }
+    return false;
+  }
+
   void VisitDecl(const Decl *D) {
     assert(!DeferredRegion && "Deferred region never completed");
 
@@ -770,14 +786,14 @@
     Counter ExitCount = propagateCounts(getRegionCounter(Body), Body);
     assert(RegionStack.empty() && "Regions entered but never exited");
 
-    // Special case: if the last statement is a return, throw away the
-    // deferred region. This allows the closing brace to have a count.
-    if (auto *CS = dyn_cast_or_null<CompoundStmt>(Body))
-      if (dyn_cast_or_null<ReturnStmt>(CS->body_back()))
+    if (DeferredRegion) {
+      // Complete (or discard) any deferred regions introduced by the last
+      // statement.
+      if (discardFinalDeferredRegionInDecl(Body))
         DeferredRegion = None;
-
-    // Complete any deferred regions introduced by the last statement.
-    popRegions(completeDeferred(ExitCount, getEnd(Body)));
+      else
+        popRegions(completeDeferred(ExitCount, getEnd(Body)));
+    }
   }
 
   void VisitReturnStmt(const ReturnStmt *S) {
@@ -1083,16 +1099,18 @@
   }
 
   void VisitBinLAnd(const BinaryOperator *E) {
-    extendRegion(E);
-    Visit(E->getLHS());
+    extendRegion(E->getLHS());
+    propagateCounts(getRegion().getCounter(), E->getLHS());
+    handleFileExit(getEnd(E->getLHS()));
 
     extendRegion(E->getRHS());
     propagateCounts(getRegionCounter(E), E->getRHS());
   }
 
   void VisitBinLOr(const BinaryOperator *E) {
-    extendRegion(E);
-    Visit(E->getLHS());
+    extendRegion(E->getLHS());
+    propagateCounts(getRegion().getCounter(), E->getLHS());
+    handleFileExit(getEnd(E->getLHS()));
 
     extendRegion(E->getRHS());
     propagateCounts(getRegionCounter(E), E->getRHS());
diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp
index aa3da10..e828753 100644
--- a/test/CodeGenCXX/catch-undef-behavior.cpp
+++ b/test/CodeGenCXX/catch-undef-behavior.cpp
@@ -426,6 +426,66 @@
   p(42);
 }
 
+namespace FunctionSanitizerVirtualCalls {
+struct A {
+  virtual void f() {}
+  virtual void g() {}
+  void h() {}
+};
+
+struct B : virtual A {
+  virtual void b() {}
+  virtual void f();
+  void g() final {}
+  static void q() {}
+};
+
+void B::f() {}
+
+void force_irgen() {
+  A a;
+  a.g();
+  a.h();
+
+  B b;
+  b.f();
+  b.b();
+  b.g();
+  B::q();
+}
+
+// CHECK-LABEL: define void @_ZN29FunctionSanitizerVirtualCalls1B1fEv
+// CHECK-NOT: prologue
+//
+// CHECK-LABEL: define void @_ZTv0_n24_N29FunctionSanitizerVirtualCalls1B1fEv
+// CHECK-NOT: prologue
+//
+// CHECK-LABEL: define void @_ZN29FunctionSanitizerVirtualCalls11force_irgenEv()
+// CHECK: prologue
+//
+// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1AC1Ev
+// CHECK-NOT: prologue
+//
+// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1A1gEv
+// CHECK-NOT: prologue
+//
+// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1A1hEv
+// CHECK-NOT: prologue
+//
+// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1BC1Ev
+// CHECK-NOT: prologue
+//
+// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1bEv
+// CHECK-NOT: prologue
+//
+// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1gEv
+// CHECK-NOT: prologue
+//
+// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1qEv
+// CHECK: prologue
+
+}
+
 namespace UpcastPointerTest {
 struct S {};
 struct T : S { double d; };
diff --git a/test/CoverageMapping/deferred-region.cpp b/test/CoverageMapping/deferred-region.cpp
index 743b635..3504588 100644
--- a/test/CoverageMapping/deferred-region.cpp
+++ b/test/CoverageMapping/deferred-region.cpp
@@ -31,11 +31,28 @@
 // CHECK-LABEL: _Z3mazv:
 void maz() {
   if (true)
-    return; // CHECK: Gap,File 0, [[@LINE]]:11 -> 36:3 = (#0 - #1)
+    return; // CHECK: Gap,File 0, [[@LINE]]:11 -> [[@LINE+2]]:3 = (#0 - #1)
 
   return; // CHECK-NOT: Gap
 }
 
+// CHECK-LABEL: _Z4maazv:
+void maaz() {
+  if (true)
+    return; // CHECK: Gap,File 0, [[@LINE]]:11
+  else
+    return; // CHECK-NOT: Gap,File 0, [[@LINE]]
+}
+
+// CHECK-LABEL: _Z5maaazv:
+void maaaz() {
+  if (true) {
+    return;
+  } else {  // CHECK: Gap,File 0, [[@LINE]]:4 -> [[@LINE]]:10
+    return; // CHECK-NOT: Gap,File 0, [[@LINE]]
+  }
+}
+
 // CHECK-LABEL: _Z3bari:
 void bar(int x) {
   IF (x)
@@ -158,6 +175,9 @@
   foo(1);
   fooo(0);
   fooo(1);
+  maz();
+  maaz();
+  maaaz();
   baz();
   bar(0);
   bar(1);
diff --git a/test/CoverageMapping/logical.cpp b/test/CoverageMapping/logical.cpp
index 198cc60..bc7c785 100644
--- a/test/CoverageMapping/logical.cpp
+++ b/test/CoverageMapping/logical.cpp
@@ -1,13 +1,18 @@
 // RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name logical.cpp %s | FileCheck %s
 
-int main() {                        // CHECK: File 0, [[@LINE]]:12 -> [[@LINE+10]]:2 = #0
+int main() {                        // CHECK: File 0, [[@LINE]]:12 -> [[@LINE+15]]:2 = #0
   bool bt = true;
   bool bf = false;
-  bool a = bt && bf;                // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE]]:20 = #1
-  a = bt &&
+  bool a = bt && bf;                // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE]]:14 = #0
+                                    // CHECK-NEXT: File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:20 = #1
+
+  a = bt &&                         // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #0
       bf;                           // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #2
-  a = bf || bt;                     // CHECK-NEXT: File 0, [[@LINE]]:13 -> [[@LINE]]:15 = #3
-  a = bf ||
+
+  a = bf || bt;                     // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #0
+                                    // CHECK-NEXT: File 0, [[@LINE-1]]:13 -> [[@LINE-1]]:15 = #3
+
+  a = bf ||                         // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #0
       bt;                           // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #4
   return 0;
 }
diff --git a/test/CoverageMapping/macro-expansion.c b/test/CoverageMapping/macro-expansion.c
index 3fca975..4e52558 100644
--- a/test/CoverageMapping/macro-expansion.c
+++ b/test/CoverageMapping/macro-expansion.c
@@ -23,10 +23,12 @@
 // CHECK-NEXT: Expansion,File 4, [[@LINE+2]]:20 -> [[@LINE+2]]:22 = (#0 + #8)
 // CHECK-NEXT: File 4, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = (#0 + #8)
 #define M3(x) do { M2(x); } while (0)
-// CHECK-NEXT: File 5, [[@LINE+2]]:15 -> [[@LINE+2]]:27 = #0
+// CHECK-NEXT: File 5, [[@LINE+3]]:15 -> [[@LINE+3]]:27 = #0
+// CHECK-NEXT: File 5, [[@LINE+2]]:16 -> [[@LINE+2]]:19 = #0
 // CHECK-NEXT: File 5, [[@LINE+1]]:23 -> [[@LINE+1]]:26 = #12
 #define M4(x) ((x) && (x))
-// CHECK-NEXT: File 6, [[@LINE+2]]:15 -> [[@LINE+2]]:27 = #0
+// CHECK-NEXT: File 6, [[@LINE+3]]:15 -> [[@LINE+3]]:27 = #0
+// CHECK-NEXT: File 6, [[@LINE+2]]:16 -> [[@LINE+2]]:19 = #0
 // CHECK-NEXT: File 6, [[@LINE+1]]:23 -> [[@LINE+1]]:26 = #14
 #define M5(x) ((x) || (x))
 // CHECK-NEXT: File 7, [[@LINE+1]]:15 -> [[@LINE+1]]:26 = #0