forked from OSchip/llvm-project
Fix a cluster of related issues involving value-dependence and constant
expression evaluation: - When folding a non-value-dependent expression, we may try to use the initializer of a value-dependent variable. If that happens, give up. - In C++98, actually check that a const, non-volatile DeclRefExpr inside an ICE is of integral or enumeration type (a reference isn't OK!) - In C++11, DeclRefExprs for objects of const literal type initialized with value-dependent expressions are themselves value-dependent. - So are references initialized with value-dependent expressions (though this case is missing from the C++11 standard, along with many others). llvm-svn: 144056
This commit is contained in:
parent
f2a9bd4b1e
commit
ec8dcd2716
|
@ -185,21 +185,29 @@ static void computeDeclRefDependence(NamedDecl *D, QualType T,
|
|||
|
||||
// (VD) - a constant with integral or enumeration type and is
|
||||
// initialized with an expression that is value-dependent.
|
||||
// (VD) - a constant with literal type and is initialized with an
|
||||
// expression that is value-dependent [C++11].
|
||||
// (VD) - FIXME: Missing from the standard:
|
||||
// - an entity with reference type and is initialized with an
|
||||
// expression that is value-dependent [C++11]
|
||||
if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
|
||||
if (Var->getType()->isIntegralOrEnumerationType() &&
|
||||
Var->getType().getCVRQualifiers() == Qualifiers::Const) {
|
||||
if ((D->getASTContext().getLangOptions().CPlusPlus0x ?
|
||||
Var->getType()->isLiteralType() :
|
||||
Var->getType()->isIntegralOrEnumerationType()) &&
|
||||
(Var->getType().getCVRQualifiers() == Qualifiers::Const ||
|
||||
Var->getType()->isReferenceType())) {
|
||||
if (const Expr *Init = Var->getAnyInitializer())
|
||||
if (Init->isValueDependent()) {
|
||||
ValueDependent = true;
|
||||
InstantiationDependent = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// (VD) - FIXME: Missing from the standard:
|
||||
// - a member function or a static data member of the current
|
||||
// instantiation
|
||||
else if (Var->isStaticDataMember() &&
|
||||
Var->getDeclContext()->isDependentContext()) {
|
||||
if (Var->isStaticDataMember() &&
|
||||
Var->getDeclContext()->isDependentContext()) {
|
||||
ValueDependent = true;
|
||||
InstantiationDependent = true;
|
||||
}
|
||||
|
@ -213,8 +221,7 @@ static void computeDeclRefDependence(NamedDecl *D, QualType T,
|
|||
if (isa<CXXMethodDecl>(D) && D->getDeclContext()->isDependentContext()) {
|
||||
ValueDependent = true;
|
||||
InstantiationDependent = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeclRefExpr::computeDependence() {
|
||||
|
|
|
@ -552,7 +552,7 @@ static bool EvaluateVarDeclInit(EvalInfo &Info, const VarDecl *VD,
|
|||
return false;
|
||||
|
||||
const Expr *Init = VD->getAnyInitializer();
|
||||
if (!Init)
|
||||
if (!Init || Init->isValueDependent())
|
||||
return false;
|
||||
|
||||
if (APValue *V = VD->getEvaluatedValue()) {
|
||||
|
@ -3640,6 +3640,9 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
|
|||
// A variable of non-volatile const-qualified integral or enumeration
|
||||
// type initialized by an ICE can be used in ICEs.
|
||||
if (const VarDecl *Dcl = dyn_cast<VarDecl>(D)) {
|
||||
if (!Dcl->getType()->isIntegralOrEnumerationType())
|
||||
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
|
||||
|
||||
// Look for a declaration of this variable that has an initializer.
|
||||
const VarDecl *ID = 0;
|
||||
const Expr *Init = Dcl->getAnyInitializer(ID);
|
||||
|
|
|
@ -322,3 +322,18 @@ static_assert_fold((&zs[0][0][0][2])[-1] == 2, "");
|
|||
static_assert_fold(**(**(zs + 1) + 1) == 11, "");
|
||||
|
||||
}
|
||||
|
||||
namespace DependentValues {
|
||||
|
||||
struct I { int n; typedef I V[10]; };
|
||||
I::V x, y;
|
||||
template<bool B> struct S {
|
||||
int k;
|
||||
void f() {
|
||||
I::V &cells = B ? x : y;
|
||||
I &i = cells[k];
|
||||
switch (i.n) {}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -95,3 +95,10 @@ void diags(int n) {
|
|||
;
|
||||
}
|
||||
}
|
||||
|
||||
namespace IntOrEnum {
|
||||
const int k = 0;
|
||||
const int &p = k;
|
||||
template<int n> struct S {};
|
||||
S<p> s; // expected-error {{not an integral constant expression}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue