[modules] When finding the owning module of an instantiated context in template

instantiation, follow lexical parents not semantic ones: we want to find the
module where the pattern was written.

llvm-svn: 316055
This commit is contained in:
Richard Smith 2017-10-18 01:41:38 +00:00
parent 1fc49627e4
commit 17ad3ac2aa
4 changed files with 64 additions and 5 deletions

View 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:

View 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;

View 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));

View File

@ -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}}
}