Modules: Fix an assertion in DeclContext::buildLookup.
authorManman Ren <manman.ren@gmail.com>
Tue, 6 Sep 2016 18:16:54 +0000 (18:16 +0000)
committerManman Ren <manman.ren@gmail.com>
Tue, 6 Sep 2016 18:16:54 +0000 (18:16 +0000)
When calling getMostRecentDecl, we can pull in more definitions from
a module. We call getPrimaryContext afterwards to make sure that
we buildLookup on a primary context.

rdar://27926200

llvm-svn: 280728

clang/lib/AST/DeclBase.cpp
clang/test/Modules/Inputs/lookup-assert/Base.h [new file with mode: 0644]
clang/test/Modules/Inputs/lookup-assert/Derive.h [new file with mode: 0644]
clang/test/Modules/Inputs/lookup-assert/H3.h [new file with mode: 0644]
clang/test/Modules/Inputs/lookup-assert/module.map [new file with mode: 0644]
clang/test/Modules/lookup-assert.m [new file with mode: 0644]

index 8342c0f..4586d4b 100644 (file)
@@ -1411,10 +1411,6 @@ DeclContext::lookup(DeclarationName Name) const {
   assert(DeclKind != Decl::LinkageSpec &&
          "Should not perform lookups into linkage specs!");
 
-  const DeclContext *PrimaryContext = getPrimaryContext();
-  if (PrimaryContext != this)
-    return PrimaryContext->lookup(Name);
-
   // If we have an external source, ensure that any later redeclarations of this
   // context have been loaded, since they may add names to the result of this
   // lookup (or add external visible storage).
@@ -1422,6 +1418,12 @@ DeclContext::lookup(DeclarationName Name) const {
   if (Source)
     (void)cast<Decl>(this)->getMostRecentDecl();
 
+  // getMostRecentDecl can change the result of getPrimaryContext. Call
+  // getPrimaryContext afterwards.
+  const DeclContext *PrimaryContext = getPrimaryContext();
+  if (PrimaryContext != this)
+    return PrimaryContext->lookup(Name);
+
   if (hasExternalVisibleStorage()) {
     assert(Source && "external visible storage but no external source?");
 
diff --git a/clang/test/Modules/Inputs/lookup-assert/Base.h b/clang/test/Modules/Inputs/lookup-assert/Base.h
new file mode 100644 (file)
index 0000000..8d5e06b
--- /dev/null
@@ -0,0 +1,4 @@
+@interface BaseInterface
+- (void) test;
+@end
+
diff --git a/clang/test/Modules/Inputs/lookup-assert/Derive.h b/clang/test/Modules/Inputs/lookup-assert/Derive.h
new file mode 100644 (file)
index 0000000..313a961
--- /dev/null
@@ -0,0 +1,3 @@
+#include "Base.h"
+@interface DerivedInterface : BaseInterface
+@end
diff --git a/clang/test/Modules/Inputs/lookup-assert/H3.h b/clang/test/Modules/Inputs/lookup-assert/H3.h
new file mode 100644 (file)
index 0000000..3d8f878
--- /dev/null
@@ -0,0 +1 @@
+#include "Base.h"
diff --git a/clang/test/Modules/Inputs/lookup-assert/module.map b/clang/test/Modules/Inputs/lookup-assert/module.map
new file mode 100644 (file)
index 0000000..e8a89eb
--- /dev/null
@@ -0,0 +1,4 @@
+module X {
+  header "H3.h"
+  export *
+}
diff --git a/clang/test/Modules/lookup-assert.m b/clang/test/Modules/lookup-assert.m
new file mode 100644 (file)
index 0000000..2697fb1
--- /dev/null
@@ -0,0 +1,10 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/lookup-assert %s -verify
+// expected-no-diagnostics
+
+#include "Derive.h"
+#import <H3.h>
+@implementation DerivedInterface
+- (void)test {
+}
+@end