From 11a14b7ed3594b61559ed1b62e3080ff1fb04c72 Mon Sep 17 00:00:00 2001 From: Hannes Vogt Date: Thu, 4 Apr 2019 22:36:40 +0200 Subject: [PATCH] Bug 545756 - Improve EvalBinding.isConstantExpression() Previously, all variables with an initial value (even non-const) were treated as constant expressions, now only constexpr variables, static const members and global const variables are treated as constant expression. Change-Id: I2acb4033a1f75110302ea25640afb070d025ec2b Signed-off-by: Hannes Vogt --- .../core/parser/tests/ast2/AST2CPPTests.java | 12 +++++++++++ .../parser/tests/ast2/AST2TemplateTests.java | 16 ++++++++++++++ .../core/dom/parser/cpp/CPPVariable.java | 2 +- .../semantics/AggregateInitialization.java | 6 ++++-- .../dom/parser/cpp/semantics/EvalBinding.java | 21 +++++++++++++++++-- .../parser/cpp/semantics/ExpressionTypes.java | 2 +- 6 files changed, 53 insertions(+), 6 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index fc1f30c02c7..f89cfcd5470 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -13031,6 +13031,18 @@ public class AST2CPPTests extends AST2CPPTestBase { parseAndCheckImplicitNameBindings(); } + // struct A { + // int x; + // }; + // + // template + // struct B { + // A a{sizeof(T)}; + // }; + public void testAggregateInitNoNarrowingConversionInDependentConstContext_545756() throws Exception { + parseAndCheckImplicitNameBindings(); + } + // struct type{ // int a; // }; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 1323628a656..c53ccaa951c 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -11282,4 +11282,20 @@ public class AST2TemplateTests extends AST2CPPTestBase { helper.assertVariableValue("val1", 42); helper.assertVariableValue("val2", 43); } + + // template + // constexpr T id(T a) { + // return a; + // } + // + // template struct Waldo {using type = int;}; + // + // const int forty_two = 42; + // using const_int_ref = int const&; + // const_int_ref ref_forty_two = forty_two; + // + // Waldo::type a; + public void testGlobalConstWorksAsConstExpression_545756() throws Exception { + parseAndCheckBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java index 4999c631b5f..9bce0ccd1fe 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java @@ -202,7 +202,7 @@ public class CPPVariable extends PlatformObject implements ICPPInternalDeclaredV @Override public boolean isConstexpr() { - return VariableHelpers.isConstexpr(fDefinition); + return VariableHelpers.isConstexpr(fDefinition != null ? fDefinition : fDeclarations[0]); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AggregateInitialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AggregateInitialization.java index 64648a5231e..fb1190eb5d0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AggregateInitialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AggregateInitialization.java @@ -103,8 +103,10 @@ class AggregateInitialization { fIndex++; // [dcl.init.aggr] If the initializer-clause is an expression and a narrowing conversion is // required to convert the expression, the program is ill-formed. - if (!(initializer instanceof EvalInitList) && costWithoutElision.isNarrowingConversion()) { - return Cost.NO_CONVERSION; + if (!initializer.isConstantExpression()) { + if (!(initializer instanceof EvalInitList) && costWithoutElision.isNarrowingConversion()) { + return Cost.NO_CONVERSION; + } } if (costWithoutElision.compareTo(worstCost) > 0) { worstCost = costWithoutElision; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java index 6cf8de08188..bec2013b6f2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java @@ -32,6 +32,7 @@ import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.IVariable; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType; @@ -257,8 +258,24 @@ public class EvalBinding extends CPPDependentEvaluation { } private boolean computeIsConstantExpression() { - return fBinding instanceof IEnumerator || fBinding instanceof ICPPFunction - || (fBinding instanceof IVariable && isConstexprValue(((IVariable) fBinding).getInitialValue())); + if (fBinding instanceof IEnumerator || fBinding instanceof ICPPFunction) + return true; + else if (fBinding instanceof ICPPVariable) { + if (!isConstexprValue(((IVariable) fBinding).getInitialValue())) + return false; + ICPPVariable var = (ICPPVariable) fBinding; + if (var.isConstexpr()) + return true; + IType type = SemanticUtil.getNestedType(var.getType(), SemanticUtil.TDEF | SemanticUtil.REF); + if (ExpressionTypes.isConst(type)) { + if (var instanceof ICPPField) { + if (var.isStatic()) + return true; + } else + return true; + } + } + return false; } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExpressionTypes.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExpressionTypes.java index e882751221a..2481dbbcb82 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExpressionTypes.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExpressionTypes.java @@ -113,7 +113,7 @@ public class ExpressionTypes { return type; } - private static boolean isConst(IType type) { + public static boolean isConst(IType type) { if (type instanceof IQualifierType) { return ((IQualifierType) type).isConst(); } else if (type instanceof IPointerType) {