From: Eli Friedman Date: Wed, 29 Feb 2012 03:16:56 +0000 (+0000) Subject: Make the odr-use logic work correctly for constant-expressions. PR12006. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ac6260187b6b2f26faa9264d170d649a501f58a9;p=clang Make the odr-use logic work correctly for constant-expressions. PR12006. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151699 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index cc264698da..499ee31d4a 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2341,6 +2341,8 @@ public: ExprResult TranformToPotentiallyEvaluated(Expr *E); ExprResult HandleExprEvaluationContextForTypeof(Expr *E); + ExprResult ActOnConstantExpression(ExprResult Res); + // Functions for marking a declaration referenced. These functions also // contain the relevant logic for marking if a reference to a function or // variable is an odr-use (in the C++11 sense). There are separate variants diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 26a2a11444..2f30e6bd2b 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -258,7 +258,8 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) { Sema::ConstantEvaluated); ExprResult LHS(ParseCastExpression(false, false, isTypeCast)); - return ParseRHSOfBinaryExpression(LHS, prec::Conditional); + ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); + return Actions.ActOnConstantExpression(Res); } /// ParseRHSOfBinaryExpression - Parse a binary expression that starts with diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 30a02b2953..5a2b2dc7e9 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -10023,6 +10023,18 @@ void Sema::UpdateMarkingForLValueToRValue(Expr *E) { MaybeODRUseExprs.erase(E->IgnoreParens()); } +ExprResult Sema::ActOnConstantExpression(ExprResult Res) { + if (!Res.isUsable()) + return Res; + + // If a constant-expression is a reference to a variable where we delay + // deciding whether it is an odr-use, just assume we will apply the + // lvalue-to-rvalue conversion. In the one case where this doesn't happen + // (a non-type template argument), we have special handling anyway. + UpdateMarkingForLValueToRValue(Res.get()); + return Res; +} + void Sema::CleanupVarDeclMarking() { for (llvm::SmallPtrSetIterator i = MaybeODRUseExprs.begin(), e = MaybeODRUseExprs.end(); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 11f03fc133..82bfe6fa70 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2950,6 +2950,7 @@ bool TreeTransform::TransformTemplateArgument( EnterExpressionEvaluationContext Unevaluated(getSema(), Sema::ConstantEvaluated); ExprResult E = getDerived().TransformExpr(SourceExpr); + E = SemaRef.ActOnConstantExpression(E); SourceExpr = (E.isInvalid() ? 0 : E.take()); } @@ -2990,6 +2991,7 @@ bool TreeTransform::TransformTemplateArgument( if (!InputExpr) InputExpr = Input.getArgument().getAsExpr(); ExprResult E = getDerived().TransformExpr(InputExpr); + E = SemaRef.ActOnConstantExpression(E); if (E.isInvalid()) return true; Output = TemplateArgumentLoc(TemplateArgument(E.take()), E.take()); return false; @@ -3654,6 +3656,7 @@ TreeTransform::TransformConstantArrayType(TypeLocBuilder &TLB, EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::ConstantEvaluated); Size = getDerived().TransformExpr(Size).template takeAs(); + Size = SemaRef.ActOnConstantExpression(Size).take(); } NewTL.setSizeExpr(Size); @@ -3744,6 +3747,7 @@ TreeTransform::TransformDependentSizedArrayType(TypeLocBuilder &TLB, ExprResult sizeResult = getDerived().TransformExpr(origSize); + sizeResult = SemaRef.ActOnConstantExpression(sizeResult); if (sizeResult.isInvalid()) return QualType(); @@ -3788,6 +3792,7 @@ QualType TreeTransform::TransformDependentSizedExtVectorType( Sema::ConstantEvaluated); ExprResult Size = getDerived().TransformExpr(T->getSizeExpr()); + Size = SemaRef.ActOnConstantExpression(Size); if (Size.isInvalid()) return QualType(); @@ -5061,11 +5066,13 @@ TreeTransform::TransformCaseStmt(CaseStmt *S) { // Transform the left-hand case value. LHS = getDerived().TransformExpr(S->getLHS()); + LHS = SemaRef.ActOnConstantExpression(LHS); if (LHS.isInvalid()) return StmtError(); // Transform the right-hand case value (for the GNU case-range extension). RHS = getDerived().TransformExpr(S->getRHS()); + RHS = SemaRef.ActOnConstantExpression(RHS); if (RHS.isInvalid()) return StmtError(); } diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp index e7eb5af891..9da9fcea1f 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp @@ -52,9 +52,8 @@ void f1(int i) { // expected-note{{declared here}} auto m1 = [=]{ int const M = 30; auto m2 = [i]{ - // FIXME: We odr-use here, but we shouldn't. - // int x[N][M]; - // x[0][0] = i; + int x[N][M]; + x[0][0] = i; }; (void)N; (void)M;