When attempting to complete an incomplete array bound type in an expression,

update the type from the definition even if we didn't instantiate a definition.

We may have instantiated the definition in an earlier stage of semantic
analysis, after creating the DeclRefExpr but before we reach a point where a
complete expression type is required.

llvm-svn: 320709
This commit is contained in:
Richard Smith 2017-12-14 15:40:16 +00:00
parent 12cdb4fd33
commit 2faf8e127f
2 changed files with 30 additions and 17 deletions

View File

@ -7268,27 +7268,29 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
void Sema::completeExprArrayBound(Expr *E) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
if (isTemplateInstantiation(Var->getTemplateSpecializationKind()) &&
!Var->getDefinition()) {
SourceLocation PointOfInstantiation = E->getExprLoc();
InstantiateVariableDefinition(PointOfInstantiation, Var);
if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) {
auto *Def = Var->getDefinition();
if (!Def) {
SourceLocation PointOfInstantiation = E->getExprLoc();
InstantiateVariableDefinition(PointOfInstantiation, Var);
Def = Var->getDefinition();
// If we don't already have a point of instantiation, and we managed to
// instantiate a definition, this is the point of instantiation.
// Otherwise, we don't request an end-of-TU instantiation, so this is
// not a point of instantiation.
// FIXME: Is this really the right behavior?
if (Var->getPointOfInstantiation().isInvalid() && Def) {
assert(Var->getTemplateSpecializationKind() ==
TSK_ImplicitInstantiation &&
"explicit instantiation with no point of instantiation");
Var->setTemplateSpecializationKind(
Var->getTemplateSpecializationKind(), PointOfInstantiation);
// If we don't already have a point of instantiation, and we managed
// to instantiate a definition, this is the point of instantiation.
// Otherwise, we don't request an end-of-TU instantiation, so this is
// not a point of instantiation.
// FIXME: Is this really the right behavior?
if (Var->getPointOfInstantiation().isInvalid() && Def) {
assert(Var->getTemplateSpecializationKind() ==
TSK_ImplicitInstantiation &&
"explicit instantiation with no point of instantiation");
Var->setTemplateSpecializationKind(
Var->getTemplateSpecializationKind(), PointOfInstantiation);
}
}
// Update the type to the newly instantiated definition's type both
// here and within the expression.
// Update the type to the definition's type both here and within the
// expression.
if (Def) {
DRE->setDecl(Def);
QualType T = Def->getType();

View File

@ -5,3 +5,14 @@ template<bool> struct DominatorTreeBase {
};
extern template class DominatorTreeBase<false>;
constexpr bool k = DominatorTreeBase<false>::IsPostDominator;
namespace CompleteType {
template<unsigned N> constexpr int f(const bool (&)[N]) { return 0; }
template<bool ...V> struct X {
static constexpr bool arr[] = {V...};
static constexpr int value = f(arr);
};
constexpr int n = X<true>::value;
}