forked from OSchip/llvm-project
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:
parent
12cdb4fd33
commit
2faf8e127f
|
@ -7268,27 +7268,29 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
|
||||||
void Sema::completeExprArrayBound(Expr *E) {
|
void Sema::completeExprArrayBound(Expr *E) {
|
||||||
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
|
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
|
||||||
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
|
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
|
||||||
if (isTemplateInstantiation(Var->getTemplateSpecializationKind()) &&
|
if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) {
|
||||||
!Var->getDefinition()) {
|
|
||||||
SourceLocation PointOfInstantiation = E->getExprLoc();
|
|
||||||
InstantiateVariableDefinition(PointOfInstantiation, Var);
|
|
||||||
auto *Def = Var->getDefinition();
|
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
|
// If we don't already have a point of instantiation, and we managed
|
||||||
// instantiate a definition, this is the point of instantiation.
|
// to instantiate a definition, this is the point of instantiation.
|
||||||
// Otherwise, we don't request an end-of-TU instantiation, so this is
|
// Otherwise, we don't request an end-of-TU instantiation, so this is
|
||||||
// not a point of instantiation.
|
// not a point of instantiation.
|
||||||
// FIXME: Is this really the right behavior?
|
// FIXME: Is this really the right behavior?
|
||||||
if (Var->getPointOfInstantiation().isInvalid() && Def) {
|
if (Var->getPointOfInstantiation().isInvalid() && Def) {
|
||||||
assert(Var->getTemplateSpecializationKind() ==
|
assert(Var->getTemplateSpecializationKind() ==
|
||||||
TSK_ImplicitInstantiation &&
|
TSK_ImplicitInstantiation &&
|
||||||
"explicit instantiation with no point of instantiation");
|
"explicit instantiation with no point of instantiation");
|
||||||
Var->setTemplateSpecializationKind(
|
Var->setTemplateSpecializationKind(
|
||||||
Var->getTemplateSpecializationKind(), PointOfInstantiation);
|
Var->getTemplateSpecializationKind(), PointOfInstantiation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the type to the newly instantiated definition's type both
|
// Update the type to the definition's type both here and within the
|
||||||
// here and within the expression.
|
// expression.
|
||||||
if (Def) {
|
if (Def) {
|
||||||
DRE->setDecl(Def);
|
DRE->setDecl(Def);
|
||||||
QualType T = Def->getType();
|
QualType T = Def->getType();
|
||||||
|
|
|
@ -5,3 +5,14 @@ template<bool> struct DominatorTreeBase {
|
||||||
};
|
};
|
||||||
extern template class DominatorTreeBase<false>;
|
extern template class DominatorTreeBase<false>;
|
||||||
constexpr bool k = DominatorTreeBase<false>::IsPostDominator;
|
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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue