Merge pull request #9454 from slavapestov/se-0110-strikes-again

Sema: Fix another SE-0110 issue
diff --git a/include/swift/AST/DiagnosticsSIL.def b/include/swift/AST/DiagnosticsSIL.def
index 50eb90c..696ba7f 100644
--- a/include/swift/AST/DiagnosticsSIL.def
+++ b/include/swift/AST/DiagnosticsSIL.def
@@ -85,24 +85,26 @@
       "previous aliasing argument", ())
 
 WARNING(exclusivity_access_required_swift3,none,
-        "simultaneous accesses to %0 %1; "
+        "simultaneous accesses to %0 %1, but "
         "%select{initialization|read|modification|deinitialization}2 requires "
-        "exclusive access", (DescriptiveDeclKind, Identifier, unsigned))
+        "exclusive access; consider copying to a local variable",
+        (DescriptiveDeclKind, Identifier, unsigned))
 
 ERROR(exclusivity_access_required,none,
-      "simultaneous accesses to %0 %1; "
+      "simultaneous accesses to %0 %1, but "
       "%select{initialization|read|modification|deinitialization}2 requires "
-      "exclusive access", (DescriptiveDeclKind, Identifier, unsigned))
+      "exclusive access; consider copying to a local variable",
+      (DescriptiveDeclKind, Identifier, unsigned))
 
 ERROR(exclusivity_access_required_unknown_decl,none,
-        "simultaneous accesses; "
+        "simultaneous accesses, but "
         "%select{initialization|read|modification|deinitialization}0 requires "
-        "exclusive access", (unsigned))
+        "exclusive access; consider copying to a local variable", (unsigned))
 
 WARNING(exclusivity_access_required_unknown_decl_swift3,none,
-        "simultaneous accesses; "
+        "simultaneous accesses, but "
         "%select{initialization|read|modification|deinitialization}0 requires "
-        "exclusive access", (unsigned))
+"exclusive access; consider copying to a local variable", (unsigned))
 
 NOTE(exclusivity_conflicting_access,none,
      "conflicting access is here", ())
diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h
index 7dc6219..25c2b35 100644
--- a/include/swift/AST/IRGenOptions.h
+++ b/include/swift/AST/IRGenOptions.h
@@ -76,6 +76,9 @@
   /// The command line string that is to be stored in the DWARF debug info.
   std::string DWARFDebugFlags;
 
+  /// List of -Xcc -D macro definitions.
+  std::vector<std::string> ClangDefines;
+
   /// The libraries and frameworks specified on the command line.
   SmallVector<LinkLibrary, 4> LinkLibraries;
 
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 48d921e..64557d0 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1470,6 +1470,14 @@
     }
   }
 
+  for (const Arg *A : make_range(Args.filtered_begin(OPT_Xcc),
+                                 Args.filtered_end())) {
+    StringRef Opt = A->getValue();
+    if (Opt.startswith("-D") || Opt.startswith("-U"))
+      Opts.ClangDefines.push_back(Opt);
+  }
+
+
   for (const Arg *A : make_range(Args.filtered_begin(OPT_l, OPT_framework),
                                  Args.filtered_end())) {
     LibraryKind Kind;
diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp
index 83a4898..64d7b73 100644
--- a/lib/IRGen/IRGenDebugInfo.cpp
+++ b/lib/IRGen/IRGenDebugInfo.cpp
@@ -99,6 +99,7 @@
 
   llvm::BumpPtrAllocator DebugInfoNames;
   StringRef CWDName;                    /// The current working directory.
+  SmallString<0> ConfigMacros;          /// User-provided -D macro definitions.
   llvm::DICompileUnit *TheCU = nullptr; /// The current compilation unit.
   llvm::DIFile *MainFile = nullptr;     /// The main file.
   llvm::DIModule *MainModule = nullptr; /// The current module.
@@ -588,13 +589,13 @@
   }
 
   llvm::DIModule *getOrCreateModule(StringRef Key, llvm::DIScope *Parent,
-                                    StringRef Name, StringRef IncludePath) {
+                                    StringRef Name, StringRef IncludePath,
+                                    StringRef ConfigMacros = StringRef()) {
     // Look in the cache first.
     auto Val = DIModuleCache.find(Key);
     if (Val != DIModuleCache.end())
       return cast<llvm::DIModule>(Val->second);
 
-    StringRef ConfigMacros;
     StringRef Sysroot = IGM.Context.SearchPathOpts.SDKPath;
     auto M =
         DBuilder.createModule(Parent, Name, ConfigMacros, IncludePath, Sysroot);
@@ -612,11 +613,12 @@
         Parent = getOrCreateModule(PM);
       }
       return getOrCreateModule(ClangModule->getFullModuleName(), Parent,
-                               Desc.getModuleName(), Desc.getPath());
+                               Desc.getModuleName(), Desc.getPath(),
+                               ConfigMacros);
     }
     // Handle PCH.
     return getOrCreateModule(Desc.getASTFile(), nullptr, Desc.getModuleName(),
-                             Desc.getPath());
+                             Desc.getPath(), ConfigMacros);
   };
 
   TypeAliasDecl *getMetadataType() {
@@ -1540,6 +1542,24 @@
   MainModule =
       getOrCreateModule(Opts.ModuleName, TheCU, Opts.ModuleName, AbsMainFile);
   DBuilder.createImportedModule(MainFile, MainModule, 1);
+
+  // Macro definitions that were defined by the user with "-Xcc -D" on the
+  // command line. This does not include any macros defined by ClangImporter.
+  llvm::raw_svector_ostream OS(ConfigMacros);
+  unsigned I = 0;
+  // Translate the macro definitions back into a commmand line.
+  for (auto &Macro : Opts.ClangDefines) {
+    if (++I > 1)
+      OS << ' ';
+    OS << '"';
+    for (char c : Macro)
+      switch (c) {
+      case '\\': OS << "\\\\"; break;
+      case '"':  OS << "\\\""; break;
+      default: OS << c;
+      }
+    OS << '"';
+  }
 }
 
 void IRGenDebugInfoImpl::finalize() {
diff --git a/test/DebugInfo/ImportClangSubmodule.swift b/test/DebugInfo/ImportClangSubmodule.swift
index e7718c6..c2a35fe 100644
--- a/test/DebugInfo/ImportClangSubmodule.swift
+++ b/test/DebugInfo/ImportClangSubmodule.swift
@@ -1,4 +1,5 @@
-// RUN: %target-swift-frontend -emit-ir %s -g -I %S/Inputs -o - | %FileCheck %s
+// RUN: %target-swift-frontend -emit-ir %s -g -I %S/Inputs \
+// RUN:   -Xcc -DFOO="foo" -Xcc -UBAR -o - | %FileCheck %s
 
 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Bar",
 // CHECK-SAME:             scope: ![[SUBMODULE:[0-9]+]]
@@ -6,6 +7,9 @@
 // CHECK: ![[SUBMODULE]] = !DIModule(scope: ![[CLANGMODULE:[0-9]+]],
 // CHECK-SAME:                       name: "SubModule",
 // CHECK: ![[CLANGMODULE]] = !DIModule(scope: null, name: "ClangModule",
+// CHECK-SAME:                         configMacros:
+// CHECK-SAME:                         {{..}}-DFOO=foo{{..}}
+// CHECK-SAME:                         {{..}}-UBAR{{..}}
 // CHECK: !DIImportedEntity({{.*}}, entity: ![[SUBMODULE]], line: [[@LINE+1]])
 import ClangModule.SubModule
 
diff --git a/test/SILOptimizer/exclusivity_static_diagnostics.sil b/test/SILOptimizer/exclusivity_static_diagnostics.sil
index 812efd0..ab6f71b 100644
--- a/test/SILOptimizer/exclusivity_static_diagnostics.sil
+++ b/test/SILOptimizer/exclusivity_static_diagnostics.sil
@@ -38,7 +38,7 @@
   %3 = project_box %2 : ${ var Int }, 0
   store %0 to [trivial] %3 : $*Int
   %4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
-  %5 = begin_access [modify] [unknown] %3 : $*Int  // expected-error {{simultaneous accesses; modification requires exclusive access}}
+  %5 = begin_access [modify] [unknown] %3 : $*Int  // expected-error {{simultaneous accesses, but modification requires exclusive access; consider copying to a local variable}}
   %6 = begin_access [modify] [unknown] %3 : $*Int  // expected-note {{conflicting access is here}}
   %7 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
   end_access %6 : $*Int
@@ -55,7 +55,7 @@
   %3 = project_box %2 : ${ var Int }, 0
   store %0 to [trivial] %3 : $*Int
   %4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
-  %5 = begin_access [modify] [unknown] %3 : $*Int  // expected-error {{simultaneous accesses; modification requires exclusive access}}
+  %5 = begin_access [modify] [unknown] %3 : $*Int  // expected-error {{simultaneous accesses, but modification requires exclusive access; consider copying to a local variable}}
   %6 = begin_access [modify] [unknown] %5 : $*Int
   %7 = begin_access [modify] [unknown] %3 : $*Int  // expected-note {{conflicting access is here}}
   %8 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
@@ -147,7 +147,7 @@
   br bb1
 bb1:
   // Make sure we don't diagnose twice.
-  %4 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{simultaneous accesses; modification requires exclusive access}}
+  %4 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{simultaneous accesses, but modification requires exclusive access; consider copying to a local variable}}
   %5 = begin_access [modify] [unknown] %3 : $*Int // expected-note {{conflicting access is here}}
   end_access %5: $*Int
   end_access %4: $*Int
@@ -199,7 +199,7 @@
   %2 = project_box %1 : ${ var Int }, 0
   store %0 to [trivial] %2 : $*Int
   %4 = begin_access [read] [unknown] %2 : $*Int // expected-note {{conflicting access is here}}
-  %5 = begin_access [modify] [unknown] %2 : $*Int // expected-error {{simultaneous accesses; modification requires exclusive access}}
+  %5 = begin_access [modify] [unknown] %2 : $*Int // expected-error {{simultaneous accesses, but modification requires exclusive access; consider copying to a local variable}}
   end_access %5 : $*Int
   end_access %4: $*Int
   destroy_value %1 : ${ var Int }
@@ -213,7 +213,7 @@
   %1 = alloc_box ${ var Int }
   %2 = project_box %1 : ${ var Int }, 0
   store %0 to [trivial] %2 : $*Int
-  %4 = begin_access [modify] [unknown] %2 : $*Int // expected-error {{simultaneous accesses; modification requires exclusive access}}
+  %4 = begin_access [modify] [unknown] %2 : $*Int // expected-error {{simultaneous accesses, but modification requires exclusive access; consider copying to a local variable}}
   %5 = begin_access [read] [unknown] %2 : $*Int // expected-note {{conflicting access is here}}
   end_access %5 : $*Int
   end_access %4: $*Int
@@ -232,7 +232,7 @@
 bb0(%0 : $ClassWithStoredProperty):
   %1 = ref_element_addr %0 : $ClassWithStoredProperty, #ClassWithStoredProperty.f
 
-  // expected-error@+1{{simultaneous accesses to var 'f'; modification requires exclusive access}}
+  // expected-error@+1{{simultaneous accesses to var 'f', but modification requires exclusive access; consider copying to a local variable}}
   %2 = begin_access [modify] [dynamic] %1 : $*Int
   %3 = ref_element_addr %0 : $ClassWithStoredProperty, #ClassWithStoredProperty.f
 
@@ -252,7 +252,7 @@
   %2 = begin_borrow %0 : $ClassWithStoredProperty
   %3 = ref_element_addr %1 : $ClassWithStoredProperty, #ClassWithStoredProperty.f
 
-  // expected-error@+1{{simultaneous accesses to var 'f'; modification requires exclusive access}}
+  // expected-error@+1{{simultaneous accesses to var 'f', but modification requires exclusive access; consider copying to a local variable}}
   %4 = begin_access [modify] [dynamic] %3 : $*Int
   %5 = ref_element_addr %2 : $ClassWithStoredProperty, #ClassWithStoredProperty.f
 
@@ -279,7 +279,7 @@
   store %0 to [trivial] %3 : $*Int
   %4 = copy_value %2 : ${ var Int }
   %5 = project_box %4 : ${ var Int }, 0
-  %6 = begin_access [modify] [unknown] %3 : $*Int  // expected-error {{simultaneous accesses; modification requires exclusive access}}
+  %6 = begin_access [modify] [unknown] %3 : $*Int  // expected-error {{simultaneous accesses, but modification requires exclusive access; consider copying to a local variable}}
   %7 = begin_access [modify] [unknown] %5 : $*Int  // expected-note {{conflicting access is here}}
   end_access %7 : $*Int
   end_access %6: $*Int
@@ -297,7 +297,7 @@
   %3 = project_box %2 : ${ var Int }, 0
   store %0 to [trivial] %3 : $*Int
   %4 = project_box %2 : ${ var Int }, 0
-  %5 = begin_access [modify] [unknown] %3 : $*Int  // expected-error {{simultaneous accesses; modification requires exclusive access}}
+  %5 = begin_access [modify] [unknown] %3 : $*Int  // expected-error {{simultaneous accesses, but modification requires exclusive access; consider copying to a local variable}}
   %6 = begin_access [modify] [unknown] %4 : $*Int  // expected-note {{conflicting access is here}}
   end_access %6 : $*Int
   end_access %5: $*Int
@@ -315,7 +315,7 @@
 bb0(%0 : $Int):
   %1 = global_addr @global1 :$*Int
   %2 = global_addr @global1 :$*Int
-  %3 = begin_access [modify] [unknown] %1 : $*Int  // expected-error {{simultaneous accesses; modification requires exclusive access}}
+  %3 = begin_access [modify] [unknown] %1 : $*Int  // expected-error {{simultaneous accesses, but modification requires exclusive access; consider copying to a local variable}}
   %4 = begin_access [modify] [unknown] %2 : $*Int  // expected-note {{conflicting access is here}}
   end_access %4 : $*Int
   end_access %3: $*Int
@@ -348,7 +348,7 @@
   store %0 to [trivial] %3 : $*Int
   %4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
   %5 = begin_access [read] [unknown] %3 : $*Int  // expected-note {{conflicting access is here}}
-  %6 = begin_access [modify] [unknown] %3 : $*Int  // expected-error {{simultaneous accesses; modification requires exclusive access}}
+  %6 = begin_access [modify] [unknown] %3 : $*Int  // expected-error {{simultaneous accesses, but modification requires exclusive access; consider copying to a local variable}}
   %7 = begin_access [read] [unknown] %3 : $*Int // no-error
   %8 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
   end_access %7 : $*Int
@@ -368,7 +368,7 @@
   %3 = project_box %2 : ${ var Int }, 0
   store %0 to [trivial] %3 : $*Int
   %4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
-  %5 = begin_access [modify] [unknown] %3 : $*Int  // expected-error {{simultaneous accesses; modification requires exclusive access}}
+  %5 = begin_access [modify] [unknown] %3 : $*Int  // expected-error {{simultaneous accesses, but modification requires exclusive access; consider copying to a local variable}}
   %6 = begin_access [modify] [unknown] %3 : $*Int  // expected-note {{conflicting access is here}}
   %7 = begin_access [modify] [unknown] %3 : $*Int  // no-error
   %8 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
@@ -392,7 +392,7 @@
   %4 = function_ref @takesTwoInouts : $@convention(thin) (@inout Int, @inout Int) -> ()
   %5 = begin_access [modify] [unknown] %3 : $*Int  // no-note
   end_access %5 : $*Int
-  %6 = begin_access [modify] [unknown] %3 : $*Int  // expected-error {{simultaneous accesses; modification requires exclusive access}}
+  %6 = begin_access [modify] [unknown] %3 : $*Int  // expected-error {{simultaneous accesses, but modification requires exclusive access; consider copying to a local variable}}
   %7 = begin_access [modify] [unknown] %3 : $*Int  // expected-note {{conflicting access is here}}
   %8 = apply %4(%5, %6) : $@convention(thin) (@inout Int, @inout Int) -> ()
   end_access %7 : $*Int
diff --git a/test/SILOptimizer/exclusivity_static_diagnostics.swift b/test/SILOptimizer/exclusivity_static_diagnostics.swift
index 787da8e..8ea7779 100644
--- a/test/SILOptimizer/exclusivity_static_diagnostics.swift
+++ b/test/SILOptimizer/exclusivity_static_diagnostics.swift
@@ -11,7 +11,7 @@
   // turned on by default.
   // expected-error@+4{{inout arguments are not allowed to alias each other}}
   // expected-note@+3{{previous aliasing argument}}
-  // expected-error@+2{{simultaneous accesses to var 'i'; modification requires exclusive access}}
+  // expected-error@+2{{simultaneous accesses to var 'i', but modification requires exclusive access; consider copying to a local variable}}
   // expected-note@+1{{conflicting access is here}}
   takesTwoInouts(&i, &i)
 }
@@ -19,7 +19,7 @@
 func inoutOnInoutParameter(p: inout Int) {
   // expected-error@+4{{inout arguments are not allowed to alias each other}}
   // expected-note@+3{{previous aliasing argument}}
-  // expected-error@+2{{simultaneous accesses to parameter 'p'; modification requires exclusive access}}
+  // expected-error@+2{{simultaneous accesses to parameter 'p', but modification requires exclusive access; consider copying to a local variable}}
   // expected-note@+1{{conflicting access is here}}
   takesTwoInouts(&p, &p)
 }
@@ -27,7 +27,7 @@
 func swapNoSuppression(_ i: Int, _ j: Int) {
   var a: [Int] = [1, 2, 3]
 
-  // expected-error@+2{{simultaneous accesses to var 'a'; modification requires exclusive access}}
+  // expected-error@+2{{simultaneous accesses to var 'a', but modification requires exclusive access; consider copying to a local variable}}
   // expected-note@+1{{conflicting access is here}}
   swap(&a[i], &a[j]) // no-warning
 }
@@ -42,13 +42,13 @@
   mutating func callMutatingMethodThatTakesSelfInout() {
     // expected-error@+4{{inout arguments are not allowed to alias each other}}
     // expected-note@+3{{previous aliasing argument}}
-    // expected-error@+2{{simultaneous accesses to parameter 'self'; modification requires exclusive access}}
+    // expected-error@+2{{simultaneous accesses to parameter 'self', but modification requires exclusive access; consider copying to a local variable}}
     // expected-note@+1{{conflicting access is here}}
     mutate(&self)
   }
 
   mutating func callMutatingMethodThatTakesSelfStoredPropInout() {
-    // expected-error@+2{{simultaneous accesses to parameter 'self'; modification requires exclusive access}}
+    // expected-error@+2{{simultaneous accesses to parameter 'self', but modification requires exclusive access; consider copying to a local variable}}
     // expected-note@+1{{conflicting access is here}}
     mutate(&self.f)
   }
@@ -56,7 +56,7 @@
 
 var globalStruct1 = StructWithMutatingMethodThatTakesSelfInout()
 func callMutatingMethodThatTakesGlobalStoredPropInout() {
-  // expected-error@+2{{simultaneous accesses to var 'globalStruct1'; modification requires exclusive access}}
+  // expected-error@+2{{simultaneous accesses to var 'globalStruct1', but modification requires exclusive access; consider copying to a local variable}}
   // expected-note@+1{{conflicting access is here}}
   globalStruct1.mutate(&globalStruct1.f)
 }
@@ -68,13 +68,13 @@
   func callMutatingMethodThatTakesClassStoredPropInout() {
     s1.mutate(&s2.f) // no-warning
 
-    // expected-error@+2{{simultaneous accesses to var 's1'; modification requires exclusive access}}
+    // expected-error@+2{{simultaneous accesses to var 's1', but modification requires exclusive access; consider copying to a local variable}}
     // expected-note@+1{{conflicting access is here}}
     s1.mutate(&s1.f)
 
     let local1 = self
 
-    // expected-error@+2{{simultaneous accesses to var 's1'; modification requires exclusive access}}
+    // expected-error@+2{{simultaneous accesses to var 's1', but modification requires exclusive access; consider copying to a local variable}}
     // expected-note@+1{{conflicting access is here}}
     local1.s1.mutate(&local1.s1.f)
   }
@@ -84,7 +84,7 @@
   var local = p
   // expected-error@+4{{inout arguments are not allowed to alias each other}}
   // expected-note@+3{{previous aliasing argument}}
-  // expected-error@+2{{simultaneous accesses to var 'local'; modification requires exclusive access}}
+  // expected-error@+2{{simultaneous accesses to var 'local', but modification requires exclusive access; consider copying to a local variable}}
   // expected-note@+1{{conflicting access is here}}
   takesTwoInouts(&local, &local)
 }
diff --git a/test/SILOptimizer/exclusivity_static_diagnostics_swift3.swift b/test/SILOptimizer/exclusivity_static_diagnostics_swift3.swift
index 40fc02c..cf37f51 100644
--- a/test/SILOptimizer/exclusivity_static_diagnostics_swift3.swift
+++ b/test/SILOptimizer/exclusivity_static_diagnostics_swift3.swift
@@ -12,7 +12,7 @@
 
   // expected-error@+4{{inout arguments are not allowed to alias each other}}
   // expected-note@+3{{previous aliasing argument}}
-  // expected-warning@+2{{simultaneous accesses to var 'i'; modification requires exclusive access}}
+  // expected-warning@+2{{simultaneous accesses to var 'i', but modification requires exclusive access; consider copying to a local variable}}
   // expected-note@+1{{conflicting access is here}}
   takesTwoInouts(&i, &i)
 }
@@ -24,7 +24,7 @@
 func diagnoseOnSameField() {
   var x = X()
 
-  // expected-warning@+2{{simultaneous accesses to var 'x'; modification requires exclusive access}}
+  // expected-warning@+2{{simultaneous accesses to var 'x', but modification requires exclusive access; consider copying to a local variable}}
   // expected-note@+1{{conflicting access is here}}
   takesTwoInouts(&x.f, &x.f)
 }
diff --git a/test/SILOptimizer/exclusivity_suppress_swap.swift b/test/SILOptimizer/exclusivity_suppress_swap.swift
index b6749f6..b8ed856 100644
--- a/test/SILOptimizer/exclusivity_suppress_swap.swift
+++ b/test/SILOptimizer/exclusivity_suppress_swap.swift
@@ -9,7 +9,7 @@
 
   swap(&a[i], &a[j]) // no-warning
 
-  // expected-warning@+2{{simultaneous accesses to var 'a'; modification requires exclusive access}}
+  // expected-warning@+2{{simultaneous accesses to var 'a', but modification requires exclusive access; consider copying to a local variable}}
   // expected-note@+1{{conflicting access is here}}
   takesTwoInouts(&a[i], &a[j])
 }
@@ -20,7 +20,7 @@
   // We don't suppress when swap() is used as a value
   let mySwap: (inout Int, inout Int) -> () = swap
 
-  // expected-warning@+2{{simultaneous accesses to var 'a'; modification requires exclusive access}}
+  // expected-warning@+2{{simultaneous accesses to var 'a', but modification requires exclusive access; consider copying to a local variable}}
   // expected-note@+1{{conflicting access is here}}
   mySwap(&a[i], &a[j])
 }
@@ -33,7 +33,7 @@
     return (p1, p2) = (p2, p1)
   }
 
-  // expected-warning@+2{{simultaneous accesses to var 'a'; modification requires exclusive access}}
+  // expected-warning@+2{{simultaneous accesses to var 'a', but modification requires exclusive access; consider copying to a local variable}}
   // expected-note@+1{{conflicting access is here}}
   swap(&a[i], &a[j])
 }