From: Richard Smith Date: Tue, 8 Nov 2011 01:31:09 +0000 (+0000) Subject: Fix a cluster of related issues involving value-dependence and constant X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=db1822c6de43ff4aa5fa00234bf8222f6f4816e8;p=clang 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). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144056 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 848e079744..92b05344ec 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -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(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(D) && D->getDeclContext()->isDependentContext()) { ValueDependent = true; InstantiationDependent = true; - return; - } + } } void DeclRefExpr::computeDependence() { diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 746b094619..d6e263b447 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -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(D)) { + if (!Dcl->getType()->isIntegralOrEnumerationType()) + return ICEDiag(2, cast(E)->getLocation()); + // Look for a declaration of this variable that has an initializer. const VarDecl *ID = 0; const Expr *Init = Dcl->getAnyInitializer(ID); diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index bba949bbd5..8481c8a6e1 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -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 struct S { + int k; + void f() { + I::V &cells = B ? x : y; + I &i = cells[k]; + switch (i.n) {} + } +}; + +} diff --git a/test/SemaCXX/constant-expression.cpp b/test/SemaCXX/constant-expression.cpp index e3f45c5ec0..2d2f1aee2b 100644 --- a/test/SemaCXX/constant-expression.cpp +++ b/test/SemaCXX/constant-expression.cpp @@ -95,3 +95,10 @@ void diags(int n) { ; } } + +namespace IntOrEnum { + const int k = 0; + const int &p = k; + template struct S {}; + S

s; // expected-error {{not an integral constant expression}} +}