Modules: Search for a visible definition of the decl context when computing visibility of a default template parameter

The code is/was already correct for the case where a parameter is a
parameter of its enclosing lexical DeclContext (functions and classes).
But for other templates (alias and variable templates) they don't create
their own scope to be members of - in those cases, they parameter should
be considered visible if any definition of the lexical decl context is
visible.

[this should cleanup the failure on the libstdc++ modules buildbot]
[this doesn't actually fix the variable template case for a
secondary/compounding reason (its lexical decl context is incorrectly
considered to be the translation unit)]

Test covers all 4 kinds of templates with default args, including a
regression test for the still broken variable template case.

Reviewers: rsmith

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

llvm-svn: 358795
This commit is contained in:
David Blaikie 2019-04-19 23:02:30 +00:00
parent a30920c31f
commit aa3bf6ce72
15 changed files with 95 additions and 2 deletions

View File

@ -1543,8 +1543,21 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
// and in C we must not because each declaration of a function gets its own
// set of declarations for tags in prototype scope.
bool VisibleWithinParent;
if (D->isTemplateParameter() || isa<ParmVarDecl>(D) ||
(isa<FunctionDecl>(DC) && !SemaRef.getLangOpts().CPlusPlus))
if (D->isTemplateParameter()) {
bool SearchDefinitions = true;
if (const auto *DCD = dyn_cast<Decl>(DC)) {
if (const auto *TD = DCD->getDescribedTemplate()) {
TemplateParameterList *TPL = TD->getTemplateParameters();
auto Index = getDepthAndIndex(D).second;
SearchDefinitions = Index >= TPL->size() || TPL->getParam(Index) != D;
}
}
if (SearchDefinitions)
VisibleWithinParent = SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC));
else
VisibleWithinParent = isVisible(SemaRef, cast<NamedDecl>(DC));
} else if (isa<ParmVarDecl>(D) ||
(isa<FunctionDecl>(DC) && !SemaRef.getLangOpts().CPlusPlus))
VisibleWithinParent = isVisible(SemaRef, cast<NamedDecl>(DC));
else if (D->isModulePrivate()) {
// A module-private declaration is only visible if an enclosing lexical

View File

@ -0,0 +1,7 @@
#ifndef ALIAS_H
#define ALIAS_H
struct alias_outer {
template <typename = int>
using alias = int;
};
#endif

View File

@ -0,0 +1 @@
#include "alias.h"

View File

@ -0,0 +1 @@
#include "alias.h"

View File

@ -0,0 +1,7 @@
#ifndef FUNC_H
#define FUNC_H
struct func_outer {
template <typename = int>
void func();
};
#endif

View File

@ -0,0 +1 @@
#include "func.h"

View File

@ -0,0 +1 @@
#include "func.h"

View File

@ -0,0 +1,24 @@
module ALIAS1 {
header "alias1.h"
module ALIAS2 {
header "alias2.h"
}
}
module VAR1 {
header "var1.h"
module VAR2 {
header "var2.h"
}
}
module FUNC1 {
header "func1.h"
module FUNC2 {
header "func2.h"
}
}
module STRCT1 {
header "strct1.h"
module STRCT2 {
header "strct2.h"
}
}

View File

@ -0,0 +1,7 @@
#ifndef STRCT_H
#define STRCT_H
struct strct_outer {
template <typename = int>
struct strct;
};
#endif

View File

@ -0,0 +1 @@
#include "strct.h"

View File

@ -0,0 +1 @@
#include "strct.h"

View File

@ -0,0 +1,9 @@
#ifndef VAR_H
#define VAR_H
struct var_outer {
template <typename = int>
static int var;
};
#endif

View File

@ -0,0 +1 @@
#include "var.h"

View File

@ -0,0 +1 @@
#include "var.h"

View File

@ -0,0 +1,18 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -x c++ -fmodules -fimplicit-module-maps -fmodules-cache-path=%t \
// RUN: -I %S/Inputs/nested-template-default-arg-redecl -std=c++14 \
// RUN: -fmodules-local-submodule-visibility -verify %s
#include "alias2.h"
#include "var2.h"
#include "strct2.h"
#include "func2.h"
// FIXME: Variable templates lexical decl context appears to be the translation
// unit, which is incorrect. Fixing this will hopefully address the following
// error/bug:
// expected-note@Inputs/nested-template-default-arg-redecl/var.h:4 {{default argument declared here}}
auto var = &var_outer::var<>; // expected-error {{default argument of 'var' must be imported from module 'VAR1' before it is required}}
auto func = &func_outer::func<>;
strct_outer::strct<> *strct;
alias_outer::alias<> *alias;