[modules] When finding the owning module of an instantiated context in template
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 18 Oct 2017 01:41:38 +0000 (01:41 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 18 Oct 2017 01:41:38 +0000 (01:41 +0000)
instantiation, follow lexical parents not semantic ones: we want to find the
module where the pattern was written.

llvm-svn: 316055

clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
clang/lib/Sema/SemaLookup.cpp
clang/test/Modules/visibility-in-instantiation.cpp [new file with mode: 0644]

index 475f07f..8d71fb9 100644 (file)
@@ -176,7 +176,8 @@ public:
       : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),
         Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) {
     assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
-    assert(!DiagnosticLoc.isInvalid() && "DiagnosticLoc is invalid!");
+    assert((!DiagnosticLoc.isInvalid() || MatchAnyLine) &&
+           "DiagnosticLoc is invalid!");
     }
 
   private:
index 427d15e..a49c424 100644 (file)
@@ -416,9 +416,12 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
           MatchAnyLine = true;
           ExpectedLoc = SM.translateFileLineCol(FE, 1, 1);
         }
+      } else if (PH.Next("*")) {
+        MatchAnyLine = true;
+        ExpectedLoc = SourceLocation();
       }
 
-      if (ExpectedLoc.isInvalid()) {
+      if (ExpectedLoc.isInvalid() && !MatchAnyLine) {
         Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
                      diag::err_verify_missing_line) << KindStr;
         continue;
@@ -650,7 +653,10 @@ static unsigned PrintExpected(DiagnosticsEngine &Diags,
   llvm::raw_svector_ostream OS(Fmt);
   for (auto *DirPtr : DL) {
     Directive &D = *DirPtr;
-    OS << "\n  File " << SourceMgr.getFilename(D.DiagnosticLoc);
+    if (D.DiagnosticLoc.isInvalid())
+      OS << "\n  File *";
+    else
+      OS << "\n  File " << SourceMgr.getFilename(D.DiagnosticLoc);
     if (D.MatchAnyLine)
       OS << " Line *";
     else
@@ -708,7 +714,8 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
             continue;
         }
 
-        if (!IsFromSameFile(SourceMgr, D.DiagnosticLoc, II->first))
+        if (!D.DiagnosticLoc.isInvalid() &&
+            !IsFromSameFile(SourceMgr, D.DiagnosticLoc, II->first))
           continue;
 
         const std::string &RightText = II->second;
index 827c701..73aceaa 100644 (file)
@@ -1374,7 +1374,7 @@ static Module *getDefiningModule(Sema &S, Decl *Entity) {
 
   // Walk up to the containing context. That might also have been instantiated
   // from a template.
-  DeclContext *Context = Entity->getDeclContext();
+  DeclContext *Context = Entity->getLexicalDeclContext();
   if (Context->isFileContext())
     return S.getOwningModule(Entity);
   return getDefiningModule(S, cast<Decl>(Context));
diff --git a/clang/test/Modules/visibility-in-instantiation.cpp b/clang/test/Modules/visibility-in-instantiation.cpp
new file mode 100644 (file)
index 0000000..8689758
--- /dev/null
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -std=c++11 -fmodules %s -verify
+
+#pragma clang module build M
+  module M { module A {} module B {} module C {} }
+#pragma clang module contents
+  
+  #pragma clang module begin M.A
+    template<typename U> struct X {
+      template<typename T> void f();
+    };
+  #pragma clang module end
+  
+  #pragma clang module begin M.B
+    template<typename T, typename U = void> struct ST { static void f(); };
+  #pragma clang module end
+  
+  #pragma clang module begin M.C
+    template<typename U> struct X;
+    void foo(X<int>);
+  #pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build N
+  module N {}
+#pragma clang module contents
+  #pragma clang module begin N
+    #pragma clang module import M.B // not re-exported
+
+    template<typename U> struct X {
+      template<typename T> void f();
+      template<typename T> void g();
+    };
+
+    template<typename U> template<typename T>
+    void X<U>::f() {
+      ST<T>::f(); // definition and default argument found in M.B
+      foo(*this); // found by ADL in M.C
+    };
+
+    #pragma clang module import M.C // not re-exported
+  #pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module import N
+void g() {
+  X<int>().f<int>();
+
+  ST<int>::f(); // expected-error {{must be imported from module 'M.B'}}
+  foo(X<int>()); // expected-error {{must be imported from module 'M.C'}}
+  // expected-note@* 2{{previous declaration is here}}
+}