From 532a634d671d1dad27d4e7ce0c97d9411ab22447 Mon Sep 17 00:00:00 2001
From: Richard Smith <richard-llvm@metafoo.co.uk>
Date: Mon, 5 Jun 2017 22:29:36 +0000
Subject: [PATCH] Fix crash when an 'import a module' TypoCorrection has its
 CorrectionDecls replaced by visible decls.

Make sure that all paths through checkCorrectionVisibility set the
RequiresImport flag appropriately, so we don't end up using a stale value.
Patch by Jorge Gorbe!

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


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@304745 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Sema/SemaLookup.cpp                             | 13 ++++++-------
 .../crash-typo-correction-visibility/module.h       |  1 +
 .../module.modulemap                                |  3 +++
 test/Modules/crash-typo-correction-visibility.cpp   | 10 ++++++++++
 4 files changed, 20 insertions(+), 7 deletions(-)
 create mode 100644 test/Modules/Inputs/crash-typo-correction-visibility/module.h
 create mode 100644 test/Modules/Inputs/crash-typo-correction-visibility/module.modulemap
 create mode 100644 test/Modules/crash-typo-correction-visibility.cpp

diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 1d32e579681..1fb25f4e0e7 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -3747,20 +3747,19 @@ static void LookupPotentialTypoResult(Sema &SemaRef,
                                       bool FindHidden);
 
 /// \brief Check whether the declarations found for a typo correction are
-/// visible, and if none of them are, convert the correction to an 'import
-/// a module' correction.
+/// visible. Set the correction's RequiresImport flag to true if none of the
+/// declarations are visible, false otherwise.
 static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) {
-  if (TC.begin() == TC.end())
-    return;
-
   TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end();
 
   for (/**/; DI != DE; ++DI)
     if (!LookupResult::isVisible(SemaRef, *DI))
       break;
-  // Nothing to do if all decls are visible.
-  if (DI == DE)
+  // No filtering needed if all decls are visible.
+  if (DI == DE) {
+    TC.setRequiresImport(false);
     return;
+  }
 
   llvm::SmallVector<NamedDecl*, 4> NewDecls(TC.begin(), DI);
   bool AnyVisibleDecls = !NewDecls.empty();
diff --git a/test/Modules/Inputs/crash-typo-correction-visibility/module.h b/test/Modules/Inputs/crash-typo-correction-visibility/module.h
new file mode 100644
index 00000000000..6e73c3c729e
--- /dev/null
+++ b/test/Modules/Inputs/crash-typo-correction-visibility/module.h
@@ -0,0 +1 @@
+struct member;
diff --git a/test/Modules/Inputs/crash-typo-correction-visibility/module.modulemap b/test/Modules/Inputs/crash-typo-correction-visibility/module.modulemap
new file mode 100644
index 00000000000..7310d6a2ef1
--- /dev/null
+++ b/test/Modules/Inputs/crash-typo-correction-visibility/module.modulemap
@@ -0,0 +1,3 @@
+module "module" {
+  header "module.h"
+}
diff --git a/test/Modules/crash-typo-correction-visibility.cpp b/test/Modules/crash-typo-correction-visibility.cpp
new file mode 100644
index 00000000000..518293026a6
--- /dev/null
+++ b/test/Modules/crash-typo-correction-visibility.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-name=module -o %T/module.pcm -emit-module %S/Inputs/crash-typo-correction-visibility/module.modulemap
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-file=%T/module.pcm %s -verify
+
+struct S {
+  int member; // expected-note {{declared here}}
+};
+
+int f(...);
+
+int b = sizeof(f(member)); // expected-error {{undeclared identifier 'member'}}
-- 
GitLab